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) { // /인증 <토큰> 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): 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(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 ) }