Explorar el Código

Separate `mirai-console` series from main repository

Him188 hace 6 años
padre
commit
c6ae8e32c2
Se han modificado 35 ficheros con 0 adiciones y 3369 borrados
  1. 0 6
      mirai-console-graphical/README.md
  2. 0 45
      mirai-console-graphical/build.gradle.kts
  3. 0 36
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/MiraiGraphical.kt
  4. 0 94
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalUIController.kt
  5. 0 19
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/BotModel.kt
  6. 0 17
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/ConsoleInfo.kt
  7. 0 20
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/PluginModel.kt
  8. 0 17
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/VerificationCodeModel.kt
  9. 0 47
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/styleSheet/LoginViewStyleSheet.kt
  10. 0 21
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/styleSheet/PrimaryStyleSheet.kt
  11. 0 48
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/util/JFoenixAdaptor.kt
  12. 0 9
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/Decorator.kt
  13. 0 50
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/LoginView.kt
  14. 0 33
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsView.kt
  15. 0 99
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PrimaryView.kt
  16. 0 36
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/SettingsView.kt
  17. 0 19
      mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/VerificationCodeFragment.kt
  18. BIN
      mirai-console-graphical/src/main/resources/character.png
  19. BIN
      mirai-console-graphical/src/main/resources/logo.png
  20. 0 6
      mirai-console-terminal/README.md
  21. 0 44
      mirai-console-terminal/build.gradle.kts
  22. 0 31
      mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalLoader.kt
  23. 0 662
      mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt
  24. 0 88
      mirai-console/README.MD
  25. 0 46
      mirai-console/build.gradle.kts
  26. 0 218
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt
  27. 0 242
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt
  28. 0 265
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/DefaultCommands.kt
  29. 0 525
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSection.kt
  30. 0 410
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt
  31. 0 16
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt
  32. 0 81
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleUIPure.kt
  33. 0 41
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/BotHelper.kt
  34. 0 75
      mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleUI.kt
  35. 0 3
      settings.gradle

+ 0 - 6
mirai-console-graphical/README.md

@@ -1,6 +0,0 @@
-### Mirai Console Graphical 
-支持windows/mac
-有正式UI界面实现的CONSOLE
-优点: 适合新手/完全不懂编程的/界面美丽
-缺点: 不能在linux服务器运行
-所使用插件系统与terminal版本一致 可以来回切换

+ 0 - 45
mirai-console-graphical/build.gradle.kts

@@ -1,45 +0,0 @@
-plugins {
-    id("kotlinx-serialization")
-    id("org.openjfx.javafxplugin") version "0.0.8"
-    id("kotlin")
-    id("java")
-}
-
-javafx {
-    version = "13.0.2"
-    modules = listOf("javafx.controls")
-    //mainClassName = "Application"
-}
-
-apply(plugin = "com.github.johnrengelman.shadow")
-
-val kotlinVersion: String by rootProject.ext
-val atomicFuVersion: String by rootProject.ext
-val coroutinesVersion: String by rootProject.ext
-val kotlinXIoVersion: String by rootProject.ext
-val coroutinesIoVersion: String by rootProject.ext
-
-val klockVersion: String by rootProject.ext
-val ktorVersion: String by rootProject.ext
-
-val serializationVersion: String by rootProject.ext
-
-fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$version"
-
-fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
-
-dependencies {
-    api(project(":mirai-core"))
-    api(project(":mirai-core-qqandroid"))
-    api(project(":mirai-api-http"))
-    api(project(":mirai-console"))
-    runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main"))
-    api(group = "no.tornado", name = "tornadofx", version = "1.7.19")
-    api(group = "com.jfoenix", name = "jfoenix", version = "9.0.8")
-    api("org.bouncycastle:bcprov-jdk15on:1.64")
-    // classpath is not set correctly by IDE
-}
-
-tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
-    kotlinOptions.jvmTarget = "1.8"
-}

+ 0 - 36
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/MiraiGraphical.kt

@@ -1,36 +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.graphical
-
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
-import net.mamoe.mirai.console.graphical.styleSheet.PrimaryStyleSheet
-import net.mamoe.mirai.console.graphical.view.Decorator
-import tornadofx.App
-import tornadofx.find
-import tornadofx.launch
-
-fun main(args: Array<String>) {
-    launch<MiraiGraphicalUI>(args)
-}
-
-class MiraiGraphicalUI : App(Decorator::class, PrimaryStyleSheet::class) {
-
-    override fun init() {
-        super.init()
-
-        MiraiConsole.start(find<MiraiGraphicalUIController>())
-    }
-
-    override fun stop() {
-        super.stop()
-        MiraiConsole.stop()
-    }
-}

+ 0 - 94
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/controller/MiraiGraphicalUIController.kt

