Rework logger structure, extract pure frontend from miraio-console

This commit is contained in:
Him188 2020-05-14 09:02:02 +08:00
parent 33022deeae
commit 41112affa8
20 changed files with 194 additions and 511 deletions

View File

@ -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<WeakRef<Bot>>
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() {
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()
try {
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 {

View File

@ -55,9 +55,3 @@ interface PluginCenter {
val name:String
}
internal fun handleReplacement(
){
}

View File

@ -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<String, Command> = mutableMapOf()
val commands: Collection<Command> get() = registeredCommand.values
private val pluginCommands: MutableMap<PluginBase, MutableCollection<Command>> = 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<Boolean> {
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<FullCommand> = 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<Boolean> =
CommandManager.runCommandAsync(this, sender, command)
class UnknownCommandException(command: String) : Exception("unknown command \"$command\"")
object CommandManager

View File

@ -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)
) : ContactCommandSender(bot, subject)

View File

@ -27,7 +27,7 @@ import java.util.jar.JarFile
val PluginBase.description: PluginDescription get() = PluginManager.getPluginDescription(this)
object PluginManager {
object PluginManagerOld {
/**
* 通过插件获取介绍
* @see description

View File

@ -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()
})
}
}
}

View File

@ -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
*
* identitylog 所属的 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

View File

@ -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<MiraiGraphicalUIController>(),MiraiConsoleGraphicalLoader.coreVersion,MiraiConsoleGraphicalLoader.consoleVersion)
MiraiConsole.start(
find<MiraiGraphicalFrontEndController>(),
MiraiConsoleGraphicalLoader.coreVersion,
MiraiConsoleGraphicalLoader.consoleVersion
)
}
override fun stop() {

View File

@ -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<GlobalSettingModel>()
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<PluginModel> =
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) {

View File

@ -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<Bot>(null)
var bot: Bot by botProperty
val logHistory = observableListOf<Pair<String, String>>()
val logger: SimpleLogger =
SimpleLogger(uin.toString()) { priority: SimpleLogger.LogPriority, message: String?, e: Throwable? ->
val frontend = find<MiraiGraphicalFrontEndController>()
frontend.run {
logHistory.apply {
val time = sdf.format(Date())
add("[$time] $uin $message" to priority.name)
trim()
}
}
}
val admins = observableListOf<Long>()
}

View File

@ -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<MiraiGraphicalUIController>()
private val controller = find<MiraiGraphicalFrontEndController>()
private val qq = SimpleStringProperty("")
private val psd = SimpleStringProperty("")

View File

@ -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<MiraiGraphicalUIController>()
private val controller = find<MiraiGraphicalFrontEndController>()
private val center get() = MiraiConsole.frontEnd.pluginCenter
private val plugins: ObservableList<PluginModel> = observableListOf()

View File

@ -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<MiraiGraphicalUIController>()
private val controller = find<MiraiGraphicalFrontEndController>()
val plugins = controller.pluginList
override val root = jfxTreeTableView(plugins) {

View File

@ -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<MiraiGraphicalUIController>()
private val controller = find<MiraiGraphicalFrontEndController>()
private lateinit var mainTabPane: TabPane
override val root = borderpane {

View File

@ -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<MiraiGraphicalUIController>()
private val controller = find<MiraiGraphicalFrontEndController>()
private val settingModel = find<GlobalSettingModel>()
override val root = vbox {

View File

@ -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}")

View File

@ -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

View File

@ -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()
}

View File

@ -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"

View File

@ -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()
})
}
}