Newer
Older
Twilight / src / main / kotlin / net / taehui / twilight / taehui / TaehuiAvatar.kt
package net.taehui.twilight.taehui

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 TaehuiAvatar : SimpleChannelInboundHandler<FullHttpRequest>(), Logger {
    class QwilightDate {
        var date = ""
        var hashAMD64 = ""
        var hashARM64 = ""
        var titleAMD64 = ""
        var titleARM64 = ""

        @Deprecated("hashAMD64")
        var hash = ""
        @Deprecated("hashAMD64")
        var hashX64 = ""

        @Deprecated("titleAMD64")
        var title = ""
        @Deprecated("titleAMD64")
        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(Configure.path.datePath)
            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")
        if (mode == 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())
                    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 qwilightDateFilePath = Configure.path.wwwPath.resolve(Configure.path.datePath)
                    val qwilightDate = jm.readValue(Files.readString(qwilightDateFilePath), QwilightDate::class.java)
                    qwilightDate.date = date
                    qwilightDate.hashAMD64 = hashAMD64
                    qwilightDate.hashARM64 = hashARM64
                    qwilightDate.hash = hashAMD64
                    qwilightDate.hashX64 = hashAMD64
                    Files.newBufferedWriter(qwilightDateFilePath).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))
        }
    }
}