CommandExecuteResult for executeCommand

This commit is contained in:
Him188 2020-08-23 00:34:34 +08:00
parent cdc9f8f613
commit cd60a60d97
14 changed files with 168 additions and 130 deletions

View File

@ -0,0 +1,74 @@
# mirai-console backend
欢迎来到 mirai-console 后端开发文档。
## 包结构
- `net.mamoe.mirai.console.`
- `command`:指令模块:[Command]
- `data`:存储模块:[PluginData], [PluginConfig], [PluginDataStorage]
- `event`Console 实现的事件.
- `plugin`:插件模块:[Plugin], [PluginLoader], [JvmPlugin]
- `util`:工具类:[Annotations], [BotManager], [ConsoleInput], [JavaPluginScheduler]
- `internal`:内部实现
## 基础
### `Plugin` 模块
Console 支持拥有强扩展性的插件加载器。内建 JVM 插件支持 ([JarPluginLoader])。
#### [插件加载器 `PluginLoader`][PluginLoader]
Console 本身是一套高扩展性的「框架」,必然拥有通用的 [插件加载器][PluginLoader]。
Console 内置 [JarPluginLoader],支持加载使用 Kotlin、 Java或其他 JVM 平台编程语言并打包为 jar 的插件 (详见下文 `JvmPlugin`)。
扩展的 [插件加载器][PluginLoader] 可以由一个特别的 [JVM 插件][JvmPlugin] 提供。在启动时, Console 首先加载那些提供扩展 [插件加载器][PluginLoader] 的插件. 并允许它们 [注册扩展加载器]。
#### [`Plugin`][Plugin]
所有 Console 插件都必须实现 [`Plugin`][Plugin] 接口。
虽然 Console 是 JVM 平台程序, 但也拥有支持其他平台的插件管理系统。
[`Plugin`][Plugin] 可在相应 [插件加载器 `PluginLoader`][PluginLoader] 的帮助下,成为任何语言实现的插件与 Console 建立联系的桥梁。
#### [JVM 插件][JvmPlugin]
#### 实现 Kotlin 插件
添加一个类
#### 实现 Java 插件
[Plugin]: src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt
[PluginDescription]: src/main/kotlin/net/mamoe/mirai/console/plugin/description.kt
[PluginLoader]: src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt
[JarPluginLoader]: src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt
[JvmPlugin]: src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt
[AbstractJvmPlugin]: src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt
[KotlinPlugin]: src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/KotlinPlugin.kt
[JavaPlugin]: src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JavaPlugin.kt
[PluginData]: src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt
[PluginConfig]: src/main/kotlin/net/mamoe/mirai/console/data/PluginConfig.kt
[PluginDataStorage]: src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt
[MiraiConsole]: src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt
[MiraiConsoleImplementation]: src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt
<!--[MiraiConsoleFrontEnd]: src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleFrontEnd.kt-->
[Command]: src/main/kotlin/net/mamoe/mirai/console/command/Command.kt
[CompositeCommand]: src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt
[SimpleCommand]: src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt
[RawCommand]: src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt
[CommandManager]: src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt
[BotManager]: src/main/kotlin/net/mamoe/mirai/console/util/BotManager.kt
[Annotations]: src/main/kotlin/net/mamoe/mirai/console/util/Annotations.kt
[ConsoleInput]: src/main/kotlin/net/mamoe/mirai/console/util/ConsoleInput.kt
[JavaPluginScheduler]: src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JavaPluginScheduler.kt
[注册扩展加载器]: src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt#L49-L51

View File