@@ -1,94 +0,0 @@
-package net.mamoe.mirai.console.graphical.controller
-
-import javafx.application.Platform
-import javafx.collections.ObservableList
-import javafx.stage.Modality
-import kotlinx.io.core.IoBuffer
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.graphical.model.BotModel
-import net.mamoe.mirai.console.graphical.model.ConsoleInfo
-import net.mamoe.mirai.console.graphical.model.PluginModel
-import net.mamoe.mirai.console.graphical.model.VerificationCodeModel
-import net.mamoe.mirai.console.graphical.view.VerificationCodeFragment
-import net.mamoe.mirai.console.utils.MiraiConsoleUI
-import net.mamoe.mirai.utils.LoginSolver
-import tornadofx.*
-
-class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
-
-    private val loginSolver = GraphicalLoginSolver()
-    private val cache = mutableMapOf<Long, BotModel>()
-    val mainLog = observableListOf<String>()
-
-
-    val botList = observableListOf<BotModel>()
-    val pluginList: ObservableList<PluginModel> by lazy(::getPluginsFromConsole)
-
-    val consoleInfo = ConsoleInfo()
-
-    fun login(qq: String, psd: String) {
-        MiraiConsole.CommandProcessor.runConsoleCommandBlocking("/login $qq $psd")
-    }
-
-    fun sendCommand(command: String) = MiraiConsole.CommandProcessor.runConsoleCommandBlocking(command)
-
-    override fun pushLog(identity: Long, message: String) = Platform.runLater {
-        when (identity) {
-            0L -> mainLog.add(message)
-            else -> cache[identity]?.logHistory?.add(message)
-        }
-    }
-
-    override fun prePushBot(identity: Long) = Platform.runLater {
-        BotModel(identity).also {
-            cache[identity] = it
-            botList.add(it)
-        }
-    }
-
-    override fun pushBot(bot: Bot) = Platform.runLater {
-        cache[bot.uin]?.bot = bot
-    }
-
-    override fun pushVersion(consoleVersion: String, consoleBuild: String, coreVersion: String) {
-        Platform.runLater {
-            consoleInfo.consoleVersion = consoleVersion
-            consoleInfo.consoleBuild = consoleBuild
-            consoleInfo.coreVersion = coreVersion
-        }
-    }
-
-    override suspend fun requestInput(question: String): String {
-        val model = VerificationCodeModel()
-        find<VerificationCodeFragment>(Scope(model)).openModal(
-            modality = Modality.APPLICATION_MODAL,
-            resizable = false
-        )
-        return model.code.value
-    }
-
-    override fun pushBotAdminStatus(identity: Long, admins: List<Long>) = Platform.runLater {
-        cache[identity]?.admins?.setAll(admins)
-    }
-
-    override fun createLoginSolver(): LoginSolver = loginSolver
-
-    private fun getPluginsFromConsole(): ObservableList<PluginModel> =
-        MiraiConsole.pluginManager.getAllPluginDescriptions().map(::PluginModel).toObservable()
-
-}
-
-class GraphicalLoginSolver : LoginSolver() {
-    override suspend fun onSolvePicCaptcha(bot: Bot, data: IoBuffer): String? {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-
-    override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-
-    override suspend fun onSolveUnsafeDeviceLoginVerify(bot: Bot, url: String): String? {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
-    }
-}

+ 0 - 19
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/BotModel.kt

@@ -1,19 +0,0 @@
-package net.mamoe.mirai.console.graphical.model
-
-import javafx.beans.property.SimpleObjectProperty
-import net.mamoe.mirai.Bot
-import tornadofx.*
-
-class BotModel(val uin: Long) {
-    val botProperty = SimpleObjectProperty<Bot>(null)
-    var bot: Bot by botProperty
-
-    val logHistory = observableListOf<String>()
-    val admins = observableListOf<Long>()
-}
-
-class BotViewModel(botModel: BotModel? = null) : ItemViewModel<BotModel>(botModel) {
-    val bot = bind(BotModel::botProperty)
-    val logHistory = bind(BotModel::logHistory)
-    val admins = bind(BotModel::admins)
-}

+ 0 - 17
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/ConsoleInfo.kt

@@ -1,17 +0,0 @@
-package net.mamoe.mirai.console.graphical.model
-
-import javafx.beans.property.SimpleStringProperty
-import tornadofx.setValue
-import tornadofx.getValue
-
-class ConsoleInfo {
-
-    val consoleVersionProperty = SimpleStringProperty()
-    var consoleVersion by consoleVersionProperty
-
-    val consoleBuildProperty = SimpleStringProperty()
-    var consoleBuild by consoleBuildProperty
-
-    val coreVersionProperty = SimpleStringProperty()
-    var coreVersion by coreVersionProperty
-}

+ 0 - 20
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/PluginModel.kt

@@ -1,20 +0,0 @@
-package net.mamoe.mirai.console.graphical.model
-
-import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject
-import javafx.beans.property.SimpleBooleanProperty
-import javafx.beans.property.SimpleStringProperty
-import net.mamoe.mirai.console.plugins.PluginDescription
-import tornadofx.getValue
-import tornadofx.setValue
-
-class PluginModel(
-    val name: String,
-    val version: String,
-    val author: String,
-    val description: String
-) : RecursiveTreeObject<PluginModel>() {
-    constructor(plugin: PluginDescription):this(plugin.name, plugin.version, plugin.author, plugin.info)
-
-    val enabledProperty = SimpleBooleanProperty(this, "enabledProperty")
-    var enabled by enabledProperty
-}

+ 0 - 17
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/model/VerificationCodeModel.kt

@@ -1,17 +0,0 @@
-package net.mamoe.mirai.console.graphical.model
-
-import javafx.beans.property.SimpleStringProperty
-import tornadofx.ItemViewModel
-import tornadofx.getValue
-import tornadofx.setValue
-
-class VerificationCode {
-    val codeProperty = SimpleStringProperty("")
-    var code: String by codeProperty
-}
-
-class VerificationCodeModel(code: VerificationCode) : ItemViewModel<VerificationCode>(code) {
-    constructor(): this(VerificationCode())
-
-    val code = bind(VerificationCode::codeProperty)
-}

+ 0 - 47
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/styleSheet/LoginViewStyleSheet.kt

@@ -1,47 +0,0 @@
-package net.mamoe.mirai.console.graphical.styleSheet
-
-import javafx.scene.Cursor
-import javafx.scene.effect.BlurType
-import javafx.scene.effect.DropShadow
-import javafx.scene.paint.Color
-import javafx.scene.text.FontWeight
-import tornadofx.*
-
-class LoginViewStyleSheet : Stylesheet() {
-
-    companion object {
-        val vBox by csselement("VBox")
-    }
-
-    init {
-
-        vBox {
-            maxWidth = 500.px
-            maxHeight = 500.px
-
-            backgroundColor += c("39c5BB", 0.3)
-            backgroundRadius += box(15.px)
-
-            padding = box(50.px, 100.px)
-            spacing = 25.px
-
-            borderRadius += box(15.px)
-            effect = DropShadow(BlurType.THREE_PASS_BOX, Color.GRAY, 10.0, 0.0, 15.0, 15.0)
-        }
-
-        textField {
-            prefHeight = 30.px
-            textFill = Color.BLACK
-            fontWeight = FontWeight.BOLD
-        }
-
-        button {
-            backgroundColor += c("00BCD4", 0.8)
-            padding = box(10.px, 0.px)
-            prefWidth = 500.px
-            textFill = Color.WHITE
-            fontWeight = FontWeight.BOLD
-            cursor = Cursor.HAND
-        }
-    }
-}

+ 0 - 21
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/styleSheet/PrimaryStyleSheet.kt

@@ -1,21 +0,0 @@
-package net.mamoe.mirai.console.graphical.styleSheet
-
-import tornadofx.*
-
-class PrimaryStyleSheet : Stylesheet() {
-    companion object {
-        val jfxTitle by cssclass("jfx-decorator-buttons-container")
-        val container by cssclass("jfx-decorator-content-container")
-    }
-
-    init {
-        jfxTitle {
-            backgroundColor += c("00BCD4")
-        }
-
-        container {
-            borderColor += box(c("00BCD4"))
-            borderWidth += box(0.px, 4.px, 4.px, 4.px)
-        }
-    }
-}

+ 0 - 48
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/util/JFoenixAdaptor.kt

@@ -1,48 +0,0 @@
-package net.mamoe.mirai.console.graphical.util
-
-import com.jfoenix.controls.*
-import com.jfoenix.controls.datamodels.treetable.RecursiveTreeObject
-import javafx.beans.value.ObservableValue
-import javafx.collections.ObservableList
-import javafx.event.EventTarget
-import javafx.scene.Node
-import javafx.scene.control.*
-import tornadofx.SortedFilteredList
-import tornadofx.attachTo
-import tornadofx.bind
-
-internal fun EventTarget.jfxTabPane(op: TabPane.() -> Unit = {}) = JFXTabPane().attachTo(this, op)
-
-internal fun EventTarget.jfxButton(text: String = "", graphic: Node? = null, op: Button.() -> Unit = {}) =
-    JFXButton(text).attachTo(this, op) {
-        if (graphic != null) it.graphic = graphic
-    }
-
-fun EventTarget.jfxTextfield(value: String? = null, op: JFXTextField.() -> Unit = {}) = JFXTextField().attachTo(this, op) {
-    if (value != null) it.text = value
-}
-
-fun EventTarget.jfxTextfield(property: ObservableValue<String>, op: JFXTextField.() -> Unit = {}) = jfxTextfield().apply {
-    bind(property)
-    op(this)
-}
-
-fun EventTarget.jfxPasswordfield(value: String? = null, op: JFXPasswordField.() -> Unit = {}) = JFXPasswordField().attachTo(this, op) {
-    if (value != null) it.text = value
-}
-
-fun EventTarget.jfxPasswordfield(property: ObservableValue<String>, op: JFXPasswordField.() -> Unit = {}) = jfxPasswordfield().apply {
-    bind(property)
-    op(this)
-}
-
-internal fun <T> EventTarget.jfxListView(values: ObservableList<T>? = null, op: ListView<T>.() -> Unit = {}) =
-    JFXListView<T>().attachTo(this, op) {
-        if (values != null) {
-            if (values is SortedFilteredList<T>) values.bindTo(it)
-            else it.items = values
-        }
-    }
-
-fun <T : RecursiveTreeObject<T>?> EventTarget.jfxTreeTableView(items: ObservableList<T>? = null, op: JFXTreeTableView<T>.() -> Unit = {})
-        = JFXTreeTableView<T>(RecursiveTreeItem(items, RecursiveTreeObject<T>::getChildren)).attachTo(this, op)

+ 0 - 9
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/Decorator.kt

@@ -1,9 +0,0 @@
-package net.mamoe.mirai.console.graphical.view
-
-import com.jfoenix.controls.JFXDecorator
-import tornadofx.View
-
-class Decorator: View() {
-
-    override val root = JFXDecorator(primaryStage, find<PrimaryView>().root)
-}

+ 0 - 50
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/LoginView.kt

@@ -1,50 +0,0 @@
-package net.mamoe.mirai.console.graphical.view
-
-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.styleSheet.LoginViewStyleSheet
-import net.mamoe.mirai.console.graphical.util.jfxButton
-import net.mamoe.mirai.console.graphical.util.jfxPasswordfield
-import net.mamoe.mirai.console.graphical.util.jfxTextfield
-import tornadofx.*
-
-class LoginView : View("CNM") {
-
-    private val controller = find<MiraiGraphicalUIController>()
-    private val qq = SimpleStringProperty("")
-    private val psd = SimpleStringProperty("")
-
-    override val root = borderpane {
-
-        addStylesheet(LoginViewStyleSheet::class)
-
-        center = vbox {
-
-            imageview(Image(LoginView::class.java.classLoader.getResourceAsStream("character.png"))) {
-                alignment = Pos.CENTER
-            }
-
-            jfxTextfield(qq) {
-                promptText = "QQ"
-                isLabelFloat = true
-            }
-
-            jfxPasswordfield(psd) {
-                promptText = "Password"
-                isLabelFloat = true
-            }
-
-            jfxButton("Login").action {
-                runAsync {
-                    runBlocking { controller.login(qq.value, psd.value) }
-                }.ui {
-                    qq.value = ""
-                    psd.value = ""
-                }
-            }
-        }
-    }
-}

+ 0 - 33
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PluginsView.kt

@@ -1,33 +0,0 @@
-package net.mamoe.mirai.console.graphical.view
-
-import com.jfoenix.controls.JFXTreeTableColumn
-import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
-import net.mamoe.mirai.console.graphical.model.PluginModel
-import net.mamoe.mirai.console.graphical.util.jfxTreeTableView
-import tornadofx.View
-
-class PluginsView : View() {
-
-    private val controller = find<MiraiGraphicalUIController>()
-    val plugins = controller.pluginList
-
-    override val root = jfxTreeTableView(plugins) {
-        columns.addAll(
-            JFXTreeTableColumn<PluginModel, String>("插件名").apply {
-                prefWidthProperty().bind([email protected]().multiply(0.1))
-            },
-            JFXTreeTableColumn<PluginModel, String>("版本").apply {
-                prefWidthProperty().bind([email protected]().multiply(0.1))
-            },
-            JFXTreeTableColumn<PluginModel, String>("作者").apply {
-                prefWidthProperty().bind([email protected]().multiply(0.1))
-            },
-            JFXTreeTableColumn<PluginModel, String>("介绍").apply {
-                prefWidthProperty().bind([email protected]().multiply(0.6))
-            },
-            JFXTreeTableColumn<PluginModel, String>("操作").apply {
-                prefWidthProperty().bind([email protected]().multiply(0.08))
-            }
-        )
-    }
-}

+ 0 - 99
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/PrimaryView.kt

@@ -1,99 +0,0 @@
-package net.mamoe.mirai.console.graphical.view
-
-import com.jfoenix.controls.*
-import javafx.collections.ObservableList
-import javafx.scene.control.Tab
-import javafx.scene.control.TabPane
-import javafx.scene.image.Image
-import javafx.scene.input.KeyCode
-import kotlinx.coroutines.runBlocking
-import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
-import net.mamoe.mirai.console.graphical.model.BotModel
-import net.mamoe.mirai.console.graphical.util.jfxListView
-import net.mamoe.mirai.console.graphical.util.jfxTabPane
-import tornadofx.*
-
-class PrimaryView : View() {
-
-    private val controller = find<MiraiGraphicalUIController>()
-
-    override val root = borderpane {
-
-        prefWidth = 1000.0
-        prefHeight = 650.0
-
-        left = vbox {
-
-            imageview(Image(PrimaryView::class.java.classLoader.getResourceAsStream("logo.png")))
-
-            // bot list
-            jfxListView(controller.botList) {
-                fitToParentSize()
-
-                setCellFactory {
-                    object : JFXListCell<BotModel>() {
-                        init {
-                            onDoubleClick {
-                                (center as TabPane).logTab(
-                                    text = item.uin.toString(),
-                                    logs = item.logHistory
-                                ).select()
-                            }
-                        }
-
-                        override fun updateItem(item: BotModel?, empty: Boolean) {
-                            super.updateItem(item, empty)
-                            if (item != null && !empty) {
-                                graphic = null
-                                text = item.uin.toString()
-                            } else {
-                                graphic = null
-                                text = ""
-                            }
-                        }
-                    }
-                }
-            }
-
-            // command input
-            textfield {
-                setOnKeyPressed {
-                    if (it.code == KeyCode.ENTER) {
-                        runAsync {
-                            runBlocking { controller.sendCommand(text) }
-                        }.ui { text = "" }
-                    }
-                }
-            }
-        }
-
-        center = jfxTabPane {
-
-            tab("Login").content = find<LoginView>().root
-
-            tab("Plugins").content = find<PluginsView>().root
-
-            tab("Settings").content = find<SettingsView>().root
-
-            logTab("Main", controller.mainLog)
-        }
-    }
-}
-
-private fun TabPane.logTab(
-    text: String? = null,
-    logs: ObservableList<String>,
-    op: Tab.() -> Unit = {}
-)= tab(text) {
-    listview(logs) {
-
-        fitToParentSize()
-        cellFormat {
-            graphic = label(it) {
-                maxWidthProperty().bind([email protected]())
-                isWrapText = true
-            }
-        }
-    }
-    also(op)
-}

+ 0 - 36
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/SettingsView.kt

@@ -1,36 +0,0 @@
-package net.mamoe.mirai.console.graphical.view
-
-import net.mamoe.mirai.console.graphical.controller.MiraiGraphicalUIController
-import net.mamoe.mirai.console.graphical.util.jfxButton
-import net.mamoe.mirai.console.graphical.util.jfxTextfield
-import tornadofx.*
-
-class SettingsView : View() {
-
-    private val controller = find<MiraiGraphicalUIController>()
-
-    override val root = form {
-
-        fieldset {
-            field {
-                jfxButton("撤掉") {  }
-                jfxButton("保存") {  }
-            }
-        }
-
-        fieldset("插件目录") {
-            field {
-                jfxTextfield("...") { isEditable = false }
-                jfxButton("打开目录")
-            }
-        }
-
-        fieldset("最大日志容量") {
-            field {
-                jfxTextfield("...") {
-
-                }
-            }
-        }
-    }
-}

+ 0 - 19
mirai-console-graphical/src/main/kotlin/net/mamoe/mirai/console/graphical/view/VerificationCodeFragment.kt

@@ -1,19 +0,0 @@
-package net.mamoe.mirai.console.graphical.view
-
-import javafx.scene.Parent
-import tornadofx.*
-
-class VerificationCodeFragment : Fragment() {
-
-    override val root = vbox {
-        //TODO: 显示验证码
-
-        form {
-            fieldset {
-                field("验证码") {
-                    textfield()
-                }
-            }
-        }
-    }
-}

BIN
mirai-console-graphical/src/main/resources/character.png


BIN
mirai-console-graphical/src/main/resources/logo.png


+ 0 - 6
mirai-console-terminal/README.md

@@ -1,6 +0,0 @@
-### Mirai Console Terminal
-支持windows/mac/linux
-在terminal环境下的Console, 由控制台富文本实现简易UI
-优点: 可以在linux环境下运行/简洁使用效率高
-缺点: 需要有略微的terminal知识
-所使用插件系统与graphical版本一致 可以来回切换

+ 0 - 44
mirai-console-terminal/build.gradle.kts

@@ -1,44 +0,0 @@
-plugins {
-    id("kotlinx-serialization")
-    id("kotlin")
-    id("java")
-}
-
-
-apply(plugin = "com.github.johnrengelman.shadow")
-
-
-tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>() {
-    manifest {
-        attributes["Main-Class"] = "net.mamoe.mirai.console.MiraiConsoleTerminalLoader"
-    }
-}
-
-val kotlinVersion: String by rootProject.ext
-val atomicFuVersion: String by rootProject.ext
-val coroutinesVersion: String by rootProject.ext
-val kotlinXIoVersion: String by rootProject.ext
-val coroutinesIoVersion: String by rootProject.ext
-
-val klockVersion: String by rootProject.ext
-val ktorVersion: String by rootProject.ext
-
-val serializationVersion: String by rootProject.ext
-
-fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$version"
-
-fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
-
-
-
-dependencies {
-    api(project(":mirai-core"))
-    api(project(":mirai-core-qqandroid"))
-    api(project(":mirai-api-http"))
-    api(project(":mirai-console"))
-    runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main"))
-    runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main"))
-    api(group = "com.googlecode.lanterna", name = "lanterna", version = "3.0.2")
-    api("org.bouncycastle:bcprov-jdk15on:1.64")
-    // classpath is not set correctly by IDE
-}

+ 0 - 31
mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalLoader.kt

@@ -1,31 +0,0 @@
-package net.mamoe.mirai.console
-
-import net.mamoe.mirai.console.pure.MiraiConsoleUIPure
-import kotlin.concurrent.thread
-
-class MiraiConsoleTerminalLoader {
-    companion object {
-        @JvmStatic
-        fun main(args: Array<String>) {
-            if (args.contains("pure") || args.contains("-pure") || System.getProperty(
-                    "os.name",
-                    ""
-                ).toLowerCase().contains("windows")
-            ) {
-                println("[MiraiConsoleTerminalLoader]: 将以Pure[兼容模式]启动Console")
-                MiraiConsole.start(MiraiConsoleUIPure())
-            } else {
-                MiraiConsoleTerminalUI.start()
-                thread {
-                    MiraiConsole.start(
-                        MiraiConsoleTerminalUI
-                    )
-                }
-            }
-            Runtime.getRuntime().addShutdownHook(thread(start = false) {
-                MiraiConsole.stop()
-                MiraiConsoleTerminalUI.exit()
-            })
-        }
-    }
-}

+ 0 - 662
mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt

@@ -1,662 +0,0 @@
-package net.mamoe.mirai.console
-
-import com.googlecode.lanterna.SGR
-import com.googlecode.lanterna.TerminalSize
-import com.googlecode.lanterna.TextColor
-import com.googlecode.lanterna.graphics.TextGraphics
-import com.googlecode.lanterna.input.KeyStroke
-import com.googlecode.lanterna.input.KeyType
-import com.googlecode.lanterna.terminal.DefaultTerminalFactory
-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 kotlinx.coroutines.*
-import kotlinx.coroutines.io.close
-import kotlinx.io.core.IoBuffer
-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.utils.MiraiConsoleUI
-import net.mamoe.mirai.utils.LoginSolver
-import net.mamoe.mirai.utils.createCharImg
-import net.mamoe.mirai.utils.writeChannel
-import java.io.File
-import java.io.OutputStream
-import java.io.PrintStream
-import java.nio.charset.Charset
-import java.util.*
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.ConcurrentLinkedDeque
-import javax.imageio.ImageIO
-import kotlin.concurrent.thread
-import kotlin.system.exitProcess
-
-/**
- * 此文件不推荐任何人看
- * 可能导致
- *  1:心肌梗死
- *  2:呼吸困难
- *  3:想要重写但是发现改任何一个看似不合理的地方都会崩
- *
- * @author NaturalHG
- *
- */
-
-fun String.actualLength(): Int {
-    var x = 0
-    this.forEach {
-        if (it.isChineseChar()) {
-            x += 2
-        } else {
-            x += 1
-        }
-    }
-    return x
-}
-
-fun String.getSubStringIndexByActualLength(widthMax: Int): Int {
-    var index = 0
-    var currentLength = 0
-    this.forEach {
-        if (it.isChineseChar()) {
-            currentLength += 2
-        } else {
-            currentLength += 1
-        }
-        if (currentLength > widthMax) {
-            return@forEach
-        }
-        ++index
-    }
-    if (index < 2) {
-        index = 2
-    }
-    return index
-}
-
-fun Char.isChineseChar(): Boolean {
-    return this.toString().isChineseChar()
-}
-
-fun String.isChineseChar(): Boolean {
-    return this.matches(Regex("[\u4e00-\u9fa5]"))
-}
-
-
-object MiraiConsoleTerminalUI : MiraiConsoleUI {
-    val cacheLogSize = 50
-    var mainTitle = "Mirai Console v0.01 Core v0.15"
-
-    override fun pushVersion(consoleVersion: String, consoleBuild: String, coreVersion: String) {
-        mainTitle = "Mirai Console(Terminal) $consoleVersion $consoleBuild Core $coreVersion"
-    }
-
-    override fun pushLog(identity: Long, message: String) {
-        log[identity]!!.push(message)
-        if (identity == screens[currentScreenId]) {
-            drawLog(message)
-        }
-    }
-
-    override fun prePushBot(identity: Long) {
-        log[identity] = LimitLinkedQueue(cacheLogSize)
-    }
-
-    override fun pushBot(bot: Bot) {
-        botAdminCount[bot.uin] = 0
-        screens.add(bot.uin)
-        drawFrame(this.getScreenName(currentScreenId))
-        if (terminal is SwingTerminalFrame) {
-            terminal.flush()
-        }
-    }
-
-    var requesting = false
-    var requestResult: String? = null
-    override suspend fun requestInput(question: String): String {
-        requesting = true
-        while (requesting) {
-            delay(100)//不然会卡死 迷惑吧
-        }
-        return requestResult!!
-    }
-
-
-    suspend fun provideInput(input: String) {
-        if (requesting) {
-            requestResult = input
-            requesting = false
-        } else {
-            MiraiConsole.CommandProcessor.runConsoleCommand(commandBuilder.toString())
-        }
-    }
-
-
-    override fun pushBotAdminStatus(identity: Long, admins: List<Long>) {
-        botAdminCount[identity] = admins.size
-    }
-
-    override fun createLoginSolver(): LoginSolver {
-        return object : LoginSolver() {
-            override suspend fun onSolvePicCaptcha(bot: Bot, data: IoBuffer): String? {
-                val tempFile: File = createTempFile(suffix = ".png").apply { deleteOnExit() }
-                withContext(Dispatchers.IO) {
-                    tempFile.createNewFile()
-                    pushLog(0, "[Login Solver]需要图片验证码登录, 验证码为 4 字母")
-                    try {
-                        tempFile.writeChannel().apply {
-                            writeFully(data)
-                            close()
-                        }
-                        pushLog(0, "请查看文件 ${tempFile.absolutePath}")
-                    } catch (e: Exception) {
-                        error("[Login Solver]验证码无法保存[Error0001]")
-                    }
-                }
-
-                var toLog = ""
-                tempFile.inputStream().use {
-                    val img = ImageIO.read(it)
-                    if (img == null) {
-                        toLog += "无法创建字符图片. 请查看文件\n"
-                    } else {
-                        toLog += img.createCharImg((terminal.terminalSize.columns / 1.5).toInt())
-                    }
-                }
-                pushLog(0, "$toLog[Login Solver]请输验证码. ${tempFile.absolutePath}")
-                return requestInput("[Login Solver]请输入 4 位字母验证码. 若要更换验证码, 请直接回车")!!
-                    .takeUnless { it.isEmpty() || it.length != 4 }
-                    .also {
-                        pushLog(0, "[Login Solver]正在提交[$it]中...")
-                    }
-            }
-
-            override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? {
-                pushLog(0, "[Login Solver]需要滑动验证码")
-                pushLog(0, "[Login Solver]请在任意浏览器中打开以下链接并完成验证码. ")
-                pushLog(0, "[Login Solver]完成后请输入任意字符 ")
-                pushLog(0, url)
-                return requestInput("[Login Solver]完成后请输入任意字符").also {
-                    pushLog(0, "[Login Solver]正在提交中")
-                }
-            }
-
-            override suspend fun onSolveUnsafeDeviceLoginVerify(bot: Bot, url: String): String? {
-                pushLog(0, "[Login Solver]需要进行账户安全认证")
-                pushLog(0, "[Login Solver]该账户有[设备锁]/[不常用登录地点]/[不常用设备登录]的问题")
-                pushLog(0, "[Login Solver]完成以下账号认证即可成功登录|理论本认证在mirai每个账户中最多出现1次")
-                pushLog(0, "[Login Solver]请将该链接在QQ浏览器中打开并完成认证, 成功后输入任意字符")
-                pushLog(0, "[Login Solver]这步操作将在后续的版本中优化")
-                pushLog(0, url)
-                return requestInput("[Login Solver]完成后请输入任意字符").also {
-                    pushLog(0, "[Login Solver]正在提交中...")
-                }
-            }
-
-        }
-    }
-
-    val log = ConcurrentHashMap<Long, LimitLinkedQueue<String>>().also {
-        it[0L] = LimitLinkedQueue(cacheLogSize)
-    }
-
-    val botAdminCount = ConcurrentHashMap<Long, Int>()
-
-    private val screens = mutableListOf(0L)
-    private var currentScreenId = 0
-
-
-    lateinit var terminal: Terminal
-    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(internalPrinter, System.`in`, Charset.defaultCharset())
-        try {
-            terminal = defaultTerminalFactory.createTerminal()
-            terminal.enterPrivateMode()
-            terminal.clearScreen()
-            terminal.setCursorVisible(false)
-        } catch (e: Exception) {
-            try {
-                terminal = SwingTerminalFrame("Mirai Console")
-                terminal.enterPrivateMode()
-                terminal.clearScreen()
-                terminal.setCursorVisible(false)
-            } catch (e: Exception) {
-                error("can not create terminal")
-            }
-        }
-        textGraphics = terminal.newTextGraphics()
-
-        /*
-        var lastRedrawTime = 0L
-        var lastNewWidth = 0
-        var lastNewHeight = 0
-
-        terminal.addResizeListener(TerminalResizeListener { terminal1: Terminal, newSize: TerminalSize ->
-            try {
-                if (lastNewHeight == newSize.rows
-                    &&
-                    lastNewWidth == newSize.columns
-                ) {
-                    return@TerminalResizeListener
-                }
-                lastNewHeight = newSize.rows
-                lastNewWidth = newSize.columns
-                terminal.clearScreen()
-                if(terminal !is SwingTerminalFrame) {
-                    Thread.sleep(300)
-                }
-                update()
-                redrawCommand()
-                redrawLogs(log[screens[currentScreenId]]!!)
-            }catch (ignored:Exception){
-
-            }
-        })
-
-       */
-        var lastJob: Job? = null
-        terminal.addResizeListener(TerminalResizeListener { terminal1: Terminal, newSize: TerminalSize ->
-            lastJob = GlobalScope.launch {
-                try {
-                    delay(300)
-                    if (lastJob == coroutineContext[Job]) {
-                        terminal.clearScreen()
-                        //inited = false
-                        update()
-                        redrawCommand()
-                        redrawLogs(log[screens[currentScreenId]]!!)
-                    }
-                } catch (e: Exception) {
-                    pushLog(0, "[UI ERROR] ${e.message}")
-                }
-            }
-        })
-
-        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)
-
-        try {
-            update()
-        } catch (e: Exception) {
-            pushLog(0, "[UI ERROR] ${e.message}")
-        }
-
-        val charList = listOf(',', '.', '/', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '=', '+', '!', ' ')
-        thread {
-            while (true) {
-                try {
-                    var keyStroke: KeyStroke = terminal.readInput()
-
-                    when (keyStroke.keyType) {
-                        KeyType.ArrowLeft -> {
-                            currentScreenId =
-                                getLeftScreenId()
-                            clearRows(2)
-                            cleanPage()
-                            update()
-                        }
-                        KeyType.ArrowRight -> {
-                            currentScreenId =
-                                getRightScreenId()
-                            clearRows(2)
-                            cleanPage()
-                            update()
-                        }
-                        KeyType.Enter -> {
-                            runBlocking {
-                                provideInput(commandBuilder.toString())
-                            }
-                            emptyCommand()
-                        }
-                        KeyType.Escape -> {
-                            exit()
-                        }
-                        else -> {
-                            if (keyStroke.character != null) {
-                                if (keyStroke.character.toInt() == 8) {
-                                    deleteCommandChar()
-                                }
-                                if (keyStroke.character.isLetterOrDigit() || charList.contains(keyStroke.character)) {
-                                    addCommandChar(keyStroke.character)
-                                }
-                            }
-                        }
-                    }
-                } catch (e: Exception) {
-                    pushLog(0, "[UI ERROR] ${e.message}")
-                }
-            }
-        }
-    }
-
-    private fun getLeftScreenId(): Int {
-        var newId = currentScreenId - 1
-        if (newId < 0) {
-            newId = screens.size - 1
-        }
-        return newId
-    }
-
-    private fun getRightScreenId(): Int {
-        var newId = 1 + currentScreenId
-        if (newId >= screens.size) {
-            newId = 0
-        }
-        return newId
-    }
-
-    private fun getScreenName(id: Int): String {
-        return when (screens[id]) {
-            0L -> {
-                "Console Screen"
-            }
-            else -> {
-                "Bot: ${screens[id]}"
-            }
-        }
-    }
-
-
-    fun clearRows(row: Int) {
-        textGraphics.putString(
-            0, row, " ".repeat(
-                terminal.terminalSize.columns
-            )
-        )
-    }
-
-    fun drawFrame(
-        title: String
-    ) {
-        val width = terminal.terminalSize.columns
-        val height = terminal.terminalSize.rows
-        terminal.setBackgroundColor(TextColor.ANSI.DEFAULT)
-
-        textGraphics.foregroundColor = TextColor.ANSI.WHITE
-        textGraphics.backgroundColor = TextColor.ANSI.GREEN
-        textGraphics.putString((width - mainTitle.actualLength()) / 2, 1, mainTitle, SGR.BOLD)
-        textGraphics.foregroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.putString(2, 3, "-".repeat(width - 4))
-        textGraphics.putString(2, 5, "-".repeat(width - 4))
-        textGraphics.putString(2, height - 4, "-".repeat(width - 4))
-        textGraphics.putString(2, height - 3, "|>>>")
-        textGraphics.putString(width - 3, height - 3, "|")
-        textGraphics.putString(2, height - 2, "-".repeat(width - 4))
-
-        textGraphics.foregroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-        val leftName =
-            getScreenName(getLeftScreenId())
-        // clearRows(2)
-        textGraphics.putString((width - title.actualLength()) / 2 - "$leftName << ".length, 2, "$leftName << ")
-        textGraphics.foregroundColor = TextColor.ANSI.WHITE
-        textGraphics.backgroundColor = TextColor.ANSI.YELLOW
-        textGraphics.putString((width - title.actualLength()) / 2, 2, title, SGR.BOLD)
-        textGraphics.foregroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-        val rightName =
-            getScreenName(getRightScreenId())
-        textGraphics.putString((width + title.actualLength()) / 2 + 1, 2, ">> $rightName")
-    }
-
-    fun drawMainFrame(
-        onlineBotCount: Number
-    ) {
-        drawFrame("Console Screen")
-        val width = terminal.terminalSize.columns
-        textGraphics.foregroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-        clearRows(4)
-        textGraphics.putString(2, 4, "|Online Bots: $onlineBotCount")
-        textGraphics.putString(
-            width - 2 - "Powered By Mamoe Technologies|".actualLength(),
-            4,
-            "Powered By Mamoe Technologies|"
-        )
-    }
-
-    fun drawBotFrame(
-        qq: Long,
-        adminCount: Number
-    ) {
-        drawFrame("Bot: $qq")
-        val width = terminal.terminalSize.columns
-        textGraphics.foregroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-        clearRows(4)
-        textGraphics.putString(2, 4, "|Admins: $adminCount")
-        textGraphics.putString(width - 2 - "Add admins via commands|".actualLength(), 4, "Add admins via commands|")
-    }
-
-
-    object LoggerDrawer {
-        var currentHeight = 6
-
-        fun drawLog(string: String, flush: Boolean = true) {
-            val maxHeight = terminal.terminalSize.rows - 4
-            val heightNeed = (string.actualLength() / (terminal.terminalSize.columns - 6)) + 1
-            if (heightNeed - 1 > maxHeight) {
-                pushLog(0, "[UI ERROR]: 您的屏幕太小, 有一条超长LOG无法显示")
-                return//拒绝打印
-            }
-            if (currentHeight + heightNeed > maxHeight) {
-                cleanPage()//翻页
-            }
-            if (string.contains("\n")) {
-                string.split("\n").forEach {
-                    drawLog(string, false)
-                }
-            } else {
-                val width = terminal.terminalSize.columns - 6
-                var x = string
-                while (true) {
-                    if (x == "") {
-                        break
-                    }
-                    val toWrite = if (x.actualLength() > width) {
-                        val index = x.getSubStringIndexByActualLength(width)
-                        x.substring(0, index).also {
-                            x = if (index < x.length) {
-                                x.substring(index)
-                            } else {
-                                ""
-                            }
-                        }
-                    } else {
-                        x.also {
-                            x = ""
-                        }
-                    }
-                    try {
-                        textGraphics.foregroundColor = TextColor.ANSI.GREEN
-                        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-                        textGraphics.putString(
-                            3,
-                            currentHeight, toWrite, SGR.ITALIC
-                        )
-                    } catch (ignored: Exception) {
-                        //
-                    }
-                    ++currentHeight
-                }
-            }
-            if (flush && terminal is SwingTerminalFrame) {
-                terminal.flush()
-            }
-        }
-
-
-        fun cleanPage() {
-            for (index in 6 until terminal.terminalSize.rows - 4) {
-                clearRows(index)
-            }
-            currentHeight = 6
-        }
-
-
-        fun redrawLogs(toDraw: Queue<String>) {
-            //this.cleanPage()
-            currentHeight = 6
-            var logsToDraw = 0
-            var vara = 0
-            val toPrint = mutableListOf<String>()
-            toDraw.forEach {
-                val heightNeed = (it.actualLength() / (terminal.terminalSize.columns - 6)) + 1
-                vara += heightNeed
-                if (currentHeight + vara < terminal.terminalSize.rows - 4) {
-                    logsToDraw++
-                    toPrint.add(it)
-                } else {
-                    return@forEach
-                }
-            }
-            toPrint.reversed().forEach {
-                drawLog(it, false)
-            }
-            if (terminal is SwingTerminalFrame) {
-                terminal.flush()
-            }
-        }
-    }
-
-
-    var commandBuilder = StringBuilder()
-    fun redrawCommand() {
-        val height = terminal.terminalSize.rows
-        val width = terminal.terminalSize.columns
-        clearRows(height - 3)
-        textGraphics.foregroundColor = TextColor.ANSI.DEFAULT
-        textGraphics.putString(2, height - 3, "|>>>")
-        textGraphics.putString(width - 3, height - 3, "|")
-        textGraphics.foregroundColor = TextColor.ANSI.WHITE
-        textGraphics.backgroundColor = TextColor.ANSI.BLACK
-        textGraphics.putString(7, height - 3, commandBuilder.toString())
-        if (terminal is SwingTerminalFrame) {
-            terminal.flush()
-        }
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-    }
-
-    private fun addCommandChar(
-        c: Char
-    ) {
-        if (!requesting && commandBuilder.isEmpty() && c != '/') {
-            addCommandChar('/')
-        }
-        textGraphics.foregroundColor = TextColor.ANSI.WHITE
-        textGraphics.backgroundColor = TextColor.ANSI.BLACK
-        val height = terminal.terminalSize.rows
-        commandBuilder.append(c)
-        if (terminal is SwingTerminalFrame) {
-            redrawCommand()
-        } else {
-            textGraphics.putString(6 + commandBuilder.length, height - 3, c.toString())
-        }
-        textGraphics.backgroundColor = TextColor.ANSI.DEFAULT
-    }
-
-    private fun deleteCommandChar() {
-        if (!commandBuilder.isEmpty()) {
-            commandBuilder = StringBuilder(commandBuilder.toString().substring(0, commandBuilder.length - 1))
-        }
-        val height = terminal.terminalSize.rows
-        if (terminal is SwingTerminalFrame) {
-            redrawCommand()
-        } else {
-            textGraphics.putString(7 + commandBuilder.length, height - 3, " ")
-        }
-    }
-
-
-    var lastEmpty: Job? = null
-    private fun emptyCommand() {
-        commandBuilder = StringBuilder()
-        if (terminal is SwingTerminal) {
-            redrawCommand()
-            terminal.flush()
-        } else {
-            lastEmpty = GlobalScope.launch {
-                try {
-                    delay(100)
-                    if (lastEmpty == coroutineContext[Job]) {
-                        terminal.clearScreen()
-                        //inited = false
-                        update()
-                        redrawCommand()
-                        redrawLogs(log[screens[currentScreenId]]!!)
-                    }
-                } catch (e: Exception) {
-                    pushLog(0, "[UI ERROR] ${e.message}")
-                }
-            }
-        }
-    }
-
-    fun update() {
-        when (screens[currentScreenId]) {
-            0L -> {
-                drawMainFrame(screens.size - 1)
-            }
-            else -> {
-                drawBotFrame(
-                    screens[currentScreenId],
-                    0
-                )
-            }
-        }
-        redrawLogs(log[screens[currentScreenId]]!!)
-    }
-
-    fun exit() {
-        try {
-            terminal.exitPrivateMode()
-            terminal.close()
-            exitProcess(0)
-        } catch (ignored: Exception) {
-
-        }
-    }
-}
-
-
-class LimitLinkedQueue<T>(
-    val limit: Int = 50
-) : ConcurrentLinkedDeque<T>() {
-    override fun push(e: T) {
-        if (size >= limit) {
-            this.pollLast()
-        }
-        return super.push(e)
-    }
-}

