package net.taehui.twilight.system import net.taehui.twilight.BaseCompiler import net.taehui.twilight.Logger import net.taehui.twilight.TwilightComponent import net.taehui.twilight.Utility import org.jline.reader.UserInterruptException 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) ?: "" "alarm" -> { if (w.size > 2) { SiteHandler.setSiteNotify( SiteHandler.getSiteID(w[1]), w[2] ) } else if (w.size > 1) { AvatarHandler.justNotify(w[1]) } else { logInfo("alarm <Site ID> <Text>") } } "avatar" -> { if (w.size > 1) { when (w[1]) { "view" -> { AvatarHandler.doInfo(this) continue } "quit" -> { if (w.size > 2) { AvatarHandler.handleNotSignIn(w[2]) } else { logInfo("avatar quit <Avatar ID>") } 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") } } } else { logInfo("avatar ban <Avatar ID> <Date>") } continue } "allow" -> { if (w.size > 2) { BannedIP.wipeBannedIP(w[2]) } else { logInfo("avatar allow <Avatar IP>") } continue } } } logInfo("avatar [view] View Avatars") logInfo("avatar [quit] Quit Avatar") logInfo("avatar [ban] Ban Avatar IP") logInfo("avatar [allow] 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 ) } else { logInfo("awilight set <Count>") } continue } } } logInfo("awilight [set] 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: Throwable) { 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) { BannedNote.putBannedNoteFile(w[2], w[3]) } else { logInfo("note ban <Note ID> <Comment>") } continue } "allow" -> { if (w.size > 2) { BannedNote.wipeBannedNoteFile(w[2]) } else { logInfo("note allow <Note ID>") } 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> <Comment> 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]) } else if (w.size > 2) { PlatformIDSystem.wipePlatformID(w[2]) } else { logInfo("platform avatar <Platform ID> <Qwilight ID>") } continue } "view" -> { logInfo(PlatformSystem.platformStatus) continue } "dispose" -> { PlatformSystem.dispose() continue } "handle" -> { PlatformSystem.handleSystem() continue } } } logInfo("platform [avatar] Handle Avatars") logInfo("platform [view] View Platform") logInfo("platform [dispose] Close Platform") logInfo("platform [handle] Handle 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]) } else { logInfo("site put <Name>") } continue } "wipe" -> { if (w.size > 2) { SiteHandler.wipeSite(SiteHandler.getSiteID(w[2])) } else { logInfo("site wipe <Site ID>") } continue } "silent" -> { if (w.size > 2) { SiteHandler.silentSite(SiteHandler.getSiteID(w[2])) } else { logInfo("site silent <Site ID>") } continue } } } logInfo("site [view] View Sites") logInfo("site [put] Put Site") logInfo("site [wipe] Wipe Site") logInfo("site [silent] Silent Site") } "tv" -> { if (w.size > 1) { when (w[1]) { "view" -> { logInfo(TVSystem.tvStatus) continue } "dispose" -> { TVSystem.dispose() continue } "handle" -> { TVSystem.handleSystem() continue } } } logInfo("tv [view] View TV") logInfo("tv [dispose] Close TV") logInfo("tv [handle] Handle TV") } else -> { logInfo("[alarm] Send Notify") logInfo("[avatar] Handle Avatars") logInfo("[awilight] Handle Awilight") 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: Throwable) { logFault(e) } } return stopText } }