From 41112affa8f2e8e454ce44bec4a413d47eecaf28 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 14 May 2020 09:02:02 +0800 Subject: [PATCH] Rework logger structure, extract pure frontend from miraio-console --- .../net/mamoe/mirai/console/MiraiConsole.kt | 184 +++------------ .../mirai/console/center/PluginCenter.kt | 6 - .../mirai/console/command/CommandManager.kt | 219 +----------------- .../mirai/console/command/CommandSender.kt | 9 +- .../{PluginManager.kt => PluginManagerOld.kt} | 2 +- .../console/pure/MiraiConsolePureLoader.kt | 32 --- ...aiConsoleUI.kt => MiraiConsoleFrontEnd.kt} | 21 +- .../mirai/console/graphical/MiraiGraphical.kt | 8 +- ...kt => MiraiGraphicalFrontEndController.kt} | 52 +++-- .../mirai/console/graphical/model/BotModel.kt | 22 +- .../mirai/console/graphical/view/LoginView.kt | 4 +- .../graphical/view/PluginsCenterView.kt | 4 +- .../console/graphical/view/PluginsView.kt | 4 +- .../console/graphical/view/PrimaryView.kt | 4 +- .../console/graphical/view/SettingsView.kt | 4 +- frontend/mirai-console-pure/build.gradle.kts | 1 + .../console/pure/MiraiConsoleFrontEndPure.kt | 39 +--- .../console/pure/MiraiConsolePureLoader.kt | 74 ++++++ ...lUI.kt => MiraiConsoleTerminalFrontEnd.kt} | 10 +- .../console/MiraiConsoleTerminalLoader.kt | 6 +- 20 files changed, 194 insertions(+), 511 deletions(-) rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/{PluginManager.kt => PluginManagerOld.kt} (99%) delete mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/{MiraiConsoleUI.kt => MiraiConsoleFrontEnd.kt} (79%) rename frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/{MiraiGraphicalUIController.kt => MiraiGraphicalFrontEndController.kt} (86%) rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleUIPure.kt => frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleFrontEndPure.kt (70%) create mode 100644 frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt rename frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/{MiraiConsoleTerminalUI.kt => MiraiConsoleTerminalFrontEnd.kt} (98%) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 868573899..9c1d59a82 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -10,190 +10,66 @@ package net.mamoe.mirai.console import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.io.charsets.Charset import net.mamoe.mirai.Bot import net.mamoe.mirai.console.command.CommandManager -import net.mamoe.mirai.console.command.DefaultCommands import net.mamoe.mirai.console.plugins.PluginManager -import net.mamoe.mirai.console.utils.MiraiConsoleUI -import net.mamoe.mirai.utils.SimpleLogger.LogPriority -import net.mamoe.mirai.utils.WeakRef +import net.mamoe.mirai.console.utils.MiraiConsoleFrontEnd +import net.mamoe.mirai.utils.MiraiLogger import java.io.ByteArrayOutputStream import java.io.PrintStream -import kotlin.coroutines.EmptyCoroutineContext +import kotlin.coroutines.CoroutineContext - -object MiraiConsole : CoroutineScope by CoroutineScope(EmptyCoroutineContext) { - /** - * 发布的版本名 - */ - const val build = "Pkmon" - - lateinit var version: String - internal set - - /** - * 获取从Console登陆上的Bot, Bots - * */ - @Suppress("DEPRECATION") - @Deprecated("use Bot.instances from mirai-core", replaceWith = ReplaceWith("Bot.instances", "net.mamoe.mirai.Bot")) - val bots: List> - get() = Bot.instances - - fun getBotOrNull(uin: Long): Bot? { - return Bot.botInstances.firstOrNull { it.id == uin } - } - - class BotNotFoundException(uin: Long) : Exception("Bot $uin Not Found") - - fun getBotOrThrow(uin: Long): Bot { - return Bot.botInstances.firstOrNull { it.id == uin } ?: throw BotNotFoundException(uin) - } - - /** - * 与前端交互所使用的Logger - */ - internal var logger = MiraiConsoleLogger +// 前端使用 +interface IMiraiConsole : CoroutineScope { + val build: String + val version: String /** * Console运行路径 */ - lateinit var path: String - internal set + val path: String /** * Console前端接口 */ - lateinit var frontEnd: MiraiConsoleUI - internal set - - - private var started = false - - - @Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN) - @Suppress("FunctionName") - @JvmSynthetic - @JvmStatic - fun /* synthetic */`start$default`( - miraiConsole: MiraiConsole, - miraiConsoleUI: MiraiConsoleUI?, - string: String?, - string2: String?, - n: Int, - @Suppress("UNUSED_PARAMETER") `object`: Any? - ) { - @Suppress("NAME_SHADOWING") - var string = string - - @Suppress("NAME_SHADOWING") - var string2 = string2 - if (n and 2 != 0) { - string = "0.0.0" - } - if (n and 4 != 0) { - string2 = "0.0.0" - } - miraiConsole.start(miraiConsoleUI!!, string!!, string2!!) - } + val frontEnd: MiraiConsoleFrontEnd /** - * 启动Console + * 与前端交互所使用的Logger */ - @JvmOverloads - fun start( - frontEnd: MiraiConsoleUI, - coreVersion: String = "0.0.0", - consoleVersion: String = "0.0.0", - path: String = System.getProperty("user.dir") - ) { - if (started) { - return - } - started = true - this.path = path - /* 初始化前端 */ - this.version = consoleVersion - this.frontEnd = frontEnd - this.frontEnd.pushVersion(consoleVersion, build, coreVersion) - logger("Mirai-console now running under $path") - logger("Get news in github: https://github.com/mamoe/mirai") - logger("Mirai为开源项目,请自觉遵守开源项目协议") - logger("Powered by Mamoe Technologies and contributors") + val mainLogger: MiraiLogger +} - /* 依次启用功能 */ - DefaultCommands() - PluginManager.loadPlugins() - CommandManager.start() +object MiraiConsole : CoroutineScope, IMiraiConsole { + private lateinit var instance: IMiraiConsole - /* 通知启动完成 */ - logger("Mirai-console 启动完成") - logger("\"login qqnumber qqpassword \" to login a bot") - logger("\"login qq号 qq密码 \" 来登录一个BOT") - - /* 尝试从系统配置自动登录 */ - DefaultCommands.tryLoginAuto() + /** 由前端调用 */ + internal fun init(instance: IMiraiConsole) { + this.instance = instance } - /** - * 关闭 Console - */ - fun stop() { - PluginManager.disablePlugins() - CommandManager.cancel() - try { + override val build: String get() = instance.build + override val version: String get() = instance.version + override val path: String get() = instance.path + override val frontEnd: MiraiConsoleFrontEnd get() = instance.frontEnd + override val mainLogger: MiraiLogger get() = instance.mainLogger + override val coroutineContext: CoroutineContext get() = instance.coroutineContext + + init { + this.coroutineContext[Job]!!.invokeOnCompletion { + PluginManager.disablePlugins() + CommandManager.cancel() Bot.botInstances.forEach { it.close() } - } catch (ignored: Exception) { } } + } -internal object MiraiConsoleLogger { - operator fun invoke(any: Any?) { - invoke( - "[Mirai ${MiraiConsole.version} ${MiraiConsole.build}]", - 0L, - any - ) - } - - operator fun invoke(e: Throwable?) { - invoke( - "[Mirai ${MiraiConsole.version} ${MiraiConsole.build}]", - 0L, - e - ) - } - - operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, any: Any? = null) { - if (any != null) { - MiraiConsole.frontEnd.pushLog(priority, identityStr, identity, "$any") - } - } - - operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, e: Throwable? = null) { - if (e != null) { - MiraiConsole.frontEnd.pushLog(priority, identityStr, identity, e.stacktraceString) - } - } - - // 设置默认的pushLog输出为 INFO 类型 - operator fun invoke(identityStr: String, identity: Long, any: Any? = null) { - if (any != null) { - MiraiConsole.frontEnd.pushLog(LogPriority.INFO, identityStr, identity, "$any") - } - } - - operator fun invoke(identityStr: String, identity: Long, e: Throwable? = null) { - if (e != null) { - MiraiConsole.frontEnd.pushLog(LogPriority.INFO, identityStr, identity, e.stacktraceString) - } - } -} - internal val Throwable.stacktraceString: String get() = ByteArrayOutputStream().apply { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/center/PluginCenter.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/center/PluginCenter.kt index a7e061098..4456b7f34 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/center/PluginCenter.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/center/PluginCenter.kt @@ -55,9 +55,3 @@ interface PluginCenter { val name:String } - -internal fun handleReplacement( - -){ - -} diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt index 7b9631341..17df0bdda 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt @@ -1,220 +1,3 @@ -/* - * Copyright 2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -@file:Suppress("unused", "MemberVisibilityCanBePrivate") - package net.mamoe.mirai.console.command -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel -import net.mamoe.mirai.console.MiraiConsole -import net.mamoe.mirai.console.command.CommandManager.processCommandQueue -import net.mamoe.mirai.console.plugins.PluginBase -import net.mamoe.mirai.console.plugins.PluginManager -import java.util.concurrent.Executors - -interface CommandOwner - -class PluginCommandOwner(val pluginBase: PluginBase) : CommandOwner -internal object ConsoleCommandOwner : CommandOwner - -fun PluginBase.asCommandOwner() = PluginCommandOwner(this) - - -object CommandManager : Job by { - GlobalScope.launch(start = CoroutineStart.LAZY) { - processCommandQueue() - } -}() { - private val registeredCommand: MutableMap = mutableMapOf() - val commands: Collection get() = registeredCommand.values - private val pluginCommands: MutableMap> = mutableMapOf() - - internal fun clearPluginsCommands() { - pluginCommands.values.forEach { a -> - a.forEach { - unregister(it) - } - } - pluginCommands.clear() - } - - internal fun clearPluginCommands( - pluginBase: PluginBase - ) { - pluginCommands[pluginBase]?.run { - this.forEach { unregister(it) } - this.clear() - } - } - - /** - * 注册这个指令. - * - * @throws IllegalStateException 当已注册的指令与 [command] 重名时 - */ - fun register(commandOwner: CommandOwner, command: Command) { - val allNames = mutableListOf(command.name).also { it.addAll(command.alias) } - allNames.forEach { - if (registeredCommand.containsKey(it)) { - error("Command Name(or Alias) $it is already registered, consider if same functional plugin was installed") - } - } - allNames.forEach { - registeredCommand[it] = command - } - if (commandOwner is PluginCommandOwner) { - pluginCommands.computeIfAbsent(commandOwner.pluginBase) { mutableSetOf() }.add(command) - } - } - - fun register(pluginBase: PluginBase, command: Command) = - CommandManager.register(pluginBase.asCommandOwner(), command) - - fun unregister(command: Command) { - command.alias.forEach { - registeredCommand.remove(it) - } - registeredCommand.remove(command.name) - } - - fun unregister(commandName: String): Boolean { - return registeredCommand.remove(commandName) != null - } - - - /** - * 最基础的执行指令的方式 - * 指令将会被加入队列,依次执行 - * - * @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender] - */ - fun runCommand(sender: CommandSender, command: String) { - commandChannel.offer( - FullCommand(sender, command) - ) - } - - /** - * 插队异步执行一个指令并返回 [Deferred] - * - * @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender] - * @see PluginBase.runCommandAsync 扩展 - */ - fun runCommandAsync(pluginBase: PluginBase, sender: CommandSender, command: String): Deferred { - return pluginBase.async { - processCommand(sender, command) - } - } - - /** - * 插队执行一个指令并返回 [Deferred] - * - * @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender] - * @see PluginBase.runCommandAsync 扩展 - */ - @Suppress("KDocUnresolvedReference") - suspend fun dispatchCommand(sender: CommandSender, command: String): Boolean { - return processCommand(sender, command) - } - - - /** - * 阻塞当前线程, 插队执行一个指令 - * - * @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender] - */ - // for java - fun dispatchCommandBlocking(sender: CommandSender, command: String): Boolean = - runBlocking { dispatchCommand(sender, command) } - - - // internal - - /** - * 单线程执行指令 - */ - private val commandDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher() - - private suspend fun processCommand(sender: CommandSender, fullCommand: String): Boolean { - return withContext(commandDispatcher) { - processCommandImpl(sender, fullCommand) - } - } - - private suspend fun processCommandImpl(sender: CommandSender, fullCommand: String): Boolean { - val blocks = fullCommand.split(" ") - val commandHead = blocks[0].removePrefix(DefaultCommands.commandPrefix) - val args = blocks.drop(1) - return registeredCommand[commandHead]?.run { - try { - return onCommand(sender, ArrayList(args)).also { - if (it) { - PluginManager.onCommand(this, sender, args) - } else { - sender.sendMessage(this.usage) - } - } - } catch (e: Exception) { - sender.sendMessage("在运行指令时出现了未知错误") - MiraiConsole.logger(e) - false - } finally { - (sender as AbstractCommandSender).flushMessage() - } - } ?: throw UnknownCommandException(commandHead) - } - - internal class FullCommand( - val sender: CommandSender, - val commandLine: String - ) - - private val commandChannel: Channel = Channel(Channel.UNLIMITED) - - private tailrec suspend fun processCommandQueue() { - val command = commandChannel.receive() - try { - processCommand(command.sender, command.commandLine) - } catch (e: UnknownCommandException) { - command.sender.sendMessage("未知指令 " + command.commandLine) - (command.sender as? ConsoleCommandSender)?.apply { - val cmd = command.commandLine.let { - val index = it.indexOf(' ') - if (index == -1) return@let it - return@let it.substring(0, index) - } - if (cmd.isNotEmpty()) { - if (cmd[0] == '/') { - registeredCommand[cmd.substring(1)]?.let { - sendMessage("请问你是不是想执行 `${command.commandLine.substring(1)}`") - } - } - } - } - } catch (e: Throwable) {//should never happen - MiraiConsole.logger(e) - } - if (isActive) { - processCommandQueue() - } - } -} - -/** - * 插队异步执行一个指令并返回 [Deferred] - * - * @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender] - * @see PluginBase.runCommandAsync 扩展 - */ -fun PluginBase.runCommandAsync(sender: CommandSender, command: String): Deferred = - CommandManager.runCommandAsync(this, sender, command) - - -class UnknownCommandException(command: String) : Exception("unknown command \"$command\"") \ No newline at end of file +object CommandManager \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt index 9654fc5f1..2ea05fb90 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt @@ -28,6 +28,7 @@ interface CommandSender { suspend fun sendMessage(messageChain: Message) suspend fun sendMessage(message: String) + /** * 写入要发送的内容 所有内容最后会被以一条发出 */ @@ -74,8 +75,8 @@ object ConsoleCommandSender : AbstractCommandSender() { * 指向性CommandSender * 你可以获得用户在和哪个Bot说指令 */ -interface BotAware{ - val bot:Bot +interface BotAware { + val bot: Bot } @@ -83,7 +84,7 @@ interface BotAware{ * 联系人指令执行者. 代表由一个 QQ 用户私聊执行指令 */ @Suppress("MemberVisibilityCanBePrivate") -open class ContactCommandSender(override val bot: Bot, val contact: Contact) : AbstractCommandSender(), BotAware{ +open class ContactCommandSender(override val bot: Bot, val contact: Contact) : AbstractCommandSender(), BotAware { override suspend fun sendMessage(messageChain: Message) { contact.sendMessage(messageChain) } @@ -100,4 +101,4 @@ open class GroupContactCommandSender( bot: Bot, val realSender: Member, subject: Contact -):ContactCommandSender(bot,subject) \ No newline at end of file +) : ContactCommandSender(bot, subject) \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManager.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManagerOld.kt similarity index 99% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManager.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManagerOld.kt index 38b068946..f391515f1 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManager.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginManagerOld.kt @@ -27,7 +27,7 @@ import java.util.jar.JarFile val PluginBase.description: PluginDescription get() = PluginManager.getPluginDescription(this) -object PluginManager { +object PluginManagerOld { /** * 通过插件获取介绍 * @see description diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt deleted file mode 100644 index fb2f5b648..000000000 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.console.pure - -import net.mamoe.mirai.console.MiraiConsole -import kotlin.concurrent.thread - -class MiraiConsolePureLoader { - companion object { - @JvmStatic - fun load( - coreVersion: String, - consoleVersion: String - ) { - MiraiConsole.start( - MiraiConsoleUIPure(), - coreVersion, - consoleVersion - ) - Runtime.getRuntime().addShutdownHook(thread(start = false) { - MiraiConsole.stop() - }) - } - } -} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleUI.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleFrontEnd.kt similarity index 79% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleUI.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleFrontEnd.kt index 624685049..d03192a41 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleUI.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleFrontEnd.kt @@ -14,35 +14,20 @@ import net.mamoe.mirai.console.center.CuiPluginCenter import net.mamoe.mirai.console.center.PluginCenter import net.mamoe.mirai.utils.LoginSolver import net.mamoe.mirai.utils.MiraiInternalAPI -import net.mamoe.mirai.utils.SimpleLogger.LogPriority +import net.mamoe.mirai.utils.MiraiLogger /** * 只需要实现一个这个传入 MiraiConsole 就可以绑定 UI 层与 Console 层 * 需要保证线程安全 */ @MiraiInternalAPI -interface MiraiConsoleUI { +interface MiraiConsoleFrontEnd { /** * 提供 [PluginCenter] */ val pluginCenter: PluginCenter get() = CuiPluginCenter - /** - * 让 UI 层展示一条 log - * - * identity:log 所属的 screen, Main=0; Bot=Bot.uin - */ - fun pushLog( - identity: Long, - message: String - ) - - fun pushLog( - priority: LogPriority, - identityStr: String, - identity: Long, - message: String - ) + fun loggerFor(identity: Long): MiraiLogger /** * 让 UI 层准备接受新增的一个BOT diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/MiraiGraphical.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/MiraiGraphical.kt index b12f55ce2..e3a336c48 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/MiraiGraphical.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/MiraiGraphical.kt @@ -10,7 +10,7 @@ package net.mamoe.mirai.console.graphical import net.mamoe.mirai.console.MiraiConsole -import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController import net.mamoe.mirai.console.graphical.stylesheet.PrimaryStyleSheet import net.mamoe.mirai.console.graphical.view.Decorator import tornadofx.App @@ -28,7 +28,11 @@ class MiraiGraphicalUI : App(Decorator::class, PrimaryStyleSheet::class) { override fun init() { super.init() - MiraiConsole.start(find(),MiraiConsoleGraphicalLoader.coreVersion,MiraiConsoleGraphicalLoader.consoleVersion) + MiraiConsole.start( + find(), + MiraiConsoleGraphicalLoader.coreVersion, + MiraiConsoleGraphicalLoader.consoleVersion + ) } override fun stop() { diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalUIController.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalFrontEndController.kt similarity index 86% rename from frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalUIController.kt rename to frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalFrontEndController.kt index 7b77dcf65..2d09d3c3f 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalUIController.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalFrontEndController.kt @@ -16,16 +16,25 @@ import net.mamoe.mirai.console.graphical.model.* import net.mamoe.mirai.console.graphical.view.dialog.InputDialog import net.mamoe.mirai.console.graphical.view.dialog.VerificationCodeFragment import net.mamoe.mirai.console.plugins.PluginManager -import net.mamoe.mirai.console.utils.MiraiConsoleUI +import net.mamoe.mirai.console.utils.MiraiConsoleFrontEnd import net.mamoe.mirai.network.CustomLoginFailedException import net.mamoe.mirai.utils.LoginSolver +import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.utils.SimpleLogger import net.mamoe.mirai.utils.SimpleLogger.LogPriority -import tornadofx.* +import tornadofx.Controller +import tornadofx.Scope +import tornadofx.find +import tornadofx.observableListOf import java.text.SimpleDateFormat import java.util.* +import kotlin.collections.List +import kotlin.collections.forEach +import kotlin.collections.mutableMapOf +import kotlin.collections.set import kotlin.coroutines.resume -class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { +class MiraiGraphicalFrontEndController : Controller(), MiraiConsoleFrontEnd { private val settingModel = find() private val loginSolver = GraphicalLoginSolver() @@ -38,7 +47,7 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { private val consoleInfo = ConsoleInfo() - private val sdf by lazy { SimpleDateFormat("HH:mm:ss") } + internal val sdf by lazy { SimpleDateFormat("HH:mm:ss") } init { // 监听插件重载事件,以重新从console获取插件列表 @@ -65,27 +74,23 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { fun sendCommand(command: String) = runCommand(ConsoleCommandSender, command) - override fun pushLog(identity: Long, message: String) = Platform.runLater { - this.pushLog(LogPriority.INFO, "", identity, message) - } - // 修改interface之后用来暂时占位 - override fun pushLog(priority: LogPriority, identityStr: String, identity: Long, message: String) { + private val mainLogger = SimpleLogger(null) { priority: LogPriority, message: String?, e: Throwable? -> Platform.runLater { - val time = sdf.format(Date()) - - if (identity == 0L) { - mainLog - } else { - cache[identity]?.logHistory - }?.apply { - add("[$time] $identityStr $message" to priority.name) + mainLog.apply { + add("[$time] $message" to priority.name) trim() } } } + override fun loggerFor(identity: Long): MiraiLogger { + return if (identity == 0L) return mainLogger + else cache[identity]?.logger ?: kotlin.error("bot not found: $identity") + } + + override fun prePushBot(identity: Long) = Platform.runLater { if (!cache.containsKey(identity)) { BotModel(identity).also { @@ -123,13 +128,6 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { private fun getPluginsFromConsole(): ObservableList = PluginManager.getAllPluginDescriptions().map(::PluginModel).toObservable() - - private fun ObservableList<*>.trim() { - while (size > settingModel.item.maxLongNum) { - this.removeAt(0) - } - } - fun checkUpdate(plugin: PluginModel) { pluginList.forEach { if (it.name == plugin.name && it.author == plugin.author) { @@ -153,6 +151,12 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI { return false } + internal fun ObservableList<*>.trim() { + while (size > settingModel.item.maxLongNum) { + this.removeAt(0) + } + } + fun reloadPlugins() { with(PluginManager) { diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/BotModel.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/BotModel.kt index 660948f35..1ee6aba9b 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/BotModel.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/BotModel.kt @@ -2,16 +2,30 @@ package net.mamoe.mirai.console.graphical.model import javafx.beans.property.SimpleObjectProperty import net.mamoe.mirai.Bot -import tornadofx.ItemViewModel -import tornadofx.getValue -import tornadofx.observableListOf -import tornadofx.setValue +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController +import net.mamoe.mirai.utils.SimpleLogger +import tornadofx.* +import java.util.* class BotModel(val uin: Long) { val botProperty = SimpleObjectProperty(null) var bot: Bot by botProperty val logHistory = observableListOf>() + val logger: SimpleLogger = + SimpleLogger(uin.toString()) { priority: SimpleLogger.LogPriority, message: String?, e: Throwable? -> + + val frontend = find() + + frontend.run { + logHistory.apply { + val time = sdf.format(Date()) + add("[$time] $uin $message" to priority.name) + trim() + } + } + } + val admins = observableListOf() } diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/LoginView.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/LoginView.kt index 4d79d55d8..6ed16c396 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/LoginView.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/LoginView.kt @@ -4,7 +4,7 @@ import javafx.beans.property.SimpleStringProperty import javafx.geometry.Pos import javafx.scene.image.Image import kotlinx.coroutines.runBlocking -import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController import net.mamoe.mirai.console.graphical.stylesheet.LoginViewStyleSheet import net.mamoe.mirai.console.graphical.util.jfxButton import net.mamoe.mirai.console.graphical.util.jfxPasswordfield @@ -13,7 +13,7 @@ import tornadofx.* class LoginView : View("CNM") { - private val controller = find() + private val controller = find() private val qq = SimpleStringProperty("") private val psd = SimpleStringProperty("") diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsCenterView.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsCenterView.kt index b5d84174b..9d1679e35 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsCenterView.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsCenterView.kt @@ -8,7 +8,7 @@ import javafx.scene.control.Button import javafx.scene.control.TreeTableCell import kotlinx.coroutines.runBlocking import net.mamoe.mirai.console.MiraiConsole -import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController import net.mamoe.mirai.console.graphical.event.ReloadEvent import net.mamoe.mirai.console.graphical.model.PluginModel import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet @@ -19,7 +19,7 @@ import tornadofx.* class PluginsCenterView : View() { - private val controller = find() + private val controller = find() private val center get() = MiraiConsole.frontEnd.pluginCenter private val plugins: ObservableList = observableListOf() diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsView.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsView.kt index 2753ad9cf..358388bb6 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsView.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsView.kt @@ -2,7 +2,7 @@ package net.mamoe.mirai.console.graphical.view import com.jfoenix.controls.JFXTreeTableColumn import javafx.scene.control.TreeTableCell -import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController import net.mamoe.mirai.console.graphical.model.PluginModel import net.mamoe.mirai.console.graphical.stylesheet.PluginViewStyleSheet import net.mamoe.mirai.console.graphical.util.jfxButton @@ -13,7 +13,7 @@ import tornadofx.visibleWhen class PluginsView : View() { - private val controller = find() + private val controller = find() val plugins = controller.pluginList override val root = jfxTreeTableView(plugins) { diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PrimaryView.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PrimaryView.kt index 4e2d1e3f6..d5b4658df 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PrimaryView.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PrimaryView.kt @@ -14,14 +14,14 @@ import javafx.scene.input.KeyCode import javafx.scene.layout.Priority import javafx.stage.FileChooser import kotlinx.coroutines.runBlocking -import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController import net.mamoe.mirai.console.graphical.model.BotModel import net.mamoe.mirai.console.graphical.util.* import tornadofx.* class PrimaryView : View() { - private val controller = find() + private val controller = find() private lateinit var mainTabPane: TabPane override val root = borderpane { diff --git a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/SettingsView.kt b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/SettingsView.kt index ac5c5de1f..0fb03be12 100644 --- a/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/SettingsView.kt +++ b/frontend/mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/SettingsView.kt @@ -1,7 +1,7 @@ package net.mamoe.mirai.console.graphical.view import javafx.geometry.Pos -import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController +import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalFrontEndController import net.mamoe.mirai.console.graphical.model.GlobalSettingModel import net.mamoe.mirai.console.graphical.util.jfxButton import net.mamoe.mirai.console.graphical.util.jfxTextfield @@ -12,7 +12,7 @@ import java.io.File class SettingsView : View() { - private val controller = find() + private val controller = find() private val settingModel = find() override val root = vbox { diff --git a/frontend/mirai-console-pure/build.gradle.kts b/frontend/mirai-console-pure/build.gradle.kts index 324ea9df4..c0ce1e6a7 100644 --- a/frontend/mirai-console-pure/build.gradle.kts +++ b/frontend/mirai-console-pure/build.gradle.kts @@ -27,6 +27,7 @@ kotlin { } dependencies { compileOnly(project(":mirai-console")) + compileOnly("net.mamoe:mirai-core:${Versions.Mirai.core}") compileOnly(kotlin("stdlib")) // embedded by core testApi("net.mamoe:mirai-core-qqandroid:${Versions.Mirai.core}") diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleUIPure.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleFrontEndPure.kt similarity index 70% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleUIPure.kt rename to frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleFrontEndPure.kt index 0688b0886..e000b7a7d 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleUIPure.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleFrontEndPure.kt @@ -13,16 +13,17 @@ import kotlinx.coroutines.delay import net.mamoe.mirai.Bot import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.ConsoleCommandSender -import net.mamoe.mirai.console.utils.MiraiConsoleUI +import net.mamoe.mirai.console.utils.MiraiConsoleFrontEnd +import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.DefaultLoginSolver import net.mamoe.mirai.utils.LoginSolver -import net.mamoe.mirai.utils.SimpleLogger.LogPriority +import net.mamoe.mirai.utils.MiraiLogger import java.text.SimpleDateFormat import java.util.* import kotlin.concurrent.thread -class MiraiConsoleUIPure : MiraiConsoleUI { +class MiraiConsoleFrontEndPure : MiraiConsoleFrontEnd { private var requesting = false private var requestStr = "" @@ -60,34 +61,12 @@ class MiraiConsoleUIPure : MiraiConsoleUI { SimpleDateFormat("HH:mm:ss") } - override fun pushLog(identity: Long, message: String) { + override val logger: MiraiLogger = DefaultLogger("Console") // CLI logger from mirai-core + + fun pushLog(identity: Long, message: String) { println("\u001b[0m " + sdf.format(Date()) + " $message") } - override fun pushLog(priority: LogPriority, identityStr: String, identity: Long, message: String) { - var priorityStr = "[${priority.name}]" - /* - * 通过ANSI控制码添加颜色 - * 更多的颜色定义在 [MiraiConsoleUIPure] 的 companion - */ - priorityStr = when (priority) { - LogPriority.ERROR - -> COLOR_RED + priorityStr + COLOR_RESET - - LogPriority.WARNING - -> COLOR_RED + priorityStr + COLOR_RESET - - LogPriority.VERBOSE - -> COLOR_NAVY + priorityStr + COLOR_RESET - - LogPriority.DEBUG - -> COLOR_PINK + priorityStr + COLOR_RESET - - else -> priorityStr - } - println("\u001b[0m " + sdf.format(Date()) + " $priorityStr $identityStr ${message + COLOR_RESET}") - } - override fun prePushBot(identity: Long) { } @@ -100,8 +79,8 @@ class MiraiConsoleUIPure : MiraiConsoleUI { } - override suspend fun requestInput(hint:String): String { - if(hint.isNotEmpty()){ + override suspend fun requestInput(hint: String): String { + if (hint.isNotEmpty()) { println("\u001b[0m " + sdf.format(Date()) + COLOR_PINK + " $hint") } requesting = true diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt new file mode 100644 index 000000000..d5a144a5c --- /dev/null +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.pure + +import net.mamoe.mirai.console.MiraiConsole +import net.mamoe.mirai.console.command.CommandManager +import net.mamoe.mirai.console.command.DefaultCommands +import net.mamoe.mirai.console.plugins.PluginManager +import net.mamoe.mirai.console.utils.MiraiConsoleFrontEnd +import kotlin.concurrent.thread + +class MiraiConsolePureLoader { + companion object { + @JvmStatic + fun load( + coreVersion: String, + consoleVersion: String + ) { + start( + MiraiConsoleFrontEndPure(), + coreVersion, + consoleVersion + ) + Runtime.getRuntime().addShutdownHook(thread(start = false) { + MiraiConsole.stop() + }) + } + } +} + +/** + * 启动 Console + */ +@JvmOverloads +internal fun start( + frontEnd: MiraiConsoleFrontEnd, + coreVersion: String = "0.0.0", + consoleVersion: String = "0.0.0", + path: String = System.getProperty("user.dir") +) { + if (MiraiConsole.started) { + return + } + MiraiConsole.started = true + this.path = path + /* 初始化前端 */ + this.version = consoleVersion + this.frontEnd = frontEnd + this.frontEnd.pushVersion(consoleVersion, MiraiConsole.build, coreVersion) + logger("Mirai-console now running under $path") + logger("Get news in github: https://github.com/mamoe/mirai") + logger("Mirai为开源项目,请自觉遵守开源项目协议") + logger("Powered by Mamoe Technologies and contributors") + + /* 依次启用功能 */ + DefaultCommands() + PluginManager.loadPlugins() + CommandManager.start() + + /* 通知启动完成 */ + logger("Mirai-console 启动完成") + logger("\"login qqnumber qqpassword \" to login a bot") + logger("\"login qq号 qq密码 \" 来登录一个BOT") + + /* 尝试从系统配置自动登录 */ + DefaultCommands.tryLoginAuto() +} \ No newline at end of file diff --git a/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt b/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalFrontEnd.kt similarity index 98% rename from frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt rename to frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalFrontEnd.kt index 9db3cd724..231efbf7f 100644 --- a/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt +++ b/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalFrontEnd.kt @@ -19,12 +19,12 @@ import kotlinx.coroutines.io.jvm.nio.copyTo import kotlinx.coroutines.io.reader import kotlinx.io.core.use import net.mamoe.mirai.Bot -import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.cleanPage -import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.drawLog -import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.redrawLogs +import net.mamoe.mirai.console.MiraiConsoleTerminalFrontEnd.LoggerDrawer.cleanPage +import net.mamoe.mirai.console.MiraiConsoleTerminalFrontEnd.LoggerDrawer.drawLog +import net.mamoe.mirai.console.MiraiConsoleTerminalFrontEnd.LoggerDrawer.redrawLogs import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.ConsoleCommandSender -import net.mamoe.mirai.console.utils.MiraiConsoleUI +import net.mamoe.mirai.console.utils.MiraiConsoleFrontEnd import net.mamoe.mirai.utils.LoginSolver import net.mamoe.mirai.utils.SimpleLogger.LogPriority import java.awt.Image @@ -72,7 +72,7 @@ val String.isChineseChar: Boolean } -object MiraiConsoleTerminalUI : MiraiConsoleUI { +object MiraiConsoleTerminalFrontEnd : MiraiConsoleFrontEnd { const val cacheLogSize = 50 var mainTitle = "Mirai Console v0.01 Core v0.15" diff --git a/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalLoader.kt b/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalLoader.kt index 9da5cf122..cc4464ef5 100644 --- a/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalLoader.kt +++ b/frontend/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalLoader.kt @@ -15,16 +15,16 @@ class MiraiConsoleTerminalLoader { println("[MiraiConsoleTerminalLoader]: 将以Pure[兼容模式]启动Console") MiraiConsole.start(MiraiConsoleUIPure()) } else { - MiraiConsoleTerminalUI.start() + MiraiConsoleTerminalFrontEnd.start() thread { MiraiConsole.start( - MiraiConsoleTerminalUI + MiraiConsoleTerminalFrontEnd ) } } Runtime.getRuntime().addShutdownHook(thread(start = false) { MiraiConsole.stop() - MiraiConsoleTerminalUI.exit() + MiraiConsoleTerminalFrontEnd.exit() }) } }