Newer
Older
Twilight / src / main / kotlin / net / taehui / twilight / system / IO.kt
@Taehui Taehui 1 hour ago 25 KB v1.0-SNAPSHOT
package net.taehui.twilight.system

import net.taehui.twilight.*
import net.taehui.twilight.qwilight.QwilightAvatar
import net.taehui.twilight.site.SiteAvatar
import org.apache.commons.lang3.RandomStringUtils
import org.jline.reader.UserInterruptException
import java.net.InetSocketAddress
import java.nio.file.Files
import java.nio.file.Path
import java.time.LocalDateTime
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
import java.util.concurrent.atomic.AtomicInteger
import java.util.stream.StreamSupport


object IO : Logger {
    private val futureLearnNotesStatus = AtomicInteger()
    private var futureLearnNotes: CompletableFuture<Void>? = null
    private val futureLearnCommentsStatus = AtomicInteger()
    private var futureLearnComments: CompletableFuture<Void>? = null
    private val futureLearnHandledStatus = AtomicInteger()
    private var futureLearnHandled: CompletableFuture<Void>? = null
    private var futureWipeNotes: Collection<String>? = null
    private var futurePMSNotes: Collection<String>? = null
    private var futureWipeComments: Collection<Path>? = null
    private var futureWipeBundles: Collection<Path>? = null

    fun handleSystem(): String {
        var stopText: String? = null
        val r = Window.window.r
        while (stopText == null) {
            try {
                val line = r.readLine("> ")
                if (line.isNotEmpty()) {
                    val w = r.parsedLine.words()
                    val w0 = w[0]
                    if (w0 != "future") {
                        val isY = w0 == "y"
                        if (futureWipeNotes != null) {
                            if (isY) {
                                futureWipeNotes?.forEach {
                                    DB.wipeNote(it, this)
                                }
                            } else {
                                logInfo("Cancelled")
                            }
                            futureWipeNotes = null
                            continue
                        }
                        if (futurePMSNotes != null) {
                            if (isY) {
                                futurePMSNotes?.forEach {
                                    DB.pmsNote(it, this)
                                }
                            } else {
                                logInfo("Cancelled")
                            }
                            futurePMSNotes = null
                            continue
                        }
                        if (futureWipeComments != null) {
                            if (isY) {
                                DB.wipeComments(futureWipeComments!!).thenAccept {
                                    logInfo("Wiped $it Comment Files")
                                }
                            } else {
                                logInfo("Cancelled")
                            }
                            futureWipeComments = null
                            continue
                        }
                        if (futureWipeBundles != null) {
                            if (isY) {
                                DB.wipeBundles(futureWipeBundles!!).thenAccept {
                                    logInfo("Wiped $it Bundle Files")
                                }
                            } else {
                                logInfo("Cancelled")
                            }
                            futureWipeBundles = null
                            continue
                        }
                    }
                    when (w0) {
                        "stop" -> stopText = w.elementAtOrNull(1) ?: ""

                        "avatar" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "view" -> {
                                        AvatarHandler.doInfo(this)
                                        continue
                                    }

                                    "exile" -> {
                                        if (w.size > 2) {
                                            AvatarHandler.handleNotLogIn(w[2])
                                            continue
                                        }
                                    }

                                    "ban" -> {
                                        if (w.size > 3) {
                                            AvatarHandler.getAvatar(
                                                w[2]
                                            ).let {
                                                if (it != null) {
                                                    BannedIP.putBannedIP(
                                                        it.remote, LocalDateTime.parse(
                                                            w[3]
                                                        )
                                                    )
                                                    it.close()
                                                } else {
                                                    logInfo("Failed to Find ID")
                                                }
                                            }
                                            continue
                                        }
                                    }

                                    "allow" -> {
                                        if (w.size > 2) {
                                            BannedIP.wipeBannedIP(w[2])
                                            continue
                                        }
                                    }
                                }
                            }
                            logInfo("avatar view: View Avatars")
                            logInfo("avatar exile <Avatar ID>: Exile Avatar")
                            logInfo("avatar ban <Avatar ID> <Date>: Ban Avatar IP")
                            logInfo("avatar allow <Avatar IP>: Allow Avatar IP")
                        }

                        "awilight" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "set" -> {
                                        if (w.size > 2) {
                                            val awilightCount = w[2].toInt()
                                            Configure.awilightCount =
                                                0.coerceAtLeast(Configure.awilightCount + awilightCount)
                                            AwilightHandler.setAwilightCount(
                                                awilightCount
                                            )
                                            continue
                                        }
                                    }
                                }
                            }

