diff --git a/src/main/kotlin/net/taehui/twilight/Avatar.kt b/src/main/kotlin/net/taehui/twilight/Avatar.kt index b75085f..c35d6ea 100644 --- a/src/main/kotlin/net/taehui/twilight/Avatar.kt +++ b/src/main/kotlin/net/taehui/twilight/Avatar.kt @@ -37,7 +37,6 @@ var situationText: String var isValve: Boolean var avatarCompetence: Int - var qwilightHash: String var qwilightDate: String var qwilightID: String var qwilightName: String diff --git a/src/main/kotlin/net/taehui/twilight/JSON.kt b/src/main/kotlin/net/taehui/twilight/JSON.kt index 7d06721..7bf8d8e 100644 --- a/src/main/kotlin/net/taehui/twilight/JSON.kt +++ b/src/main/kotlin/net/taehui/twilight/JSON.kt @@ -111,9 +111,9 @@ val langCode: String = "" ) + @JsonIgnoreProperties(ignoreUnknown = true) class QwilightEstablish { var qwilightName = "" - var hash = "" var date = "" var language = "" var amd64 = "" diff --git a/src/main/kotlin/net/taehui/twilight/Utility.kt b/src/main/kotlin/net/taehui/twilight/Utility.kt index d874e8c..53cb3c7 100644 --- a/src/main/kotlin/net/taehui/twilight/Utility.kt +++ b/src/main/kotlin/net/taehui/twilight/Utility.kt @@ -3,6 +3,7 @@ import io.netty.handler.codec.DecoderException import net.taehui.twilight.system.PlatformIDSystem import org.apache.commons.codec.binary.Hex +import java.io.InputStream import java.net.MalformedURLException import java.net.SocketException import java.net.URI @@ -77,10 +78,6 @@ } } - fun isValidFault(e: Throwable): Boolean { - return !(e is SocketException && e.localizedMessage?.contains("Connection reset") == true) - } - fun getID512(noteFileData: ByteArray): String { val hashComputer = MessageDigest.getInstance("SHA-512") hashComputer.update(noteFileData) diff --git a/src/main/kotlin/net/taehui/twilight/awilight/DefaultCompute.kt b/src/main/kotlin/net/taehui/twilight/awilight/DefaultCompute.kt index 91762ca..f3addab 100644 --- a/src/main/kotlin/net/taehui/twilight/awilight/DefaultCompute.kt +++ b/src/main/kotlin/net/taehui/twilight/awilight/DefaultCompute.kt @@ -9,6 +9,7 @@ import net.taehui.twilight.note.InputNote import net.taehui.twilight.note.JudgedNoteData import net.taehui.twilight.note.JudgedNoteData.ID +import net.taehui.twilight.system.Configure import org.apache.commons.lang3.time.StopWatch import java.nio.file.Files import java.nio.file.Path @@ -22,7 +23,7 @@ private val sentIOAvatarIDs = mutableListOf() val modeComponentValue = ModeComponent() val comment: CommentOuterClass.Comment.Builder = - CommentOuterClass.Comment.newBuilder().setDate("2.0.0") + CommentOuterClass.Comment.newBuilder().setDate(Configure.date) private val handlingNotes = mutableListOf() val notes = mutableListOf() val waitAudioNoteMap = TreeSet() diff --git a/src/main/kotlin/net/taehui/twilight/etc/EtcAvatar.kt b/src/main/kotlin/net/taehui/twilight/etc/EtcAvatar.kt index 99d15ee..56e3a2c 100644 --- a/src/main/kotlin/net/taehui/twilight/etc/EtcAvatar.kt +++ b/src/main/kotlin/net/taehui/twilight/etc/EtcAvatar.kt @@ -10,23 +10,25 @@ import net.taehui.twilight.Utility import net.taehui.twilight.system.AvatarHandler import net.taehui.twilight.system.Configure +import org.apache.commons.compress.archivers.zip.ZipFile import org.slf4j.LoggerFactory import java.net.InetSocketAddress import java.net.URLDecoder import java.nio.charset.StandardCharsets import java.nio.file.Files +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.createParentDirectories +import kotlin.io.path.deleteRecursively class EtcAvatar : SimpleChannelInboundHandler(), Logger { - class QwilightDate { + class TaehuiQwilightDate { var date = "" var hashAMD64 = "" var hashARM64 = "" - var titleAMD64 = "" - var titleARM64 = "" - @Deprecated("hashX64") - var hashX64 = "" - @Deprecated("titleX64") - var titleX64 = "" + var titleAMD64 = "Qwilight.AMD64.zip" + var titleARM64 = "Qwilight.ARM64.zip" + var hashesAMD64 = mutableMapOf() + var hashesARM64 = mutableMapOf() } private var avatarIP = "" @@ -40,13 +42,8 @@ avatarIP = (ctx.channel().remoteAddress() as InetSocketAddress).address.hostAddress } + @OptIn(ExperimentalPathApi::class) 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") @@ -61,7 +58,31 @@ "/date/AMD64" -> { val data = ByteBufUtil.getBytes(msg.content()) logFuture { - Files.write(Configure.path.wwwPath.resolve(getQwilightDate().titleAMD64), data) + val jm = ObjectMapper() + val filePath = Configure.path.wwwPath.resolve("qwilight.json") + val text = jm.readValue(Files.readString(filePath), TaehuiQwilightDate::class.java) + + Files.write(Configure.path.wwwPath.resolve("Qwilight.AMD64.zip"), data) + val zipAMD64EntryPath = Configure.path.wwwPath.resolve("zip").resolve("AMD64") + zipAMD64EntryPath.deleteRecursively() + + ZipFile.builder().setByteArray(data).get().use { + for (entry in it.entries) { + if (!entry.isDirectory) { + val targetPath = zipAMD64EntryPath.resolve(entry.name) + targetPath.createParentDirectories() + it.getInputStream(entry).use { zis -> + val rawData = zis.readAllBytes() + Files.write(targetPath, rawData) + text.hashesAMD64[entry.name] = Utility.getID128(rawData) + } + } + } + } + + Files.newBufferedWriter(filePath).use { + jm.writerWithDefaultPrettyPrinter().writeValue(it, text) + } send204(ctx) } } @@ -69,35 +90,46 @@ "/date/ARM64" -> { val data = ByteBufUtil.getBytes(msg.content()) logFuture { - Files.write(Configure.path.wwwPath.resolve(getQwilightDate().titleARM64), data) + val jm = ObjectMapper() + val filePath = Configure.path.wwwPath.resolve("qwilight.json") + val text = jm.readValue(Files.readString(filePath), TaehuiQwilightDate::class.java) + + Files.write(Configure.path.wwwPath.resolve("Qwilight.ARM64.zip"), data) + val zipARM64EntryPath = Configure.path.wwwPath.resolve("zip").resolve("ARM64") + zipARM64EntryPath.deleteRecursively() + + ZipFile.builder().setByteArray(data).get().use { + for (entry in it.entries) { + if (!entry.isDirectory) { + val targetPath = zipARM64EntryPath.resolve(entry.name) + targetPath.createParentDirectories() + it.getInputStream(entry).use { zis -> + val rawData = zis.readAllBytes() + Files.write(targetPath, rawData) + text.hashesARM64[entry.name] = Utility.getID128(rawData) + } + } + } + } + + Files.newBufferedWriter(filePath).use { + jm.writerWithDefaultPrettyPrinter().writeValue(it, text) + } send204(ctx) } } "/date" -> { - val data = msg.content().toString(StandardCharsets.UTF_8).split(" ".toRegex()) + val data = msg.content().toString(StandardCharsets.UTF_8) 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) + val filePath = Configure.path.wwwPath.resolve("qwilight.json") + val text = jm.readValue(Files.readString(filePath), TaehuiQwilightDate::class.java) + text.date = data + Files.newBufferedWriter(filePath).use { + jm.writerWithDefaultPrettyPrinter().writeValue(it, text) } + Configure.loadDate() send204(ctx) } } @@ -142,8 +174,6 @@ } override fun logFault(e: Throwable) { - if (Utility.isValidFault(e)) { - LoggerFactory.getLogger(javaClass).error("[{}] {}", avatarIP, Utility.getFaultText(e)) - } + LoggerFactory.getLogger(javaClass).error("[{}] {}", avatarIP, Utility.getFaultText(e)) } } \ No newline at end of file diff --git a/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt b/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt index 14248a5..77ee7b3 100644 --- a/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt +++ b/src/main/kotlin/net/taehui/twilight/qwilight/QwilightAvatar.kt @@ -44,7 +44,6 @@ override var isEstablished = false override var isLoggedIn = false override var isValve = false - override var qwilightHash = "" override var qwilightDate = "" override var language = "ko-KR" override var qwilightID = "" @@ -225,10 +224,9 @@ val text = jm.readValue(eventText, JSON.QwilightEstablish::class.java) val isValve = eventData.size > 0 language = text.language - qwilightHash = text.hash qwilightDate = text.date val isAllowedIP = avatarIP.isSiteLocalAddress || avatarIP.isLoopbackAddress - val isAllowedClient = Configure.hash.contains(qwilightHash) + val isAllowedClient = Configure.date == qwilightDate if (Configure.mode.pause) { send(EventOuterClass.Event.EventID.NOTIFY, object { val text = translateLanguage("pause") @@ -254,7 +252,7 @@ AvatarHandler.establish(this, avatarID, text.qwilightName, isValve, false) if (!isAllowedClient) { send(EventOuterClass.Event.EventID.NOTIFY, object { - val text = qwilightHash + val text = qwilightDate val isUrgent = false val v = 2 }) @@ -1460,33 +1458,21 @@ override val loggerID: String get() = if (isEstablished) { if (isLoggedIn) { - "{ID: $avatarID, Name: $avatarName, IP: $remote, Date: v$qwilightDate (${ - qwilightHash.substring( - 0, 8 - ) - })}" + "{ID: $avatarID, Name: $avatarName, IP: $remote, Date: v$qwilightDate}" } else { if (isAwilight) { "{ID: $avatarID, Name: $avatarName}" } else if (avatarEstimatedID.isNotEmpty()) { - "{ID: $avatarID ($avatarEstimatedID?), Name: $avatarName, IP: $remote, Date: v$qwilightDate (${ - qwilightHash.substring( - 0, 8 - ) - })}" + "{ID: $avatarID ($avatarEstimatedID?), Name: $avatarName, IP: $remote, Date: v$qwilightDate}" } else { - "{ID: $avatarID, Name: $avatarName, IP: $remote, Date: v$qwilightDate (${ - qwilightHash.substring( - 0, 8 - ) - })}" + "{ID: $avatarID, Name: $avatarName, IP: $remote, Date: v$qwilightDate}" } } } else { - if (qwilightDate.isEmpty() || qwilightHash.isEmpty()) { - "{IP: $remote}}" + if (qwilightDate.isEmpty()) { + "{IP: $remote}" } else { - "{IP: $remote}, Date: v$qwilightDate (${qwilightHash.substring(0, 8)})}" + "{IP: $remote, Date: v$qwilightDate}" } } @@ -1499,9 +1485,7 @@ } override fun logFault(e: Throwable) { - if (Utility.isValidFault(e)) { - LoggerFactory.getLogger(javaClass).error("[{}] {}", loggerID, Utility.getFaultText(e)) - } + LoggerFactory.getLogger(javaClass).error("[{}] {}", loggerID, Utility.getFaultText(e)) } companion object { diff --git a/src/main/kotlin/net/taehui/twilight/site/SiteAvatar.kt b/src/main/kotlin/net/taehui/twilight/site/SiteAvatar.kt index 60f3132..1cbe9a5 100644 --- a/src/main/kotlin/net/taehui/twilight/site/SiteAvatar.kt +++ b/src/main/kotlin/net/taehui/twilight/site/SiteAvatar.kt @@ -42,7 +42,6 @@ override var isEstablished = false override var isLoggedIn = false override var isValve = false - override var qwilightHash = "" override var qwilightDate = "" override var language = "ko-KR" override var qwilightID = "" @@ -264,8 +263,6 @@ } override fun logFault(e: Throwable) { - if (Utility.isValidFault(e)) { - LoggerFactory.getLogger(javaClass).error("[{}] {}", loggerID, Utility.getFaultText(e)) - } + LoggerFactory.getLogger(javaClass).error("[{}] {}", loggerID, Utility.getFaultText(e)) } } \ No newline at end of file diff --git a/src/main/kotlin/net/taehui/twilight/system/AwilightHandler.kt b/src/main/kotlin/net/taehui/twilight/system/AwilightHandler.kt index 367bfef..336c0ea 100644 --- a/src/main/kotlin/net/taehui/twilight/system/AwilightHandler.kt +++ b/src/main/kotlin/net/taehui/twilight/system/AwilightHandler.kt @@ -49,8 +49,7 @@ }.thenAccept { val text = object { val qwilightName = avatar.qwilightName - val hash = Configure.hash.random() - val date = "2.0.0" + val date = Configure.date val language = "ko-KR" } if (it != null) { diff --git a/src/main/kotlin/net/taehui/twilight/system/Configure.kt b/src/main/kotlin/net/taehui/twilight/system/Configure.kt index 95665a6..64607f2 100644 --- a/src/main/kotlin/net/taehui/twilight/system/Configure.kt +++ b/src/main/kotlin/net/taehui/twilight/system/Configure.kt @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import net.taehui.twilight.Logger import net.taehui.twilight.TwilightComponent +import net.taehui.twilight.etc.EtcAvatar.TaehuiQwilightDate import java.lang.reflect.Modifier import java.nio.file.Files import java.nio.file.Path @@ -56,13 +57,15 @@ lateinit var path: PathItem lateinit var db: DBItem - var hash = mutableSetOf() lateinit var mode: Mode lateinit var www: Www lateinit var nhn: NHN var awilightCount = 0 @JsonIgnore + var date = "" + + @JsonIgnore var defaultNoteDate = 0L @JsonIgnore @@ -79,9 +82,17 @@ saveConfigure() + loadDate() loadDefaultDate() } + fun loadDate() { + val jm = ObjectMapper() + val filePath = path.wwwPath.resolve("qwilight.json") + val text = jm.readValue(Files.readString(filePath), TaehuiQwilightDate::class.java) + date = text.date + } + fun loadDefaultDate() { defaultNoteDate = Files.list(TwilightComponent.DEFAULT_NOTE_ENTRY).map { Files.getLastModifiedTime(it).to(TimeUnit.MILLISECONDS) diff --git a/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt b/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt index 4053a5d..6c5211d 100644 --- a/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt +++ b/src/main/kotlin/net/taehui/twilight/www/WwwAvatar.kt @@ -708,8 +708,6 @@ } override fun logFault(e: Throwable) { - if (Utility.isValidFault(e)) { - LoggerFactory.getLogger(javaClass).error("[{}] {}", avatarIP, Utility.getFaultText(e)) - } + LoggerFactory.getLogger(javaClass).error("[{}] {}", avatarIP, Utility.getFaultText(e)) } } \ No newline at end of file