package net.taehui.twilight.etc import com.fasterxml.jackson.databind.ObjectMapper import io.netty.buffer.ByteBufUtil import io.netty.channel.ChannelFutureListener import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler import io.netty.handler.codec.http.* import net.taehui.twilight.Logger import net.taehui.twilight.Utility import net.taehui.twilight.system.AvatarHandler import net.taehui.twilight.system.Configure import org.slf4j.LoggerFactory import java.net.InetSocketAddress import java.net.URLDecoder import java.nio.charset.StandardCharsets import java.nio.file.Files class EtcAvatar : SimpleChannelInboundHandler<FullHttpRequest>(), Logger { class QwilightDate { var date = "" var hashAMD64 = "" var hashARM64 = "" var titleAMD64 = "" var titleARM64 = "" @Deprecated("hashX64") var hashX64 = "" @Deprecated("titleX64") var titleX64 = "" } private var avatarIP = "" private fun send204(handler: ChannelHandlerContext) { handler.writeAndFlush(DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NO_CONTENT)) .addListener(ChannelFutureListener.CLOSE) } override fun channelActive(ctx: ChannelHandlerContext) { avatarIP = (ctx.channel().remoteAddress() as InetSocketAddress).address.hostAddress } public override fun channelRead0(ctx: ChannelHandlerContext, msg: FullHttpRequest) { fun getQwilightDate(): QwilightDate { val jm = ObjectMapper() val qwilightDateFilePath = Configure.path.wwwPath.resolve("qwilight.json") return jm.readValue(Files.readString(qwilightDateFilePath), QwilightDate::class.java) } val path = URLDecoder.decode(msg.uri(), StandardCharsets.UTF_8) val mode = msg.method() logInfo("$mode $path") when (mode) { HttpMethod.GET -> when (path) { "/health" -> { send204(ctx) } } HttpMethod.PATCH -> when (path) { "/date/AMD64" -> { val data = ByteBufUtil.getBytes(msg.content()) logFuture { Files.write(Configure.path.wwwPath.resolve(getQwilightDate().titleAMD64), data) send204(ctx) } } "/date/ARM64" -> { val data = ByteBufUtil.getBytes(msg.content()) logFuture { Files.write(Configure.path.wwwPath.resolve(getQwilightDate().titleARM64), data) send204(ctx) } } "/date" -> { val data = msg.content().toString(StandardCharsets.UTF_8).split(" ".toRegex()) logFuture { var date = data[0] val hashAMD64 = data[1] val hashARM64 = data[2] if (date.contains("!")) { Configure.hash.clear() date = date.replace("!", "") } Configure.hash.add(hashAMD64) Configure.hash.add(hashARM64) Configure.saveConfigure() val jm = ObjectMapper() val dateFilePath = Configure.path.wwwPath.resolve("qwilight.json") val qwilightDate = jm.readValue(Files.readString(dateFilePath), QwilightDate::class.java) qwilightDate.date = date qwilightDate.hashAMD64 = hashAMD64 qwilightDate.hashARM64 = hashARM64 qwilightDate.hashX64 = hashAMD64 Files.newBufferedWriter(dateFilePath).use { jm.writerWithDefaultPrettyPrinter().writeValue(it, qwilightDate) } send204(ctx) } } "/drawing" -> { AvatarHandler.sendInvalidateAvatarDrawing(msg.content().toString(StandardCharsets.UTF_8)) send204(ctx) } "/totem" -> { AvatarHandler.handleNotLogIn(msg.content().toString(StandardCharsets.UTF_8)) send204(ctx) } else -> ctx.writeAndFlush( DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND ) ).addListener( ChannelFutureListener.CLOSE ) } else -> ctx.writeAndFlush( DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.METHOD_NOT_ALLOWED ) ).addListener( ChannelFutureListener.CLOSE ) } } override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) { logFault(cause) } override fun logInfo(toNotify: String) { LoggerFactory.getLogger(javaClass).info("[{}] {}", avatarIP, toNotify) } override fun logFault(e: Throwable) { if (Utility.isValidFault(e)) { LoggerFactory.getLogger(javaClass).error("[{}] {}", avatarIP, Utility.getFaultText(e)) } } }