+ 0 - 88
mirai-console/README.MD

@@ -1,88 +0,0 @@
-# Mirai Console
-你可以在全平台运行Mirai高效率机器人框架
-### Mirai Console提供了6个版本以满足各种需要
-#### 所有版本的Mirai Console API相同 插件系统相同
-
-|  名字    | 介绍 |
-| --- | --- |
-| Mirai-Console-Pure  |  最纯净版, CLI环境, 通过标准输入与标准输出 交互 |
-| Mirai-Console-Terminal  |  (UNIX)Terminal环境 提供简洁的富文本控制台 |
-| Mirai-Console-Android   |  安卓APP (TODO) |
-| Mirai-Console-Graphical  |  JavaFX的图形化界面 (.jar/.exe/.dmg) |
-| Mirai-Console-WebPanel  |   Web Panel操作(TODO) |
-| Mirai-Console-Ios   |  IOS APP (TODO) |
-
-
-
-### 如何选择版本
-1:  Mirai-Console-Pure 兼容性最高, 在其他都表现不佳的时候请使用</br>
-2:  以系统区分
-```kotlin
-    return when(operatingSystem){
-        WINDOWS -> listOf("Graphical","WebPanel","Pure")
-        MAC_OS  -> listOf("Graphical","Terminal","WebPanel","Pure") 
-        LINUX   -> listOf("Terminal","Pure")
-        ANDROID -> listOf("Android","Pure","WebPanel") 
-        IOS     -> listOf("Ios") 
-        else    -> listOf("Pure") 
-    }      
-```
-3: 以策略区分
-```kotlin
-    return when(task){
-        体验         -> listOf("Graphical","Terminal","WebPanel","Android","Pure")
-        测试插件      -> listOf("Pure") 
-        调试插件      -> byOperatingSystem() 
-        稳定挂机      -> listOf("Terminal","Pure") 
-        else         -> listOf("Pure") 
-    }      
-```
-
-
-#### More Importantly, Mirai Console support <b>Plugins</b>, tells the bot what to do
-#### Mirai Console 支持插件系统, 你可以自己开发或使用公开的插件来逻辑化机器人, 如群管
-<br>
-
-#### download 下载
-#### how to get/write plugins 如何获取/写插件
-<br>
-<br>
-
-### how to use(如何使用)
-#### how to run Mirai Console
-<ul>
-    <li>download mirai-console.jar</li>
-    <li>open command line/terminal</li>
-    <li>create a folder and put mirai-console.jar in</li>
-    <li>cd that folder</li>
-    <li>"java -jar mirai-console.jar"</li>
-</ul>
-
-<ul>
-    <li>下载mirai-console.jar</li>
-    <li>打开终端</li>
-    <li>在任何地方创建一个文件夹, 并放入mirai-console.jar</li>
-    <li>在终端中打开该文件夹"cd"</li>
-    <li>输入"java -jar mirai-console.jar"</li>
-</ul>
-
-#### how to add plugins
-<ul>
-    <li>After first time of running mirai console</li>
-    <li>/plugins/folder will be created next to mirai-console.jar</li>
-    <li>put plugin(.jar) into /plugins/</li>
-    <li>restart mirai console</li>
-    <li>checking logger and check if the plugin is loaded successfully</li>
-    <li>if the plugin has it own Config file, it normally appears in /plugins/{pluginName}/</li>
-</ul>
-
-<ul>
-    <li>在首次运行mirai console后</li>
-    <li>mirai-console.jar 的同级会出现/plugins/文件夹</li>
-    <li>将插件(.jar)放入/plugins/文件夹</li>
-    <li>重启mirai console</li>
-    <li>在开启后检查日志, 是否成功加载</li>
-    <li>如该插件有配置文件, 配置文件一般会创建在/plugins/插件名字/ 文件夹下</li>
-</ul>
-
-