                            logInfo("awilight set <Count>: Set Awilight")
                        }

                        "bundle" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "wipe" -> {
                                        DB.getWipeBundles().thenAccept {
                                            if (it.isNotEmpty()) {
                                                futureWipeBundles = it
                                            }
                                            logInfo("${it.size} Bundle Files")
                                        }
                                        continue
                                    }
                                }
                            }

                            logInfo("bundle wipe: Clean Bundle Files")
                        }

                        "comment" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "learn" -> {
                                        if (w.size > 2) {
                                            DB.setCommentMax(w[2])
                                        } else {
                                            if (futureLearnComments?.isDone != false) {
                                                futureLearnCommentsStatus.set(0)
                                                futureLearnComments =
                                                    DB.learnComments(futureLearnCommentsStatus).thenAccept {
                                                        logInfo(
                                                            "Learned ${futureLearnCommentsStatus.get()} Comments"
                                                        )
                                                    }
                                            } else {
                                                logInfo(
                                                    "Learning ${futureLearnCommentsStatus.get()} Comments"
                                                )
                                            }
                                        }
                                        continue
                                    }

                                    "wipe" -> {
                                        DB.getWipeComments().thenAccept {
                                            if (it.isNotEmpty()) {
                                                futureWipeComments = it
                                            }
                                            logInfo("${it.size} Comment Files")
                                        }
                                        continue
                                    }
                                }
                            }

                            logInfo("comment learn <Note_ID>: Learn Comments")
                            logInfo("comment wipe: Clean Comment Files")
                        }

                        "future" -> {
                            fun getFutureText(futureStatus: AtomicInteger, future: CompletableFuture<Void>?): String {
                                return if (future != null) {
                                    val futureState = future.state()
                                    if (futureState == Future.State.FAILED) {
                                        "$futureState (${future.exceptionNow()})"
                                    } else {
                                        "$futureState ($futureStatus)"
                                    }
                                } else {
                                    Future.State.CANCELLED.toString()
                                }
                            }

                            logInfo("Learning Notes: ${getFutureText(futureLearnNotesStatus, futureLearnNotes)}")
                            logInfo(
                                "Learning Comments: ${
                                    getFutureText(
                                        futureLearnCommentsStatus,
                                        futureLearnComments
                                    )
                                }"
                            )
                            logInfo(
                                "Learning Handled: ${
                                    getFutureText(
                                        futureLearnHandledStatus,
                                        futureLearnHandled
                                    )
                                }"
                            )
                            logInfo("Pending Wipe Notes: ${futureWipeNotes?.size ?: 0}")
                            logInfo("Pending PMS Notes: ${futurePMSNotes?.size ?: 0}")
                            logInfo("Pending Wipe Comments: ${futureWipeComments?.size ?: 0}")
                            logInfo("Pending Wipe Bundles: ${futureWipeBundles?.size ?: 0}")
                        }

                        "handled" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "learn" -> {
                                        if (futureLearnHandled?.isDone != false) {
                                            futureLearnHandledStatus.set(0)
                                            futureLearnHandled = DB.wipeHandled().thenAccept {
                                                DB.learnHandled(futureLearnHandledStatus)
                                                logInfo(
                                                    "Learned ${futureLearnHandledStatus.get()} Handled"
                                                )
                                            }
                                        } else {
                                            logInfo(
                                                "Learning ${futureLearnHandledStatus.get()} Handled"
                                            )
                                        }
                                        continue
                                    }
                                }
                            }

                            logInfo("handled learn: Learn Handled")
                        }

                        "note" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "learn" -> {
                                        if (futureLearnNotes?.isDone != false) {
                                            futureLearnNotesStatus.set(0)
                                            futureLearnNotes = DB.wipeNotes().thenAccept {
                                                try {
                                                    Files.newDirectoryStream(
                                                        TwilightComponent.NOTE_ENTRY_PATH
                                                    ).use { noteEntryPaths ->
                                                        StreamSupport.stream(noteEntryPaths.spliterator(), true)
                                                            .use { parallel ->
                                                                parallel.forEach { noteFilePath ->
                                                                    try {
                                                                        val noteFileData =
                                                                            Files.readAllBytes(noteFilePath)
                                                                        BaseCompiler.handleCompile(noteFileData, -1)
                                                                            .forEach {
                                                                                DB.setNote(
                                                                                    it.noteID,
                                                                                    Utility.getID128(noteFileData),
                                                                                    Utility.getID256(noteFileData),
                                                                                    it
                                                                                )
                                                                            }
                                                                    } catch (e: Exception) {
                                                                        logFault(e)
                                                                    } finally {
                                                                        futureLearnNotesStatus.incrementAndGet()
                                                                    }
                                                                }
                                                            }
                                                    }
                                                } finally {
                                                    logInfo(
                                                        "Learned ${futureLearnNotesStatus.get()} Notes"
                                                    )
                                                    NoteFilesSystem.loadNoteFiles()
                                                }
                                            }
                                        } else {
                                            logInfo(
                                                "Learning ${futureLearnNotesStatus.get()} Notes"
                                            )
                                        }
                                        continue
                                    }

                                    "ban" -> {
                                        if (w.size > 3) {
                                            val noteID = w[2]
                                            BannedNote.putBannedNoteFile(noteID, w[3])
                                            DB.wipeNote(noteID, this)
                                            continue
                                        }
                                    }

                                    "allow" -> {
                                        if (w.size > 2) {
                                            BannedNote.wipeBannedNoteFile(w[2])
                                            continue
                                        }
                                    }

                                    "wipe" -> {
                                        if (w.size > 2) {
                                            DB.wipeNote(w[2], this)
                                        } else {
                                            DB.getWipeNotes().thenAccept {
                                                if (it.isNotEmpty()) {
                                                    futureWipeNotes = it
                                                }
                                                logInfo("${it.size} Notes")
                                            }
                                        }
                                        continue
                                    }

                                    "pms" -> {
                                        if (w.size > 2) {
                                            DB.pmsNote(w[2], this)
                                        } else {
                                            DB.getPMSNotes().thenAccept {
                                                if (it.isNotEmpty()) {
                                                    futurePMSNotes = it
                                                }
                                                logInfo("${it.size} Notes")
                                            }
                                        }
                                        continue
                                    }
                                }
                            }

                            logInfo("note learn: Learn Notes")
                            logInfo("note ban <Note ID> <Commentary>: Ban Note")
                            logInfo("note allow <Note ID>: Allow Note")
                            logInfo("note wipe <Note ID>: Clean or Wipe Note File")
                            logInfo("note pms <Note ID>: PMS Note File")
                        }

                        "pause" -> {
                            Configure.mode.pause = !Configure.mode.pause
                            if (w.size > 1) {
                                AvatarHandler.pause(w[1])
                            } else {
                                AvatarHandler.pause("")
                            }
                        }

                        "platform" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "avatar" -> {
                                        if (w.size > 3) {
                                            PlatformIDSystem.putPlatformID(w[2], w[3])
                                            continue
                                        }
                                    }

                                    "view" -> {
                                        logInfo(PlatformSystem.platformStatus)
                                        continue
                                    }

                                    "handle" -> {
                                        PlatformSystem.handleSystem()
                                        continue
                                    }

                                    "dispose" -> {
                                        PlatformSystem.dispose()
                                        continue
                                    }
                                }
                            }

                            logInfo("platform avatar <Platform ID> <Qwilight ID>: Put Avatar")
                            logInfo("platform view: View Platform")
                            logInfo("platform handle: Handle Platform")
                            logInfo("platform dispose: Close Platform")
                        }

                        "ram" -> {
                            Runtime.getRuntime().gc()
                            logInfo(
                                "Heap: ${
                                    Runtime.getRuntime().totalMemory() / 1000 / 1000
                                } MB / ${Runtime.getRuntime().maxMemory() / 1000 / 1000} MB"
                            )
                        }

                        "site" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "view" -> {
                                        SiteHandler.doInfo(this)
                                        continue
                                    }

                                    "put" -> {
                                        if (w.size > 2) {
                                            SiteHandler.putSite(w[2])
                                            continue
                                        }
                                    }

                                    "wipe" -> {
                                        if (w.size > 2) {
                                            SiteHandler.wipeSite(SiteHandler.getSiteID(w[2]))
                                            continue
                                        }
                                    }

                                    "silent" -> {
                                        if (w.size > 2) {
                                            SiteHandler.silentSite(SiteHandler.getSiteID(w[2]))
                                            continue
                                        }
                                    }

                                    "alarm" -> {
                                        if (w.size > 3) {
                                            SiteHandler.setSiteNotify(
                                                SiteHandler.getSiteID(w[2]), w[3]
                                            )
                                            continue
                                        }
                                    }
                                }
                            }
                            logInfo("site view: View Sites")
                            logInfo("site put <Name>: Put Site")
                            logInfo("site wipe <Site ID>: Wipe Site")
                            logInfo("site silent: Silent Site")
                            logInfo("site alarm <Site ID> <Text>: Send Notify")
                        }

                        "tv" -> {
                            if (w.size > 1) {
                                when (w[1]) {
                                    "view" -> {
                                        logInfo(TVSystem.tvStatus)
                                        continue
                                    }

                                    "handle" -> {
                                        TVSystem.handleSystem()
                                        continue
                                    }

                                    "dispose" -> {
                                        TVSystem.dispose()
                                        continue
                                    }
                                }
                            }
                            logInfo("tv view: View TV")
                            logInfo("tv handle: Handle TV")
                            logInfo("tv dispose: Close TV")
                        }

                        else -> {
                            logInfo("avatar: Handle Avatars")
                            logInfo("awilight: Handle Awilights")
                            logInfo("bundle: Handle Bundles")
                            logInfo("comment: Handle Comments")
                            logInfo("future: View Futures")
                            logInfo("note: Handle Notes")
                            logInfo("pause: Pause Twilight")
                            logInfo("platform: Handle Platform")
                            logInfo("site: Handle Sites")
                            logInfo("tv: Handle TV")
                            logInfo("stop: Stop Twilight")
                        }
                    }
                }
            } catch (_: UserInterruptException) {
            } catch (e: Exception) {
                logFault(e)
            }
        }
        return stopText
    }
}