diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt index 3e6dcaf75..6ceafc843 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt @@ -15,15 +15,18 @@ import io.ktor.server.engine.applicationEngineEnvironment import io.ktor.server.engine.connector import io.ktor.server.engine.embeddedServer import io.ktor.util.KtorExperimentalAPI +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import net.mamoe.mirai.api.http.route.mirai import net.mamoe.mirai.utils.DefaultLogger -import org.slf4j.LoggerFactory -import org.slf4j.helpers.NOPLogger import org.slf4j.helpers.NOPLoggerFactory +import kotlin.coroutines.CoroutineContext -object MiraiHttpAPIServer { +object MiraiHttpAPIServer : CoroutineScope { private val logger = DefaultLogger("Mirai HTTP API") + override val coroutineContext: CoroutineContext = CoroutineExceptionHandler { _, throwable -> logger.error(throwable) } init { SessionManager.authKey = generateSessionKey()//用于验证的key, 使用和SessionKey相同的方法生成, 但意义不同 @@ -43,20 +46,19 @@ object MiraiHttpAPIServer { SessionManager.authKey = authKey // TODO: start是无阻塞的,理应获取启动状态后再执行后续代码 - try { + launch { embeddedServer(CIO, environment = applicationEngineEnvironment { + this.parentCoroutineContext = coroutineContext this.log = NOPLoggerFactory().getLogger("NMYSL") this.module(Application::mirai) connector { this.port = port } - }).start() - - logger.info("Http api server is running with authKey: ${SessionManager.authKey}") - callback?.invoke() - } catch (e: Exception) { - logger.error("Http api server launch error") + }).start(wait = true) } + + logger.info("Http api server is running with authKey: ${SessionManager.authKey}") + callback?.invoke() } } \ No newline at end of file diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt index 47187677d..c4837f415 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsole.kt @@ -237,7 +237,7 @@ object MiraiConsole { object CommandListener { fun start() { thread { - processNextCommandLine() + //processNextCommandLine() } } @@ -281,7 +281,6 @@ class MiraiConsoleLoader { companion object { @JvmStatic fun main(args: Array) { - MiraiConsole.start() Runtime.getRuntime().addShutdownHook(thread(start = false) { MiraiConsole.stop() diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsoleUI.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsoleUI.kt index 259ed2ea5..7d08f6b81 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsoleUI.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/MiraiConsoleUI.kt @@ -11,11 +11,15 @@ import com.googlecode.lanterna.terminal.Terminal import com.googlecode.lanterna.terminal.TerminalResizeListener import com.googlecode.lanterna.terminal.swing.SwingTerminal import com.googlecode.lanterna.terminal.swing.SwingTerminalFrame +import net.mamoe.mirai.MiraiConsoleUI.LoggerDrawer.drawLog +import net.mamoe.mirai.MiraiConsoleUI.LoggerDrawer.redrawLogs +import net.mamoe.mirai.utils.currentTimeSeconds import java.io.OutputStream import java.io.PrintStream -import java.lang.StringBuilder +import java.nio.charset.Charset import java.util.* import kotlin.concurrent.thread +import kotlin.math.ceil object MiraiConsoleUI { @@ -36,12 +40,17 @@ object MiraiConsoleUI { lateinit var textGraphics: TextGraphics var hasStart = false + private lateinit var internalPrinter: PrintStream fun start() { if (hasStart) { return } + + internalPrinter = System.out + + hasStart = true - val defaultTerminalFactory = DefaultTerminalFactory() + val defaultTerminalFactory = DefaultTerminalFactory(internalPrinter, System.`in`, Charset.defaultCharset()) try { terminal = defaultTerminalFactory.createTerminal() terminal.enterPrivateMode() @@ -64,8 +73,27 @@ object MiraiConsoleUI { inited = false update() redrawCommand() + redrawLogs(log[screens[currentScreenId]]!!) }) + if (terminal !is SwingTerminalFrame) { + System.setOut(PrintStream(object : OutputStream() { + var builder = java.lang.StringBuilder() + override fun write(b: Int) { + with(b.toChar()) { + if (this == '\n') { + pushLog(0, builder.toString()) + builder = java.lang.StringBuilder() + } else { + builder.append(this) + } + } + } + })) + } + + System.setErr(System.out) + update() val charList = listOf(',', '.', '/', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '=', '+', '!', ' ') @@ -197,52 +225,83 @@ object MiraiConsoleUI { textGraphics.putString(width - 2 - "Add admins via commands|".length, 4, "Add admins via commands|") } - fun drawLogs(values: List) { - val width = terminal.terminalSize.columns - 6 - val heightMin = 5 - var currentHeight = terminal.terminalSize.rows - 5 + object LoggerDrawer { + var currentHeight = 6 - for (index in heightMin until currentHeight) { - clearRows(index) - } - - values.forEach { - if (currentHeight > heightMin) { - var x = it - while (currentHeight > heightMin) { - if (x.isEmpty() || x.isBlank()) break - textGraphics.foregroundColor = TextColor.ANSI.GREEN - textGraphics.backgroundColor = TextColor.ANSI.DEFAULT - val towrite = if (x.length > width) { - x.substring(0, width).also { - x = x.substring(width) - } - } else { - x.also { - x = "" - } + fun drawLog(string: String, flush: Boolean = true) { + val maxHeight = terminal.terminalSize.rows - 6 + val heightNeed = (string.length / (terminal.terminalSize.columns - 6)) + 1 + if (currentHeight + heightNeed > maxHeight) { + cleanPage() + } + textGraphics.foregroundColor = TextColor.ANSI.GREEN + textGraphics.backgroundColor = TextColor.ANSI.DEFAULT + val width = terminal.terminalSize.columns - 6 + var x = string + while (true) { + if (x == "") break + val toWrite = if (x.length > width) { + x.substring(0, width).also { + x = x.substring(width) + } + } else { + x.also { + x = "" } - textGraphics.putString(3, currentHeight, towrite, SGR.ITALIC) - --currentHeight } + try { + textGraphics.putString(3, currentHeight, toWrite, SGR.ITALIC) + } catch (ignored: Exception) { + // + } + ++currentHeight + } + if (flush && terminal is SwingTerminalFrame) { + terminal.flush() } } - textGraphics.putString(3, 9, "AAAAAAAAAAAAAAAAAAAAAAa", SGR.ITALIC) - terminal.flush() + + fun cleanPage() { + for (index in 6 until terminal.terminalSize.rows - 6) { + clearRows(index) + } + currentHeight = 6 + } + + + fun redrawLogs(toDraw: List) { + this.cleanPage() + var logsToDraw = 0 + var vara = 0 + toDraw.reversed().forEach { + val heightNeed = (it.length / (terminal.terminalSize.columns - 6)) + 1 + vara += heightNeed + if (currentHeight + vara < terminal.terminalSize.rows - 6) { + logsToDraw++ + } else { + return + } + } + for (index in (toDraw.size - logsToDraw) until toDraw.size - 1) { + drawLog(toDraw[index], false) + } + if (terminal is SwingTerminalFrame) { + terminal.flush() + } + } } fun pushLog(uin: Long, str: String) { log[uin]!!.push(str) if (uin == screens[currentScreenId]) { - drawLogs(log[screens[currentScreenId]]!!) + drawLog(str) } } var commandBuilder = StringBuilder() - fun redrawCommand() { val height = terminal.terminalSize.rows val width = terminal.terminalSize.columns @@ -303,7 +362,7 @@ object MiraiConsoleUI { drawBotFrame(screens[currentScreenId], 0) } } - terminal.flush() + redrawLogs(log[screens[currentScreenId]]!!) } }