+ 0 - 46
mirai-console/build.gradle.kts

@@ -1,46 +0,0 @@
-plugins {
-    id("kotlinx-serialization")
-    id("kotlin")
-    id("java")
-}
-
-
-apply(plugin = "com.github.johnrengelman.shadow")
-
-val kotlinVersion: String by rootProject.ext
-val atomicFuVersion: String by rootProject.ext
-val coroutinesVersion: String by rootProject.ext
-val kotlinXIoVersion: String by rootProject.ext
-val coroutinesIoVersion: String by rootProject.ext
-
-val klockVersion: String by rootProject.ext
-val ktorVersion: String by rootProject.ext
-
-val serializationVersion: String by rootProject.ext
-
-fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$version"
-
-fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
-
-tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>() {
-    manifest {
-        attributes["Main-Class"] = "net.mamoe.mirai.console.pure.MiraiConsolePureLoader"
-    }
-}
-
-
-dependencies {
-    api(project(":mirai-core"))
-    api(project(":mirai-core-qqandroid"))
-    // api(project(":mirai-api-http"))
-    runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main"))
-    runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main"))
-    api(kotlin("serialization"))
-    api(group = "com.alibaba", name = "fastjson", version = "1.2.62")
-    api(group = "org.yaml", name = "snakeyaml", version = "1.25")
-    api(group = "com.moandjiezana.toml", name = "toml4j", version = "0.7.2")
-    api("org.bouncycastle:bcprov-jdk15on:1.64")
-
-    implementation("no.tornado:tornadofx:1.7.19")
-    // classpath is not set correctly by IDE
-}

+ 0 - 218
mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt

