mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-09 18:00:33 +08:00
Merge branch 'master' of https://github.com/mamoe/mirai-console
Conflicts: mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt
This commit is contained in:
commit
de742bf904
@ -1,7 +1,7 @@
|
|||||||
# style guide
|
# style guide
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
# config
|
# config
|
||||||
miraiVersion=0.26.1
|
miraiVersion=0.28.0
|
||||||
miraiConsoleVersion=0.3.4
|
miraiConsoleVersion=0.3.4
|
||||||
miraiConsoleWrapperVersion=0.1.3
|
miraiConsoleWrapperVersion=0.1.3
|
||||||
kotlin.incremental.multiplatform=true
|
kotlin.incremental.multiplatform=true
|
||||||
|
@ -6,9 +6,11 @@ import javafx.stage.Modality
|
|||||||
import javafx.stage.StageStyle
|
import javafx.stage.StageStyle
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.console.MiraiConsole
|
import net.mamoe.mirai.console.command.CommandManager
|
||||||
|
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||||
import net.mamoe.mirai.console.graphical.model.*
|
import net.mamoe.mirai.console.graphical.model.*
|
||||||
import net.mamoe.mirai.console.graphical.view.VerificationCodeFragment
|
import net.mamoe.mirai.console.graphical.view.dialog.InputDialog
|
||||||
|
import net.mamoe.mirai.console.graphical.view.dialog.VerificationCodeFragment
|
||||||
import net.mamoe.mirai.console.plugins.PluginManager
|
import net.mamoe.mirai.console.plugins.PluginManager
|
||||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
||||||
import net.mamoe.mirai.network.WrongPasswordException
|
import net.mamoe.mirai.network.WrongPasswordException
|
||||||
@ -30,10 +32,10 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
|
|||||||
val consoleInfo = ConsoleInfo()
|
val consoleInfo = ConsoleInfo()
|
||||||
|
|
||||||
fun login(qq: String, psd: String) {
|
fun login(qq: String, psd: String) {
|
||||||
MiraiConsole.CommandProcessor.runConsoleCommandBlocking("/login $qq $psd")
|
CommandManager.runCommand(ConsoleCommandSender, "/login $qq $psd")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendCommand(command: String) = MiraiConsole.CommandProcessor.runConsoleCommandBlocking(command)
|
fun sendCommand(command: String) = CommandManager.runCommand(ConsoleCommandSender, command)
|
||||||
|
|
||||||
override fun pushLog(identity: Long, message: String) = Platform.runLater {
|
override fun pushLog(identity: Long, message: String) = Platform.runLater {
|
||||||
fun ObservableList<*>.trim() {
|
fun ObservableList<*>.trim() {
|
||||||
@ -78,13 +80,15 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun requestInput(): String {
|
override suspend fun requestInput(hint: String): String {
|
||||||
val model = VerificationCodeModel()
|
var ret: String? = null
|
||||||
find<VerificationCodeFragment>(Scope(model)).openModal(
|
|
||||||
modality = Modality.APPLICATION_MODAL,
|
// UI必须在UI线程执行,requestInput在协程种被调用
|
||||||
resizable = false
|
Platform.runLater {
|
||||||
)
|
ret = InputDialog(hint).open()
|
||||||
return model.code.value
|
}
|
||||||
|
while (ret == null) { delay(1000) }
|
||||||
|
return ret!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pushBotAdminStatus(identity: Long, admins: List<Long>) = Platform.runLater {
|
override fun pushBotAdminStatus(identity: Long, admins: List<Long>) = Platform.runLater {
|
||||||
@ -102,7 +106,7 @@ class GraphicalLoginSolver : LoginSolver() {
|
|||||||
override suspend fun onSolvePicCaptcha(bot: Bot, data: ByteArray): String? {
|
override suspend fun onSolvePicCaptcha(bot: Bot, data: ByteArray): String? {
|
||||||
val code = VerificationCodeModel(VerificationCode(data))
|
val code = VerificationCodeModel(VerificationCode(data))
|
||||||
|
|
||||||
// 界面需要运行在主线程
|
// UI必须在UI线程执行,requestInput在协程种被调用
|
||||||
Platform.runLater {
|
Platform.runLater {
|
||||||
find<VerificationCodeFragment>(Scope(code)).openModal(
|
find<VerificationCodeFragment>(Scope(code)).openModal(
|
||||||
stageStyle = StageStyle.UNDECORATED,
|
stageStyle = StageStyle.UNDECORATED,
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package net.mamoe.mirai.console.graphical.styleSheet
|
||||||
|
|
||||||
|
import tornadofx.Stylesheet
|
||||||
|
import tornadofx.c
|
||||||
|
|
||||||
|
open class BaseStyleSheet : Stylesheet() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val primaryColor = "0EA987"
|
||||||
|
const val stressColor = "35867C"
|
||||||
|
const val secondaryColor = "32CABA"
|
||||||
|
const val lightColor ="9FD1CC"
|
||||||
|
const val FontColor = "FFFFFF"
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ import javafx.scene.paint.Color
|
|||||||
import javafx.scene.text.FontWeight
|
import javafx.scene.text.FontWeight
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class LoginViewStyleSheet : Stylesheet() {
|
class LoginViewStyleSheet : BaseStyleSheet() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val vBox by csselement("VBox")
|
val vBox by csselement("VBox")
|
||||||
@ -15,11 +15,14 @@ class LoginViewStyleSheet : Stylesheet() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* center box
|
||||||
|
*/
|
||||||
vBox {
|
vBox {
|
||||||
maxWidth = 500.px
|
maxWidth = 500.px
|
||||||
maxHeight = 500.px
|
maxHeight = 500.px
|
||||||
|
|
||||||
backgroundColor += c("39c5BB", 0.3)
|
backgroundColor += c(primaryColor, 0.3)
|
||||||
backgroundRadius += box(15.px)
|
backgroundRadius += box(15.px)
|
||||||
|
|
||||||
padding = box(50.px, 100.px)
|
padding = box(50.px, 100.px)
|
||||||
@ -35,8 +38,11 @@ class LoginViewStyleSheet : Stylesheet() {
|
|||||||
fontWeight = FontWeight.BOLD
|
fontWeight = FontWeight.BOLD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* login button
|
||||||
|
*/
|
||||||
button {
|
button {
|
||||||
backgroundColor += c("00BCD4", 0.8)
|
backgroundColor += c(stressColor, 0.8)
|
||||||
padding = box(10.px, 0.px)
|
padding = box(10.px, 0.px)
|
||||||
prefWidth = 500.px
|
prefWidth = 500.px
|
||||||
textFill = Color.WHITE
|
textFill = Color.WHITE
|
||||||
|
@ -1,21 +1,51 @@
|
|||||||
package net.mamoe.mirai.console.graphical.styleSheet
|
package net.mamoe.mirai.console.graphical.styleSheet
|
||||||
|
|
||||||
|
import javafx.scene.Cursor
|
||||||
|
import javafx.scene.paint.Color
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class PrimaryStyleSheet : Stylesheet() {
|
class PrimaryStyleSheet : BaseStyleSheet() {
|
||||||
companion object {
|
companion object {
|
||||||
|
// window
|
||||||
val jfxTitle by cssclass("jfx-decorator-buttons-container")
|
val jfxTitle by cssclass("jfx-decorator-buttons-container")
|
||||||
val container by cssclass("jfx-decorator-content-container")
|
val container by cssclass("jfx-decorator-content-container")
|
||||||
|
|
||||||
|
// tab
|
||||||
|
val jfxTabPane by cssclass("tab-header-background")
|
||||||
|
val closeButton by cssclass("tab-close-button")
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
/*
|
||||||
|
* window
|
||||||
|
*/
|
||||||
jfxTitle {
|
jfxTitle {
|
||||||
backgroundColor += c("00BCD4")
|
backgroundColor += c(primaryColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
container {
|
container {
|
||||||
borderColor += box(c("00BCD4"))
|
borderColor += box(c(primaryColor))
|
||||||
borderWidth += box(0.px, 4.px, 4.px, 4.px)
|
borderWidth += box(0.px, 4.px, 4.px, 4.px)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tab pane
|
||||||
|
*/
|
||||||
|
jfxTabPane {
|
||||||
|
backgroundColor += c(primaryColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除JFoenix默认样式
|
||||||
|
tab {
|
||||||
|
and(":closable") {
|
||||||
|
borderWidth += box(0.px)
|
||||||
|
borderInsets += box(6.px, 0.px)
|
||||||
|
}
|
||||||
|
|
||||||
|
closeButton {
|
||||||
|
and(hover) { cursor = Cursor.HAND }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,12 +8,11 @@ import javafx.event.EventTarget
|
|||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
import javafx.scene.control.Button
|
import javafx.scene.control.Button
|
||||||
import javafx.scene.control.ListView
|
import javafx.scene.control.ListView
|
||||||
import javafx.scene.control.TabPane
|
|
||||||
import tornadofx.SortedFilteredList
|
import tornadofx.SortedFilteredList
|
||||||
import tornadofx.attachTo
|
import tornadofx.attachTo
|
||||||
import tornadofx.bind
|
import tornadofx.bind
|
||||||
|
|
||||||
internal fun EventTarget.jfxTabPane(op: TabPane.() -> Unit = {}) = JFXTabPane().attachTo(this, op)
|
internal fun EventTarget.jfxTabPane(op: JFXTabPane.() -> Unit = {}) = JFXTabPane().attachTo(this, op)
|
||||||
|
|
||||||
internal fun EventTarget.jfxButton(text: String = "", graphic: Node? = null, op: Button.() -> Unit = {}) =
|
internal fun EventTarget.jfxButton(text: String = "", graphic: Node? = null, op: Button.() -> Unit = {}) =
|
||||||
JFXButton(text).attachTo(this, op) {
|
JFXButton(text).attachTo(this, op) {
|
||||||
|
@ -23,7 +23,9 @@ class PrimaryView : View() {
|
|||||||
|
|
||||||
left = vbox {
|
left = vbox {
|
||||||
|
|
||||||
imageview(Image(PrimaryView::class.java.classLoader.getResourceAsStream("logo.png")))
|
imageview(Image(PrimaryView::class.java.classLoader.getResourceAsStream("logo.png"))) {
|
||||||
|
isPreserveRatio = true
|
||||||
|
}
|
||||||
|
|
||||||
// bot list
|
// bot list
|
||||||
jfxListView(controller.botList) {
|
jfxListView(controller.botList) {
|
||||||
@ -70,13 +72,15 @@ class PrimaryView : View() {
|
|||||||
|
|
||||||
center = jfxTabPane {
|
center = jfxTabPane {
|
||||||
|
|
||||||
|
tabClosingPolicy = TabPane.TabClosingPolicy.ALL_TABS
|
||||||
|
|
||||||
logTab("Main", controller.mainLog, closeable = false)
|
logTab("Main", controller.mainLog, closeable = false)
|
||||||
|
|
||||||
tab("Plugins").content = find<PluginsView>().root
|
tab("Plugins").apply { isClosable = false }.content = find<PluginsView>().root
|
||||||
|
|
||||||
tab("Settings").content = find<SettingsView>().root
|
tab("Settings").apply { isClosable = false }.content = find<SettingsView>().root
|
||||||
|
|
||||||
tab("Login").content = find<LoginView>().root
|
tab("Login").apply { isClosable = false }.content = find<LoginView>().root
|
||||||
|
|
||||||
mainTabPane = this
|
mainTabPane = this
|
||||||
}
|
}
|
||||||
@ -95,6 +99,8 @@ private fun TabPane.logTab(
|
|||||||
op: Tab.() -> Unit = {}
|
op: Tab.() -> Unit = {}
|
||||||
) = tab(text) {
|
) = tab(text) {
|
||||||
|
|
||||||
|
this.isClosable = closeable
|
||||||
|
|
||||||
vbox {
|
vbox {
|
||||||
buttonbar {
|
buttonbar {
|
||||||
|
|
||||||
@ -117,8 +123,6 @@ private fun TabPane.logTab(
|
|||||||
}.ui {// isSucceed: Boolean ->
|
}.ui {// isSucceed: Boolean ->
|
||||||
// notify something
|
// notify something
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closeable) button("关闭").action { close() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package net.mamoe.mirai.console.graphical.view.dialog
|
||||||
|
|
||||||
|
import javafx.scene.control.TextField
|
||||||
|
import javafx.stage.Modality
|
||||||
|
import javafx.stage.StageStyle
|
||||||
|
import tornadofx.*
|
||||||
|
|
||||||
|
class InputDialog(title: String) : Fragment() {
|
||||||
|
|
||||||
|
private lateinit var input: TextField
|
||||||
|
|
||||||
|
init {
|
||||||
|
titleProperty.value = title
|
||||||
|
}
|
||||||
|
|
||||||
|
override val root = form {
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
field(title) {
|
||||||
|
input = textfield("")
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonbar {
|
||||||
|
|
||||||
|
button("提交").action { close() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun open(): String {
|
||||||
|
// 阻塞窗口直到关闭
|
||||||
|
openModal(
|
||||||
|
stageStyle = StageStyle.DECORATED,
|
||||||
|
modality = Modality.APPLICATION_MODAL,
|
||||||
|
block = true
|
||||||
|
)
|
||||||
|
return input.text
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package net.mamoe.mirai.console.graphical.view
|
package net.mamoe.mirai.console.graphical.view.dialog
|
||||||
|
|
||||||
import javafx.scene.image.Image
|
import javafx.scene.image.Image
|
||||||
import net.mamoe.mirai.console.graphical.model.VerificationCodeModel
|
import net.mamoe.mirai.console.graphical.model.VerificationCodeModel
|
||||||
@ -30,7 +30,8 @@ class VerificationCodeFragment : Fragment() {
|
|||||||
this@VerificationCodeFragment.close()
|
this@VerificationCodeFragment.close()
|
||||||
}
|
}
|
||||||
button("取消").action {
|
button("取消").action {
|
||||||
code.code.value = MAGIC_KEY
|
code.code.value =
|
||||||
|
MAGIC_KEY
|
||||||
code.commit()
|
code.commit()
|
||||||
this@VerificationCodeFragment.close()
|
this@VerificationCodeFragment.close()
|
||||||
}
|
}
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.cleanPage
|
|||||||
import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.drawLog
|
import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.drawLog
|
||||||
import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.redrawLogs
|
import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.redrawLogs
|
||||||
import net.mamoe.mirai.console.command.CommandManager
|
import net.mamoe.mirai.console.command.CommandManager
|
||||||
|
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
||||||
import net.mamoe.mirai.utils.LoginSolver
|
import net.mamoe.mirai.utils.LoginSolver
|
||||||
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
||||||
@ -124,7 +125,7 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
|
|||||||
requestResult = input
|
requestResult = input
|
||||||
requesting = false
|
requesting = false
|
||||||
} else {
|
} else {
|
||||||
CommandManager.runConsoleCommand(commandBuilder.toString())
|
CommandManager.runCommand(ConsoleCommandSender, commandBuilder.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ const val CONSOLE_TERMINAL = "Terminal"
|
|||||||
const val CONSOLE_GRAPHICAL = "Graphical"
|
const val CONSOLE_GRAPHICAL = "Graphical"
|
||||||
|
|
||||||
|
|
||||||
object ConsoleUpdater {
|
internal object ConsoleUpdater {
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
private object Links : HashMap<String, Map<String, String>>() {
|
private object Links : HashMap<String, Map<String, String>>() {
|
||||||
|
@ -20,7 +20,7 @@ import java.net.URLClassLoader
|
|||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
object CoreUpdator {
|
internal object CoreUpdater {
|
||||||
|
|
||||||
fun getProtocolLib(): File? {
|
fun getProtocolLib(): File? {
|
||||||
contentPath.listFiles()?.forEach { file ->
|
contentPath.listFiles()?.forEach { file ->
|
@ -1,9 +1,9 @@
|
|||||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.wrapper
|
package net.mamoe.mirai.console.wrapper
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.engine.cio.CIO
|
import io.ktor.client.engine.cio.CIO
|
||||||
import io.ktor.client.features.ClientRequestException
|
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.statement.HttpResponse
|
import io.ktor.client.statement.HttpResponse
|
||||||
import io.ktor.utils.io.ByteReadChannel
|
import io.ktor.utils.io.ByteReadChannel
|
||||||
@ -11,14 +11,11 @@ import io.ktor.utils.io.jvm.javaio.copyTo
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
val Http: HttpClient
|
internal val Http: HttpClient = HttpClient(CIO)
|
||||||
get() = HttpClient(CIO)
|
|
||||||
|
|
||||||
|
internal inline fun <R> tryNTimesOrQuit(repeat: Int, errorHint: String, block: (Int) -> R) {
|
||||||
inline fun <R> tryNTimesOrQuit(repeat: Int, errorHint: String, block: (Int) -> R){
|
|
||||||
var lastException: Throwable? = null
|
var lastException: Throwable? = null
|
||||||
|
|
||||||
repeat(repeat) {
|
repeat(repeat) {
|
||||||
@ -38,7 +35,7 @@ inline fun <R> tryNTimesOrQuit(repeat: Int, errorHint: String, block: (Int) -> R
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend inline fun HttpClient.downloadRequest(url: String): ByteReadChannel {
|
internal suspend inline fun HttpClient.downloadRequest(url: String): ByteReadChannel {
|
||||||
return with(this.get<HttpResponse>(url)) {
|
return with(this.get<HttpResponse>(url)) {
|
||||||
if (this.status.value == 404 || this.status.value == 403) {
|
if (this.status.value == 404 || this.status.value == 403) {
|
||||||
error("File not found")
|
error("File not found")
|
||||||
@ -51,7 +48,9 @@ suspend inline fun HttpClient.downloadRequest(url: String): ByteReadChannel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val jcenterPath = "https://jcenter.bintray.com/{group}/{project}/{version}/:{project}-{version}.{extension}"
|
private val jcenterPath = "https://jcenter.bintray.com/{group}/{project}/{version}/:{project}-{version}.{extension}"
|
||||||
private val aliyunPath = "https://maven.aliyun.com/nexus/content/repositories/jcenter/{group}/{project}/{version}/{project}-{version}.{extension}"
|
private val aliyunPath =
|
||||||
|
"https://maven.aliyun.com/nexus/content/repositories/jcenter/{group}/{project}/{version}/{project}-{version}.{extension}"
|
||||||
|
|
||||||
private fun String.buildPath(
|
private fun String.buildPath(
|
||||||
groupName: String,
|
groupName: String,
|
||||||
projectName: String,
|
projectName: String,
|
||||||
@ -73,7 +72,7 @@ private fun String.buildPath(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun HttpClient.downloadMaven(
|
internal suspend fun HttpClient.downloadMaven(
|
||||||
groupName: String,
|
groupName: String,
|
||||||
projectName: String,
|
projectName: String,
|
||||||
version: String,
|
version: String,
|
||||||
@ -90,7 +89,7 @@ suspend fun HttpClient.downloadMaven(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun HttpClient.downloadMavenArchive(
|
internal suspend inline fun HttpClient.downloadMavenArchive(
|
||||||
groupName: String,
|
groupName: String,
|
||||||
projectName: String,
|
projectName: String,
|
||||||
version: String
|
version: String
|
||||||
@ -98,7 +97,7 @@ suspend inline fun HttpClient.downloadMavenArchive(
|
|||||||
return downloadMaven(groupName, projectName, version, "jar")
|
return downloadMaven(groupName, projectName, version, "jar")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun HttpClient.downloadMavenPom(
|
internal suspend inline fun HttpClient.downloadMavenPom(
|
||||||
groupName: String,
|
groupName: String,
|
||||||
projectName: String,
|
projectName: String,
|
||||||
version: String
|
version: String
|
||||||
@ -106,7 +105,7 @@ suspend inline fun HttpClient.downloadMavenPom(
|
|||||||
return downloadMaven(groupName, projectName, version, "pom")
|
return downloadMaven(groupName, projectName, version, "pom")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun HttpClient.downloadMavenPomAsString(
|
internal suspend fun HttpClient.downloadMavenPomAsString(
|
||||||
groupName: String,
|
groupName: String,
|
||||||
projectName: String,
|
projectName: String,
|
||||||
version: String
|
version: String
|
||||||
@ -123,11 +122,10 @@ suspend fun HttpClient.downloadMavenPomAsString(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 只要填 content path 后面的就可以
|
* 只要填 content path 后面的就可以
|
||||||
*/
|
*/
|
||||||
suspend fun ByteReadChannel.saveToContent(filepath:String){
|
internal suspend fun ByteReadChannel.saveToContent(filepath: String) {
|
||||||
val fileStream = File(contentPath.absolutePath + "/" + filepath).also {
|
val fileStream = File(contentPath.absolutePath + "/" + filepath).also {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
it.createNewFile()
|
it.createNewFile()
|
||||||
|
@ -9,7 +9,10 @@
|
|||||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
package net.mamoe.mirai.console.wrapper
|
package net.mamoe.mirai.console.wrapper
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -56,21 +59,21 @@ object WrapperMain {
|
|||||||
println("Starting version check...")
|
println("Starting version check...")
|
||||||
runBlocking {
|
runBlocking {
|
||||||
launch {
|
launch {
|
||||||
CoreUpdator.versionCheck()
|
CoreUpdater.versionCheck()
|
||||||
}
|
}
|
||||||
launch {
|
launch {
|
||||||
ConsoleUpdater.versionCheck(type)
|
ConsoleUpdater.versionCheck(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println("Version check complete, starting Mirai")
|
println("Version check complete, starting Mirai")
|
||||||
println("Core :" + CoreUpdator.getCore()!!)
|
println("Core :" + CoreUpdater.getCore()!!)
|
||||||
println("Protocol:" + CoreUpdator.getProtocolLib()!!)
|
println("Protocol:" + CoreUpdater.getProtocolLib()!!)
|
||||||
println("Console :" + ConsoleUpdater.getFile()!!)
|
println("Console :" + ConsoleUpdater.getFile()!!)
|
||||||
println("Root :" + System.getProperty("user.dir") + "/")
|
println("Root :" + System.getProperty("user.dir") + "/")
|
||||||
|
|
||||||
val loader = MiraiClassLoader(
|
val loader = MiraiClassLoader(
|
||||||
CoreUpdator.getCore()!!,
|
CoreUpdater.getCore()!!,
|
||||||
CoreUpdator.getProtocolLib()!!,
|
CoreUpdater.getProtocolLib()!!,
|
||||||
ConsoleUpdater.getFile()!!,
|
ConsoleUpdater.getFile()!!,
|
||||||
this.javaClass.classLoader
|
this.javaClass.classLoader
|
||||||
)
|
)
|
||||||
@ -80,7 +83,7 @@ object WrapperMain {
|
|||||||
loader.loadClass(
|
loader.loadClass(
|
||||||
"net.mamoe.mirai.console.pure.MiraiConsolePureLoader"
|
"net.mamoe.mirai.console.pure.MiraiConsolePureLoader"
|
||||||
).getMethod("load", String::class.java, String::class.java)
|
).getMethod("load", String::class.java, String::class.java)
|
||||||
.invoke(null,CoreUpdator.getCurrentVersion(),ConsoleUpdater.getCurrentVersion())
|
.invoke(null, CoreUpdater.getCurrentVersion(), ConsoleUpdater.getCurrentVersion())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console
|
package net.mamoe.mirai.console
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.runBlocking
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.console.command.CommandManager
|
import net.mamoe.mirai.console.command.CommandManager
|
||||||
import net.mamoe.mirai.console.command.CommandSender
|
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.command.DefaultCommands
|
||||||
import net.mamoe.mirai.console.plugins.PluginManager
|
import net.mamoe.mirai.console.plugins.PluginManager
|
||||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
||||||
@ -45,14 +46,16 @@ object MiraiConsole {
|
|||||||
* Console运行路径
|
* Console运行路径
|
||||||
*/
|
*/
|
||||||
var path: String = System.getProperty("user.dir")
|
var path: String = System.getProperty("user.dir")
|
||||||
|
internal set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console前端接口
|
* Console前端接口
|
||||||
*/
|
*/
|
||||||
lateinit var frontEnd: MiraiConsoleUI
|
lateinit var frontEnd: MiraiConsoleUI
|
||||||
|
internal set
|
||||||
|
|
||||||
|
|
||||||
var start = false
|
private var started = false
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,10 +66,10 @@ object MiraiConsole {
|
|||||||
coreVersion: String = "0.0.0",
|
coreVersion: String = "0.0.0",
|
||||||
consoleVersion: String = "0.0.0"
|
consoleVersion: String = "0.0.0"
|
||||||
) {
|
) {
|
||||||
if (start) {
|
if (started) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
start = true
|
started = true
|
||||||
|
|
||||||
/* 初始化前端 */
|
/* 初始化前端 */
|
||||||
this.version = consoleVersion
|
this.version = consoleVersion
|
||||||
@ -110,49 +113,55 @@ object MiraiConsole {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("RedundantSuspendModifier") // binary compatibility
|
||||||
@Deprecated("Please use CommandManager directly, this will be removed in later release")
|
@Deprecated("Please use CommandManager directly, this will be removed in later release")
|
||||||
object CommandProcessor {
|
object CommandProcessor {
|
||||||
@Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
@Deprecated(
|
||||||
|
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||||
"CommandManager.runConsoleCommand(command)",
|
"CommandManager.runConsoleCommand(command)",
|
||||||
"net.mamoe.mirai.console.command.CommandManager"
|
"net.mamoe.mirai.console.command.CommandManager"
|
||||||
)
|
), level = DeprecationLevel.ERROR
|
||||||
)
|
)
|
||||||
suspend fun runConsoleCommand(command: String) {
|
suspend fun runConsoleCommand(command: String) {
|
||||||
CommandManager.runConsoleCommand(command)
|
CommandManager.runCommand(ConsoleCommandSender, command)
|
||||||
}
|
}
|
||||||
@Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
|
||||||
|
@Deprecated(
|
||||||
|
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||||
"CommandManager.runCommand(sender, command)",
|
"CommandManager.runCommand(sender, command)",
|
||||||
"net.mamoe.mirai.console.command.CommandManager"
|
"net.mamoe.mirai.console.command.CommandManager"
|
||||||
)
|
), level = DeprecationLevel.ERROR
|
||||||
)
|
)
|
||||||
suspend fun runCommand(sender: CommandSender, command: String) {
|
suspend fun runCommand(sender: CommandSender, command: String) {
|
||||||
CommandManager.runCommand(sender, command)
|
CommandManager.runCommand(sender, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
@Deprecated(
|
||||||
"CommandManager.runConsoleCommand(command)",
|
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||||
"net.mamoe.mirai.console.command.CommandManager"
|
"CommandManager.runCommand(command)",
|
||||||
|
"net.mamoe.mirai.console.command.CommandManager",
|
||||||
|
"net.mamoe.mirai.console.command.ConsoleCommandSender"
|
||||||
|
), level = DeprecationLevel.ERROR
|
||||||
)
|
)
|
||||||
)
|
fun runConsoleCommandBlocking(command: String) =
|
||||||
fun runConsoleCommandBlocking(command: String) = runBlocking { runConsoleCommand(command)}
|
runBlocking { CommandManager.runCommand(ConsoleCommandSender, command) }
|
||||||
|
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@Deprecated("Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
@Deprecated(
|
||||||
|
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||||
"CommandManager.runCommand(sender, command)",
|
"CommandManager.runCommand(sender, command)",
|
||||||
"net.mamoe.mirai.console.command.CommandManager"
|
"net.mamoe.mirai.console.command.CommandManager"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fun runCommandBlocking(sender: CommandSender, command: String) = runBlocking { runCommand(sender, command) }
|
fun runCommandBlocking(sender: CommandSender, command: String) = runBlocking {
|
||||||
|
CommandManager.runCommand(sender, command)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirai Console的logger
|
|
||||||
* 它用于适配不同的Console前段
|
|
||||||
*/
|
|
||||||
internal object MiraiConsoleLogger {
|
internal object MiraiConsoleLogger {
|
||||||
operator fun invoke(any: Any? = null) {
|
operator fun invoke(any: Any? = null) {
|
||||||
invoke(
|
invoke(
|
||||||
|
@ -7,90 +7,53 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("NOTHING_TO_INLINE")
|
@file:Suppress("NOTHING_TO_INLINE", "MemberVisibilityCanBePrivate")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import net.mamoe.mirai.console.MiraiConsole
|
|
||||||
import net.mamoe.mirai.console.plugins.PluginBase
|
import net.mamoe.mirai.console.plugins.PluginBase
|
||||||
import net.mamoe.mirai.contact.Contact
|
|
||||||
import net.mamoe.mirai.contact.sendMessage
|
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
|
||||||
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
|
||||||
|
|
||||||
interface CommandSender {
|
|
||||||
/**
|
|
||||||
* 立刻发送一条Message
|
|
||||||
*/
|
|
||||||
|
|
||||||
suspend fun sendMessage(messageChain: MessageChain)
|
|
||||||
|
|
||||||
suspend fun sendMessage(message: String)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入要发送的内容 所有内容最后会被以一条发出
|
* 指令
|
||||||
|
*
|
||||||
|
* @see register 注册这个指令
|
||||||
|
* @see registerCommand 注册指令 DSL
|
||||||
*/
|
*/
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Command {
|
interface Command {
|
||||||
|
/**
|
||||||
|
* 指令主名称
|
||||||
|
*/
|
||||||
val name: String
|
val name: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 别名
|
||||||
|
*/
|
||||||
val alias: List<String>
|
val alias: List<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述, 将会显示在 "/help" 指令中
|
||||||
|
*/
|
||||||
val description: String
|
val description: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用法说明
|
||||||
|
*/
|
||||||
val usage: String
|
val usage: String
|
||||||
|
|
||||||
suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean
|
suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册这个指令
|
||||||
|
*/
|
||||||
inline fun Command.register() = CommandManager.register(this)
|
inline fun Command.register() = CommandManager.register(this)
|
||||||
|
|
||||||
|
/**
|
||||||
fun registerCommand(builder: CommandBuilder.() -> Unit): Command {
|
* 构造并注册一个指令
|
||||||
|
*/
|
||||||
|
inline fun registerCommand(builder: CommandBuilder.() -> Unit): Command {
|
||||||
return CommandBuilder().apply(builder).register()
|
return CommandBuilder().apply(builder).register()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +67,9 @@ abstract class BlockingCommand(
|
|||||||
override val usage: String = ""
|
override val usage: String = ""
|
||||||
) : Command {
|
) : Command {
|
||||||
/**
|
/**
|
||||||
* 最高优先级监听器
|
* 最高优先级监听器.
|
||||||
* 如果 return `false`, 这次指令不会被 [PluginBase] 的全局 onCommand 监听器监听
|
*
|
||||||
|
* 指令调用将优先触发 [Command.onCommand], 若该函数返回 `false`, 则不会调用 [PluginBase.onCommand]
|
||||||
* */
|
* */
|
||||||
final override suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean {
|
final override suspend fun onCommand(sender: CommandSender, args: List<String>): Boolean {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
@ -116,7 +80,27 @@ abstract class BlockingCommand(
|
|||||||
abstract fun onCommandBlocking(sender: CommandSender, args: List<String>): Boolean
|
abstract fun onCommandBlocking(sender: CommandSender, args: List<String>): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnonymousCommand internal constructor(
|
/**
|
||||||
|
* @see registerCommand
|
||||||
|
*/
|
||||||
|
class CommandBuilder @PublishedApi internal constructor() {
|
||||||
|
var name: String? = null
|
||||||
|
var alias: List<String>? = null
|
||||||
|
var description: String = ""
|
||||||
|
var usage: String = "use /help for help"
|
||||||
|
|
||||||
|
internal var onCommand: (suspend CommandSender.(args: List<String>) -> Boolean)? = null
|
||||||
|
|
||||||
|
fun onCommand(commandProcess: suspend CommandSender.(args: List<String>) -> Boolean) {
|
||||||
|
onCommand = commandProcess
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal
|
||||||
|
|
||||||
|
|
||||||
|
internal class AnonymousCommand internal constructor(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val alias: List<String>,
|
override val alias: List<String>,
|
||||||
override val description: String,
|
override val description: String,
|
||||||
@ -128,19 +112,8 @@ class AnonymousCommand internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommandBuilder internal constructor() {
|
@PublishedApi
|
||||||
var name: String? = null
|
internal fun CommandBuilder.register(): AnonymousCommand {
|
||||||
var alias: List<String>? = null
|
|
||||||
var description: String = ""
|
|
||||||
var usage: String = "use /help for help"
|
|
||||||
internal var onCommand: (suspend CommandSender.(args: List<String>) -> Boolean)? = null
|
|
||||||
|
|
||||||
fun onCommand(commandProcess: suspend CommandSender.(args: List<String>) -> Boolean) {
|
|
||||||
onCommand = commandProcess
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun CommandBuilder.register(): AnonymousCommand {
|
|
||||||
if (name == null || onCommand == null) {
|
if (name == null || onCommand == null) {
|
||||||
error("CommandBuilder not complete")
|
error("CommandBuilder not complete")
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("unused")
|
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
@ -18,7 +18,6 @@ import net.mamoe.mirai.console.plugins.PluginBase
|
|||||||
import net.mamoe.mirai.console.plugins.PluginManager
|
import net.mamoe.mirai.console.plugins.PluginManager
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
|
||||||
object CommandManager : Job by {
|
object CommandManager : Job by {
|
||||||
GlobalScope.launch(start = CoroutineStart.LAZY) {
|
GlobalScope.launch(start = CoroutineStart.LAZY) {
|
||||||
processCommandQueue()
|
processCommandQueue()
|
||||||
@ -28,6 +27,11 @@ object CommandManager : Job by {
|
|||||||
|
|
||||||
val commands: Collection<Command> get() = registeredCommand.values
|
val commands: Collection<Command> get() = registeredCommand.values
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册这个指令.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException 当已注册的指令与 [command] 重名时
|
||||||
|
*/
|
||||||
fun register(command: Command) {
|
fun register(command: Command) {
|
||||||
val allNames = mutableListOf(command.name).also { it.addAll(command.alias) }
|
val allNames = mutableListOf(command.name).also { it.addAll(command.alias) }
|
||||||
allNames.forEach {
|
allNames.forEach {
|
||||||
@ -41,9 +45,10 @@ object CommandManager : Job by {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun unregister(command: Command) {
|
fun unregister(command: Command) {
|
||||||
(command.alias.asSequence() + command.name).forEach {
|
command.alias.forEach {
|
||||||
registeredCommand.remove(it)
|
registeredCommand.remove(it)
|
||||||
}
|
}
|
||||||
|
registeredCommand.remove(command.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unregister(commandName: String): Boolean {
|
fun unregister(commandName: String): Boolean {
|
||||||
@ -52,23 +57,65 @@ object CommandManager : Job by {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令是单线程运行的
|
* 最基础的执行指令的方式
|
||||||
|
* 指令将会被加入队列,依次执行
|
||||||
|
*
|
||||||
|
* @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender]
|
||||||
|
*/
|
||||||
|
fun runCommand(sender: CommandSender, command: String) {
|
||||||
|
commandChannel.offer(
|
||||||
|
FullCommand(sender, command)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插队异步执行一个指令并返回 [Deferred]
|
||||||
|
*
|
||||||
|
* @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender]
|
||||||
|
* @see PluginBase.runCommandAsync 扩展
|
||||||
|
*/
|
||||||
|
fun runCommandAsync(pluginBase: PluginBase, sender: CommandSender, command: String): Deferred<Boolean> {
|
||||||
|
return pluginBase.async {
|
||||||
|
processCommand(sender, command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插队执行一个指令并返回 [Deferred]
|
||||||
|
*
|
||||||
|
* @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender]
|
||||||
|
* @see PluginBase.runCommandAsync 扩展
|
||||||
|
*/
|
||||||
|
@Suppress("KDocUnresolvedReference")
|
||||||
|
suspend fun dispatchCommand(sender: CommandSender, command: String): Boolean {
|
||||||
|
return processCommand(sender, command)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阻塞当前线程, 插队执行一个指令
|
||||||
|
*
|
||||||
|
* @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender]
|
||||||
|
*/
|
||||||
|
// for java
|
||||||
|
fun dispatchCommandBlocking(sender: CommandSender, command: String): Boolean =
|
||||||
|
runBlocking { dispatchCommand(sender, command) }
|
||||||
|
|
||||||
|
|
||||||
|
// internal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单线程执行指令
|
||||||
*/
|
*/
|
||||||
private val commandDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
|
private val commandDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行一个指令, 但是如果你想模拟一个指令的执行
|
|
||||||
* 请向下看
|
|
||||||
*
|
|
||||||
* 返回一个指令是否执行成功
|
|
||||||
*/
|
|
||||||
private suspend fun processCommand(sender: CommandSender, fullCommand: String): Boolean {
|
private suspend fun processCommand(sender: CommandSender, fullCommand: String): Boolean {
|
||||||
return withContext(commandDispatcher) {
|
return withContext(commandDispatcher) {
|
||||||
_processCommand(sender, fullCommand)
|
processCommandImpl(sender, fullCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun _processCommand(sender: CommandSender, fullCommand: String): Boolean {
|
private suspend fun processCommandImpl(sender: CommandSender, fullCommand: String): Boolean {
|
||||||
val blocks = fullCommand.split(" ")
|
val blocks = fullCommand.split(" ")
|
||||||
val commandHead = blocks[0].replace("/", "")
|
val commandHead = blocks[0].replace("/", "")
|
||||||
val args = blocks.drop(1)
|
val args = blocks.drop(1)
|
||||||
@ -86,12 +133,11 @@ object CommandManager : Job by {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
false
|
false
|
||||||
} finally {
|
} finally {
|
||||||
(sender as CommandSenderImpl).flushMessage()
|
(sender as AbstractCommandSender).flushMessage()
|
||||||
}
|
}
|
||||||
} ?: throw UnknownCommandException(commandHead)
|
} ?: throw UnknownCommandException(commandHead)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class FullCommand(
|
internal class FullCommand(
|
||||||
val sender: CommandSender,
|
val sender: CommandSender,
|
||||||
val commandStr: String
|
val commandStr: String
|
||||||
@ -110,54 +156,16 @@ object CommandManager : Job by {
|
|||||||
}
|
}
|
||||||
processCommandQueue()
|
processCommandQueue()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* runCommand()是最基础的执行指令的方式
|
* 插队异步执行一个指令并返回 [Deferred]
|
||||||
* 指令将会被加入队列,依次执行
|
*
|
||||||
* 方法由0.27.0的阻塞模式改为不阻塞(鉴于commandChannel大小无限)
|
* @param sender 指令执行者, 可为 [ConsoleCommandSender] 或 [ContactCommandSender]
|
||||||
|
* @see PluginBase.runCommandAsync 扩展
|
||||||
*/
|
*/
|
||||||
fun runCommand(sender: CommandSender, command: String) {
|
fun PluginBase.runCommandAsync(sender: CommandSender, command: String): Deferred<Boolean> =
|
||||||
runBlocking {//it wont be blocking
|
CommandManager.runCommandAsync(this, sender, command)
|
||||||
commandChannel.send(
|
|
||||||
FullCommand(sender, command)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
fun runConsoleCommand(command: String) = runCommand(ConsoleCommandSender,command)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* runCommandAnsyc()执行一个指令并返回deferred
|
|
||||||
* 为插队执行
|
|
||||||
*/
|
|
||||||
fun runCommandAsync(pluginBase: PluginBase, sender: CommandSender, command: String):Deferred<Boolean>{
|
|
||||||
return pluginBase.async{
|
|
||||||
processCommand(sender,command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun runConsoleCommandAsync(pluginBase: PluginBase, command: String):Deferred<Boolean> = runCommandAsync(pluginBase,ConsoleCommandSender,command)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dispatchCommand()执行一个指令并等到完成
|
|
||||||
* 为插队执行
|
|
||||||
*/
|
|
||||||
suspend fun dispatchCommand(sender: CommandSender,command: String):Boolean{
|
|
||||||
return processCommand(sender,command)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun dispatchConsoleCommand(command: String):Boolean = dispatchCommand(ConsoleCommandSender,command)
|
|
||||||
|
|
||||||
fun dispatchCommandBlocking(sender: CommandSender,command: String):Boolean = runBlocking { dispatchCommand(sender, command) }
|
|
||||||
|
|
||||||
fun dispatchConsoleCommandBlocking(command: String):Boolean = runBlocking { dispatchConsoleCommandBlocking(command) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun PluginBase.runCommandAsnyc(sender: CommandSender, command: String):Deferred<Boolean> = CommandManager.runCommandAsync(this,sender,command)
|
|
||||||
|
|
||||||
fun PluginBase.runConsoleCommandAsync(command: String):Deferred<Boolean> = CommandManager.runConsoleCommandAsync(this,command)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UnknownCommandException(command: String) : Exception("unknown command \"$command\"")
|
class UnknownCommandException(command: String) : Exception("unknown command \"$command\"")
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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.runBlocking
|
||||||
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
|
import net.mamoe.mirai.contact.Contact
|
||||||
|
import net.mamoe.mirai.contact.sendMessage
|
||||||
|
import net.mamoe.mirai.message.data.Message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令发送者
|
||||||
|
*
|
||||||
|
* @see AbstractCommandSender 请继承于该抽象类
|
||||||
|
*/
|
||||||
|
interface CommandSender {
|
||||||
|
/**
|
||||||
|
* 立刻发送一条消息
|
||||||
|
*/
|
||||||
|
suspend fun sendMessage(messageChain: Message)
|
||||||
|
|
||||||
|
suspend fun sendMessage(message: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入要发送的内容 所有内容最后会被以一条发出
|
||||||
|
*/
|
||||||
|
fun appendMessage(message: String)
|
||||||
|
|
||||||
|
fun sendMessageBlocking(messageChain: Message) = runBlocking { sendMessage(messageChain) }
|
||||||
|
fun sendMessageBlocking(message: String) = runBlocking { sendMessage(message) }
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractCommandSender : CommandSender {
|
||||||
|
internal val builder = StringBuilder()
|
||||||
|
|
||||||
|
override fun appendMessage(message: String) {
|
||||||
|
builder.append(message).append("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
internal open suspend fun flushMessage() {
|
||||||
|
if (builder.isNotEmpty()) {
|
||||||
|
sendMessage(builder.toString().removeSuffix("\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制台指令执行者. 代表由控制台执行指令
|
||||||
|
*/
|
||||||
|
object ConsoleCommandSender : AbstractCommandSender() {
|
||||||
|
override suspend fun sendMessage(messageChain: Message) {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系人指令执行者. 代表由一个 QQ 用户执行指令
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
open class ContactCommandSender(val contact: Contact) : AbstractCommandSender() {
|
||||||
|
override suspend fun sendMessage(messageChain: Message) {
|
||||||
|
contact.sendMessage(messageChain)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun sendMessage(message: String) {
|
||||||
|
contact.sendMessage(message)
|
||||||
|
}
|
||||||
|
}
|
@ -143,7 +143,7 @@ object DefaultCommands {
|
|||||||
startsWith("/") { message ->
|
startsWith("/") { message ->
|
||||||
if (bot.checkManager(this.sender.id)) {
|
if (bot.checkManager(this.sender.id)) {
|
||||||
val sender = ContactCommandSender(this.subject)
|
val sender = ContactCommandSender(this.subject)
|
||||||
MiraiConsole.CommandProcessor.runCommand(
|
CommandManager.runCommand(
|
||||||
sender, message
|
sender, message
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,3 @@ import net.mamoe.mirai.event.Event
|
|||||||
import net.mamoe.mirai.event.broadcast
|
import net.mamoe.mirai.event.broadcast
|
||||||
|
|
||||||
internal fun <E : Event> broadcast(e: E): E = runBlocking { e.broadcast() }
|
internal fun <E : Event> broadcast(e: E): E = runBlocking { e.broadcast() }
|
||||||
|
|
||||||
class A{
|
|
||||||
|
|
||||||
var x = 0
|
|
||||||
|
|
||||||
var width:Int
|
|
||||||
get() = x
|
|
||||||
set(value){
|
|
||||||
x = value
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,17 +15,17 @@ import kotlinx.coroutines.*
|
|||||||
import net.mamoe.mirai.console.MiraiConsole
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
import net.mamoe.mirai.console.command.Command
|
import net.mamoe.mirai.console.command.Command
|
||||||
import net.mamoe.mirai.console.command.CommandSender
|
import net.mamoe.mirai.console.command.CommandSender
|
||||||
import net.mamoe.mirai.console.pure.MiraiConsoleUIPure
|
|
||||||
import net.mamoe.mirai.utils.MiraiLogger
|
import net.mamoe.mirai.utils.MiraiLogger
|
||||||
import net.mamoe.mirai.utils.SimpleLogger
|
import net.mamoe.mirai.utils.SimpleLogger
|
||||||
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有插件的基类
|
||||||
|
*/
|
||||||
abstract class PluginBase
|
abstract class PluginBase
|
||||||
@JvmOverloads constructor(coroutineContext: CoroutineContext = EmptyCoroutineContext) : CoroutineScope {
|
@JvmOverloads constructor(coroutineContext: CoroutineContext = EmptyCoroutineContext) : CoroutineScope {
|
||||||
|
|
||||||
@ -36,9 +36,8 @@ abstract class PluginBase
|
|||||||
* 插件被分配的数据目录。数据目录会与插件名称同名。
|
* 插件被分配的数据目录。数据目录会与插件名称同名。
|
||||||
*/
|
*/
|
||||||
val dataFolder: File by lazy {
|
val dataFolder: File by lazy {
|
||||||
File(PluginManager.pluginsPath + "/" + PluginManager.lastPluginName).also {
|
File(PluginManager.pluginsPath + "/" + PluginManager.lastPluginName)
|
||||||
it.mkdir()
|
.also { it.mkdir() }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,37 +62,21 @@ abstract class PluginBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当任意指令被使用
|
* 当任意指令被使用时调用.
|
||||||
|
*
|
||||||
|
* 指令调用将优先触发 [Command.onCommand], 若该函数返回 `false`, 则不会调用 [PluginBase.onCommand]
|
||||||
*/
|
*/
|
||||||
open fun onCommand(command: Command, sender: CommandSender, args: List<String>) {
|
open fun onCommand(command: Command, sender: CommandSender, args: List<String>) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun enable() {
|
|
||||||
this.onEnable()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载一个data folder中的Config
|
* 加载一个 [dataFolder] 中的 [Config]
|
||||||
* 这个config是read-write的
|
|
||||||
*/
|
*/
|
||||||
fun loadConfig(fileName: String): Config {
|
fun loadConfig(fileName: String): Config {
|
||||||
return Config.load(dataFolder.absolutePath + "/" + fileName)
|
return Config.load(dataFolder.absolutePath + "/" + fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
internal fun disable(throwable: CancellationException? = null) {
|
|
||||||
this.coroutineContext[Job]!!.cancelChildren(throwable)
|
|
||||||
try {
|
|
||||||
this.onDisable()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.info(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal var pluginName: String = ""
|
|
||||||
|
|
||||||
val logger: MiraiLogger by lazy {
|
val logger: MiraiLogger by lazy {
|
||||||
SimpleLogger("Plugin $pluginName") { priority, message, e ->
|
SimpleLogger("Plugin $pluginName") { priority, message, e ->
|
||||||
val identityString = "[${pluginName}]"
|
val identityString = "[${pluginName}]"
|
||||||
@ -120,16 +103,34 @@ abstract class PluginBase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载 resource 中的 [Config]
|
* 加载 resource 中的 [Config]
|
||||||
* 这个 [Config] 是 read-only 的
|
* 这个 [Config] 是只读的
|
||||||
*/
|
*/
|
||||||
fun getResourcesConfig(fileName: String): Config {
|
fun getResourcesConfig(fileName: String): Config {
|
||||||
if (!fileName.contains(".")) {
|
require(fileName.contains(".")) { "Unknown Config Type" }
|
||||||
error("Unknown Config Type")
|
|
||||||
}
|
|
||||||
return Config.load(getResources(fileName) ?: error("No such file: $fileName"), fileName.substringAfter('.'))
|
return Config.load(getResources(fileName) ?: error("No such file: $fileName"), fileName.substringAfter('.'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// internal
|
||||||
|
|
||||||
|
internal fun enable() {
|
||||||
|
this.onEnable()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun disable(throwable: CancellationException? = null) {
|
||||||
|
this.coroutineContext[Job]!!.cancelChildren(throwable)
|
||||||
|
try {
|
||||||
|
this.onDisable()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.info(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal var pluginName: String = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件描述
|
||||||
|
*/
|
||||||
class PluginDescription(
|
class PluginDescription(
|
||||||
val name: String,
|
val name: String,
|
||||||
val author: String,
|
val author: String,
|
||||||
|
@ -19,28 +19,27 @@ import net.mamoe.mirai.utils.SimpleLogger
|
|||||||
import net.mamoe.mirai.utils.io.encodeToString
|
import net.mamoe.mirai.utils.io.encodeToString
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.lang.reflect.Constructor
|
||||||
|
import java.lang.reflect.Method
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.jar.JarFile
|
import java.util.jar.JarFile
|
||||||
|
|
||||||
|
|
||||||
object PluginManager {
|
object PluginManager {
|
||||||
@Volatile
|
|
||||||
internal var lastPluginName: String = ""
|
|
||||||
|
|
||||||
internal val pluginsPath = (System.getProperty("user.dir") + "/plugins/").replace("//", "/").also {
|
internal val pluginsPath = (System.getProperty("user.dir") + "/plugins/").replace("//", "/").also {
|
||||||
File(it).mkdirs()
|
File(it).mkdirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val logger = SimpleLogger("Plugin Manager") { _, message, e ->
|
private val logger = SimpleLogger("Plugin Manager") { p, message, e ->
|
||||||
MiraiConsole.logger("[Plugin Manager]", 0, message)
|
MiraiConsole.logger(p, "[Plugin Manager]", 0, message)
|
||||||
MiraiConsole.logger("[Plugin Manager]", 0, e)
|
MiraiConsole.logger(p, "[Plugin Manager]", 0, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
//已完成加载的
|
//已完成加载的
|
||||||
private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf()
|
private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf()
|
||||||
private val pluginDescriptions: MutableMap<String, PluginDescription> = mutableMapOf()
|
private val pluginDescriptions: MutableMap<String, PluginDescription> = mutableMapOf()
|
||||||
|
|
||||||
fun onCommand(command: Command, sender: CommandSender, args: List<String>) {
|
internal fun onCommand(command: Command, sender: CommandSender, args: List<String>) {
|
||||||
nameToPluginBaseMap.values.forEach {
|
nameToPluginBaseMap.values.forEach {
|
||||||
try {
|
try {
|
||||||
it.onCommand(command, sender, args)
|
it.onCommand(command, sender, args)
|
||||||
@ -64,6 +63,10 @@ object PluginManager {
|
|||||||
return pluginDescriptions.values
|
return pluginDescriptions.values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
internal var lastPluginName: String = ""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试加载全部插件
|
* 尝试加载全部插件
|
||||||
*/
|
*/
|
||||||
@ -153,27 +156,31 @@ object PluginManager {
|
|||||||
|
|
||||||
//real load
|
//real load
|
||||||
logger.info("loading plugin " + description.name)
|
logger.info("loading plugin " + description.name)
|
||||||
lastPluginName = description.name
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val pluginClass = try {
|
val pluginClass = try {
|
||||||
PluginClassLoader(
|
PluginClassLoader(
|
||||||
(pluginsLocation[description.name]!!),
|
(pluginsLocation[description.name]!!),
|
||||||
this.javaClass.classLoader
|
this.javaClass.classLoader
|
||||||
)
|
).loadClass(description.basePath)
|
||||||
.loadClass(description.basePath)
|
|
||||||
} catch (e: ClassNotFoundException) {
|
} catch (e: ClassNotFoundException) {
|
||||||
logger.info("failed to find Main: " + description.basePath + " checking if it's kotlin's path")
|
logger.info("failed to find Main: " + description.basePath + " checking if it's kotlin's path")
|
||||||
PluginClassLoader(
|
PluginClassLoader(
|
||||||
(pluginsLocation[description.name]!!),
|
(pluginsLocation[description.name]!!),
|
||||||
this.javaClass.classLoader
|
this.javaClass.classLoader
|
||||||
)
|
).loadClass("${description.basePath}Kt")
|
||||||
.loadClass("${description.basePath}Kt")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val subClass = pluginClass.asSubclass(PluginBase::class.java)
|
val subClass = pluginClass.asSubclass(PluginBase::class.java)
|
||||||
|
|
||||||
|
lastPluginName = description.name
|
||||||
val plugin: PluginBase =
|
val plugin: PluginBase =
|
||||||
subClass.kotlin.objectInstance ?: subClass.getDeclaredConstructor().newInstance()
|
subClass.kotlin.objectInstance ?: subClass.getDeclaredConstructor().apply {
|
||||||
|
againstPermission()
|
||||||
|
}.newInstance()
|
||||||
|
plugin.dataFolder // initialize right now
|
||||||
|
|
||||||
description.loaded = true
|
description.loaded = true
|
||||||
logger.info("successfully loaded plugin " + description.name + " version " + description.version + " by " + description.author)
|
logger.info("successfully loaded plugin " + description.name + " version " + description.version + " by " + description.author)
|
||||||
logger.info(description.info)
|
logger.info(description.info)
|
||||||
@ -270,4 +277,18 @@ object PluginManager {
|
|||||||
return URL("jar:file:" + jarFile.absoluteFile + "!/" + toFindFile.name).openConnection().inputStream
|
return URL("jar:file:" + jarFile.absoluteFile + "!/" + toFindFile.name).openConnection().inputStream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val trySetAccessibleMethod: Method? = runCatching {
|
||||||
|
Class.forName("java.lang.reflect.AccessibleObject").getMethod("trySetAccessible")
|
||||||
|
}.getOrNull()
|
||||||
|
|
||||||
|
private fun Constructor<out PluginBase>.againstPermission() {
|
||||||
|
trySetAccessibleMethod?.let { it.invoke(this, true) }
|
||||||
|
?: kotlin.runCatching {
|
||||||
|
@Suppress("DEPRECATED")
|
||||||
|
this.isAccessible = true
|
||||||
|
}
|
||||||
}
|
}
|
@ -11,7 +11,8 @@ package net.mamoe.mirai.console.pure
|
|||||||
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.console.MiraiConsole
|
import net.mamoe.mirai.console.command.CommandManager
|
||||||
|
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
||||||
import net.mamoe.mirai.utils.DefaultLoginSolver
|
import net.mamoe.mirai.utils.DefaultLoginSolver
|
||||||
import net.mamoe.mirai.utils.LoginSolver
|
import net.mamoe.mirai.utils.LoginSolver
|
||||||
@ -49,7 +50,7 @@ class MiraiConsoleUIPure : MiraiConsoleUI {
|
|||||||
requestStr = input
|
requestStr = input
|
||||||
requesting = false
|
requesting = false
|
||||||
} else {
|
} else {
|
||||||
MiraiConsole.CommandProcessor.runConsoleCommandBlocking(input)
|
CommandManager.runCommand(ConsoleCommandSender, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,8 +66,7 @@ class MiraiConsoleUIPure : MiraiConsoleUI {
|
|||||||
|
|
||||||
override fun pushLog(priority: LogPriority, identityStr: String, identity: Long, message: String) {
|
override fun pushLog(priority: LogPriority, identityStr: String, identity: Long, message: String) {
|
||||||
var priorityStr = "[${priority.name}]"
|
var priorityStr = "[${priority.name}]"
|
||||||
val _message = message + COLOR_RESET
|
/*
|
||||||
/**
|
|
||||||
* 通过ANSI控制码添加颜色
|
* 通过ANSI控制码添加颜色
|
||||||
* 更多的颜色定义在 [MiraiConsoleUIPure] 的 companion
|
* 更多的颜色定义在 [MiraiConsoleUIPure] 的 companion
|
||||||
*/
|
*/
|
||||||
@ -85,7 +85,7 @@ class MiraiConsoleUIPure : MiraiConsoleUI {
|
|||||||
|
|
||||||
else -> priorityStr
|
else -> priorityStr
|
||||||
}
|
}
|
||||||
println("\u001b[0m " + sdf.format(Date()) + " $priorityStr $identityStr $_message")
|
println("\u001b[0m " + sdf.format(Date()) + " $priorityStr $identityStr ${message + COLOR_RESET}")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prePushBot(identity: Long) {
|
override fun prePushBot(identity: Long) {
|
||||||
|
@ -43,27 +43,3 @@ fun <T:PluginBase> T.repeatTask(
|
|||||||
intervalInMs, runnable
|
intervalInMs, runnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun <T> repeatTask(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class X: PluginBase() {
|
|
||||||
override fun onLoad() {
|
|
||||||
//kotlin
|
|
||||||
this.repeatTask(5){
|
|
||||||
|
|
||||||
}
|
|
||||||
//java1
|
|
||||||
RepeatTask.of<X>(5){
|
|
||||||
|
|
||||||
}
|
|
||||||
//java2
|
|
||||||
class Xtask:RepeatTask<X>(5){
|
|
||||||
override fun onRun() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
package net.mamoe.mirai.console.utils
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
@ -15,9 +15,8 @@ import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 只需要实现一个这个传入 MiraiConsole 就可以绑定 UI 层与 Console 层
|
* 只需要实现一个这个传入 MiraiConsole 就可以绑定 UI 层与 Console 层
|
||||||
* 注意线程
|
* 需要保证线程安全
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface MiraiConsoleUI {
|
interface MiraiConsoleUI {
|
||||||
/**
|
/**
|
||||||
* 让 UI 层展示一条 log
|
* 让 UI 层展示一条 log
|
||||||
@ -58,14 +57,13 @@ interface MiraiConsoleUI {
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让UI层提供一个Input
|
* 让 UI 层提供一个输入, 相当于 [readLine]
|
||||||
* 这个Input 不 等于 Command
|
|
||||||
*/
|
*/
|
||||||
suspend fun requestInput(hint: String): String
|
suspend fun requestInput(hint: String): String
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让UI层更新BOT管理员的数据
|
* 让 UI 层更新 bot 管理员的数据
|
||||||
*/
|
*/
|
||||||
fun pushBotAdminStatus(
|
fun pushBotAdminStatus(
|
||||||
identity: Long,
|
identity: Long,
|
||||||
@ -73,7 +71,7 @@ interface MiraiConsoleUI {
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 由UI层创建一个LoginSolver
|
* 由 UI 层创建一个 [LoginSolver]
|
||||||
*/
|
*/
|
||||||
fun createLoginSolver(): LoginSolver
|
fun createLoginSolver(): LoginSolver
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user