153 lines
5.8 KiB
Kotlin
153 lines
5.8 KiB
Kotlin
package com.beemer.serverstatus.command
|
|
|
|
import com.beemer.serverstatus.ServerStatusMod
|
|
import com.mojang.brigadier.CommandDispatcher
|
|
import com.mojang.brigadier.arguments.StringArgumentType
|
|
import com.mojang.brigadier.context.CommandContext
|
|
import java.net.HttpURLConnection
|
|
import java.net.URI
|
|
import kotlinx.serialization.Serializable
|
|
import kotlinx.serialization.encodeToString
|
|
import kotlinx.serialization.json.Json
|
|
import net.minecraft.commands.CommandSourceStack
|
|
import net.minecraft.commands.Commands
|
|
import net.minecraft.network.chat.Component
|
|
import net.minecraft.server.level.ServerPlayer
|
|
|
|
/** /인증 명령어 처리 웹사이트 계정 연동을 위한 명령어 */
|
|
object AuthCommand {
|
|
|
|
private val json = Json {
|
|
ignoreUnknownKeys = true
|
|
encodeDefaults = true
|
|
}
|
|
|
|
// 웹 서버 연동 API URL (환경 또는 설정에서 가져올 수 있음)
|
|
private const val WEB_API_URL = "http://minecraft-status/link/verify"
|
|
|
|
/** 명령어 등록 */
|
|
fun register(dispatcher: CommandDispatcher<CommandSourceStack>) {
|
|
// /인증 <토큰>
|
|
dispatcher.register(
|
|
Commands.literal("인증")
|
|
.then(
|
|
Commands.argument("token", StringArgumentType.word()).executes {
|
|
context ->
|
|
executeAuth(context)
|
|
}
|
|
)
|
|
)
|
|
|
|
ServerStatusMod.LOGGER.info("[${ServerStatusMod.MOD_ID}] /인증 명령어 등록됨")
|
|
}
|
|
|
|
/** 인증 명령어 실행 */
|
|
private fun executeAuth(context: CommandContext<CommandSourceStack>): Int {
|
|
val source = context.source
|
|
val player = source.player
|
|
|
|
// 플레이어만 사용 가능
|
|
if (player == null) {
|
|
source.sendFailure(Component.literal("§c플레이어만 이 명령어를 사용할 수 있습니다."))
|
|
return 0
|
|
}
|
|
|
|
val token = StringArgumentType.getString(context, "token").uppercase()
|
|
|
|
// 토큰 검증 (6자리 영숫자)
|
|
if (!token.matches(Regex("^[A-Z0-9]{6}$"))) {
|
|
source.sendFailure(Component.literal("§c유효하지 않은 인증 코드입니다."))
|
|
return 0
|
|
}
|
|
|
|
// 비동기로 웹 API 호출
|
|
Thread {
|
|
try {
|
|
val result = verifyWithWebServer(token, player)
|
|
|
|
// UI 스레드에서 메시지 전송
|
|
player.server.execute {
|
|
if (result.success) {
|
|
player.sendSystemMessage(
|
|
Component.literal("§a§l✓ 계정 연동 완료!\n§7웹사이트에서 프로필이 업데이트됩니다.")
|
|
)
|
|
} else {
|
|
player.sendSystemMessage(
|
|
Component.literal(
|
|
"§c✗ 연동 실패: ${result.error ?: "알 수 없는 오류"}"
|
|
)
|
|
)
|
|
}
|
|
}
|
|
} catch (e: Exception) {
|
|
ServerStatusMod.LOGGER.error(
|
|
"[${ServerStatusMod.MOD_ID}] 인증 오류: ${e.message}"
|
|
)
|
|
player.server.execute {
|
|
player.sendSystemMessage(Component.literal("§c✗ 연동 처리 중 오류가 발생했습니다."))
|
|
}
|
|
}
|
|
}
|
|
.start()
|
|
|
|
// 즉시 응답
|
|
source.sendSuccess({ Component.literal("§e인증 처리 중...") }, false)
|
|
return 1
|
|
}
|
|
|
|
/** 웹 서버에 연동 요청 */
|
|
private fun verifyWithWebServer(token: String, player: ServerPlayer): VerifyResponse {
|
|
val requestBody =
|
|
json.encodeToString(
|
|
VerifyRequest(
|
|
token = token,
|
|
uuid = player.stringUUID,
|
|
name = player.name.string
|
|
)
|
|
)
|
|
|
|
val url = URI(WEB_API_URL).toURL()
|
|
val conn = url.openConnection() as HttpURLConnection
|
|
|
|
try {
|
|
conn.requestMethod = "POST"
|
|
conn.doOutput = true
|
|
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8")
|
|
conn.connectTimeout = 5000
|
|
conn.readTimeout = 5000
|
|
|
|
// 요청 전송
|
|
conn.outputStream.use { os -> os.write(requestBody.toByteArray(Charsets.UTF_8)) }
|
|
|
|
// 응답 처리
|
|
val responseCode = conn.responseCode
|
|
val responseBody =
|
|
if (responseCode in 200..299) {
|
|
conn.inputStream.bufferedReader().use { it.readText() }
|
|
} else {
|
|
conn.errorStream?.bufferedReader()?.use { it.readText() } ?: ""
|
|
}
|
|
|
|
ServerStatusMod.LOGGER.info(
|
|
"[${ServerStatusMod.MOD_ID}] 인증 응답: $responseCode - $responseBody"
|
|
)
|
|
|
|
return try {
|
|
json.decodeFromString<VerifyResponse>(responseBody)
|
|
} catch (e: Exception) {
|
|
VerifyResponse(success = responseCode in 200..299, error = responseBody)
|
|
}
|
|
} finally {
|
|
conn.disconnect()
|
|
}
|
|
}
|
|
|
|
@Serializable data class VerifyRequest(val token: String, val uuid: String, val name: String)
|
|
|
|
@Serializable
|
|
data class VerifyResponse(
|
|
val success: Boolean = false,
|
|
val message: String? = null,
|
|
val error: String? = null
|
|
)
|
|
}
|