@@ -1,218 +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
-
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.Channel
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.console.MiraiConsole.CommandProcessor.processNextCommandLine
-import net.mamoe.mirai.console.command.CommandManager
-import net.mamoe.mirai.console.command.CommandSender
-import net.mamoe.mirai.console.command.ConsoleCommandSender
-import net.mamoe.mirai.console.command.DefaultCommands
-import net.mamoe.mirai.console.plugins.PluginManager
-import net.mamoe.mirai.console.plugins.loadAsConfig
-import net.mamoe.mirai.console.plugins.withDefaultWrite
-import net.mamoe.mirai.console.utils.MiraiConsoleUI
-import net.mamoe.mirai.utils.cryptor.ECDH
-import java.io.File
-
-
-object MiraiConsole {
-    /**
-     * 发布的版本号 统一修改位置
-     */
-    const val version = "0.1.0"
-    const val coreVersion = "v0.18.0"
-    const val build = "Alpha"
-
-
-    /**
-     * 获取从Console登陆上的Bot, Bots
-     * */
-    val bots get() = Bot.instances
-
-    fun getBotByUIN(uin: Long): Bot? {
-        bots.forEach {
-            if (it.get()?.uin == uin) {
-                return it.get()
-            }
-        }
-        return null
-    }
-
-    /**
-     * PluginManager
-     */
-    val pluginManager: PluginManager get() = PluginManager
-
-    /**
-     * 与前端交互所使用的Logger
-     */
-    var logger = UIPushLogger
-
-    /**
-     * Console运行路径
-     */
-    var path: String = System.getProperty("user.dir")
-
-    /**
-     * Console前端接口
-     */
-    lateinit var frontEnd: MiraiConsoleUI
-
-
-    /**
-     * 启动Console
-     */
-    var start = false
-
-    fun start(
-        frontEnd: MiraiConsoleUI
-    ) {
-        if (start) {
-            return
-        }
-        start = true
-
-        /* 加载ECDH */
-        try {
-            ECDH()
-        } catch (ignored: Exception) {
-        }
-        //Security.removeProvider("BC")
-
-
-        /* 初始化前端 */
-        this.frontEnd = frontEnd
-        frontEnd.pushVersion(version, build, coreVersion)
-        logger("Mirai-console [$version $build | core version $coreVersion] is still in testing stage, major features are available")
-        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()
-        HTTPAPIAdaptar()
-        pluginManager.loadPlugins()
-        CommandProcessor.start()
-
-        /* 通知启动完成 */
-        logger("Mirai-console 启动完成")
-        logger("\"/login qqnumber qqpassword \" to login a bot")
-        logger("\"/login qq号 qq密码 \" 来登录一个BOT")
-    }
-
-    fun stop() {
-        PluginManager.disableAllPlugins()
-        try {
-            bots.forEach {
-                it.get()?.close()
-            }
-        } catch (ignored: Exception) {
-
-        }
-    }
-
-
-    object CommandProcessor : Job by {
-        GlobalScope.launch(start = CoroutineStart.LAZY) {
-            processNextCommandLine()
-        }
-    }() {
-
-        internal class FullCommand(
-            val sender: CommandSender,
-            val commandStr: String
-        )
-
-        private val commandChannel: Channel<FullCommand> = Channel()
-
-        suspend fun runConsoleCommand(command: String) {
-            commandChannel.send(
-                FullCommand(ConsoleCommandSender, command)
-            )
-        }
-
-        suspend fun runCommand(sender: CommandSender, command: String) {
-            commandChannel.send(
-                FullCommand(sender, command)
-            )
-        }
-
-        fun runConsoleCommandBlocking(command: String) = runBlocking { runConsoleCommand(command) }
-
-        fun runCommandBlocking(sender: CommandSender, command: String) = runBlocking { runCommand(sender, command) }
-
-        private suspend fun processNextCommandLine() {
-            for (command in commandChannel) {
-                var commandStr = command.commandStr
-                if (!commandStr.startsWith("/")) {
-                    commandStr = "/$commandStr"
-                }
-                if (!CommandManager.runCommand(command.sender, commandStr)) {
-                    command.sender.sendMessage("未知指令 $commandStr")
-                }
-            }
-        }
-    }
-
-    object UIPushLogger {
-        operator fun invoke(any: Any? = null) {
-            invoke(
-                "[Mirai$version $build]",
-                0L,
-                any
-            )
-        }
-
-        operator fun invoke(identityStr: String, identity: Long, any: Any? = null) {
-            if (any != null) {
-                frontEnd.pushLog(identity, "$identityStr: $any")
-            }
-        }
-    }
-
-}
-
-object MiraiProperties {
-    var config = File("${MiraiConsole.path}/mirai.properties").loadAsConfig()
-
-    var HTTP_API_ENABLE: Boolean by config.withDefaultWrite { true }
-    var HTTP_API_PORT: Int by config.withDefaultWrite { 8080 }
-    /*
-    var HTTP_API_AUTH_KEY: String by config.withDefaultWriteSave {
-        "InitKey" + generateSessionKey()
-    }*/
-}
-
-object HTTPAPIAdaptar {
-    operator fun invoke() {
-        /*
-        if (MiraiProperties.HTTP_API_ENABLE) {
-            if (MiraiProperties.HTTP_API_AUTH_KEY.startsWith("InitKey")) {
-                MiraiConsole.logger("请尽快更改初始生成的HTTP API AUTHKEY")
-            }
-            MiraiConsole.logger("正在启动HTTPAPI; 端口=" + MiraiProperties.HTTP_API_PORT)
-            MiraiHttpAPIServer.logger = SimpleLogger("HTTP API") { _, message, e ->
-                MiraiConsole.logger("[Mirai HTTP API]", 0, message)
-            }
-            MiraiHttpAPIServer.start(
-                MiraiProperties.HTTP_API_PORT,
-                MiraiProperties.HTTP_API_AUTH_KEY
-            )
-            MiraiConsole.logger("HTTPAPI启动完成; 端口= " + MiraiProperties.HTTP_API_PORT)
-        }*/
-    }
-}
-
-
-

+ 0 - 242
mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt

@@ -1,242 +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.command
-
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withContext
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.plugins.PluginManager
-import net.mamoe.mirai.contact.Contact
-import net.mamoe.mirai.contact.Group
-import net.mamoe.mirai.contact.sendMessage
-import net.mamoe.mirai.message.GroupMessage
-import net.mamoe.mirai.message.MessageReceipt
-import net.mamoe.mirai.message.data.MessageChain
-import net.mamoe.mirai.message.data.quote
-import net.mamoe.mirai.message.data.toMessage
-import net.mamoe.mirai.utils.MiraiExperimentalAPI
-import java.lang.StringBuilder
-
-object CommandManager {
-    private val registeredCommand: MutableMap<String, Command> = mutableMapOf()
-
-    fun getCommands(): Collection<Command> {
-        return registeredCommand.values
-    }
-
-
-    fun register(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
-        }
-    }
-
-    fun unregister(command: Command) {
-        val allNames = mutableListOf<String>(command.name).also { it.addAll(command.alias) }
-        allNames.forEach {
-            registeredCommand.remove(it)
-        }
-    }
-
-    fun unregister(commandName: String) {
-        registeredCommand.remove(commandName)
-    }
-
-    /*
-    * Index: MiraiConsole
-    * */
-    internal suspend fun runCommand(sender: CommandSender, fullCommand: String): Boolean {
-        val blocks = fullCommand.split(" ")
-        val commandHead = blocks[0].replace("/", "")
-        if (!registeredCommand.containsKey(commandHead)) {
-            return false
-        }
-        val args = blocks.subList(1, blocks.size)
-        registeredCommand[commandHead]?.run {
-            try {
-                if (onCommand(
-                        sender,
-                        blocks.subList(1, blocks.size)
-                    )
-                ) {
-                    PluginManager.onCommand(this, args)
-                } else {
-                    sender.sendMessage(this.usage)
-                }
-            } catch (e: Exception) {
-                sender.sendMessage("在运行指令时出现了未知错误")
-                e.printStackTrace()
-            } finally {
-                (sender as CommandSenderImpl).flushMessage()
-            }
-        }
-        return true
-    }
-
-}
-
-interface CommandSender {
-    /**
-     * 立刻发送一条Message
-     */
-    suspend fun sendMessage(messageChain: MessageChain)
-
-    suspend fun sendMessage(message: String)
-    /**
-     * 写入要发送的内容 所有内容最后会被以一条发出, 不管成功与否
-     */
-    fun appendMessage(message: String)
-
-    fun sendMessageBlocking(messageChain: MessageChain) = runBlocking { sendMessage(messageChain) }
-    fun sendMessageBlocking(message: String) = runBlocking { sendMessage(message) }
-}
-
-abstract class CommandSenderImpl : CommandSender {
-    internal val builder = StringBuilder()
-
-    override fun appendMessage(message: String) {
-        builder.append(message).append("\n")
-    }
-
-    internal open suspend fun flushMessage() {
-        if (!builder.isEmpty()) {
-            sendMessage(builder.toString().removeSuffix("\n"))
-        }
-    }
-}
-
-object ConsoleCommandSender : CommandSenderImpl() {
-    override suspend fun sendMessage(messageChain: MessageChain) {
-        MiraiConsole.logger("[Command]", 0, messageChain.toString())
-    }
-
-    override suspend fun sendMessage(message: String) {
-        MiraiConsole.logger("[Command]", 0, message)
-    }
-
-    override suspend fun flushMessage() {
-        super.flushMessage()
-        builder.clear()
-    }
-}
-
-open class ContactCommandSender(val contact: Contact) : CommandSenderImpl() {
-    override suspend fun sendMessage(messageChain: MessageChain) {
-        contact.sendMessage(messageChain)
-    }
-
-    override suspend fun sendMessage(message: String) {
-        contact.sendMessage(message)
-    }
-}
-
-/**
- * 弃用中
- * */
-class GroupCommandSender(val toQuote: GroupMessage, contact: Contact) : ContactCommandSender(contact) {
-    @MiraiExperimentalAPI
-    override suspend fun sendMessage(message: String) {
-        toQuote.quoteReply(message)
-    }
-
-    @MiraiExperimentalAPI
-    override suspend fun sendMessage(messageChain: MessageChain) {
-        toQuote.quoteReply(messageChain)
-    }
-}
-
-interface Command {
-    val name: String
-    val alias: List<String>
-    val description: String
-    val usage: String
-
-    suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean
-    fun register()
-}
-
-abstract class BlockingCommand(
-    override val name: String,
-    override val alias: List<String> = listOf(),
-    override val description: String = "",
-    override val usage: String = ""
-) : Command {
-    /**
-     * 最高优先级监听器
-     * 如果 return `false` 这次指令不会被 [PluginBase] 的全局 onCommand 监听器监听
-     * */
-    final override suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean {
-        return withContext(Dispatchers.IO) {
-            onCommandBlocking(sender, args)
-        }
-    }
-
-    abstract fun onCommandBlocking(sender: CommandSender, args: List<String>): Boolean
-
-    override fun register() {
-        CommandManager.register(this)
-    }
-}
-
-class AnonymousCommand internal constructor(
-    override val name: String,
-    override val alias: List<String>,
-    override val description: String,
-    override val usage: String = "",
-    val onCommand: suspend CommandSender.(args: List<String>) -> Boolean
-) : Command {
-    override suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean {
-        return onCommand.invoke(sender, args)
-    }
-
-    override fun register() {
-        CommandManager.register(this)
-    }
-}
-
-class CommandBuilder internal constructor() {
-    var name: String? = null
-    var alias: List<String>? = null
-    var description: String = ""
-    var usage: String = "use /help for help"
-    var onCommand: (suspend CommandSender.(args: List<String>) -> Boolean)? = null
-
-    fun onCommand(commandProcess: suspend CommandSender.(args: List<String>) -> Boolean) {
-        onCommand = commandProcess
-    }
-
-    fun register(): Command {
-        if (name == null || onCommand == null) {
-            error("CommandBuilder not complete")
-        }
-        if (alias == null) {
-            alias = listOf()
-        }
-        return AnonymousCommand(
-            name!!,
-            alias!!,
-            description,
-            usage,
-            onCommand!!
-        ).also { it.register() }
-    }
-}
-
-fun registerCommand(builder: CommandBuilder.() -> Unit): Command {
-    return CommandBuilder().apply(builder).register()
-}
-

+ 0 - 265
mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/DefaultCommands.kt