@ -55,7 +55,7 @@ public sealed class CommandExecuteResult {
} }
/** 指令执行过程出现了错误 */ /** 指令执行过程出现了错误 */
public class ExecutionException( public class ExecutionFailed(
/** 指令执行时发生的错误 */ /** 指令执行时发生的错误 */
public override val exception: Throwable, public override val exception: Throwable,
/** 尝试执行的指令 */ /** 尝试执行的指令 */
@ -122,7 +122,6 @@ public sealed class CommandExecuteResult {
} }
} }
@Suppress("RemoveRedundantQualifierName") @Suppress("RemoveRedundantQualifierName")
public typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus public typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus
@ -139,19 +138,19 @@ public fun CommandExecuteResult.isSuccess(): Boolean {
} }
/** /**
* [this] [CommandExecuteResult.ExecutionException] 时返回 `true` * [this] [CommandExecuteResult.ExecutionFailed] 时返回 `true`
*/ */
@JvmSynthetic @JvmSynthetic
public fun CommandExecuteResult.isExecutionException(): Boolean { public fun CommandExecuteResult.isExecutionException(): Boolean {
contract { contract {
returns(true) implies (this@isExecutionException is CommandExecuteResult.ExecutionException) returns(true) implies (this@isExecutionException is CommandExecuteResult.ExecutionFailed)
returns(false) implies (this@isExecutionException !is CommandExecuteResult.ExecutionException) returns(false) implies (this@isExecutionException !is CommandExecuteResult.ExecutionFailed)
} }
return this is CommandExecuteResult.ExecutionException return this is CommandExecuteResult.ExecutionFailed
} }
/** /**
* [this] [CommandExecuteResult.ExecutionException] 时返回 `true` * [this] [CommandExecuteResult.ExecutionFailed] 时返回 `true`
*/ */
@JvmSynthetic @JvmSynthetic
public fun CommandExecuteResult.isPermissionDenied(): Boolean { public fun CommandExecuteResult.isPermissionDenied(): Boolean {
@ -163,7 +162,7 @@ public fun CommandExecuteResult.isPermissionDenied(): Boolean {
} }
/** /**
* [this] [CommandExecuteResult.ExecutionException] 时返回 `true` * [this] [CommandExecuteResult.ExecutionFailed] 时返回 `true`
*/ */
@JvmSynthetic @JvmSynthetic
public fun CommandExecuteResult.isCommandNotFound(): Boolean { public fun CommandExecuteResult.isCommandNotFound(): Boolean {
@ -175,7 +174,7 @@ public fun CommandExecuteResult.isCommandNotFound(): Boolean {
} }
/** /**
* [this] [CommandExecuteResult.ExecutionException] [CommandExecuteResult.CommandNotFound] 时返回 `true` * [this] [CommandExecuteResult.ExecutionFailed] [CommandExecuteResult.CommandNotFound] 时返回 `true`
*/ */
@JvmSynthetic @JvmSynthetic
public fun CommandExecuteResult.isFailure(): Boolean { public fun CommandExecuteResult.isFailure(): Boolean {

View File

@ -12,9 +12,10 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
/** /**
* [executeCommand] , [Command.onCommand] 抛出异常时包装的异常. * [CommandManager.executeCommand] , [Command.onCommand] 抛出异常时包装的异常.
*/ */
public class CommandExecutionException( public class CommandExecutionException(
/** /**

View File

@ -15,12 +15,7 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import net.mamoe.kjbb.JvmBlockingBridge import net.mamoe.kjbb.JvmBlockingBridge
import net.mamoe.mirai.console.command.CommandManagerImpl.unregisterAllCommands
import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
@ -79,27 +74,6 @@ public interface CommandManager {
*/ */
public fun Command.isRegistered(): Boolean public fun Command.isRegistered(): Boolean
/**
* 解析并执行一个指令. 将会检查指令权限, 在无权限时抛出
*
* @param messages 接受 [String] [Message], 其他对象将会被 [Any.toString]
*
* @return 成功执行的指令, 在无匹配指令时返回 `null`
* @throws CommandExecutionException [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
*/
@JvmBlockingBridge
public suspend fun CommandSender.executeCommand(vararg messages: Any): Command?
/**
* 解析并执行一个指令
*
* @return 成功执行的指令, 在无匹配指令时返回 `null`
* @throws CommandExecutionException [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
*/
@Throws(CommandExecutionException::class)
@JvmBlockingBridge
public suspend fun CommandSender.executeCommand(message: MessageChain): Command?
/** /**
* 执行一个指令 * 执行一个指令
* *
@ -127,20 +101,18 @@ public interface CommandManager {
* *
* @return 执行结果 * @return 执行结果
*/ */
@ConsoleExperimentalAPI
@JvmBlockingBridge @JvmBlockingBridge
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult public suspend fun CommandSender.executeCommand(vararg messages: Any): CommandExecuteResult
/** /**
* 解析并执行一个指令, 获取详细的指令参数等信息 * 解析并执行一个指令, 获取详细的指令参数等信息
* *
* 执行过程中产生的异常将不会直接抛出, 而会包装为 [CommandExecuteResult.ExecutionException] * 执行过程中产生的异常将不会直接抛出, 而会包装为 [CommandExecuteResult.ExecutionFailed]
* *
* @return 执行结果 * @return 执行结果
*/ */
@ConsoleExperimentalAPI
@JvmBlockingBridge @JvmBlockingBridge
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult public suspend fun CommandSender.executeCommand(messages: MessageChain): CommandExecuteResult
public companion object INSTANCE : CommandManager by CommandManagerImpl { public companion object INSTANCE : CommandManager by CommandManagerImpl {
// TODO: 2020/8/20 https://youtrack.jetbrains.com/issue/KT-41191 // TODO: 2020/8/20 https://youtrack.jetbrains.com/issue/KT-41191
@ -152,54 +124,19 @@ public interface CommandManager {
override fun Command.unregister(): Boolean = CommandManagerImpl.run { unregister() } override fun Command.unregister(): Boolean = CommandManagerImpl.run { unregister() }
override fun Command.isRegistered(): Boolean = CommandManagerImpl.run { isRegistered() } override fun Command.isRegistered(): Boolean = CommandManagerImpl.run { isRegistered() }
override val commandPrefix: String get() = CommandManagerImpl.commandPrefix override val commandPrefix: String get() = CommandManagerImpl.commandPrefix
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? =
CommandManagerImpl.run { executeCommand(*messages) }
override suspend fun CommandSender.executeCommand(message: MessageChain): Command? =
CommandManagerImpl.run { executeCommand(message) }
override suspend fun Command.execute( override suspend fun Command.execute(
sender: CommandSender, sender: CommandSender,
args: MessageChain, args: MessageChain,
checkPermission: Boolean checkPermission: Boolean
): Unit = ): Unit = CommandManagerImpl.run { execute(sender, args = args, checkPermission = checkPermission) }
CommandManagerImpl.run { execute(sender, args = args, checkPermission = checkPermission) }
override suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean): Unit = override suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean): Unit =
CommandManagerImpl.run { execute(sender, args = args, checkPermission = checkPermission) } CommandManagerImpl.run { execute(sender, args = args, checkPermission = checkPermission) }
@ConsoleExperimentalAPI override suspend fun CommandSender.executeCommand(vararg messages: Any): CommandExecuteResult =
override suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult = CommandManagerImpl.run { executeCommand(*messages) }
CommandManagerImpl.run { executeCommandDetailed(*messages) }
@ConsoleExperimentalAPI override suspend fun CommandSender.executeCommand(messages: MessageChain): CommandExecuteResult =
override suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult = CommandManagerImpl.run { executeCommand(messages) }
CommandManagerImpl.run { executeCommandDetailed(messages) }
} }
} }
/**
* 指令的所有者.
* @see PluginCommandOwner
*/
public open class CommandOwner
/**
* 插件指令所有者. 插件只能通过 [PluginCommandOwner] 管理指令.
*/
public class PluginCommandOwner(
public val plugin: Plugin
) : CommandOwner() {
init {
if (plugin is CoroutineScope) { // JVM Plugin
plugin.coroutineContext[Job]?.invokeOnCompletion {
this.unregisterAllCommands()
}
}
}
}
/**
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
*/
internal object ConsoleCommandOwner : CommandOwner()

View File

@ -10,20 +10,26 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import kotlinx.atomicfu.locks.withLock import kotlinx.atomicfu.locks.withLock
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.internal.command.* import net.mamoe.mirai.console.internal.command.executeCommandInternal
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.internal.command.flattenCommandComponents
import net.mamoe.mirai.console.internal.command.intersectsIgnoringCase
import net.mamoe.mirai.event.Listener import net.mamoe.mirai.event.Listener
import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.message.MessageEvent import net.mamoe.mirai.message.MessageEvent
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageContent import net.mamoe.mirai.message.data.MessageContent
import net.mamoe.mirai.message.data.content import net.mamoe.mirai.utils.MiraiLogger
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
internal object CommandManagerImpl : CommandManager, CoroutineScope by CoroutineScope(MiraiConsole.job) { internal object CommandManagerImpl : CommandManager, CoroutineScope by CoroutineScope(MiraiConsole.job) {
private val logger: MiraiLogger by lazy {
MiraiConsole.newLogger("command")
}
@JvmField @JvmField
internal val registeredCommands: MutableList<Command> = mutableListOf() internal val registeredCommands: MutableList<Command> = mutableListOf()
@ -49,13 +55,33 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
internal val commandListener: Listener<MessageEvent> by lazy { internal val commandListener: Listener<MessageEvent> by lazy {
subscribeAlways( subscribeAlways(
coroutineContext = CoroutineExceptionHandler { _, throwable ->
logger.error(throwable)
},
concurrency = Listener.ConcurrencyKind.CONCURRENT, concurrency = Listener.ConcurrencyKind.CONCURRENT,
priority = Listener.EventPriority.HIGH priority = Listener.EventPriority.HIGH
) { ) {
if (this.toCommandSender().executeCommand(message) != null) { val sender = this.toCommandSender()
when (val result = sender.executeCommand(message)) {
is CommandExecuteResult.PermissionDenied -> {
if (!result.command.prefixOptional) {
sender.sendMessage("权限不足")
intercept() intercept()
} }
} }
is CommandExecuteResult.Success -> {
intercept()
}
is CommandExecuteResult.ExecutionFailed -> {
sender.catchExecutionException(result.exception)
intercept()
}
is CommandExecuteResult.CommandNotFound -> {
// noop
}
}
}
} }
@ -114,17 +140,6 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
override fun Command.isRegistered(): Boolean = this in registeredCommands override fun Command.isRegistered(): Boolean = this in registeredCommands
//// executing without detailed result (faster) //// executing without detailed result (faster)
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
if (messages.isEmpty()) return null
return matchAndExecuteCommandInternal(messages, messages[0].toString().substringBefore(' '))
}
override suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
if (message.isEmpty()) return null
val msg = message.filterIsInstance<MessageContent>()
return matchAndExecuteCommandInternal(msg, msg[0].content.substringBefore(' '))
}
override suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean) { override suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean) {
sender.executeCommandInternal( sender.executeCommandInternal(
this, this,
@ -144,15 +159,14 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
} }
//// execution with detailed result //// execution with detailed result
@ConsoleExperimentalAPI override suspend fun CommandSender.executeCommand(vararg messages: Any): CommandExecuteResult {
override suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("") if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' ')) return executeCommandInternal(messages, messages[0].toString().substringBefore(' '))
} }
@ConsoleExperimentalAPI override suspend fun CommandSender.executeCommand(messages: MessageChain): CommandExecuteResult {
override suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult { val msg = messages.filterIsInstance<MessageContent>()
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("") if (msg.isEmpty()) return CommandExecuteResult.CommandNotFound("")
return executeCommandDetailedInternal(messages, messages[0].toString()) return executeCommandInternal(msg, msg[0].toString().substringBefore(' '))
} }
} }

