mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
Introduce executeCommandDetailed;
Enhance CommandExecuteResult, add type-safe classification with contracts; Introduce CommandExecutionException providing information about the command on execution failure.
This commit is contained in:
parent
f1752db580
commit
a117e73186
@ -1,6 +1,7 @@
|
|||||||
package net.mamoe.mirai.console.command;
|
package net.mamoe.mirai.console.command;
|
||||||
|
|
||||||
import kotlin.NotImplementedError;
|
import kotlin.NotImplementedError;
|
||||||
|
import kotlin.coroutines.Continuation;
|
||||||
import kotlin.coroutines.EmptyCoroutineContext;
|
import kotlin.coroutines.EmptyCoroutineContext;
|
||||||
import kotlinx.coroutines.BuildersKt;
|
import kotlinx.coroutines.BuildersKt;
|
||||||
import kotlinx.coroutines.CoroutineScope;
|
import kotlinx.coroutines.CoroutineScope;
|
||||||
@ -18,7 +19,7 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
/**
|
/**
|
||||||
* Java 适配的 {@link CommandManagerKt}
|
* Java 适配的 {@link CommandManagerKt}
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||||
public final class JCommandManager {
|
public final class JCommandManager {
|
||||||
private JCommandManager() {
|
private JCommandManager() {
|
||||||
throw new NotImplementedError();
|
throw new NotImplementedError();
|
||||||
@ -101,14 +102,17 @@ public final class JCommandManager {
|
|||||||
CommandManagerKt.unregisterAllCommands(owner);
|
CommandManagerKt.unregisterAllCommands(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析并执行一个指令
|
* 解析并执行一个指令
|
||||||
*
|
*
|
||||||
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||||
* @see CommandExecuteResult
|
* @return 成功执行的指令, 在无匹配指令时返回 <code>null</code>
|
||||||
|
* @throws CommandExecutionException 当 {@link Command#onCommand(CommandSender, Object[], Continuation)} 抛出异常时包装并附带相关指令信息抛出
|
||||||
* @see #executeCommandAsync(CoroutineScope, CommandSender, Object...)
|
* @see #executeCommandAsync(CoroutineScope, CommandSender, Object...)
|
||||||
*/
|
*/
|
||||||
public static CommandExecuteResult executeCommand(final @NotNull CommandSender sender, final @NotNull Object... args) throws InterruptedException {
|
@Nullable
|
||||||
|
public static Command executeCommand(final @NotNull CommandSender sender, final @NotNull Object... args) throws CommandExecutionException, InterruptedException {
|
||||||
Objects.requireNonNull(sender, "sender");
|
Objects.requireNonNull(sender, "sender");
|
||||||
Objects.requireNonNull(args, "args");
|
Objects.requireNonNull(args, "args");
|
||||||
for (Object arg : args) {
|
for (Object arg : args) {
|
||||||
@ -123,10 +127,11 @@ public final class JCommandManager {
|
|||||||
*
|
*
|
||||||
* @param scope 协程作用域 (用于管理协程生命周期). 一般填入 {@link JavaPlugin} 实例.
|
* @param scope 协程作用域 (用于管理协程生命周期). 一般填入 {@link JavaPlugin} 实例.
|
||||||
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||||
* @see CommandExecuteResult
|
* @return 成功执行的指令, 在无匹配指令时返回 <code>null</code>
|
||||||
* @see #executeCommand(CommandSender, Object...)
|
* @see #executeCommand(CommandSender, Object...)
|
||||||
*/
|
*/
|
||||||
public static CompletableFuture<CommandExecuteResult> executeCommandAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
@NotNull
|
||||||
|
public static CompletableFuture<@Nullable Command> executeCommandAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
||||||
Objects.requireNonNull(sender, "sender");
|
Objects.requireNonNull(sender, "sender");
|
||||||
Objects.requireNonNull(args, "args");
|
Objects.requireNonNull(args, "args");
|
||||||
Objects.requireNonNull(scope, "scope");
|
Objects.requireNonNull(scope, "scope");
|
||||||
@ -136,4 +141,46 @@ public final class JCommandManager {
|
|||||||
|
|
||||||
return FutureKt.future(scope, EmptyCoroutineContext.INSTANCE, CoroutineStart.DEFAULT, (sc, completion) -> CommandManagerKt.executeCommand(sender, args, completion));
|
return FutureKt.future(scope, EmptyCoroutineContext.INSTANCE, CoroutineStart.DEFAULT, (sc, completion) -> CommandManagerKt.executeCommand(sender, args, completion));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析并执行一个指令, 获取详细的指令参数等信息.
|
||||||
|
* <br />
|
||||||
|
* 执行过程中产生的异常将不会直接抛出, 而会包装为 {@link CommandExecuteResult.ExecutionException}
|
||||||
|
*
|
||||||
|
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||||
|
* @return 执行结果
|
||||||
|
* @see #executeCommandDetailedAsync(CoroutineScope, CommandSender, Object...)
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static CommandExecuteResult executeCommandDetailed(final @NotNull CommandSender sender, final @NotNull Object... args) throws InterruptedException {
|
||||||
|
Objects.requireNonNull(sender, "sender");
|
||||||
|
Objects.requireNonNull(args, "args");
|
||||||
|
for (Object arg : args) {
|
||||||
|
Objects.requireNonNull(arg, "element of args");
|
||||||
|
}
|
||||||
|
|
||||||
|
return BuildersKt.runBlocking(EmptyCoroutineContext.INSTANCE, (scope, completion) -> CommandManagerKt.executeCommandDetailed(sender, args, completion));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步 (在 Kotlin 协程线程池) 解析并执行一个指令, 获取详细的指令参数等信息
|
||||||
|
*
|
||||||
|
* @param scope 协程作用域 (用于管理协程生命周期). 一般填入 {@link JavaPlugin} 实例.
|
||||||
|
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||||
|
* @return 执行结果
|
||||||
|
* @see #executeCommandDetailed(CommandSender, Object...)
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static CompletableFuture<@NotNull CommandExecuteResult>
|
||||||
|
executeCommandDetailedAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
||||||
|
Objects.requireNonNull(sender, "sender");
|
||||||
|
Objects.requireNonNull(args, "args");
|
||||||
|
Objects.requireNonNull(scope, "scope");
|
||||||
|
for (Object arg : args) {
|
||||||
|
Objects.requireNonNull(arg, "element of args");
|
||||||
|
}
|
||||||
|
|
||||||
|
return FutureKt.future(scope, EmptyCoroutineContext.INSTANCE, CoroutineStart.DEFAULT, (sc, completion) -> CommandManagerKt.executeCommandDetailed(sender, args, completion));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,146 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.command.CommandExecuteResult.CommandExecuteStatus
|
||||||
|
import net.mamoe.mirai.message.data.Message
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令的执行返回
|
||||||
|
*
|
||||||
|
* @see CommandExecuteStatus
|
||||||
|
*/
|
||||||
|
sealed class CommandExecuteResult {
|
||||||
|
/** 指令最终执行状态 */
|
||||||
|
abstract val status: CommandExecuteStatus
|
||||||
|
|
||||||
|
/** 指令执行时发生的错误 (如果有) */
|
||||||
|
abstract val exception: Throwable?
|
||||||
|
|
||||||
|
/** 尝试执行的指令 (如果匹配到) */
|
||||||
|
abstract val command: Command?
|
||||||
|
|
||||||
|
/** 尝试执行的指令名 (如果匹配到) */
|
||||||
|
abstract val commandName: String?
|
||||||
|
|
||||||
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
|
abstract val args: Array<out Any>?
|
||||||
|
|
||||||
|
// abstract val to allow smart casting
|
||||||
|
|
||||||
|
/** 指令执行成功 */
|
||||||
|
class Success(
|
||||||
|
/** 尝试执行的指令 */
|
||||||
|
override val command: Command,
|
||||||
|
/** 尝试执行的指令名 */
|
||||||
|
override val commandName: String,
|
||||||
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
|
override val args: Array<out Any>
|
||||||
|
) : CommandExecuteResult() {
|
||||||
|
/** 指令执行时发生的错误, 总是 `null` */
|
||||||
|
override val exception: Nothing? get() = null
|
||||||
|
|
||||||
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.SUCCESSFUL] */
|
||||||
|
override val status: CommandExecuteStatus get() = CommandExecuteStatus.SUCCESSFUL
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 指令执行过程出现了错误 */
|
||||||
|
class ExecutionException(
|
||||||
|
/** 指令执行时发生的错误 */
|
||||||
|
override val exception: Throwable,
|
||||||
|
/** 尝试执行的指令 */
|
||||||
|
override val command: Command,
|
||||||
|
/** 尝试执行的指令名 */
|
||||||
|
override val commandName: String,
|
||||||
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
|
override val args: Array<out Any>
|
||||||
|
) : CommandExecuteResult() {
|
||||||
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.EXECUTION_EXCEPTION] */
|
||||||
|
override val status: CommandExecuteStatus get() = CommandExecuteStatus.EXECUTION_EXCEPTION
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 没有匹配的指令 */
|
||||||
|
class CommandNotFound(
|
||||||
|
/** 尝试执行的指令名 */
|
||||||
|
override val commandName: String
|
||||||
|
) : CommandExecuteResult() {
|
||||||
|
/** 指令执行时发生的错误, 总是 `null` */
|
||||||
|
override val exception: Nothing? get() = null
|
||||||
|
|
||||||
|
/** 尝试执行的指令, 总是 `null` */
|
||||||
|
override val command: Nothing? get() = null
|
||||||
|
|
||||||
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
|
override val args: Nothing? get() = null
|
||||||
|
|
||||||
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.COMMAND_NOT_FOUND] */
|
||||||
|
override val status: CommandExecuteStatus get() = CommandExecuteStatus.COMMAND_NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令的执行状态
|
||||||
|
*/
|
||||||
|
enum class CommandExecuteStatus {
|
||||||
|
/** 指令执行成功 */
|
||||||
|
SUCCESSFUL,
|
||||||
|
|
||||||
|
/** 指令执行过程出现了错误 */
|
||||||
|
EXECUTION_EXCEPTION,
|
||||||
|
|
||||||
|
/** 没有匹配的指令 */
|
||||||
|
COMMAND_NOT_FOUND
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("RemoveRedundantQualifierName")
|
||||||
|
typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当 [this] 为 [CommandExecuteResult.Success] 时返回 `true`
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
fun CommandExecuteResult.isSuccess(): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (this@isSuccess is CommandExecuteResult.Success)
|
||||||
|
returns(false) implies (this@isSuccess !is CommandExecuteResult.Success)
|
||||||
|
}
|
||||||
|
return this is CommandExecuteResult.Success
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
fun CommandExecuteResult.isExecutionException(): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (this@isExecutionException is CommandExecuteResult.ExecutionException)
|
||||||
|
returns(false) implies (this@isExecutionException !is CommandExecuteResult.ExecutionException)
|
||||||
|
}
|
||||||
|
return this is CommandExecuteResult.ExecutionException
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
fun CommandExecuteResult.isCommandNotFound(): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (this@isCommandNotFound is CommandExecuteResult.CommandNotFound)
|
||||||
|
returns(false) implies (this@isCommandNotFound !is CommandExecuteResult.CommandNotFound)
|
||||||
|
}
|
||||||
|
return this is CommandExecuteResult.CommandNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 或 [CommandExecuteResult.CommandNotFound] 时返回 `true`
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
fun CommandExecuteResult.isFailure(): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (this@isFailure !is CommandExecuteResult.Success)
|
||||||
|
returns(false) implies (this@isFailure is CommandExecuteResult.Success)
|
||||||
|
}
|
||||||
|
return this !is CommandExecuteResult.Success
|
||||||
|
}
|
@ -7,7 +7,10 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("NOTHING_TO_INLINE", "unused")
|
@file:Suppress(
|
||||||
|
"NOTHING_TO_INLINE", "unused", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "RESULT_CLASS_IN_RETURN_TYPE",
|
||||||
|
"MemberVisibilityCanBePrivate"
|
||||||
|
)
|
||||||
@file:JvmName("CommandManagerKt")
|
@file:JvmName("CommandManagerKt")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
@ -18,7 +21,6 @@ import kotlinx.coroutines.Job
|
|||||||
import net.mamoe.mirai.console.plugin.Plugin
|
import net.mamoe.mirai.console.plugin.Plugin
|
||||||
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
|
||||||
import net.mamoe.mirai.message.data.SingleMessage
|
|
||||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,104 +128,119 @@ fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock {
|
|||||||
InternalCommandManager.registeredCommands.remove(this)
|
InternalCommandManager.registeredCommands.remove(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
//// executing
|
//// executing without detailed result (faster)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析并执行一个指令
|
* 解析并执行一个指令
|
||||||
*
|
*
|
||||||
* Java 调用方式: `<static> CommandManager.executeCommand(Command)`
|
|
||||||
*
|
|
||||||
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||||
* @see CommandExecuteResult
|
*
|
||||||
|
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||||
|
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommand Java 方法
|
* @see JCommandManager.executeCommand Java 方法
|
||||||
*/
|
*/
|
||||||
suspend fun CommandSender.executeCommand(vararg messages: Any): CommandExecuteResult {
|
suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
|
||||||
if (messages.isEmpty()) return CommandExecuteResult(
|
if (messages.isEmpty()) return null
|
||||||
status = CommandExecuteStatus.EMPTY_COMMAND
|
return executeCommandInternal(messages, messages[0].toString().substringBefore(' '))
|
||||||
)
|
|
||||||
return executeCommandInternal(
|
|
||||||
messages,
|
|
||||||
messages[0].let { if (it is SingleMessage) it.toString() else it.toString().substringBefore(' ') })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmSynthetic
|
|
||||||
internal inline fun <reified T> List<T>.dropToTypedArray(n: Int): Array<T> = Array(size - n) { this[n + it] }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析并执行一个指令
|
* 解析并执行一个指令
|
||||||
* @see CommandExecuteResult
|
*
|
||||||
|
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||||
|
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommand Java 方法
|
* @see JCommandManager.executeCommand Java 方法
|
||||||
*/
|
*/
|
||||||
suspend fun CommandSender.executeCommand(message: MessageChain): CommandExecuteResult {
|
@Throws(CommandExecutionException::class)
|
||||||
if (message.isEmpty()) return CommandExecuteResult(
|
suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
||||||
status = CommandExecuteStatus.EMPTY_COMMAND
|
if (message.isEmpty()) return null
|
||||||
)
|
|
||||||
return executeCommandInternal(message, message[0].toString())
|
return executeCommandInternal(message, message[0].toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在 [executeCommand] 中, [Command.onCommand] 抛出异常时包装的异常.
|
||||||
|
*/
|
||||||
|
class CommandExecutionException(
|
||||||
|
/**
|
||||||
|
* 执行过程发生异常的指令
|
||||||
|
*/
|
||||||
|
val command: Command,
|
||||||
|
/**
|
||||||
|
* 匹配到的指令名
|
||||||
|
*/
|
||||||
|
val name: String,
|
||||||
|
/**
|
||||||
|
* 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String]
|
||||||
|
*/
|
||||||
|
val args: Array<out Any>,
|
||||||
|
cause: Throwable
|
||||||
|
) : RuntimeException(
|
||||||
|
"Exception while executing command '${command.primaryName}' with args ${args.joinToString { "'$it'" }}",
|
||||||
|
cause
|
||||||
|
) {
|
||||||
|
override fun toString(): String =
|
||||||
|
"CommandExecutionException(command=$command, name='$name', args=${args.contentToString()})"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// execution with detailed result
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||||
|
*
|
||||||
|
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
|
*
|
||||||
|
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||||
|
*/
|
||||||
|
suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
||||||
|
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||||
|
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||||
|
*
|
||||||
|
* 执行过程中产生的异常将不会直接抛出, 而会包装为 [CommandExecuteResult.ExecutionException]
|
||||||
|
*
|
||||||
|
* @return 执行结果
|
||||||
|
*
|
||||||
|
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||||
|
*/
|
||||||
|
suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
||||||
|
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||||
|
return executeCommandDetailedInternal(messages, messages[0].toString())
|
||||||
|
}
|
||||||
|
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
internal suspend inline fun CommandSender.executeCommandInternal(
|
internal suspend inline fun CommandSender.executeCommandDetailedInternal(
|
||||||
messages: Any,
|
messages: Any,
|
||||||
commandName: String
|
commandName: String
|
||||||
): CommandExecuteResult {
|
): CommandExecuteResult {
|
||||||
val command = InternalCommandManager.matchCommand(commandName) ?: return CommandExecuteResult(
|
val command =
|
||||||
status = CommandExecuteStatus.COMMAND_NOT_FOUND,
|
InternalCommandManager.matchCommand(commandName) ?: return CommandExecuteResult.CommandNotFound(commandName)
|
||||||
commandName = commandName
|
val args = messages.flattenCommandComponents().dropToTypedArray(1)
|
||||||
)
|
|
||||||
val rawInput = messages.flattenCommandComponents()
|
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
command.onCommand(this, rawInput.dropToTypedArray(1))
|
command.onCommand(this, args)
|
||||||
}.onFailure {
|
}.fold(
|
||||||
return CommandExecuteResult(
|
onSuccess = {
|
||||||
status = CommandExecuteStatus.FAILED,
|
return CommandExecuteResult.Success(
|
||||||
commandName = commandName,
|
commandName = commandName,
|
||||||
command = command,
|
command = command,
|
||||||
exception = it
|
args = args
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
return CommandExecuteResult(
|
onFailure = {
|
||||||
status = CommandExecuteStatus.SUCCESSFUL,
|
return CommandExecuteResult.ExecutionException(
|
||||||
commandName = commandName,
|
commandName = commandName,
|
||||||
command = command
|
command = command,
|
||||||
|
exception = it,
|
||||||
|
args = args
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
/**
|
|
||||||
* 命令的执行返回
|
|
||||||
*
|
|
||||||
* @param status 命令最终执行状态
|
|
||||||
* @param exception 命令执行时发生的错误(如果有)
|
|
||||||
* @param command 尝试执行的命令 (status = SUCCESSFUL | FAILED)
|
|
||||||
* @param commandName 尝试执行的命令的名字 (status != EMPTY_COMMAND)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @see CommandExecuteStatus
|
|
||||||
*/
|
|
||||||
class CommandExecuteResult(
|
|
||||||
val status: CommandExecuteStatus,
|
|
||||||
val exception: Throwable? = null,
|
|
||||||
val command: Command? = null,
|
|
||||||
val commandName: String? = null
|
|
||||||
) {
|
|
||||||
/**
|
|
||||||
* 命令的执行状态
|
|
||||||
*
|
|
||||||
* 当为 [SUCCESSFUL] 的时候,代表命令执行成功
|
|
||||||
*
|
|
||||||
* 当为 [FAILED] 的时候, 代表命令执行出现了错误
|
|
||||||
*
|
|
||||||
* 当为 [COMMAND_NOT_FOUND] 的时候,代表没有匹配的命令
|
|
||||||
*
|
|
||||||
* 当为 [EMPTY_COMMAND] 的时候, 代表尝试执行 ""
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum class CommandExecuteStatus {
|
|
||||||
SUCCESSFUL, FAILED, COMMAND_NOT_FOUND, EMPTY_COMMAND
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("RemoveRedundantQualifierName")
|
|
||||||
typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus
|
|
||||||
|
@ -157,3 +157,32 @@ internal fun Group.fuzzySearchMember(nameCardTarget: String): Member? {
|
|||||||
it.nameCard
|
it.nameCard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// internal
|
||||||
|
|
||||||
|
@JvmSynthetic
|
||||||
|
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.executeCommandInternal(
|
||||||
|
messages: Any,
|
||||||
|
commandName: String
|
||||||
|
): Command? {
|
||||||
|
val command = InternalCommandManager.matchCommand(commandName) ?: return null
|
||||||
|
val rawInput = messages.flattenCommandComponents()
|
||||||
|
|
||||||
|
val loweredArgs = rawInput.dropToTypedArray(1)
|
||||||
|
|
||||||
|
kotlin.runCatching {
|
||||||
|
command.onCommand(this, loweredArgs)
|
||||||
|
}.fold(
|
||||||
|
onSuccess = {
|
||||||
|
return command
|
||||||
|
},
|
||||||
|
onFailure = {
|
||||||
|
throw CommandExecutionException(command, commandName, loweredArgs, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -22,9 +22,8 @@ package net.mamoe.mirai.console.pure
|
|||||||
import net.mamoe.mirai.console.MiraiConsoleInitializer
|
import net.mamoe.mirai.console.MiraiConsoleInitializer
|
||||||
import net.mamoe.mirai.console.command.CommandExecuteStatus
|
import net.mamoe.mirai.console.command.CommandExecuteStatus
|
||||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||||
import net.mamoe.mirai.console.command.executeCommand
|
import net.mamoe.mirai.console.command.executeCommandDetailed
|
||||||
import net.mamoe.mirai.message.data.Message
|
import net.mamoe.mirai.message.data.Message
|
||||||
import net.mamoe.mirai.message.data.PlainText
|
|
||||||
import net.mamoe.mirai.utils.DefaultLogger
|
import net.mamoe.mirai.utils.DefaultLogger
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
@ -48,14 +47,11 @@ internal fun startConsoleThread() {
|
|||||||
while (true) {
|
while (true) {
|
||||||
val next = MiraiConsoleFrontEndPure.requestInput("")
|
val next = MiraiConsoleFrontEndPure.requestInput("")
|
||||||
consoleLogger.debug("INPUT> $next")
|
consoleLogger.debug("INPUT> $next")
|
||||||
val result = ConsoleCS.executeCommand(PlainText(next))
|
val result = ConsoleCS.executeCommandDetailed(next)
|
||||||
when (result.status) {
|
when (result.status) {
|
||||||
CommandExecuteStatus.SUCCESSFUL -> {
|
CommandExecuteStatus.SUCCESSFUL -> {
|
||||||
}
|
}
|
||||||
CommandExecuteStatus.EMPTY_COMMAND -> {
|
CommandExecuteStatus.EXECUTION_EXCEPTION -> {
|
||||||
}
|
|
||||||
CommandExecuteStatus.FAILED -> {
|
|
||||||
consoleLogger.error("An error occurred while executing the command: $next", result.exception)
|
|
||||||
}
|
}
|
||||||
CommandExecuteStatus.COMMAND_NOT_FOUND -> {
|
CommandExecuteStatus.COMMAND_NOT_FOUND -> {
|
||||||
consoleLogger.warning("Unknown command: ${result.commandName}")
|
consoleLogger.warning("Unknown command: ${result.commandName}")
|
||||||
|
Loading…
Reference in New Issue
Block a user