@@ -1,265 +0,0 @@
-package net.mamoe.mirai.console.command
-
-import kotlinx.coroutines.runBlocking
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.plugins.PluginManager
-import net.mamoe.mirai.console.utils.addManager
-import net.mamoe.mirai.console.utils.checkManager
-import net.mamoe.mirai.console.utils.getManagers
-import net.mamoe.mirai.console.utils.removeManager
-import net.mamoe.mirai.contact.sendMessage
-import net.mamoe.mirai.event.subscribeMessages
-import net.mamoe.mirai.message.GroupMessage
-import net.mamoe.mirai.utils.SimpleLogger
-import java.lang.StringBuilder
-import java.util.NoSuchElementException
-
-
-/**
- * Some defaults commands are recommend to be replaced by plugin provided commands
- */
-
-object DefaultCommands {
-    operator fun invoke() {
-        registerCommand {
-            name = "manager"
-            description = "Add a manager"
-            onCommand { it ->
-                if (this !is ConsoleCommandSender) {
-                    sendMessage("请在后台使用该指令")
-                    return@onCommand false
-                }
-                if (it.size < 2) {
-                    MiraiConsole.logger("[Bot Manager]", 0, "/manager add [bot ID] [Manager ID]")
-                    MiraiConsole.logger("[Bot Manager]", 0, "/manager remove [bot ID] [Manager ID]")
-                    MiraiConsole.logger("[Bot Manager]", 0, "/manager list [bot ID]")
-                    return@onCommand true
-                }
-                val botId = try {
-                    it[1].toLong()
-                } catch (e: Exception) {
-                    MiraiConsole.logger("[Bot Manager]", 0, it[1] + " 不是一个Bot的ID")
-                    return@onCommand false
-                }
-                val bot = MiraiConsole.getBotByUIN(botId)
-                if (bot == null) {
-                    MiraiConsole.logger("[Bot Manager]", 0, "$botId 没有在Console中登陆")
-                    return@onCommand false
-                }
-                when (it[0]) {
-                    "add" -> {
-                        if (it.size < 3) {
-                            MiraiConsole.logger("[Bot Manager]", 0, "/manager add [bot ID] [Manager ID]")
-                            return@onCommand true
-                        }
-                        val adminID = try {
-                            it[2].toLong()
-                        } catch (e: Exception) {
-                            MiraiConsole.logger("[Bot Manager]", 0, it[2] + " 不是一个ID")
-                            return@onCommand false
-                        }
-                        bot.addManager(adminID)
-                        MiraiConsole.logger("[Bot Manager]", 0, it[2] + "增加成功")
-                    }
-                    "remove" -> {
-                        if (it.size < 3) {
-                            MiraiConsole.logger("[Bot Manager]", 0, "/manager remove [bot ID] [Manager ID]")
-                            return@onCommand true
-                        }
-                        val adminID = try {
-                            it[2].toLong()
-                        } catch (e: Exception) {
-                            MiraiConsole.logger("[Bot Manager]", 0, it[1] + " 不是一个ID")
-                            return@onCommand false
-                        }
-                        if (!bot.checkManager(adminID)) {
-                            MiraiConsole.logger("[Bot Manager]", 0, it[2] + "本身不是一个Manager")
-                            return@onCommand true
-                        }
-                        bot.removeManager(adminID)
-                        MiraiConsole.logger("[Bot Manager]", 0, it[2] + "移除成功")
-                    }
-                    "list" -> {
-                        bot.getManagers().forEach {
-                            MiraiConsole.logger("[Bot Manager]", 0, " -> $it")
-                        }
-                    }
-                }
-                return@onCommand true
-            }
-        }
-
-        registerCommand {
-            name = "login"
-            description = "机器人登陆"
-            onCommand {
-                if (this !is ConsoleCommandSender) {
-                    sendMessage("请在后台使用该指令")
-                    return@onCommand false
-                }
-                if (it.size < 2) {
-                    MiraiConsole.logger("\"/login qqnumber qqpassword \" to login a bot")
-                    MiraiConsole.logger("\"/login qq号 qq密码 \" 来登录一个BOT")
-                    return@onCommand false
-                }
-                val qqNumber = it[0].toLong()
-                val qqPassword = it[1]
-                MiraiConsole.logger("[Bot Login]", 0, "login...")
-                try {
-                    MiraiConsole.frontEnd.prePushBot(qqNumber)
-                    val bot = Bot(qqNumber, qqPassword) {
-                        this.loginSolver = MiraiConsole.frontEnd.createLoginSolver()
-                        this.botLoggerSupplier = {
-                            SimpleLogger("BOT $qqNumber]") { _, message, e ->
-                                MiraiConsole.logger("[BOT $qqNumber]", qqNumber, message)
-                                if (e != null) {
-                                    MiraiConsole.logger("[NETWORK ERROR]", qqNumber, e.toString())//因为在一页 所以可以不打QQ
-                                    e.printStackTrace()
-                                }
-                            }
-                        }
-                        this.networkLoggerSupplier = {
-                            SimpleLogger("BOT $qqNumber") { _, message, e ->
-                                MiraiConsole.logger("[NETWORK]", qqNumber, message)//因为在一页 所以可以不打QQ
-                                if (e != null) {
-                                    MiraiConsole.logger("[NETWORK ERROR]", qqNumber, e.toString())//因为在一页 所以可以不打QQ
-                                    e.printStackTrace()
-                                }
-                            }
-                        }
-                    }
-                    bot.login()
-                    bot.subscribeMessages {
-                        this.startsWith("/") {
-                            if (bot.checkManager(this.sender.id)) {
-                                val sender = ContactCommandSender(this.subject)
-                                MiraiConsole.CommandProcessor.runCommand(
-                                    sender, it
-                                )
-                            }
-                        }
-                    }
-                    sendMessage("$qqNumber login successes")
-                    MiraiConsole.frontEnd.pushBot(bot)
-                } catch (e: Exception) {
-                    sendMessage("$qqNumber login failed -> " + e.message)
-                }
-                true
-            }
-        }
-
-        registerCommand {
-            name = "status"
-            description = "获取状态"
-            onCommand {
-                when (it.size) {
-                    0 -> {
-                        sendMessage("当前有" + MiraiConsole.bots.size + "个BOT在线")
-                    }
-                    1 -> {
-                        val bot = it[0]
-                        var find = false
-                        MiraiConsole.bots.forEach {
-                            if (it.get()?.uin.toString().contains(bot)) {
-                                find = true
-                                appendMessage("" + it.get()?.uin + ": 在线中; 好友数量:" + it.get()?.qqs?.size + "; 群组数量:" + it.get()?.groups?.size)
-                            }
-                        }
-                        if (!find) {
-                            sendMessage("没有找到BOT$bot")
-                        }
-                    }
-                }
-                true
-            }
-        }
-
-
-        registerCommand {
-            name = "say"
-            description = "聊天功能演示"
-            onCommand {
-                if (it.size < 2) {
-                    MiraiConsole.logger("say [好友qq号或者群号] [文本消息]     //将默认使用第一个BOT")
-                    MiraiConsole.logger("say [bot号] [好友qq号或者群号] [文本消息]")
-                    return@onCommand false
-                }
-                val bot: Bot? = if (it.size == 2) {
-                    if (MiraiConsole.bots.size == 0) {
-                        MiraiConsole.logger("还没有BOT登录")
-                        return@onCommand false
-                    }
-                    MiraiConsole.bots[0].get()
-                } else {
-                    MiraiConsole.getBotByUIN(it[0].toLong())
-                }
-                if (bot == null) {
-                    MiraiConsole.logger("没有找到BOT")
-                    return@onCommand false
-                }
-                val target = it[it.size - 2].toLong()
-                val message = it[it.size - 1]
-                try {
-                    val contact = bot[target]
-                    runBlocking {
-                        contact.sendMessage(message)
-                        MiraiConsole.logger("消息已推送")
-                    }
-                } catch (e: NoSuchElementException) {
-                    MiraiConsole.logger("没有找到群或好友 号码为${target}")
-                    return@onCommand false
-                }
-                true
-            }
-        }
-
-
-        registerCommand {
-            name = "plugins"
-            alias = listOf("plugin")
-            description = "获取插件列表"
-            onCommand {
-                PluginManager.getAllPluginDescriptions().let {
-                    it.forEach {
-                        appendMessage("\t" + it.name + " v" + it.version + " by" + it.author + " " + it.info)
-                    }
-                    appendMessage("加载了" + it.size + "个插件")
-                    true
-                }
-            }
-        }
-
-        registerCommand {
-            name = "command"
-            alias = listOf("commands", "help", "helps")
-            description = "获取指令列表"
-            onCommand {
-                CommandManager.getCommands().let {
-                    var size = 0
-                    appendMessage("")//\n
-                    it.toSet().forEach {
-                        ++size
-                        appendMessage("-> " + it.name + " :" + it.description)
-                    }
-                    appendMessage("""共有${size}条指令""")
-                }
-                true
-            }
-        }
-
-        registerCommand {
-            name = "about"
-            description = "About Mirai-Console"
-            onCommand {
-                appendMessage("v${MiraiConsole.version} ${MiraiConsole.build} is still in testing stage, major features are available")
-                appendMessage("now running under ${MiraiConsole.path}")
-                appendMessage("在Github中获取项目最新进展: https://github.com/mamoe/mirai")
-                appendMessage("Mirai为开源项目,请自觉遵守开源项目协议")
-                appendMessage("Powered by Mamoe Technologies and contributors")
-                true
-            }
-        }
-
-    }
-}

+ 0 - 525
mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSection.kt