View File

@ -0,0 +1,23 @@
/*
* Copyright 2019-2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 with Mamoe Exceptions 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 with Mamoe Exceptions license that can be found via the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.console.command
/**
* 指令的所有者. 目前仅作为标识作用.
*
* @see CommandManager.unregisterAllCommands 取消注册所有属于一个 [CommandOwner] 的指令
* @see CommandManager.registeredCommands 获取已经注册了的属于一个 [CommandOwner] 的指令列表.
*/
public interface CommandOwner
/**
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
*/
internal object ConsoleCommandOwner : CommandOwner

View File

@ -107,20 +107,6 @@ internal fun Group.fuzzySearchMember(nameCardTarget: String): Member? {
@JvmSynthetic @JvmSynthetic
internal inline fun <reified T> List<T>.dropToTypedArray(n: Int): Array<T> = Array(size - n) { this[n + it] } internal inline fun <reified T> List<T>.dropToTypedArray(n: Int): Array<T> = Array(size - n) { this[n + it] }
@JvmSynthetic
@Throws(CommandExecutionException::class)
internal suspend inline fun CommandSender.matchAndExecuteCommandInternal(
messages: Any,
commandName: String
): Command? {
val command = CommandManagerImpl.matchCommand(
commandName
) ?: return null
this.executeCommandInternal(command, messages.flattenCommandComponents().dropToTypedArray(1), commandName, true)
return command
}
@JvmSynthetic @JvmSynthetic
@Throws(CommandExecutionException::class) @Throws(CommandExecutionException::class)
internal suspend inline fun CommandSender.executeCommandInternal( internal suspend inline fun CommandSender.executeCommandInternal(
@ -149,7 +135,7 @@ internal suspend inline fun CommandSender.executeCommandInternal(
@JvmSynthetic @JvmSynthetic
internal suspend inline fun CommandSender.executeCommandDetailedInternal( internal suspend fun CommandSender.executeCommandInternal(
messages: Any, messages: Any,
commandName: String commandName: String
): CommandExecuteResult { ): CommandExecuteResult {
@ -171,7 +157,7 @@ internal suspend inline fun CommandSender.executeCommandDetailedInternal(
) )
}, },
onFailure = { onFailure = {
return CommandExecuteResult.ExecutionException( return CommandExecuteResult.ExecutionFailed(
commandName = commandName, commandName = commandName,
command = command, command = command,
exception = it, exception = it,

View File

@ -48,10 +48,10 @@ internal inline fun <reified T : PluginData> newPluginDataInstanceUsingReflectio
} }
private fun isReferenceArray(rootClass: KClass<Any>): Boolean = rootClass.java.isArray internal fun isReferenceArray(rootClass: KClass<Any>): Boolean = rootClass.java.isArray
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun KType.kclass() = when (val t = classifier) { internal fun KType.kclass() = when (val t = classifier) {
is KClass<*> -> t is KClass<*> -> t
else -> error("Only KClass supported as classifier, got $t") else -> error("Only KClass supported as classifier, got $t")
} as KClass<Any> } as KClass<Any>

View File

@ -23,7 +23,7 @@ import java.util.concurrent.locks.ReentrantLock
internal object PluginManagerImpl : PluginManager { internal object PluginManagerImpl : PluginManager {
override val pluginsPath: Path = MiraiConsole.rootPath.resolve("plugins").apply { mkdir() } override val pluginsPath: Path = MiraiConsole.rootPath.resolve("plugins").apply { mkdir() }
override val pluginsDataPath = MiraiConsole.rootPath.resolve("data").apply { mkdir() } override val pluginsDataPath: Path = MiraiConsole.rootPath.resolve("data").apply { mkdir() }
@Suppress("ObjectPropertyName") @Suppress("ObjectPropertyName")
private val _pluginLoaders: MutableList<PluginLoader<*, *>> = mutableListOf() private val _pluginLoaders: MutableList<PluginLoader<*, *>> = mutableListOf()

View File

@ -11,6 +11,7 @@
package net.mamoe.mirai.console.plugin package net.mamoe.mirai.console.plugin
import net.mamoe.mirai.console.command.CommandOwner
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
import java.io.File import java.io.File
@ -25,7 +26,7 @@ import java.nio.file.Path
* *
* @see PluginLoader 插件加载器 * @see PluginLoader 插件加载器
*/ */
public interface Plugin { public interface Plugin : CommandOwner {
/** /**
* 判断此插件是否已启用 * 判断此插件是否已启用
* *

View File

@ -38,6 +38,7 @@ import kotlin.reflect.KClass
*/ */
public interface JvmPlugin : Plugin, CoroutineScope, public interface JvmPlugin : Plugin, CoroutineScope,
PluginFileExtensions, ResourceContainer, AutoSavePluginDataHolder { PluginFileExtensions, ResourceContainer, AutoSavePluginDataHolder {
/** 日志 */ /** 日志 */
public val logger: MiraiLogger public val logger: MiraiLogger

View File

@ -123,8 +123,10 @@ internal class TestCommand {
} }
@Test @Test
fun `test throw Exception`() = runBlocking { fun `test throw Exception`() = assertTrue {
assertEquals(null, sender.executeCommand("")) runBlocking {
sender.executeCommand("").isFailure()
}
} }
@Test @Test

View File

@ -17,7 +17,7 @@
*/ */
object Versions { object Versions {
const val core = "1.2.1" const val core = "1.2.2"
const val console = "1.0-M2-1" const val console = "1.0-M2-1"
const val consoleGraphical = "0.0.7" const val consoleGraphical = "0.0.7"
const val consoleTerminal = "0.1.0" const val consoleTerminal = "0.1.0"

View File

@ -15,7 +15,7 @@ import net.mamoe.mirai.console.command.BuiltInCommands
import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandExecuteStatus import net.mamoe.mirai.console.command.CommandExecuteStatus
import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommandDetailed import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
import net.mamoe.mirai.console.util.ConsoleInternalAPI import net.mamoe.mirai.console.util.ConsoleInternalAPI
import net.mamoe.mirai.console.util.requestInput import net.mamoe.mirai.console.util.requestInput
import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.DefaultLogger
@ -62,7 +62,7 @@ internal fun startupConsoleThread() {
continue continue
} }
// consoleLogger.debug("INPUT> $next") // consoleLogger.debug("INPUT> $next")
val result = ConsoleCommandSenderImpl.executeCommandDetailed(next) val result = ConsoleCommandSenderImpl.executeCommand(next)
when (result.status) { when (result.status) {
CommandExecuteStatus.SUCCESSFUL -> { CommandExecuteStatus.SUCCESSFUL -> {
} }