Skip to content

Commit

Permalink
feat: finish backend
Browse files Browse the repository at this point in the history
  • Loading branch information
MiniDigger committed Oct 3, 2024
1 parent 0bac3e0 commit fb32dff
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
/run/
/*.iml
/kotlin-js-store/
/.kotlin/
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ services:
- "traefik.http.routers.adventure-webui.tls.certresolver=httpOnly"
- "traefik.http.routers.adventure-webui.tls.domains[0].main=webui.adventure.kyori.net"
- "traefik.http.routers.adventure-webui.tls.domains[1].main=webui.advntr.dev"
- "traefik.tcp.services.adventure-webui-mc.loadbalancer.server.port=25565"
- "traefik.tcp.routers.adventure-webui-mc.rule=HostSNI(`*`)"
- "traefik.tcp.routers.adventure-webui-mc.entrypoints=minecraft"
- "traefik.tcp.routers.adventure-webui-mc.tls.passthrough=true"
networks:
- web

Expand Down
5 changes: 5 additions & 0 deletions src/commonMain/kotlin/net/kyori/adventure/webui/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,10 @@ public const val PARAM_EDITOR_TOKEN: String = "token"
/** Path for getting a short link for a MiniMessage input. */
public const val URL_MINI_SHORTEN: String = "/mini-shorten"

/** Path for getting a hostname for an in-game MiniMessage motd preview. */
public const val URL_SETUP_MOTD_PREVIEW: String = "/setup-motd-preview"
/** Path for getting a hostname for an in-game MiniMessage kick preview. */
public const val URL_SETUP_KICK_PREVIEW: String = "/setup-kick-preview"

/** Path for getting the configuration of this WebUI instance */
public const val URL_BUILD_INFO: String = "/build"
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import io.ktor.server.websocket.WebSockets
import io.ktor.server.websocket.pingPeriod
import io.ktor.server.websocket.timeout
import io.ktor.websocket.WebSocketDeflateExtension
import net.kyori.adventure.webui.jvm.minimessage.preview.ServerStatusPreviewManager
import java.time.Duration

public fun Application.main() {
Expand Down Expand Up @@ -49,9 +48,6 @@ public fun Application.main() {
trace { route -> this@main.log.debug(route.buildText()) }
}
}