@@ -1,525 +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.plugins
-
-import com.alibaba.fastjson.JSON
-import com.alibaba.fastjson.JSONObject
-import com.alibaba.fastjson.TypeReference
-import com.alibaba.fastjson.parser.Feature
-import com.moandjiezana.toml.Toml
-import com.moandjiezana.toml.TomlWriter
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UnstableDefault
-import net.mamoe.mirai.utils.io.encodeToString
-import org.yaml.snakeyaml.Yaml
-import tornadofx.c
-import java.io.File
-import java.io.InputStream
-import java.util.*
-import java.util.concurrent.ConcurrentHashMap
-import kotlin.collections.LinkedHashMap
-import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KClass
-import kotlin.reflect.KProperty
-import kotlin.reflect.full.isSubclassOf
-
-
-/**
- * TODO: support all config types
- * only JSON is now supported
- *
- */
-
-interface Config {
-    fun getConfigSection(key: String): ConfigSection
-    fun getString(key: String): String
-    fun getInt(key: String): Int
-    fun getFloat(key: String): Float
-    fun getDouble(key: String): Double
-    fun getLong(key: String): Long
-    fun getBoolean(key: String): Boolean
-    fun getList(key: String): List<*>
-    fun getStringList(key: String): List<String>
-    fun getIntList(key: String): List<Int>
-    fun getFloatList(key: String): List<Float>
-    fun getDoubleList(key: String): List<Double>
-    fun getLongList(key: String): List<Long>
-    fun getConfigSectionList(key: String): List<ConfigSection>
-    operator fun set(key: String, value: Any)
-    operator fun get(key: String): Any?
-    operator fun contains(key: String): Boolean
-    fun exist(key: String): Boolean
-    fun setIfAbsent(key: String, value: Any)
-    fun asMap(): Map<String, Any>
-    fun save()
-
-    companion object {
-        fun load(fileName: String): Config {
-            return load(
-                File(
-                    fileName.replace(
-                        "//",
-                        "/"
-                    )
-                )
-            )
-        }
-
-        /**
-         * create a read-write config
-         * */
-        fun load(file: File): Config {
-            if (!file.exists()) {
-                file.createNewFile()
-            }
-            return when (file.extension.toLowerCase()) {
-                "json" -> JsonConfig(file)
-                "yml" -> YamlConfig(file)
-                "yaml" -> YamlConfig(file)
-                "mirai" -> YamlConfig(file)
-                "ini" -> TomlConfig(file)
-                "toml" -> TomlConfig(file)
-                "properties" -> TomlConfig(file)
-                "property" -> TomlConfig(file)
-                "data" -> TomlConfig(file)
-                else -> error("Unsupported file config type ${file.extension.toLowerCase()}")
-            }
-        }
-
-        /**
-         * create a read-only config
-         */
-        fun load(content: String, type: String): Config {
-            return when (type.toLowerCase()) {
-                "json" -> JsonConfig(content)
-                "yml" -> YamlConfig(content)
-                "yaml" -> YamlConfig(content)
-                "mirai" -> YamlConfig(content)
-                "ini" -> TomlConfig(content)
-                "toml" -> TomlConfig(content)
-                "properties" -> TomlConfig(content)
-                "property" -> TomlConfig(content)
-                "data" -> TomlConfig(content)
-                else -> error("Unsupported file config type $content")
-            }
-        }
-
-        /**
-         * create a read-only config
-         */
-        fun load(inputStream: InputStream, type: String): Config {
-            return load(inputStream.readBytes().encodeToString(), type)
-        }
-
-    }
-}
-
-
-fun File.loadAsConfig(): Config {
-    return Config.load(this)
-}
-
-/* 最简单的代理 */
-inline operator fun <reified T : Any> Config.getValue(thisRef: Any?, property: KProperty<*>): T {
-    return smartCast(property)
-}
-
-inline operator fun <reified T : Any> Config.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
-    this[property.name] = value
-}
-
-/* 带有默认值的代理 */
-inline fun <reified T : Any> Config.withDefault(
-    noinline defaultValue: () -> T
-): ReadWriteProperty<Any, T> {
-    val default by lazy { defaultValue.invoke() }
-    return object : ReadWriteProperty<Any, T> {
-        override fun getValue(thisRef: Any, property: KProperty<*>): T {
-            if ([email protected](property.name)) {//unsafe
-                return [email protected](property)
-            }
-            return default
-        }
-
-        override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
-            this@withDefault[property.name] = value
-        }
-    }
-}
-
-/* 带有默认值且如果为空会写入的代理 */
-inline fun <reified T : Any> Config.withDefaultWrite(
-    noinline defaultValue: () -> T
-): WithDefaultWriteLoader<T> {
-    return WithDefaultWriteLoader(
-        T::class,
-        this,
-        defaultValue,
-        false
-    )
-}
-
-/* 带有默认值且如果为空会写入保存的代理 */
-inline fun <reified T : Any> Config.withDefaultWriteSave(
-    noinline defaultValue: () -> T
-): WithDefaultWriteLoader<T> {
-    return WithDefaultWriteLoader(T::class, this, defaultValue, true)
-}
-
-class WithDefaultWriteLoader<T : Any>(
-    private val _class: KClass<T>,
-    private val config: Config,
-    private val defaultValue: () -> T,
-    private val save: Boolean
-) {
-    operator fun provideDelegate(
-        thisRef: Any,
-        prop: KProperty<*>
-    ): ReadWriteProperty<Any, T> {
-        val defaultValue by lazy { defaultValue.invoke() }
-        if (!config.contains(prop.name)) {
-            config[prop.name] = defaultValue
-            if (save) {
-                config.save()
-            }
-        }
-        return object : ReadWriteProperty<Any, T> {
-            override fun getValue(thisRef: Any, property: KProperty<*>): T {
-                if (config.exist(property.name)) {//unsafe
-                    return config._smartCast(property.name, _class)
-                }
-                return defaultValue
-            }
-
-            override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
-                config[property.name] = value
-            }
-        }
-    }
-}
-
-inline fun <reified T : Any> Config.smartCast(property: KProperty<*>): T {
-    return _smartCast(property.name, T::class)
-}
-
-@Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
-fun <T : Any> Config._smartCast(propertyName: String, _class: KClass<T>): T {
-    return when (_class) {
-        String::class -> this.getString(propertyName)
-        Int::class -> this.getInt(propertyName)
-        Float::class -> this.getFloat(propertyName)
-        Double::class -> this.getDouble(propertyName)
-        Long::class -> this.getLong(propertyName)
-        Boolean::class -> this.getBoolean(propertyName)
-        else -> when {
-            _class.isSubclassOf(ConfigSection::class) -> this.getConfigSection(propertyName)
-            _class == List::class || _class == MutableList::class -> {
-                val list = this.getList(propertyName)
-                return if (list.isEmpty()) {
-                    list
-                } else {
-                    when (list[0]!!::class) {
-                        String::class -> getStringList(propertyName)
-                        Int::class -> getIntList(propertyName)
-                        Float::class -> getFloatList(propertyName)
-                        Double::class -> getDoubleList(propertyName)
-                        Long::class -> getLongList(propertyName)
-                        //不去支持getConfigSectionList(propertyName)
-                        // LinkedHashMap::class -> getConfigSectionList(propertyName)//faster approach
-                        else -> {
-                            //if(list[0]!! is ConfigSection || list[0]!! is Map<*,*>){
-                            // getConfigSectionList(propertyName)
-                            //}else {
-                            error("unsupported type" + list[0]!!::class)
-                            //}
-                        }
-                    }
-                } as T
-            }
-            else -> {
-                error("unsupported type")
-            }
-        }
-    } as T
-}
-
-
-interface ConfigSection : Config, MutableMap<String, Any> {
-    override fun getConfigSection(key: String): ConfigSection {
-        val content = get(key) ?: error("ConfigSection does not contain $key ")
-        if (content is ConfigSection) {
-            return content
-        }
-        return ConfigSectionDelegation(
-            Collections.synchronizedMap(
-                (get(key) ?: error("ConfigSection does not contain $key ")) as LinkedHashMap<String, Any>
-            )
-        )
-    }
-
-    override fun getString(key: String): String {
-        return (get(key) ?: error("ConfigSection does not contain $key ")).toString()
-    }
-
-    override fun getInt(key: String): Int {
-        return (get(key) ?: error("ConfigSection does not contain $key ")).toString().toInt()
-    }
-
-    override fun getFloat(key: String): Float {
-        return (get(key) ?: error("ConfigSection does not contain $key ")).toString().toFloat()
-    }
-
-    override fun getBoolean(key: String): Boolean {
-        return (get(key) ?: error("ConfigSection does not contain $key ")).toString().toBoolean()
-    }
-
-    override fun getDouble(key: String): Double {
-        return (get(key) ?: error("ConfigSection does not contain $key ")).toString().toDouble()
-    }
-
-    override fun getLong(key: String): Long {
-        return (get(key) ?: error("ConfigSection does not contain $key ")).toString().toLong()
-    }
-
-    override fun getList(key: String): List<*> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>)
-    }
-
-    override fun getStringList(key: String): List<String> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString() }
-    }
-
-    override fun getIntList(key: String): List<Int> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toInt() }
-    }
-
-    override fun getFloatList(key: String): List<Float> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toFloat() }
-    }
-
-    override fun getDoubleList(key: String): List<Double> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toDouble() }
-    }
-
-    override fun getLongList(key: String): List<Long> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map { it.toString().toLong() }
-    }
-
-    override fun getConfigSectionList(key: String): List<ConfigSection> {
-        return ((get(key) ?: error("ConfigSection does not contain $key ")) as List<*>).map {
-            if (it is ConfigSection) {
-                it
-            } else {
-                ConfigSectionDelegation(
-                    Collections.synchronizedMap(
-                        it as MutableMap<String, Any>
-                    )
-                )
-            }
-        }
-    }
-
-    override fun exist(key: String): Boolean {
-        return get(key) != null
-    }
-
-    override fun setIfAbsent(key: String, value: Any) {
-        if (!exist(key)) set(key, value)
-    }
-}
-
-@Serializable
-open class ConfigSectionImpl() : ConcurrentHashMap<String, Any>(),
-    ConfigSection {
-    override fun set(key: String, value: Any) {
-        super.put(key, value)
-    }
-
-    override operator fun get(key: String): Any? {
-        return super.get(key)
-    }
-
-    @Suppress("RedundantOverride")
-    override fun contains(key: String): Boolean {
-        return super.contains(key)
-    }
-
-    override fun exist(key: String): Boolean {
-        return containsKey(key)
-    }
-
-    override fun asMap(): Map<String, Any> {
-        return this
-    }
-
-    override fun save() {
-
-    }
-
-    override fun setIfAbsent(key: String, value: Any) {
-        this.putIfAbsent(key, value)//atomic
-    }
-}
-
-open class ConfigSectionDelegation(
-    private val delegate: MutableMap<String, Any>
-) : ConfigSection, MutableMap<String, Any> by delegate {
-    override fun set(key: String, value: Any) {
-        delegate.put(key, value)
-    }
-
-    override fun contains(key: String): Boolean {
-        return delegate.containsKey(key)
-    }
-
-    override fun asMap(): Map<String, Any> {
-        return delegate
-    }
-
-    override fun save() {
-
-    }
-}
-
-
-interface FileConfig : Config {
-    fun deserialize(content: String): ConfigSection
-
-    fun serialize(config: ConfigSection): String
-}
-
-
-abstract class FileConfigImpl internal constructor(
-    private val rawContent: String
-) : FileConfig,
-    ConfigSection {
-
-    internal var file: File? = null
-
-
-    constructor(file: File) : this(file.readText()) {
-        this.file = file
-    }
-
-
-    private val content by lazy {
-        deserialize(rawContent)
-    }
-
-
-    override val size: Int get() = content.size
-    override val entries: MutableSet<MutableMap.MutableEntry<String, Any>> get() = content.entries
-    override val keys: MutableSet<String> get() = content.keys
-    override val values: MutableCollection<Any> get() = content.values
-    override fun containsKey(key: String): Boolean = content.containsKey(key)
-    override fun containsValue(value: Any): Boolean = content.containsValue(value)
-    override fun put(key: String, value: Any): Any? = content.put(key, value)
-    override fun isEmpty(): Boolean = content.isEmpty()
-    override fun putAll(from: Map<out String, Any>) = content.putAll(from)
-    override fun clear() = content.clear()
-    override fun remove(key: String): Any? = content.remove(key)
-
-    override fun save() {
-        if (isReadOnly()) {
-            error("Config is readonly")
-        }
-        if (!((file?.exists())!!)) {
-            file?.createNewFile()
-        }
-        file?.writeText(serialize(content))
-    }
-
-    fun isReadOnly() = file == null
-
-    override fun contains(key: String): Boolean {
-        return content.contains(key)
-    }
-
-    override fun get(key: String): Any? {
-        return content[key]
-    }
-
-    override fun set(key: String, value: Any) {
-        content[key] = value
-    }
-
-    override fun asMap(): Map<String, Any> {
-        return content.asMap()
-    }
-
-}
-
-class JsonConfig internal constructor(
-    content: String
-) : FileConfigImpl(content) {
-    constructor(file: File) : this(file.readText()) {
-        this.file = file
-    }
-
-    @UnstableDefault
-    override fun deserialize(content: String): ConfigSection {
-        if (content.isEmpty() || content.isBlank() || content == "{}") {
-            return ConfigSectionImpl()
-        }
-        return JSON.parseObject<ConfigSectionImpl>(
-            content,
-            object : TypeReference<ConfigSectionImpl>() {},
-            Feature.OrderedField
-        )
-    }
-
-    @UnstableDefault
-    override fun serialize(config: ConfigSection): String {
-        return JSONObject.toJSONString(config)
-    }
-}
-
-class YamlConfig internal constructor(content: String) : FileConfigImpl(content) {
-    constructor(file: File) : this(file.readText()) {
-        this.file = file
-    }
-
-    override fun deserialize(content: String): ConfigSection {
-        if (content.isEmpty() || content.isBlank()) {
-            return ConfigSectionImpl()
-        }
-        return ConfigSectionDelegation(
-            Collections.synchronizedMap(
-                Yaml().load<LinkedHashMap<String, Any>>(content) as LinkedHashMap<String, Any>
-            )
-        )
-    }
-
-    override fun serialize(config: ConfigSection): String {
-        return Yaml().dumpAsMap(config)
-    }
-
-}
-
-class TomlConfig internal constructor(content: String) : FileConfigImpl(content) {
-    constructor(file: File) : this(file.readText()) {
-        this.file = file
-    }
-
-    override fun deserialize(content: String): ConfigSection {
-        if (content.isEmpty() || content.isBlank()) {
-            return ConfigSectionImpl()
-        }
-        return ConfigSectionDelegation(
-            Collections.synchronizedMap(
-                Toml().read(content).toMap()
-            )
-        )
-    }
-
-    override fun serialize(config: ConfigSection): String {
-        return TomlWriter().write(config)
-    }
-}

+ 0 - 410
mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt

