mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-11 02:50:15 +08:00
Documentations and several improvements
This commit is contained in:
parent
0a7097b354
commit
775b888273
@ -16,8 +16,9 @@ import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import net.mamoe.mirai.alsoLogin
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.CommandManagerImpl.allRegisteredCommands
|
||||
import net.mamoe.mirai.console.command.CommandManagerImpl.register
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl.allRegisteredCommands
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.message.nextMessageOrNull
|
||||
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.internal.command.isValidSubName
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
@ -53,14 +53,17 @@ public interface Command {
|
||||
public val prefixOptional: Boolean
|
||||
|
||||
/**
|
||||
* 指令拥有者, 对于插件的指令通常是 [PluginCommandOwner]
|
||||
* 指令拥有者.
|
||||
* @see CommandOwner
|
||||
*/
|
||||
public val owner: CommandOwner
|
||||
|
||||
/**
|
||||
* 在指令被执行时调用.
|
||||
*
|
||||
* @param args 指令参数. 数组元素类型可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
||||
*
|
||||
* @see CommandManager.execute
|
||||
* @see CommandManager.executeCommand 查看更多信息
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
public suspend fun CommandSender.onCommand(args: Array<out Any>)
|
||||
@ -81,16 +84,23 @@ public suspend inline fun Command.onCommand(sender: CommandSender, args: Array<o
|
||||
|
||||
/**
|
||||
* [Command] 的基础实现
|
||||
*
|
||||
* @see SimpleCommand
|
||||
* @see CompositeCommand
|
||||
* @see RawCommand
|
||||
*/
|
||||
public abstract class AbstractCommand @JvmOverloads constructor(
|
||||
public final override val owner: CommandOwner,
|
||||
/** 指令拥有者. */
|
||||
public override val owner: CommandOwner,
|
||||
vararg names: String,
|
||||
description: String = "<no description available>",
|
||||
public final override val permission: CommandPermission = CommandPermission.Default,
|
||||
public final override val prefixOptional: Boolean = false
|
||||
/** 指令权限 */
|
||||
public override val permission: CommandPermission = CommandPermission.Default,
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
public override val prefixOptional: Boolean = false
|
||||
) : Command {
|
||||
public final override val description: String = description.trimIndent()
|
||||
public final override val names: Array<out String> =
|
||||
public override val description: String = description.trimIndent()
|
||||
public override val names: Array<out String> =
|
||||
names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).also { list ->
|
||||
list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") }
|
||||
}.toTypedArray()
|
||||
|
@ -18,6 +18,10 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
* 在 [CommandManager.executeCommand] 中, [Command.onCommand] 抛出异常时包装的异常.
|
||||
*/
|
||||
public class CommandExecutionException(
|
||||
/**
|
||||
* 执行者
|
||||
*/
|
||||
public val sender: CommandSender,
|
||||
/**
|
||||
* 执行过程发生异常的指令
|
||||
*/
|
||||
|
@ -16,9 +16,15 @@
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
|
||||
/**
|
||||
* 指令管理器
|
||||
*/
|
||||
public interface CommandManager {
|
||||
/**
|
||||
* 获取已经注册了的属于这个 [CommandOwner] 的指令列表.
|
||||
@ -79,6 +85,7 @@ public interface CommandManager {
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
* @see executeCommand
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
@Throws(CommandExecutionException::class)
|
||||
@ -89,6 +96,7 @@ public interface CommandManager {
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
* @see executeCommand
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
@Throws(CommandExecutionException::class)
|
||||
@ -97,6 +105,16 @@ public interface CommandManager {
|
||||
/**
|
||||
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||
*
|
||||
* 执行过程中产生的异常将不会直接抛出, 而会包装为 [CommandExecuteResult.ExecutionFailed]
|
||||
*
|
||||
* ### 指令解析流程
|
||||
* 1. [messages] 的第一个消息元素的 [内容][Message.contentToString] 被作为指令名, 在已注册指令列表中搜索. (包含 [Command.prefixOptional] 相关的处理)
|
||||
* 2. 参数语法分析.
|
||||
* 在当前的实现下, [messages] 被以空格和 [SingleMessage] 分割.
|
||||
* 如 "MessageChain("foo bar", [Image], " test")" 被分割为 "foo", "bar", [Image], "test".
|
||||
* 注意: 字符串与消息元素之间不需要空格, 会被强制分割. 如 "bar[mirai:image:]" 会被分割为 "bar" 和 [Image] 类型的消息元素.
|
||||
* 3. 参数解析. 各类型指令实现不同. 详见 [RawCommand], [CompositeCommand], [SimpleCommand]
|
||||
*
|
||||
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||
*
|
||||
* @return 执行结果
|
||||
|
@ -18,6 +18,10 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
* 总是作为 [CommandExecutionException.cause].
|
||||
*/
|
||||
public class CommandPermissionDeniedException(
|
||||
/**
|
||||
* 执行者
|
||||
*/
|
||||
public val commandSender: CommandSender,
|
||||
/**
|
||||
* 执行过程发生异常的指令
|
||||
*/
|
||||
|
@ -24,10 +24,34 @@ import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
|
||||
/**
|
||||
* 指令发送者
|
||||
* 指令发送者.
|
||||
*
|
||||
* ### 获得指令发送者
|
||||
* - [MessageEvent.toCommandSender]
|
||||
* - [FriendMessageEvent.toCommandSender]
|
||||
* - [GroupMessageEvent.toCommandSender]
|
||||
* - [TempMessageEvent.toCommandSender]
|
||||
*
|
||||
* - [Member.asCommandSender]
|
||||
* - [Friend.asCommandSender]
|
||||
* - [User.asCommandSender]
|
||||
*
|
||||
* ### 子类型
|
||||
*
|
||||
* 当真实收到由用户执行的指令时:
|
||||
* - 若用户在群内指令执行, 对应 [CommandSender] 为 [MemberCommandSenderOnMessage]
|
||||
* - 若用户在私聊环境内指令执行, 对应 [CommandSender] 为 [FriendCommandSenderOnMessage]
|
||||
* - 若用户在临时会话内指令执行, 对应 [CommandSender] 为 [TempCommandSenderOnMessage]
|
||||
*
|
||||
* 当指令由其他插件主动执行时, 插件应使用 [toCommandSender] 或 [asCommandSender], 因此
|
||||
* - 若用户在群内指令执行, 对应 [CommandSender] 为 [MemberCommandSender]
|
||||
* - 若用户在私聊环境内指令执行, 对应 [CommandSender] 为 [FriendCommandSender]
|
||||
* - 若用户在临时会话内指令执行, 对应 [CommandSender] 为 [TempCommandSender]
|
||||
*
|
||||
* @see ConsoleCommandSender 控制台
|
||||
* @see UserCommandSender [User] ([群成员][Member], [好友][Friend])
|
||||
* @see toCommandSender
|
||||
* @see asCommandSender
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
public interface CommandSender {
|
||||
@ -109,10 +133,16 @@ public abstract class ConsoleCommandSender internal constructor() : CommandSende
|
||||
}
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun FriendMessageEvent.toCommandSender(): FriendCommandSenderOnMessage = FriendCommandSenderOnMessage(this)
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun GroupMessageEvent.toCommandSender(): MemberCommandSenderOnMessage = MemberCommandSenderOnMessage(this)
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun TempMessageEvent.toCommandSender(): TempCommandSenderOnMessage = TempCommandSenderOnMessage(this)
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun MessageEvent.toCommandSender(): CommandSenderOnMessage<*> = when (this) {
|
||||
is FriendMessageEvent -> toCommandSender()
|
||||
is GroupMessageEvent -> toCommandSender()
|
||||
@ -120,9 +150,13 @@ public fun MessageEvent.toCommandSender(): CommandSenderOnMessage<*> = when (thi
|
||||
else -> throw IllegalArgumentException("unsupported MessageEvent: ${this::class.qualifiedNameOrTip}")
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun Member.asCommandSender(): MemberCommandSender = MemberCommandSender(this)
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this)
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public fun User.asCommandSender(): UserCommandSender {
|
||||
return when (this) {
|
||||
is Friend -> this.asCommandSender()
|
||||
|
@ -26,7 +26,51 @@ import kotlin.annotation.AnnotationTarget.FUNCTION
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* 复合指令.
|
||||
* 复合指令. 指令注册时候会通过反射构造指令解析器.
|
||||
*
|
||||
* 示例:
|
||||
* ```
|
||||
* @OptIn(ConsoleExperimentalAPI::class)
|
||||
* object MyCompositeCommand : CompositeCommand(
|
||||
* MyPluginMain, "manage", // "manage" 是主指令名
|
||||
* description = "示例指令", permission = MyCustomPermission,
|
||||
* // prefixOptional = true // 还有更多参数可填, 此处忽略
|
||||
* ) {
|
||||
*
|
||||
* // [参数智能解析]
|
||||
* //
|
||||
* // 在控制台执行 "/manage <群号>.<群员> <持续时间>",
|
||||
* // 或在聊天群内发送 "/manage <@一个群员> <持续时间>",
|
||||
* // 或在聊天群内发送 "/manage <目标群员的群名> <持续时间>",
|
||||
* // 或在聊天群内发送 "/manage <目标群员的账号> <持续时间>"
|
||||
* // 时调用这个函数
|
||||
* @SubCommand
|
||||
* suspend fun CommandSender.mute(target: Member, duration: Int) { // 通过 /manage mute <target> <duration> 调用
|
||||
* sendMessage("/manage mute 被调用了, 参数为: $target, $duration")
|
||||
*
|
||||
* val result = kotlin.runCatching {
|
||||
* target.mute(duration).toString()
|
||||
* }.getOrElse {
|
||||
* it.stackTraceToString()
|
||||
* } // 失败时返回堆栈信息
|
||||
*
|
||||
* sendMessage("结果: $result")
|
||||
* }
|
||||
*
|
||||
* @SubCommand
|
||||
* suspend fun CommandSender.list() { // 执行 "/manage list" 时调用这个函数
|
||||
* sendMessage("/manage list 被调用了")
|
||||
* }
|
||||
*
|
||||
* // 支持 Image 类型, 需在聊天中执行此指令.
|
||||
* @SubCommand
|
||||
* suspend fun CommandSender.test(image: Image) { // 执行 "/manage test <一张图片>" 时调用这个函数
|
||||
* sendMessage("/manage image 被调用了, 图片是 ${image.imageId}")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see buildCommandArgumentContext
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public abstract class CompositeCommand @JvmOverloads constructor(
|
||||
@ -80,3 +124,73 @@ public abstract class CompositeCommand @JvmOverloads constructor(
|
||||
internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
||||
get() = CompositeCommandSubCommandAnnotationResolver
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 复合指令. 指令注册时候会通过反射构造指令解析器.
|
||||
*
|
||||
* 示例:
|
||||
* ```
|
||||
* public final class MyCompositeCommand extends CompositeCommand {
|
||||
* public static final MyCompositeCommand INSTANCE = new MyCompositeCommand();
|
||||
*
|
||||
* public MyCompositeCommand() {
|
||||
* super(MyPluginMain.INSTANCE, "manage") // "manage" 是主指令名
|
||||
* }
|
||||
*
|
||||
* // [参数智能解析]
|
||||
* //
|
||||
* //
|
||||
* // 在控制台执行 "/manage <群号>.<群员> <持续时间>",
|
||||
* // 或在聊天群内发送 "/manage <@一个群员> <持续时间>",
|
||||
* // 或在聊天群内发送 "/manage <目标群员的群名> <持续时间>",
|
||||
* // 或在聊天群内发送 "/manage <目标群员的账号> <持续时间>"
|
||||
* // 时调用这个函数
|
||||
* @SubCommand
|
||||
* public void mute(CommandSender sender, Member target, int duration) { // 通过 /manage mute <target> <duration> 调用.
|
||||
* sender.sendMessage("/manage mute 被调用了, 参数为: " + target + ", " + duration);
|
||||
*
|
||||
*
|
||||
* String result;
|
||||
* try {
|
||||
* result = target.mute(duration).toString();
|
||||
* } catch(Exception e) {
|
||||
* result = ExceptionsKt.stackTraceToString(e);
|
||||
* }
|
||||
*
|
||||
* sender.sendMessage("结果: " + result)
|
||||
* }
|
||||
*
|
||||
* @SubCommand
|
||||
* public void list(CommandSender sender) { // 执行 "/manage list" 时调用这个方法
|
||||
* sender.sendMessage("/manage list 被调用了")
|
||||
* }
|
||||
*
|
||||
* // 支持 Image 类型, 需在聊天中执行此指令.
|
||||
* @SubCommand
|
||||
* public void test(CommandSender sender, Image image) { // 执行 "/manage test <一张图片>" 时调用这个方法
|
||||
* sender.sendMessage("/manage image 被调用了, 图片是 " + image.imageId)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see buildCommandArgumentContext
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public abstract class JCompositeCommand(
|
||||
owner: CommandOwner,
|
||||
vararg names: String
|
||||
) : CompositeCommand(owner, *names) {
|
||||
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */
|
||||
public final override var description: String = "<no descriptions given>"
|
||||
protected set
|
||||
|
||||
/** 指令权限 */
|
||||
public final override var permission: CommandPermission = CommandPermission.Default
|
||||
protected set
|
||||
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
public final override var prefixOptional: Boolean = false
|
||||
protected set
|
||||
|
||||
}
|
@ -7,18 +7,118 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
|
||||
/**
|
||||
* 无参数解析, 接收原生参数的指令.
|
||||
*
|
||||
* ### 指令执行流程
|
||||
* 继 [CommandManager.executeCommand] 所述第 3 步, [RawCommand] 不会对参数做任何解析.
|
||||
*
|
||||
* @see JRawCommand 供 Java 用户继承.
|
||||
*
|
||||
* @see SimpleCommand 简单指令
|
||||
* @see CompositeCommand 复合指令
|
||||
*/
|
||||
public abstract class RawCommand @JvmOverloads constructor(
|
||||
/**
|
||||
* 指令拥有者.
|
||||
* @see CommandOwner
|
||||
*/
|
||||
public override val owner: CommandOwner,
|
||||
/** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */
|
||||
public override vararg val names: String,
|
||||
/** 用法说明, 用于发送给用户 */
|
||||
public override val usage: String = "<no usages given>",
|
||||
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */
|
||||
public override val description: String = "<no descriptions given>",
|
||||
/** 指令权限 */
|
||||
public override val permission: CommandPermission = CommandPermission.Default,
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
public override val prefixOptional: Boolean = false
|
||||
) : Command {
|
||||
/**
|
||||
* 在指令被执行时调用.
|
||||
*
|
||||
* @param args 指令参数. 数组元素类型可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
||||
*
|
||||
* @see CommandManager.execute 查看更多信息
|
||||
*/
|
||||
public abstract override suspend fun CommandSender.onCommand(args: Array<out Any>)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 供 Java 用户继承
|
||||
*
|
||||
* 请在构造时设置相关属性.
|
||||
*
|
||||
* ```java
|
||||
* public final class MyCommand extends JRawCommand {
|
||||
* public static final MyCommand INSTANCE = new MyCommand();
|
||||
* private MyCommand () {
|
||||
* super(MyPluginMain.INSTANCE, "test")
|
||||
* // 可选设置如下属性
|
||||
* setUsage("/test")
|
||||
* setDescription("这是一个测试指令")
|
||||
* setPermission(CommandPermission.Operator.INSTANCE)
|
||||
* setPrefixOptional(true)
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public void onCommand(@NotNull CommandSender sender, @NotNull args: Object[]) {
|
||||
* // 处理指令
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see RawCommand
|
||||
*/
|
||||
public abstract class JRawCommand(
|
||||
/**
|
||||
* 指令拥有者.
|
||||
* @see CommandOwner
|
||||
*/
|
||||
public override val owner: CommandOwner,
|
||||
/** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */
|
||||
public override vararg val names: String
|
||||
) : Command {
|
||||
/** 用法说明, 用于发送给用户 */
|
||||
public override var usage: String = "<no usages given>"
|
||||
protected set
|
||||
|
||||
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */
|
||||
public final override var description: String = "<no descriptions given>"
|
||||
protected set
|
||||
|
||||
/** 指令权限 */
|
||||
public final override var permission: CommandPermission = CommandPermission.Default
|
||||
protected set
|
||||
|
||||
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
|
||||
public final override var prefixOptional: Boolean = false
|
||||
protected set
|
||||
|
||||
/**
|
||||
* 在指令被执行时调用.
|
||||
*
|
||||
* @param args 指令参数. 数组元素类型可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
||||
*
|
||||
* @see CommandManager.execute 查看更多信息
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
@JvmName("onCommand")
|
||||
public abstract fun onCommand(sender: CommandSender, args: Array<out Any>)
|
||||
|
||||
public final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
||||
withContext(Dispatchers.IO) { onCommand(this@onCommand, args) }
|
||||
}
|
||||
}
|
@ -17,19 +17,23 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
import net.mamoe.mirai.console.command.description.*
|
||||
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
|
||||
import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver
|
||||
|
||||
/**
|
||||
* 简单指令. 参数支持自动解析. [CommandArgumentParser]
|
||||
* 简单的, 支持参数自动解析的指令.
|
||||
*
|
||||
* 要查看指令解析流程, 参考 [CommandManager.executeCommand]
|
||||
* 要查看参数解析方式, 参考 [CommandArgumentParser]
|
||||
*
|
||||
* Kotlin 实现:
|
||||
* ```
|
||||
* object MySimpleCommand : SimpleCommand(
|
||||
* MyPlugin, "tell",
|
||||
* description = "Message somebody",
|
||||
* usage = "/tell <target> <message>"
|
||||
* usage = "/tell <target> <message>" // usage 如不设置则自动根据带有 @Handler 的方法生成
|
||||
* ) {
|
||||
* @Handler
|
||||
* suspend fun CommandSender.onCommand(target: User, message: String) {
|
||||
@ -38,18 +42,8 @@ import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotatio
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Java 实现:
|
||||
* ```java
|
||||
* public final class MySimpleCommand extends SimpleCommand {
|
||||
* private MySimpleCommand() {
|
||||
* super(MyPlugin.INSTANCE, new String[]{ "tell" }, "Message somebody", "/tell <target> <message>")
|
||||
* }
|
||||
* @Handler
|
||||
* public void onCommand(CommandSender sender, User target, String message) {
|
||||
* target.sendMessage(message)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @see JSimpleCommand Java 实现
|
||||
* @see [CommandManager.executeCommand]
|
||||
*/
|
||||
public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
owner: CommandOwner,
|
||||
@ -69,7 +63,7 @@ public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
*/
|
||||
protected annotation class Handler
|
||||
|
||||
public final override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
|
||||
public override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
|
||||
|
||||
public final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
||||
subCommands.single().parseAndExecute(this, args, false)
|
||||
@ -86,3 +80,40 @@ public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
||||
get() = SimpleCommandSubCommandAnnotationResolver
|
||||
}
|
||||
|
||||
/**
|
||||
* Java 实现:
|
||||
* ```java
|
||||
* public final class MySimpleCommand extends JSimpleCommand {
|
||||
* private MySimpleCommand() {
|
||||
* super(MyPlugin.INSTANCE, "tell")
|
||||
* // 可选设置如下属性
|
||||
* setDescription("这是一个测试指令")
|
||||
* setUsage("/tell <target> <message>") // 如不设置则自动根据带有 @Handler 的方法生成
|
||||
* setPermission(CommandPermission.Operator.INSTANCE)
|
||||
* setPrefixOptional(true)
|
||||
* }
|
||||
*
|
||||
* @Handler
|
||||
* public void onCommand(CommandSender sender, User target, String message) {
|
||||
* target.sendMessage(message)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see SimpleCommand
|
||||
* @see [CommandManager.executeCommand]
|
||||
*/
|
||||
public abstract class JSimpleCommand(
|
||||
owner: CommandOwner,
|
||||
vararg names: String
|
||||
) : SimpleCommand(owner, *names) {
|
||||
public override var description: String = super.description
|
||||
protected set
|
||||
public override var permission: CommandPermission = super.permission
|
||||
protected set
|
||||
public override var prefixOptional: Boolean = super.prefixOptional
|
||||
protected set
|
||||
public override var context: CommandArgumentContext = super.context
|
||||
protected set
|
||||
}
|
@ -92,7 +92,7 @@ public object BooleanArgumentParser : InternalCommandArgumentParserExtensions<Bo
|
||||
/**
|
||||
* 根据 [Bot.id] 解析一个登录后的 [Bot]
|
||||
*/
|
||||
public object ExistBotArgumentParser : InternalCommandArgumentParserExtensions<Bot> {
|
||||
public object ExistingBotArgumentParser : InternalCommandArgumentParserExtensions<Bot> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Bot =
|
||||
if (raw == "~") sender.inferBotOrFail()
|
||||
else raw.findBotOrFail()
|
||||
@ -108,7 +108,7 @@ public object ExistBotArgumentParser : InternalCommandArgumentParserExtensions<B
|
||||
*
|
||||
* 当只登录了一个 [Bot] 时, 无需上述 `botId` 参数即可
|
||||
*/
|
||||
public object ExistFriendArgumentParser : InternalCommandArgumentParserExtensions<Friend> {
|
||||
public object ExistingFriendArgumentParser : InternalCommandArgumentParserExtensions<Friend> {
|
||||
private val syntax = """
|
||||
- `botId.friendId`
|
||||
- `botId.friendNick` (模糊搜索, 寻找最优匹配)
|
||||
@ -153,7 +153,7 @@ public object ExistFriendArgumentParser : InternalCommandArgumentParserExtension
|
||||
*
|
||||
* 当只登录了一个 [Bot] 时, 无需上述 `botId` 参数即可
|
||||
*/
|
||||
public object ExistGroupArgumentParser : InternalCommandArgumentParserExtensions<Group> {
|
||||
public object ExistingGroupArgumentParser : InternalCommandArgumentParserExtensions<Group> {
|
||||
private val syntax = """
|
||||
- `botId.groupId`
|
||||
- `~` (指代指令调用人自己所在群. 仅群聊天环境下)
|
||||
|
@ -26,15 +26,18 @@ import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
/**
|
||||
* [CommandArgumentParser] 的集合, 用于 [CompositeCommand] 和 [SimpleCommand].
|
||||
* 指令参数环境, 即 [CommandArgumentParser] 的集合, 用于 [CompositeCommand] 和 [SimpleCommand].
|
||||
*
|
||||
* 在指令解析时, 总是从 [CommandArgumentContextAware.context] 搜索相关解析器
|
||||
*
|
||||
* 要构造 [CommandArgumentContext], 参考 [buildCommandArgumentContext]
|
||||
*
|
||||
* @see SimpleCommandArgumentContext 简单实现
|
||||
* @see EmptyCommandArgumentContext 空实现, 类似 [emptyList]
|
||||
* @see CommandArgumentContext.EMPTY 空实现的另一种获取方式.
|
||||
*
|
||||
* @see CommandArgumentContext.Builtins 内建 [CommandArgumentParser]
|
||||
*
|
||||
* @see CommandArgumentContext DSL
|
||||
* @see buildCommandArgumentContext DSL 构造
|
||||
*/
|
||||
public interface CommandArgumentContext {
|
||||
/**
|
||||
@ -62,7 +65,7 @@ public interface CommandArgumentContext {
|
||||
/**
|
||||
* 内建的默认 [CommandArgumentParser]
|
||||
*/
|
||||
public object Builtins : CommandArgumentContext by (CommandArgumentContext {
|
||||
public object Builtins : CommandArgumentContext by (buildCommandArgumentContext {
|
||||
Int::class with IntArgumentParser
|
||||
Byte::class with ByteArgumentParser
|
||||
Short::class with ShortArgumentParser
|
||||
@ -73,14 +76,14 @@ public interface CommandArgumentContext {
|
||||
Float::class with FloatArgumentParser
|
||||
|
||||
Member::class with ExistMemberArgumentParser
|
||||
Group::class with ExistGroupArgumentParser
|
||||
Friend::class with ExistFriendArgumentParser
|
||||
Bot::class with ExistBotArgumentParser
|
||||
Group::class with ExistingGroupArgumentParser
|
||||
Friend::class with ExistingFriendArgumentParser
|
||||
Bot::class with ExistingBotArgumentParser
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拥有 [CommandArgumentContext] 的类
|
||||
* 拥有 [buildCommandArgumentContext] 的类
|
||||
*
|
||||
* @see SimpleCommand
|
||||
* @see CompositeCommand
|
||||
@ -95,7 +98,7 @@ public interface CommandArgumentContextAware {
|
||||
public object EmptyCommandArgumentContext : CommandArgumentContext by SimpleCommandArgumentContext(listOf())
|
||||
|
||||
/**
|
||||
* 合并两个 [CommandArgumentContext], [replacer] 将会替换 [this] 中重复的 parser.
|
||||
* 合并两个 [buildCommandArgumentContext], [replacer] 将会替换 [this] 中重复的 parser.
|
||||
*/
|
||||
public operator fun CommandArgumentContext.plus(replacer: CommandArgumentContext): CommandArgumentContext {
|
||||
if (replacer == EmptyCommandArgumentContext) return this
|
||||
@ -125,9 +128,9 @@ public operator fun CommandArgumentContext.plus(replacer: List<ParserPair<*>>):
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 [CommandArgumentContext]
|
||||
* 自定义 [buildCommandArgumentContext]
|
||||
*
|
||||
* @see CommandArgumentContext
|
||||
* @see buildCommandArgumentContext
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public class SimpleCommandArgumentContext(
|
||||
@ -140,10 +143,11 @@ public class SimpleCommandArgumentContext(
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个 [CommandArgumentContext].
|
||||
* 构建一个 [buildCommandArgumentContext].
|
||||
*
|
||||
* Kotlin 实现:
|
||||
* ```
|
||||
* CommandArgumentContext {
|
||||
* val context = buildCommandArgumentContext {
|
||||
* Int::class with IntArgParser
|
||||
* Member::class with ExistMemberArgParser
|
||||
* Group::class with { s: String, sender: CommandSender ->
|
||||
@ -155,22 +159,47 @@ public class SimpleCommandArgumentContext(
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Java 实现:
|
||||
* ```java
|
||||
* CommandArgumentContext context =
|
||||
* new CommandArgumentContextBuilder()
|
||||
* .add(clazz1, parser1)
|
||||
* .add(String.class, new CommandArgumentParser<String>() {
|
||||
* public String parse(String raw, CommandSender sender) {
|
||||
* // ...
|
||||
* }
|
||||
* })
|
||||
* // 更多 add
|
||||
* .build()
|
||||
* ```
|
||||
*
|
||||
* @see CommandArgumentContextBuilder
|
||||
* @see CommandArgumentContext
|
||||
* @see buildCommandArgumentContext
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@JvmSynthetic
|
||||
public fun CommandArgumentContext(block: CommandArgumentContextBuilder.() -> Unit): CommandArgumentContext {
|
||||
return SimpleCommandArgumentContext(CommandArgumentContextBuilder().apply(block).distinctByReversed { it.klass })
|
||||
public fun buildCommandArgumentContext(block: CommandArgumentContextBuilder.() -> Unit): CommandArgumentContext {
|
||||
return CommandArgumentContextBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CommandArgumentContext
|
||||
* 参考 [buildCommandArgumentContext]
|
||||
*/
|
||||
public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutableListOf() {
|
||||
@JvmName("add") // TODO: 2020/8/19 java class support
|
||||
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgumentParser<T>): ParserPair<*> =
|
||||
ParserPair(this, parser).also { add(it) }
|
||||
/**
|
||||
* 添加一个指令解析器.
|
||||
*/
|
||||
@JvmName("add")
|
||||
public infix fun <T : Any> Class<T>.with(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder =
|
||||
this.kotlin with parser
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@JvmName("add")
|
||||
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder {
|
||||
add(ParserPair(this, parser))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
@ -179,7 +208,12 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgumentParser<T>.(s: String, sender: CommandSender) -> T
|
||||
): ParserPair<*> = ParserPair(this, CommandArgumentParser(parser)).also { add(it) }
|
||||
): CommandArgumentContextBuilder {
|
||||
add(ParserPair(this, object : CommandArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender)
|
||||
}))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
@ -187,12 +221,18 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@JvmSynthetic
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgumentParser<T>.(s: String) -> T
|
||||
): ParserPair<*> =
|
||||
ParserPair(this, CommandArgumentParser { s: String, _: CommandSender -> parser(s) }).also { add(it) }
|
||||
): CommandArgumentContextBuilder {
|
||||
add(ParserPair(this, object : CommandArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw)
|
||||
}))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
public inline fun <reified T : Any> add(parser: CommandArgumentParser<T>): ParserPair<*> =
|
||||
ParserPair(T::class, parser).also { add(it) }
|
||||
public inline fun <reified T : Any> add(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder {
|
||||
add(ParserPair(T::class, parser))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
@ -201,7 +241,9 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@JvmSynthetic
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgumentParser<*>.(s: String) -> T
|
||||
): ParserPair<*> = T::class with CommandArgumentParser { s: String, _: CommandSender -> parser(s) }
|
||||
): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
@ -211,7 +253,14 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgumentParser<*>.(s: String, sender: CommandSender) -> T
|
||||
): ParserPair<*> = T::class with CommandArgumentParser(parser)
|
||||
): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender)
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成构建, 得到 [CommandArgumentContext]
|
||||
*/
|
||||
public fun build(): CommandArgumentContext = SimpleCommandArgumentContext(this.distinctByReversed { it.klass })
|
||||
}
|
||||
|
||||
internal inline fun <T, K> List<T>.distinctByReversed(selector: (T) -> K): List<T> {
|
||||
|
@ -11,27 +11,82 @@
|
||||
|
||||
package net.mamoe.mirai.console.command.description
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.SimpleCommand
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
import net.mamoe.mirai.message.data.content
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* 指令参数解析器.
|
||||
* 指令参数解析器. 用于解析字符串或 [SingleMessage] 到特定参数类型.
|
||||
*
|
||||
* @see CommandArgumentContext
|
||||
* @see ExistFriendArgumentParser
|
||||
* ### 参数解析
|
||||
*
|
||||
* 如 [SimpleCommand] 中的示例:
|
||||
* ```
|
||||
* suspend fun CommandSender.mute(target: Member, duration: Int)
|
||||
* ```
|
||||
* [CommandManager] 总是从 [SimpleCommand.context] 搜索一个 [T] 为 [Member] 的 [CommandArgumentParser], 并调用其 [CommandArgumentParser.parse]
|
||||
*
|
||||
* ### 内建指令解析器
|
||||
* - 基础类型: [ByteArgumentParser], [ShortArgumentParser], [IntArgumentParser], [LongArgumentParser]
|
||||
* [FloatArgumentParser], [DoubleArgumentParser],
|
||||
* [BooleanArgumentParser], [StringArgumentParser]
|
||||
*
|
||||
* - [Bot]: [ExistingBotArgumentParser]
|
||||
* - [Friend]: [ExistingFriendArgumentParser]
|
||||
* - [Group]: [ExistingGroupArgumentParser]
|
||||
* - [Member]: [ExistMemberArgumentParser]
|
||||
*
|
||||
*
|
||||
* @see SimpleCommand 简单指令
|
||||
* @see CompositeCommand 复合指令
|
||||
*
|
||||
* @see buildCommandArgumentContext 指令参数环境, 即 [CommandArgumentParser] 的集合
|
||||
*/
|
||||
public interface CommandArgumentParser<out T : Any> {
|
||||
/**
|
||||
* 解析一个字符串为 [T] 类型参数
|
||||
*
|
||||
* **实现提示**: 在解析时遇到意料之中的问题, 如无法找到目标群员, 可抛出 [CommandArgumentParserException].
|
||||
* 此异常将会被特殊处理, 不会引发一个错误, 而是作为指令调用成功的情况, 将错误信息发送给用户.
|
||||
*
|
||||
* @throws CommandArgumentParserException 当解析时遇到*意料之中*的问题时抛出.
|
||||
*
|
||||
* @see CommandArgumentParserException
|
||||
*/
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
public fun parse(raw: String, sender: CommandSender): T
|
||||
|
||||
/**
|
||||
* 解析一个字符串为 [T] 类型参数
|
||||
*
|
||||
* **实现提示**: 在解析时遇到意料之中的问题, 如无法找到目标群员, 可抛出 [CommandArgumentParserException].
|
||||
* 此异常将会被特殊处理, 不会引发一个错误, 而是作为指令调用成功的情况, 将错误信息发送给用户.
|
||||
*
|
||||
* @throws CommandArgumentParserException 当解析时遇到*意料之中*的问题时抛出.
|
||||
*
|
||||
* @see CommandArgumentParserException
|
||||
*/
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
@JvmDefault
|
||||
public fun parse(raw: SingleMessage, sender: CommandSender): T = parse(raw.content, sender)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析
|
||||
* 解析一个字符串或 [SingleMessage] 为 [T] 类型参数
|
||||
*
|
||||
* @throws IllegalArgumentException 当 [raw] 既不是 [SingleMessage], 也不是 [String] 时抛出.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@Throws(IllegalArgumentException::class)
|
||||
public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||
contract {
|
||||
returns() implies (raw is String || raw is SingleMessage)
|
||||
@ -45,14 +100,23 @@ public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSen
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出一个 [CommandArgumentParserException]
|
||||
* 抛出一个 [CommandArgumentParserException] 的捷径
|
||||
*
|
||||
* @throws CommandArgumentParserException
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmSynthetic
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
public inline fun CommandArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||
throw CommandArgumentParserException(message, cause)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查参数 [condition]. 当它为 `false` 时调用 [message] 并以其返回值作为消息, 抛出异常 [CommandArgumentParserException]
|
||||
*
|
||||
* @throws CommandArgumentParserException
|
||||
*/
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
@JvmSynthetic
|
||||
public inline fun CommandArgumentParser<*>.checkArgument(
|
||||
condition: Boolean,
|
||||
@ -60,10 +124,13 @@ public inline fun CommandArgumentParser<*>.checkArgument(
|
||||
) {
|
||||
contract {
|
||||
returns() implies condition
|
||||
callsInPlace(message, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
if (!condition) illegalArgument(message())
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/**
|
||||
* 创建匿名 [CommandArgumentParser]
|
||||
*/
|
||||
@ -88,3 +155,4 @@ public inline fun <T : Any> CommandArgumentParser(
|
||||
override fun parse(raw: SingleMessage, sender: CommandSender): T = messageParser(raw, sender)
|
||||
}
|
||||
|
||||
*/
|
@ -7,16 +7,14 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
package net.mamoe.mirai.console.internal.command
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
import net.mamoe.mirai.console.internal.command.executeCommandInternal
|
||||
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.subscribeAlways
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
@ -88,7 +86,7 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
|
||||
///// IMPL
|
||||
|
||||
|
||||
override val CommandOwner.registeredCommands: List<Command> get() = this@CommandManagerImpl.registeredCommands.filter { it.owner == this }
|
||||
override val CommandOwner.registeredCommands: List<Command> get() = CommandManagerImpl.registeredCommands.filter { it.owner == this }
|
||||
override val allRegisteredCommands: List<Command> get() = registeredCommands.toList() // copy
|
||||
override val commandPrefix: String get() = "/"
|
||||
override fun CommandOwner.unregisterAllCommands() {
|
@ -9,9 +9,10 @@
|
||||
|
||||
@file:Suppress("unused", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.console.command.description
|
||||
package net.mamoe.mirai.console.internal.command
|
||||
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentParser
|
||||
import java.lang.reflect.Parameter
|
||||
import kotlin.reflect.KClass
|
||||
|
@ -14,7 +14,6 @@ package net.mamoe.mirai.console.internal.command
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
|
||||
import net.mamoe.mirai.console.command.description.CommandParameter
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
import kotlin.reflect.KAnnotatedElement
|
||||
|
@ -109,18 +109,14 @@ internal inline fun <reified T> List<T>.dropToTypedArray(n: Int): Array<T> = Arr
|
||||
|
||||
@JvmSynthetic
|
||||
@Throws(CommandExecutionException::class)
|
||||
internal suspend inline fun CommandSender.executeCommandInternal(
|
||||
internal suspend fun CommandSender.executeCommandInternal(
|
||||
command: Command,
|
||||
args: Array<out Any>,
|
||||
commandName: String,
|
||||
checkPermission: Boolean
|
||||
) {
|
||||
if (checkPermission && !command.testPermission(this)) {
|
||||
throw CommandExecutionException(
|
||||
command,
|
||||
commandName,
|
||||
CommandPermissionDeniedException(command)
|
||||
)
|
||||
throw CommandExecutionException(this, command, commandName, CommandPermissionDeniedException(this, command))
|
||||
}
|
||||
|
||||
kotlin.runCatching {
|
||||
@ -128,7 +124,7 @@ internal suspend inline fun CommandSender.executeCommandInternal(
|
||||
}.onFailure {
|
||||
catchExecutionException(it)
|
||||
if (it !is CommandArgumentParserException) {
|
||||
throw CommandExecutionException(command, commandName, it)
|
||||
throw CommandExecutionException(this, command, commandName, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.registeredCommands
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentParser
|
||||
import net.mamoe.mirai.console.command.description.buildCommandArgumentContext
|
||||
import net.mamoe.mirai.console.initTestEnvironment
|
||||
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
@ -187,7 +187,7 @@ internal class TestCommand {
|
||||
val composite = object : CompositeCommand(
|
||||
ConsoleCommandOwner,
|
||||
"test",
|
||||
overrideContext = CommandArgumentContext {
|
||||
overrideContext = buildCommandArgumentContext {
|
||||
add(object : CommandArgumentParser<MyClass> {
|
||||
override fun parse(raw: String, sender: CommandSender): MyClass {
|
||||
return MyClass(raw.toInt())
|
||||
|
Loading…
Reference in New Issue
Block a user