Newer
Older
Twilight / src / main / kotlin / net / taehui / twilight / system / Configure.kt
@Taehui Taehui on 6 Nov 9 KB 2023-11-06 오후 7:15
package net.taehui.twilight.system

import com.fasterxml.jackson.annotation.JsonGetter
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonSetter
import com.fasterxml.jackson.databind.ObjectMapper
import net.taehui.EventClass
import net.taehui.twilight.Avatar
import net.taehui.twilight.JSON
import net.taehui.twilight.Logger
import net.taehui.twilight.TwilightComponent
import org.apache.hc.client5.http.HttpResponseException
import org.apache.hc.client5.http.classic.methods.HttpPatch
import org.apache.hc.client5.http.classic.methods.HttpPost
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler
import org.apache.hc.client5.http.impl.classic.HttpClients
import org.apache.hc.core5.http.ContentType
import org.apache.hc.core5.http.io.entity.StringEntity
import java.io.IOException
import java.lang.reflect.Modifier
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit

object Configure : Logger {
    class PathItem {
        @JvmField
        var www = ""

        @JvmField
        var tmp = ""

        @JvmField
        var date = ""

        @JsonIgnore
        lateinit var wwwPath: Path

        @JsonIgnore
        lateinit var tmpPath: Path

        @JsonIgnore
        lateinit var datePath: Path

        @JsonSetter
        fun setWww(www: String) {
            this.www = www
            wwwPath = Paths.get(www)
        }

        @JsonSetter
        fun setTmp(tmp: String) {
            this.tmp = tmp
            tmpPath = Paths.get(tmp)
        }

        @JsonSetter
        fun setDate(date: String) {
            this.date = date
            datePath = Paths.get(date)
        }
    }

    class DBItem {
        var auth = ""
        var db = ""
        var remote = ""
        var avatar = ""
        var format = ""
    }

    class FaxItem {
        var auth = ""
        var remote = ""
        var avatar = ""
    }

    class JavaCipherStore {
        @get:JsonGetter
        lateinit var pw0: CharArray

        @get:JsonGetter
        lateinit var pw1: CharArray

        @JsonSetter
        fun setPw0(pw0: String) {
            this.pw0 = pw0.toCharArray()
        }

        @JsonSetter
        fun setPw1(pw1: String) {
            this.pw1 = pw1.toCharArray()
        }
    }

    class Mode {
        @JsonIgnore
        lateinit var funcEstablish: (Avatar, Array<Any>, (isPause: Boolean) -> Unit) -> Unit

        @JsonIgnore
        lateinit var funcSignIn: (Array<Any>) -> CompletableFuture<Array<Any>?>

        @JvmField
        var allowEstablish = false

        @JvmField
        var allowSignIn = false
        var pause = false
        var getAbility = false
        var platform = false
        var tv = false

        @JsonSetter
        fun setAllowEstablish(allowEstablish: Boolean) {
            this.allowEstablish = allowEstablish
            funcEstablish = { avatar, data, onHandled ->
                avatar.qwilightHash = data[0] as String
                avatar.qwilightDate = data[1] as String
                if (pause) {
                    avatar.send(EventClass.Event.EventID.WARNING, avatar.translateLanguage("pause"))
                    onHandled(true)
                } else if (BannedIP.isBanned(avatar.remote)) {
                    avatar.send(EventClass.Event.EventID.WARNING, avatar.translateLanguage("bannedIP"))
                } else if (allowEstablish || avatar.avatarIP.isLoopbackAddress || avatar.avatarIP.isSiteLocalAddress || hash.contains(
                        avatar.qwilightHash
                    )
                ) {
                    onHandled(false)
                } else {
                    if (data[2] as Boolean) {
                        avatar.send(EventClass.Event.EventID.WARNING, avatar.translateLanguage("unavailableValveDate"))
                    } else {
                        avatar.send(
                            EventClass.Event.EventID.UNAVAILABLE_DATE,
                            avatar.translateLanguage("unavailableDate")
                        )
                    }
                }
            }
        }