@@ -1,410 +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.plugins
-
-import kotlinx.coroutines.*
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.command.Command
-import net.mamoe.mirai.utils.DefaultLogger
-import net.mamoe.mirai.utils.MiraiLogger
-import net.mamoe.mirai.utils.SimpleLogger
-import net.mamoe.mirai.utils.io.encodeToString
-import java.io.File
-import java.io.InputStream
-import java.net.URL
-import java.net.URLClassLoader
-import java.util.jar.JarFile
-import kotlin.coroutines.CoroutineContext
-import kotlin.coroutines.EmptyCoroutineContext
-
-
-abstract class PluginBase(coroutineContext: CoroutineContext) : CoroutineScope {
-    constructor() : this(EmptyCoroutineContext)
-
-    private val supervisorJob = SupervisorJob()
-    final override val coroutineContext: CoroutineContext = coroutineContext + supervisorJob
-
-    /**
-     * 插件被分配的data folder, 如果插件改名了 data folder 也会变 请注意
-     */
-    val dataFolder: File by lazy {
-        File(PluginManager.pluginsPath + pluginDescription.name).also { it.mkdir() }
-    }
-
-    /**
-     * 当一个插件被加载时调用
-     */
-    open fun onLoad() {
-
-    }
-
-    /**
-     * 当所有插件全部被加载后被调用
-     */
-    open fun onEnable() {
-
-    }
-
-    /**
-     * 当插件关闭前被调用
-     */
-    open fun onDisable() {
-
-    }
-
-    /**
-     * 当任意指令被使用
-     */
-    open fun onCommand(command: Command, args: List<String>) {
-
-    }
-
-
-    internal fun enable() {
-        this.onEnable()
-    }
-
-    /**
-     * 加载一个data folder中的Config
-     * 这个config是read-write的
-     */
-    fun loadConfig(fileName: String): Config {
-        return Config.load(dataFolder.absolutePath + fileName)
-    }
-
-    @JvmOverloads
-    internal fun disable(throwable: CancellationException? = null) {
-        this.coroutineContext[Job]!!.cancelChildren(throwable)
-        this.onDisable()
-    }
-
-    private lateinit var pluginDescription: PluginDescription
-
-    internal fun init(pluginDescription: PluginDescription) {
-        this.pluginDescription = pluginDescription
-        this.onLoad()
-    }
-
-    val pluginManager = PluginManager
-
-    val logger: MiraiLogger by lazy {
-        SimpleLogger("Plugin ${pluginDescription.name}") { _, message, e ->
-            MiraiConsole.logger("[${pluginDescription.name}]", 0, message)
-            if (e != null) {
-                MiraiConsole.logger("[${pluginDescription.name}]", 0, e.toString())
-                e.printStackTrace()
-            }
-        }
-    }
-
-    /**
-     * 加载一个插件jar, resources中的东西
-     */
-    fun getResources(fileName: String): InputStream? {
-        return try {
-            this.javaClass.classLoader.getResourceAsStream(fileName)
-        } catch (e: Exception) {
-            PluginManager.getFileInJarByName(
-                this.pluginDescription.name,
-                fileName
-            )
-        }
-    }
-
-    /**
-     * 加载一个插件jar, resources中的Config
-     * 这个Config是read-only的
-     */
-    fun getResourcesConfig(fileName: String): Config {
-        if (fileName.contains(".")) {
-            error("Unknown Config Type")
-        }
-        return Config.load(getResources(fileName) ?: error("Config Not Found"), fileName.split(".")[1])
-    }
-
-}
-
-class PluginDescription(
-    val name: String,
-    val author: String,
-    val basePath: String,
-    val version: String,
-    val info: String,
-    val depends: List<String>,//插件的依赖
-    internal var loaded: Boolean = false,
-    internal var noCircularDepend: Boolean = true
-) {
-
-    override fun toString(): String {
-        return "name: $name\nauthor: $author\npath: $basePath\nver: $version\ninfo: $info\ndepends: $depends"
-    }
-
-    companion object {
-        fun readFromContent(content_: String): PluginDescription {
-            val content = content_.split("\n")
-
-            var name = "Plugin"
-            var author = "Unknown"
-            var basePath = "net.mamoe.mirai.PluginMain"
-            var info = "Unknown"
-            var version = "1.0.0"
-            val depends = mutableListOf<String>();
-
-            content.forEach {
-                val line = it.trim()
-                val lowercaseLine = line.toLowerCase()
-                if (it.contains(":")) {
-                    when {
-                        lowercaseLine.startsWith("name") -> {
-                            name = line.substringAfter(":").trim()
-                        }
-                        lowercaseLine.startsWith("author") -> {
-                            author = line.substringAfter(":").trim()
-                        }
-                        lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> {
-                            info = line.substringAfter(":").trim()
-                        }
-                        lowercaseLine.startsWith("main") || lowercaseLine.startsWith("path") || lowercaseLine.startsWith(
-                            "basepath"
-                        ) -> {
-                            basePath = line.substringAfter(":").trim()
-                        }
-                        lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> {
-                            version = line.substringAfter(":").trim()
-                        }
-                    }
-                } else if (line.startsWith("-")) {
-                    depends.add(line.substringAfter("-").trim())
-                }
-            }
-            return PluginDescription(
-                name,
-                author,
-                basePath,
-                version,
-                info,
-                depends
-            )
-        }
-    }
-}
-
-internal class PluginClassLoader(file: File, parent: ClassLoader) : URLClassLoader(arrayOf(file.toURI().toURL()), parent)
-
-object PluginManager {
-    internal val pluginsPath = System.getProperty("user.dir") + "/plugins/".replace("//", "/").also {
-        File(it).mkdirs()
-    }
-
-    val logger = SimpleLogger("Plugin Manager") { _, message, e ->
-        MiraiConsole.logger("[Plugin Manager]", 0, message)
-    }
-
-    //已完成加载的
-    private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf()
-    private val pluginDescriptions: MutableMap<String, PluginDescription> = mutableMapOf()
-
-    fun onCommand(command: Command, args: List<String>) {
-        nameToPluginBaseMap.values.forEach {
-            it.onCommand(command, args)
-        }
-    }
-
-    fun getAllPluginDescriptions(): Collection<PluginDescription> {
-        return pluginDescriptions.values
-    }
-
-    /**
-     * 尝试加载全部插件
-     */
-    fun loadPlugins() {
-        val pluginsFound: MutableMap<String, PluginDescription> = mutableMapOf()
-        val pluginsLocation: MutableMap<String, File> = mutableMapOf()
-
-        logger.info("""开始加载${pluginsPath}下的插件""")
-
-        File(pluginsPath).listFiles()?.forEach { file ->
-            if (file != null && file.extension == "jar") {
-                val jar = JarFile(file)
-                val pluginYml =
-                    jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
-                if (pluginYml == null) {
-                    logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin")
-                } else {
-                    val description =
-                        PluginDescription.readFromContent(
-                            URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.use {
-                                it.readBytes().encodeToString()
-                            })
-                    pluginsFound[description.name] = description
-                    pluginsLocation[description.name] = file
-                }
-            }
-        }
-
-        fun checkNoCircularDepends(
-            target: PluginDescription,
-            needDepends: List<String>,
-            existDepends: MutableList<String>
-        ) {
-
-            if (!target.noCircularDepend) {
-                return
-            }
-
-            existDepends.add(target.name)
-
-            if (needDepends.any { existDepends.contains(it) }) {
-                target.noCircularDepend = false
-            }
-
-            existDepends.addAll(needDepends)
-
-            needDepends.forEach {
-                if (pluginsFound.containsKey(it)) {
-                    checkNoCircularDepends(pluginsFound[it]!!, pluginsFound[it]!!.depends, existDepends)
-                }
-            }
-        }
-
-
-        pluginsFound.values.forEach {
-            checkNoCircularDepends(it, it.depends, mutableListOf())
-        }
-
-        //load
-
-
-        fun loadPlugin(description: PluginDescription): Boolean {
-            if (!description.noCircularDepend) {
-                logger.error("Failed to load plugin " + description.name + " because it has circular dependency")
-                return false
-            }
-
-            //load depends first
-            description.depends.forEach { dependent ->
-                if (!pluginsFound.containsKey(dependent)) {
-                    logger.error("Failed to load plugin " + description.name + " because it need " + dependent + " as dependency")
-                    return false
-                }
-                val depend = pluginsFound[dependent]!!
-                //还没有加载
-                if (!depend.loaded && !loadPlugin(pluginsFound[dependent]!!)) {
-                    logger.error("Failed to load plugin " + description.name + " because " + dependent + " as dependency failed to load")
-                    return false
-                }
-            }
-            //在这里所有的depends都已经加载了
-
-
-            //real load
-            logger.info("loading plugin " + description.name)
-
-            try {
-                val pluginClass = try {
-                    PluginClassLoader(
-                        (pluginsLocation[description.name]!!),
-                        this.javaClass.classLoader
-                    )
-                        .loadClass(description.basePath)
-                } catch (e: ClassNotFoundException) {
-                    logger.info("failed to find Main: " + description.basePath + " checking if it's kotlin's path")
-                    PluginClassLoader(
-                        (pluginsLocation[description.name]!!),
-                        this.javaClass.classLoader
-                    )
-                        .loadClass("${description.basePath}Kt")
-                }
-                return try {
-                    val subClass = pluginClass.asSubclass(PluginBase::class.java)
-                    val plugin: PluginBase = subClass.kotlin.objectInstance ?: subClass.getDeclaredConstructor().newInstance()
-                    description.loaded = true
-                    logger.info("successfully loaded plugin " + description.name + " version " + description.version + " by " + description.author)
-                    logger.info(description.info)
-
-                    nameToPluginBaseMap[description.name] = plugin
-                    pluginDescriptions[description.name] = description
-                    plugin.init(description)
-                    true
-                } catch (e: ClassCastException) {
-                    logger.error("failed to load plugin " + description.name + " , Main class does not extends PluginBase ")
-                    false
-                }
-            } catch (e: ClassNotFoundException) {
-                e.printStackTrace()
-                logger.error("failed to load plugin " + description.name + " , Main class not found under " + description.basePath)
-                return false
-            }
-        }
-
-        pluginsFound.values.forEach {
-            loadPlugin(it)
-        }
-
-        nameToPluginBaseMap.values.forEach {
-            it.enable()
-        }
-
-        logger.info("""加载了${nameToPluginBaseMap.size}个插件""")
-
-    }
-
-
-    @JvmOverloads
-    fun disableAllPlugins(throwable: CancellationException? = null) {
-        nameToPluginBaseMap.values.forEach {
-            it.disable(throwable)
-        }
-    }
-
-    /**
-     * 根据插件名字找Jar的文件
-     * null => 没找到
-     */
-    fun getJarPath(pluginName: String): File? {
-        File(pluginsPath).listFiles()?.forEach { file ->
-            if (file != null && file.extension == "jar") {
-                val jar = JarFile(file)
-                val pluginYml =
-                    jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
-                if (pluginYml != null) {
-                    val description =
-                        PluginDescription.readFromContent(
-                            URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.use {
-                                it.readBytes().encodeToString()
-                            })
-                    if (description.name.toLowerCase() == pluginName.toLowerCase()) {
-                        return file
-                    }
-                }
-            }
-        }
-        return null
-    }
-
-
-    /**
-     * 根据插件名字找Jar中的文件
-     * null => 没找到
-     */
-    fun getFileInJarByName(pluginName: String, toFind: String): InputStream? {
-        val jarFile = getJarPath(pluginName)
-        if (jarFile == null) {
-            return null
-        }
-        val jar = JarFile(jarFile)
-        val toFindFile =
-            jar.entries().asSequence().filter { it.name == toFind }.firstOrNull() ?: return null
-        return URL("jar:file:" + jarFile.absoluteFile + "!/" + toFindFile.name).openConnection().inputStream
-    }
-}
-
-
-

+ 0 - 16
mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt

@@ -1,16 +0,0 @@
-package net.mamoe.mirai.console.pure
-
-import net.mamoe.mirai.console.MiraiConsole
-import kotlin.concurrent.thread
-
-class MiraiConsolePureLoader {
-    companion object {
-        @JvmStatic
-        fun main(args: Array<String>) {
-            MiraiConsole.start(MiraiConsoleUIPure())
-            Runtime.getRuntime().addShutdownHook(thread(start = false) {
-                MiraiConsole.stop()
-            })
-        }
-    }
-}

+ 0 - 81
mirai-console/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleUIPure.kt

@@ -1,81 +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 kotlinx.coroutines.delay
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.utils.MiraiConsoleUI
-import net.mamoe.mirai.utils.DefaultLoginSolver
-import net.mamoe.mirai.utils.LoginSolver
-import net.mamoe.mirai.utils.LoginSolverInputReader
-import kotlin.concurrent.thread
-
-class MiraiConsoleUIPure : MiraiConsoleUI {
-    var requesting = false
-    var requestStr = ""
-
-    init {
-        thread {
-            while (true) {
-                val input = readLine() ?: return@thread
-                if (requesting) {
-                    requestStr = input
-                    requesting = false
-                } else {
-                    MiraiConsole.CommandProcessor.runConsoleCommandBlocking(input)
-                }
-            }
-        }
-    }
-
-    override fun pushLog(identity: Long, message: String) {
-        println(message)
-    }
-
-    override fun prePushBot(identity: Long) {
-
-    }
-
-    override fun pushBot(bot: Bot) {
-
-    }
-
-    override fun pushVersion(consoleVersion: String, consoleBuild: String, coreVersion: String) {
-
-    }
-
-    override suspend fun requestInput(question: String): String {
-        requesting = true
-        while (true) {
-            delay(50)
-            if (!requesting) {
-                return requestStr
-            }
-        }
-    }
-
-    override fun pushBotAdminStatus(identity: Long, admins: List<Long>) {
-
-    }
-
-    override fun createLoginSolver(): LoginSolver {
-        return DefaultLoginSolver(
-            reader = object : LoginSolverInputReader {
-                override suspend fun read(question: String): String? {
-                    return requestInput(question)
-                }
-            }
-        )
-    }
-
-}
-
-

+ 0 - 41
mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/BotHelper.kt

@@ -1,41 +0,0 @@
-package net.mamoe.mirai.console.utils
-
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.console.MiraiConsole
-import net.mamoe.mirai.console.MiraiProperties
-import net.mamoe.mirai.console.utils.BotManagers.BOT_MANAGERS
-import net.mamoe.mirai.console.plugins.ConfigSection
-import net.mamoe.mirai.console.plugins.ConfigSectionImpl
-import net.mamoe.mirai.console.plugins.loadAsConfig
-import net.mamoe.mirai.console.plugins.withDefaultWriteSave
-import java.io.File
-
-object BotManagers {
-    val config = File("${MiraiConsole.path}/bot.yml").loadAsConfig()
-    val BOT_MANAGERS: ConfigSection by config.withDefaultWriteSave { ConfigSectionImpl() }
-}
-
-fun Bot.addManager(long: Long) {
-    BOT_MANAGERS.putIfAbsent(this.uin.toString(), mutableListOf<Long>())
-    BOT_MANAGERS[this.uin.toString()] =
-        (BOT_MANAGERS.getLongList(this.uin.toString()) as MutableList<Long>).apply { add(long) }
-    BotManagers.config.save()
-}
-
-fun Bot.removeManager(long: Long) {
-    BOT_MANAGERS.putIfAbsent(this.uin.toString(), mutableListOf<Long>())
-    BOT_MANAGERS[this.uin.toString()] =
-        (BOT_MANAGERS.getLongList(this.uin.toString()) as MutableList<Long>).apply { add(long) }
-    BotManagers.config.save()
-}
-
-fun Bot.getManagers(): List<Long> {
-    BOT_MANAGERS.putIfAbsent(this.uin.toString(), mutableListOf<Long>())
-    return BOT_MANAGERS.getLongList(this.uin.toString())
-}
-
-fun Bot.checkManager(long: Long): Boolean {
-    return this.getManagers().contains(long)
-}
-
-

+ 0 - 75
mirai-console/src/main/kotlin/net/mamoe/mirai/console/utils/MiraiConsoleUI.kt

@@ -1,75 +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.utils
-
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.utils.LoginSolver
-
-/**
- * 只需要实现一个这个 传入MiraiConsole 就可以绑定UI层与Console层
- * 注意线程
- */
-
-interface MiraiConsoleUI {
-    /**
-     * 让UI层展示一条log
-     *
-     * identity:log所属的screen, Main=0; Bot=Bot.uin
-     */
-    fun pushLog(
-        identity: Long,
-        message: String
-    )
-
-    /**
-     * 让UI层准备接受新增的一个BOT
-     */
-    fun prePushBot(
-        identity: Long
-    )
-
-    /**
-     * 让UI层接受一个新的bot
-     * */
-    fun pushBot(
-        bot: Bot
-    )
-
-
-    fun pushVersion(
-        consoleVersion: String,
-        consoleBuild: String,
-        coreVersion: String
-    )
-
-    /**
-     * 让UI层提供一个Input
-     * 这个Input 不 等于 Command
-     *
-     */
-    suspend fun requestInput(
-        question: String
-    ): String
-
-
-    /**
-     * 让UI层更新BOT管理员的数据
-     */
-    fun pushBotAdminStatus(
-        identity: Long,
-        admins: List<Long>
-    )
-
-    /**
-     * 由UI层创建一个LoginSolver
-     */
-    fun createLoginSolver(): LoginSolver
-
-}

+ 0 - 3
settings.gradle

@@ -42,9 +42,6 @@ include(':mirai-core')
 //include(':mirai-core-timpc')
 include(':mirai-core-qqandroid')
 
-include(':mirai-japt')
-include(':mirai-console')
-include(':mirai-console-terminal')
 //include(':mirai-api')
 include(':mirai-api-http')
 include(':mirai-demos:mirai-demo-1')