// Initialise the server status preview manager.
ServerStatusPreviewManager(this)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import net.kyori.adventure.webui.URL_MINI_SHORTEN
import net.kyori.adventure.webui.URL_MINI_TO_HTML
import net.kyori.adventure.webui.URL_MINI_TO_JSON
import net.kyori.adventure.webui.URL_MINI_TO_TREE
import net.kyori.adventure.webui.URL_SETUP_KICK_PREVIEW
import net.kyori.adventure.webui.URL_SETUP_MOTD_PREVIEW
import net.kyori.adventure.webui.jvm.appendComponent
import net.kyori.adventure.webui.jvm.getConfigString
import net.kyori.adventure.webui.jvm.minimessage.editor.installEditor
Expand All @@ -42,6 +44,7 @@ import net.kyori.adventure.webui.jvm.minimessage.hook.INSERTION_RENDER_HOOK
import net.kyori.adventure.webui.jvm.minimessage.hook.TEXT_COLOR_RENDER_HOOK
import net.kyori.adventure.webui.jvm.minimessage.hook.TEXT_DECORATION_RENDER_HOOK
import net.kyori.adventure.webui.jvm.minimessage.hook.TEXT_RENDER_HOOK
import net.kyori.adventure.webui.jvm.minimessage.preview.ServerStatusPreviewManager
import net.kyori.adventure.webui.jvm.minimessage.storage.BytebinStorage
import net.kyori.adventure.webui.tryDecodeFromString
import net.kyori.adventure.webui.websocket.Call
Expand Down Expand Up @@ -92,6 +95,9 @@ public fun Application.miniMessage() {

BytebinStorage.BYTEBIN_INSTANCE = this.getConfigString("bytebinInstance")

// Initialise the server status preview manager.
val previewManager = ServerStatusPreviewManager(this)

routing {
// define static path to resources
static("") {
Expand Down Expand Up @@ -199,6 +205,18 @@ public fun Application.miniMessage() {
}
}

post(URL_SETUP_MOTD_PREVIEW) {
val input = call.receiveText()
val hostname = previewManager.initializeMotdPreview(input)
call.respondText(hostname)
}

post(URL_SETUP_KICK_PREVIEW) {
val input = call.receiveText()
val hostname = previewManager.initializeKickPreview(input)
call.respondText(hostname)
}

get(URL_BUILD_INFO) {
val info = BuildInfo(
startedAt = startedAt.toString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.kyori.adventure.webui.jvm.minimessage.preview

import io.github.reactivecircus.cache4k.Cache
import io.ktor.network.selector.SelectorManager
import io.ktor.network.sockets.aSocket
import io.ktor.network.sockets.openReadChannel
Expand All @@ -24,6 +25,7 @@ import org.slf4j.LoggerFactory
import java.io.ByteArrayOutputStream
import java.io.DataOutputStream
import kotlin.coroutines.CoroutineContext
import kotlin.time.Duration.Companion.hours

/** Manager class for previewing server status. */
public class ServerStatusPreviewManager(
Expand All @@ -34,10 +36,13 @@ public class ServerStatusPreviewManager(
private val managerJob = SupervisorJob(application.coroutineContext.job)
override val coroutineContext: CoroutineContext = application.coroutineContext + managerJob

private val motdPreviews = Cache.Builder<String, String>().expireAfterAccess(1.hours).build()
private val kickPreviews = Cache.Builder<String, String>().expireAfterAccess(1.hours).build()

init {
launch {
// Initialise the socket.
val serverSocket = aSocket(SelectorManager(Dispatchers.IO)).tcp().bind("127.0.0.1", 9002)
val serverSocket = aSocket(SelectorManager(Dispatchers.IO)).tcp().bind("0.0.0.0", 25565)
logger.info("Listening for pings at ${serverSocket.localAddress}")

while (true) {
Expand All @@ -64,7 +69,7 @@ public class ServerStatusPreviewManager(
sendChannel.writeMcPacket(0) {
it.writeString(
GsonComponentSerializer.gson()
.serialize(MiniMessage.miniMessage().deserialize("<red>You cant join here!"))
.serialize(MiniMessage.miniMessage().deserialize(lookupKickMessage(serverAddress)))
)
}
} else {
Expand All @@ -77,11 +82,15 @@ public class ServerStatusPreviewManager(
LegacyComponentSerializer.legacySection()
.serialize(MiniMessage.miniMessage().deserialize("<rainbow>MiniMessage"))
}",
"protocol": $protocolVersion
"protocol": 1
},
"players": {
"max": 0,
"online": 0
},
"description": ${
GsonComponentSerializer.gson().serialize(
MiniMessage.miniMessage().deserialize("<rainbow>MiniMessage is cool!")
MiniMessage.miniMessage().deserialize(lookupMotd(serverAddress))
)
}
}""".trimIndent()
Expand All @@ -100,6 +109,33 @@ public class ServerStatusPreviewManager(
}
}

private fun lookupKickMessage(serverAddress: String): String {
return kickPreviews.get(serverAddress.split("\\.")[0]) ?: "<red>You cant join here!"
}

private fun lookupMotd(serverAddress: String): String {
return motdPreviews.get(serverAddress.split("\\.")[0]) ?: "<rainbow>MiniMessage is cool!"
}

public fun initializeKickPreview(input: String): String {
val key = generateRandomString()
kickPreviews.put(key, input)
return "$key.webui.advntr.dev"
}

public fun initializeMotdPreview(input: String): String {
val key = generateRandomString()
motdPreviews.put(key, input)
return "$key.webui.advntr.dev"
}

private fun generateRandomString(length: Int = 8): String {
val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}

private suspend fun ByteWriteChannel.writeMcPacket(packetId: Int, consumer: (packet: DataOutputStream) -> Unit) {
val stream = ByteArrayOutputStream()
val packet = DataOutputStream(stream)
Expand Down

0 comments on commit fb32dff

Please sign in to comment.