        @JsonSetter
        fun setAllowSignIn(allowSignIn: Boolean) {
            this.allowSignIn = allowSignIn
            funcSignIn = if (allowSignIn) {
                { data ->
                    logValueFuture {
                        val pendingAvatarID = data[1] as String
                        arrayOf("", pendingAvatarID, pendingAvatarID, 1)
                    }
                }
            } else {
                { data ->
                    logValueFuture {
                        val avatar = data[0] as Avatar
                        val jm = ObjectMapper()
                        HttpClients.createDefault().use {
                            val dataPost = HttpPost(www.taehui + "/avatar/getTotem")
                            dataPost.setHeader("millis", System.currentTimeMillis())
                            dataPost.setHeader("X-Real-IP", avatar.remote)
                            dataPost.entity = StringEntity(
                                jm.writeValueAsString(
                                    object {
                                        val avatarID = (data[1] as String)
                                        val avatarCipher = (data[2] as String)
                                    }), ContentType.APPLICATION_JSON
                            )
                            try {
                                val taehuiGetTotem = jm.readValue(
                                    it.execute(dataPost, BasicHttpClientResponseHandler()),
                                    JSON.TaehuiGetTotem::class.java
                                )
                                arrayOf(
                                    taehuiGetTotem.totem,
                                    taehuiGetTotem.avatarID,
                                    taehuiGetTotem.avatarName,
                                    taehuiGetTotem.level
                                )
                            } catch (e: HttpResponseException) {
                                avatar.send(EventClass.Event.EventID.WARNING, avatar.translateLanguage("wrongAvatar"))
                                null
                            }
                        }
                    }
                }
            }
        }
    }

    class Www {
        var qwilight = ""
        var taehui = ""
        var remote = ""
    }

    class NHN {
        var nhnID = ""
        var nhnPw = ""
    }

    lateinit var path: PathItem
    lateinit var db: DBItem
    lateinit var fax: FaxItem
    lateinit var javaCipherStore: JavaCipherStore
    var hash = mutableSetOf<String>()
    lateinit var mode: Mode
    lateinit var www: Www
    lateinit var nhn: NHN
    var awilightCount = 0
    var defaultNoteDate = 0L
    var defaultUIDate = 0L

    fun loadConfigure() {
        try {
            val text = ObjectMapper().readValue(Paths.get("Configure.json").toFile(), Configure::class.java)
            Configure::class.java.fields.forEach {
                if (it.getAnnotation(JsonIgnore::class.java)?.value != true && it.modifiers and Modifier.FINAL != Modifier.FINAL) {
                    it[this] = it[text] ?: throw RuntimeException(it.name)
                }
            }
            defaultNoteDate = Files.getLastModifiedTime(TwilightComponent.DEFAULT_NOTE_ENTRY).to(TimeUnit.MILLISECONDS)
            defaultUIDate = Files.getLastModifiedTime(TwilightComponent.DEFAULT_UI_ENTRY).to(TimeUnit.MILLISECONDS)
            logInfo("Loaded Configure")
        } catch (e: IOException) {
            logFault(e)
        }
    }

    fun saveConfigure() {
        Files.newOutputStream(Paths.get("Configure.json")).use {
            ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(it, this)
            logInfo("Saved Configure")
        }
    }

    fun signIn(avatar: Avatar, pendingAvatarID: String, pw: String): CompletableFuture<Array<Any>?> {
        return mode.funcSignIn(arrayOf(avatar, pendingAvatarID, pw))
    }

    fun signIn(avatar: Avatar, totem: String): CompletableFuture<Array<Any>?> {
        return logValueFuture {
            HttpClients.createDefault().use {
                val data = HttpPatch(www.taehui + "/avatar/totem")
                data.setHeader("X-Real-IP", avatar.remote)
                data.setHeader("millis", System.currentTimeMillis())
                data.setHeader("totem", totem)
                try {
                    val taehuiTotem = ObjectMapper().readValue(
                        it.execute(data, BasicHttpClientResponseHandler()), JSON.TaehuiTotem::class.java
                    )
                    arrayOf(taehuiTotem.avatarID, taehuiTotem.avatarName, taehuiTotem.level)
                } catch (e: HttpResponseException) {
                    avatar.send(EventClass.Event.EventID.FAILED_VALIDATE_TOTEM, null)
                    null
                }
            }
        }
    }

    fun establish(avatar: Avatar, hash: String, date: String, isValve: Boolean, onHandled: (isPause: Boolean) -> Unit) {
        mode.funcEstablish(avatar, arrayOf(hash, date, isValve), onHandled)
    }
}