2020-09-04 10:57:32 +08:00
|
|
|
|
# Mirai Console Backend - Commands
|
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`Plugin`]: ../backend/mirai-console/src/plugin/Plugin.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginDescription`]: ../backend/mirai-console/src/plugin/description/PluginDescription.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginLoader`]: ../backend/mirai-console/src/plugin/loader/PluginLoader.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginManager`]: ../backend/mirai-console/src/plugin/PluginManager.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`JvmPluginLoader`]: ../backend/mirai-console/src/plugin/jvm/JvmPluginLoader.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`JvmPlugin`]: ../backend/mirai-console/src/plugin/jvm/JvmPlugin.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`JvmPluginDescription`]: ../backend/mirai-console/src/plugin/jvm/JvmPluginDescription.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`AbstractJvmPlugin`]: ../backend/mirai-console/src/plugin/jvm/AbstractJvmPlugin.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`KotlinPlugin`]: ../backend/mirai-console/src/plugin/jvm/KotlinPlugin.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`JavaPlugin`]: ../backend/mirai-console/src/plugin/jvm/JavaPlugin.kt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[`Value`]: ../backend/mirai-console/src/data/Value.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginData`]: ../backend/mirai-console/src/data/PluginData.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`AbstractPluginData`]: ../backend/mirai-console/src/data/AbstractPluginData.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`AutoSavePluginData`]: ../backend/mirai-console/src/data/AutoSavePluginData.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`AutoSavePluginConfig`]: ../backend/mirai-console/src/data/AutoSavePluginConfig.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginConfig`]: ../backend/mirai-console/src/data/PluginConfig.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginDataStorage`]: ../backend/mirai-console/src/data/PluginDataStorage.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`MultiFilePluginDataStorage`]: ../backend/mirai-console/src/data/PluginDataStorage.kt#L116
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`MemoryPluginDataStorage`]: ../backend/mirai-console/src/data/PluginDataStorage.kt#L100
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`AutoSavePluginDataHolder`]: ../backend/mirai-console/src/data/PluginDataHolder.kt#L45
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginDataHolder`]: ../backend/mirai-console/src/data/PluginDataHolder.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`PluginDataExtensions`]: ../backend/mirai-console/src/data/PluginDataExtensions.kt
|
|
|
|
|
|
|
|
|
|
[`MiraiConsole`]: ../backend/mirai-console/src/MiraiConsole.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`MiraiConsoleImplementation`]: ../backend/mirai-console/src/MiraiConsoleImplementation.kt
|
|
|
|
|
<!--[MiraiConsoleFrontEnd]: ../backend/mirai-console/src/MiraiConsoleFrontEnd.kt-->
|
|
|
|
|
|
|
|
|
|
[`Command`]: ../backend/mirai-console/src/command/Command.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2021-08-25 12:44:57 +08:00
|
|
|
|
[`Register`]: ../backend/mirai-console/src/command/CommandManager.kt#L77
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`AbstractCommand`]: ../backend/mirai-console/src/command/Command.kt#L90
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`CompositeCommand`]: ../backend/mirai-console/src/command/CompositeCommand.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`SimpleCommand`]: ../backend/mirai-console/src/command/SimpleCommand.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`RawCommand`]: ../backend/mirai-console/src/command/RawCommand.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`CommandManager`]: ../backend/mirai-console/src/command/CommandManager.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`CommandSender`]: ../backend/mirai-console/src/command/CommandSender.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`CommandValueArgumentParser`]: ../backend/mirai-console/src/command/descriptor/CommandValueArgumentParser.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`CommandArgumentContext`]: ../backend/mirai-console/src/command/descriptor/CommandArgumentContext.kt
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
[`CommandArgumentContext.BuiltIns`]: ../backend/mirai-console/src/command/descriptor/CommandArgumentContext.kt#L66
|
|
|
|
|
|
|
|
|
|
[`MessageScope`]: ../backend/mirai-console/src/util/MessageScope.kt
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
"指令" 目前通常是 "/commandName arg1 arg2 arg3" 格式的消息。在将来可能会被扩展。
|
|
|
|
|
|
|
|
|
|
指令拥有一个主要名称和任意个次要名称。使用任意名称都可以执行指令。
|
|
|
|
|
|
|
|
|
|
定义指令
|
|
|
|
|
------
|
|
|
|
|
|
|
|
|
|
每个指令都是一个 `Command` 类型的对象。`Command` 是一个接口,定义了基本的指令的属性:
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
interface Command {
|
2022-06-17 20:11:35 +08:00
|
|
|
|
val names: Array<out String> // 名称
|
|
|
|
|
val usage: String // 用法
|
|
|
|
|
val description: String // 描述
|
|
|
|
|
val permission: Permission // 权限
|
|
|
|
|
val prefixOptional: Boolean // 前缀可选
|
|
|
|
|
val owner: CommandOwner // 拥有者
|
|
|
|
|
|
|
|
|
|
val overloads: List<CommandSignature> // 指令的签名列表
|
2020-09-04 10:57:32 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
`AbstractCommand` 提供了对 `Command` 的基础实现。而要在插件定义指令,建议继承如下三种指令实现:
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
(注意:所有指令都需要注册到指令管理器才能生效,详见 [注册指令](#注册指令))
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 原生指令
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
原生指令即 [`RawCommand`],它直接处理触发指令的原消息链。
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
`RawCommand` 提供了两个抽象函数,在指令被执行时将会调用它们:
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Kotlin*
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```kotlin
|
|
|
|
|
open override suspend fun CommandContext.onCommand(args: MessageChain)
|
|
|
|
|
open override suspend fun CommandSender.onCommand(args: MessageChain)
|
|
|
|
|
```
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Java*
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```java
|
|
|
|
|
public abstract class JRawCommand {
|
|
|
|
|
// ...
|
|
|
|
|
public void onCommand(CommandContext context, MessageChain args) {
|
|
|
|
|
}
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
public void onCommand(CommandSender sender, MessageChain args) {
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-04 15:34:34 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
例如在聊天环境通过消息链 `/test 123 [图片]` 触发指令(`[图片]` 表示一个图片),`onCommand` 接收的 `args`
|
|
|
|
|
为包含 2
|
|
|
|
|
个元素的 `MessageChain`。第一个元素为 `PlainText("123")`,第二个元素为 `Image`。
|
|
|
|
|
|
|
|
|
|
注意,当 `onCommand(CommandSender, MessageChain)`
|
|
|
|
|
和 `onCommand(CommandContext, MessageChain)` 被同时覆盖时,
|
|
|
|
|
只有 `onCommand(CommandContext, MessageChain)` 会生效。
|
|
|
|
|
|
|
|
|
|
`CommandContext` 是当前指令的执行环境,定义如下:
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2021-08-25 12:44:57 +08:00
|
|
|
|
```kotlin
|
2022-06-17 20:11:35 +08:00
|
|
|
|
interface CommandContext {
|
|
|
|
|
val sender: CommandSender
|
|
|
|
|
val originalMessage: MessageChain
|
|
|
|
|
}
|
2021-08-25 12:44:57 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
其中 `sender` 为指令执行者。它可能是控制台(`ConsoleCmomandSender`
|
|
|
|
|
),也可能是用户(`UserCommandSender`)等;
|
|
|
|
|
`originalMessage` 为触发指令的原消息链,包含元数据,也包含指令名。
|
|
|
|
|
|
|
|
|
|
若在聊天环境触发指令,`originalMessage` 将会包含 `MessageSource`。
|
|
|
|
|
|
|
|
|
|
注意,`MessageSource` 等 `MessageMetadata` 的位置是不确定的。取决于 mirai-core
|
|
|
|
|
的版本,它可能会存在于消息链中的任意位置。因此请不要依赖于 `originalMessage` 的元素顺序。
|
|
|
|
|
|
|
|
|
|
`args` 参数的顺序是稳定的,因为它只包含消息内容(`MessageContent`)。
|
|
|
|
|
|
|
|
|
|
#### 使用 `RawCommand`
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
只需要按需继承 `onCommand` 其中一个即可。如果需要使用原消息链,则继承 `CommandContext`
|
|
|
|
|
的,否则继承 `CommandSender` 的可以使实现更简单。
|
|
|
|
|
|
|
|
|
|
通常可以以单例形式实现指令,当然非单例模式也是支持的。
|
|
|
|
|
|
|
|
|
|
下面分别为在 Kotlin 和 Java 的示例实现:
|
|
|
|
|
|
|
|
|
|
*Kotlin*
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
|
|
|
|
```kotlin
|
2022-06-17 20:11:35 +08:00
|
|
|
|
object MyCommand : RawCommand(
|
|
|
|
|
MyPluginMain, "name", // 使用插件主类对象作为指令拥有者;设置主指令名为 "name"
|
|
|
|
|
// 可选:
|
|
|
|
|
"name2", "name3", // 增加两个次要名称
|
|
|
|
|
usage = "/name arg1 arg2", // 设置用法,将会在 /help 展示
|
|
|
|
|
description = "这是一个测试指令", // 设置描述,将会在 /help 展示
|
|
|
|
|
prefixOptional = true, // 设置指令前缀是可选的,即使用 `test` 也能执行指令而不需要 `/test`
|
|
|
|
|
) {
|
|
|
|
|
override suspend fun CommandContext.onCommand(args: MessageChain) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
*Java*
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public final class MyCommand extends JRawCommand {
|
|
|
|
|
public static final MyCommand INSTANCE = new MyCommand();
|
|
|
|
|
|
|
|
|
|
private MyCommand() {
|
|
|
|
|
super(MyPluginMain.INSTANCE, "test"); // 使用插件主类对象作为指令拥有者;设置主指令名为 "test"
|
|
|
|
|
// 可选设置如下属性
|
|
|
|
|
setUsage("/test"); // 设置用法,这将会在 /help 中展示
|
|
|
|
|
setDescription("这是一个测试指令"); // 设置描述,也会在 /help 中展示
|
|
|
|
|
setPrefixOptional(true); // 设置指令前缀是可选的,即使用 `test` 也能执行指令而不需要 `/test`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onCommand(@NotNull CommandSender sender, @NotNull MessageChain args) {
|
|
|
|
|
// 处理指令
|
|
|
|
|
}
|
2020-09-04 15:34:34 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 参数智能解析
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
Console
|
|
|
|
|
提供参数智能解析功能,可以阅读用户手册的 [指令参数智能解析](../../docs/ConsoleTerminal.md#指令参数智能解析)
|
|
|
|
|
了解这一功能。
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
有两种指令实现支持这个功能,它们分别是简单指令 `SimpleCommand` 和复合指令 `CompositeCommand`。
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 复合指令
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
复合指令即 `CompositeCommand`,支持参数智能解析。
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
Console 通过反射实现参数类型识别。标注 `@SubCommand` 的函数(方法)都会被看作是子指令。
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
一个简单的子指令定义如下:
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Kotlin*
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
|
|
|
|
```kotlin
|
2022-06-17 20:11:35 +08:00
|
|
|
|
object MyComposite : CompositeCommand() {
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
|
|
@SubCommand("name")
|
|
|
|
|
suspend fun foo(context: CommandContext, arg: String) {
|
|
|
|
|
println(arg)
|
2020-09-04 15:34:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Java*
|
|
|
|
|
|
2022-03-31 02:13:16 +08:00
|
|
|
|
```java
|
2022-06-17 20:11:35 +08:00
|
|
|
|
public final class MyComposite extends JCompositeCommand {
|
|
|
|
|
// ...
|
|
|
|
|
@SubCommand("name")
|
|
|
|
|
public void foo(CommandContext context, String arg) {
|
|
|
|
|
System.out.println(arg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Java 使用者请了解 Kotlin 的 `fun foo(context: CommandContext, arg: String)` 相当于
|
|
|
|
|
Java 的 `public void foo(CommandContext context, String arg)`。下面部分简单示例将只用
|
|
|
|
|
Kotlin 展示。
|
|
|
|
|
|
|
|
|
|
#### 子指令
|
|
|
|
|
|
2022-07-01 00:12:18 +08:00
|
|
|
|
用 `@SubCommand` 标注的函数就是子指令。子指令将隶属于其主指令。定义于主指令 `main` 的名称为 `child`
|
|
|
|
|
的子指令在执行时需要使用 `/main child`,其中 `/` 表示指令前缀(如果需要)。`/main child arg1 arg2`
|
|
|
|
|
中的 `arg1` 和 `arg2` 则分别表示传递给子指令的第一个和第二个参数。
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
|
|
|
|
子指令可以拥有多个名称,即 `@SubCommand("child1", "child2")` 可以由 `/main child1`
|
|
|
|
|
或 `/main child2` 执行。
|
|
|
|
|
|
|
|
|
|
#### 子指令名称
|
|
|
|
|
|
|
|
|
|
`@SubCommand` 的参数为子指令的名称,可以有多个名称,即 `@SubCommand("name1", "name2")`
|
|
|
|
|
。若子指令名称与函数名称相同,可以省略 `@SubCommand`
|
|
|
|
|
的参数。例如 `@SubCommand("foo") suspend fun foo()`
|
|
|
|
|
可以简写为 `@SubCommand suspend fun foo()`。
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
#### 子指令参数
|
|
|
|
|
|
|
|
|
|
子指令的第一个参数(在 Kotlin 也可以是接收者(`receiver`))可以是 `CommandContext`
|
2022-07-01 00:12:18 +08:00
|
|
|
|
或 `CommandSender`,分别用来获取指令执行环境或发送人。与 `RawCommand`
|
2022-06-17 20:11:35 +08:00
|
|
|
|
相同,如果需要使用原消息链,则使用 `CommandContext`,否则使用 `CommandSender` 的可以让实现更简单。
|
|
|
|
|
|
|
|
|
|
在这个参数以外的就是是子指令的值参数。
|
2022-07-01 00:12:18 +08:00
|
|
|
|
值参数将会对应消息链。例如定义于名称为 `comp` 的 `CompositeCommand` 中的子指令 `@SubCommand fun foo(context: CommandContext, arg1: String, arg2: Int)`
|
|
|
|
|
在由 `/comp foo str 1` 执行时,`str` 将会传递给 `arg1`;`1` 将会传递给 `arg2`。将会在下文详细解释此内容。
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2022-07-01 00:12:18 +08:00
|
|
|
|
在 Kotlin,子指令既可以是 `suspend` 也可以不是。子指令在不是挂起函数时可以使用阻塞 IO(如 `File.readText`),因为子指令会在 IO 线程执行。
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
|
|
|
|
#### 定义参数
|
|
|
|
|
|
|
|
|
|
子指令函数(方法)定义的参数将按顺序成为指令的参数。如下示例中 `arg1` 将成为第一个参数,`arg2` 为第二个:
|
|
|
|
|
|
|
|
|
|
*Kotlin*
|
|
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
object MyComposite : CompositeCommand(MyPluginMain, "main") {
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
|
|
@SubCommand("name")
|
|
|
|
|
suspend fun foo(context: CommandContext, arg: String, b: Boolean) {
|
|
|
|
|
println(arg)
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
2022-06-17 20:11:35 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
*Java*
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```java
|
|
|
|
|
public final class MyComposite extends JCompositeCommand {
|
|
|
|
|
public MyComposite() {
|
|
|
|
|
super(MyPluginMain.INSTANCE, "main");
|
|
|
|
|
// ...
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
// ...
|
|
|
|
|
@SubCommand("name")
|
|
|
|
|
public void foo(CommandContext context, String arg, boolean b) {
|
|
|
|
|
System.out.println(arg);
|
|
|
|
|
}
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
在执行时,`/main name 1 true` 中 `1` 将会被解析为 `String` 类型的参数 `arg`、`true`
|
|
|
|
|
将会被解析为 `boolean` 参数的 `b`。
|
|
|
|
|
|
|
|
|
|
#### 内置智能解析
|
|
|
|
|
|
|
|
|
|
可参考 `CommandValueArgumentParser`,Console 内置支持以下类型的参数:
|
|
|
|
|
|
|
|
|
|
- `Message`
|
|
|
|
|
- `SingleMessage`
|
|
|
|
|
- `MessageContent`
|
|
|
|
|
- 原生数据类型
|
|
|
|
|
- `PlainText`
|
|
|
|
|
- `Image`
|
|
|
|
|
- `String`
|
|
|
|
|
- `Bot`
|
|
|
|
|
- `Contact`
|
|
|
|
|
- `User`
|
|
|
|
|
- `Friend`
|
|
|
|
|
- `Member`
|
|
|
|
|
- `Group`
|
|
|
|
|
- `PermissionId`
|
|
|
|
|
- `PermitteeId`
|
|
|
|
|
- `Enum`
|
|
|
|
|
- `TemporalAccessor`
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
#### 自定义智能解析
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
可在 `CmopositeCommand` 继承 `context` 属性增加自定义解析器。下面示例中为 `Boolean`
|
|
|
|
|
指定了自定义的解析器,子指令的 `b` 参数将会用此解析器解析。
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Kotlin*
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
|
|
|
|
```kotlin
|
2022-06-17 20:11:35 +08:00
|
|
|
|
object CustomBooleanParser : CommandValueArgumentParser<Boolean> {
|
|
|
|
|
override fun parse(raw: String, sender: CommandSender): Boolean {
|
|
|
|
|
return raw == "TRUE!"
|
|
|
|
|
}
|
|
|
|
|
override fun parse(
|
|
|
|
|
raw: MessageContent,
|
|
|
|
|
sender: CommandSender
|
|
|
|
|
): Boolean {
|
|
|
|
|
// 将一个图片认为是 'true'
|
|
|
|
|
if (raw is Image && raw.imageId == "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
|
|
|
|
|
return true
|
|
|
|
|
}
|
2022-08-16 11:39:15 +08:00
|
|
|
|
return super.parse(raw, sender)
|
2022-06-17 20:11:35 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object MyComposite : CompositeCommand(
|
|
|
|
|
MyPluginMain, "main",
|
|
|
|
|
overrideContext = buildCommandArgumentContext {
|
|
|
|
|
Boolean::class with CustomBooleanParser
|
|
|
|
|
}
|
2020-09-04 15:34:34 +08:00
|
|
|
|
) {
|
2022-06-17 20:11:35 +08:00
|
|
|
|
// ...
|
|
|
|
|
@SubCommand("name")
|
|
|
|
|
suspend fun foo(context: CommandContext, arg: String, b: Boolean) {
|
|
|
|
|
println(b)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
*Java*
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```java
|
|
|
|
|
// CustomBooleanParser.java
|
|
|
|
|
public final class CustomBooleanParser implements CommandValueArgumentParser<Boolean> {
|
|
|
|
|
@NotNull
|
|
|
|
|
@Override
|
|
|
|
|
public Boolean parse(@NotNull String raw, @NotNull CommandSender sender) throws CommandArgumentParserException {
|
|
|
|
|
return raw.equals("TRUE!");
|
2020-09-04 15:34:34 +08:00
|
|
|
|
}
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
|
|
|
|
@NotNull
|
|
|
|
|
@Override
|
|
|
|
|
public Boolean parse(@NotNull MessageContent raw, @NotNull CommandSender sender) throws CommandArgumentParserException {
|
|
|
|
|
// 将一个图片认为是 'true'
|
|
|
|
|
if (raw instanceof Image && ((Image) raw).getImageId().equals("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg")) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return CommandValueArgumentParser.super.parse(raw, sender);
|
2020-09-04 15:34:34 +08:00
|
|
|
|
}
|
2022-06-17 20:11:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MyComposite.java
|
|
|
|
|
public final class MyComposite extends JCompositeCommand {
|
|
|
|
|
public MyComposite() {
|
|
|
|
|
super(MyPluginMain.INSTANCE, "main");
|
|
|
|
|
// ...
|
2020-09-04 15:34:34 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
addArgumentContext(new CommandArgumentContextBuilder()
|
|
|
|
|
.add(Boolean.TYPE, new CustomBooleanParser()) // 注册解析器
|
|
|
|
|
.build());
|
2020-09-04 15:34:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
// ...
|
|
|
|
|
@SubCommand("name")
|
|
|
|
|
public void foo(CommandContext context, String arg, boolean b) {
|
|
|
|
|
System.out.println(b);
|
2020-09-04 15:34:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
在 `parse` 时抛出 `CommandArgumentParserException`
|
|
|
|
|
会被看作是正常退出,异常的内容会返回给指令调用人。在 `parse` 时抛出其他异常则会认为是插件错误。
|
|
|
|
|
|
|
|
|
|
### 简单指令
|
|
|
|
|
|
|
|
|
|
简单指令与复合指令拥有一样的智能参数解析功能。简单指令没有子指令,使用 `@Handler` 标注一个函数可以让它处理指令:
|
|
|
|
|
|
|
|
|
|
*Kotlin*
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```kotlin
|
|
|
|
|
object MySimple : SimpleCommand(MyPluginMain, "main") {
|
|
|
|
|
// ...
|
|
|
|
|
@Handler
|
|
|
|
|
suspend fun foo(context: CommandContext, arg: String, b: Boolean) {
|
|
|
|
|
println(b)
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
2022-06-17 20:11:35 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Java*
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```java
|
2022-08-25 15:05:10 +08:00
|
|
|
|
// MySimple.java
|
|
|
|
|
public final class MySimple extends JSimpleCommand {
|
|
|
|
|
public MySimple() {
|
2022-06-17 20:11:35 +08:00
|
|
|
|
super(MyPluginMain.INSTANCE, "main");
|
|
|
|
|
// ...
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
// ...
|
|
|
|
|
@Handler
|
|
|
|
|
public void foo(CommandContext context, String arg, boolean b) {
|
|
|
|
|
System.out.println(b);
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
2022-06-17 20:11:35 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在执行时,`/main aaaa false` 将会调用 `foo` 函数(方法)。`aaaa` 匹配 `String` 类型的参数 `arg`
|
|
|
|
|
,`false` 匹配 `boolean` 类型的参数 `b`。
|
|
|
|
|
|
|
|
|
|
简单指令也可以使用自定义参数解析器,用法与复合指令一样。
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Kotlin*
|
|
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
object MySimple : SimpleCommand(
|
|
|
|
|
MyPluginMain, "main",
|
|
|
|
|
overrideContext = buildCommandArgumentContext {
|
|
|
|
|
Boolean::class with CustomBooleanParser
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
// ...
|
|
|
|
|
@Handler
|
|
|
|
|
suspend fun foo(context: CommandContext, arg: String, b: Boolean) {
|
|
|
|
|
println(b)
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
2022-06-17 20:11:35 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
*Java*
|
2022-03-31 02:13:16 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
```java
|
2022-08-25 16:05:15 +08:00
|
|
|
|
// MySimple.java
|
|
|
|
|
public final class MySimple extends JSimpleCommand {
|
|
|
|
|
public MySimple() {
|
2022-06-17 20:11:35 +08:00
|
|
|
|
super(MyPluginMain.INSTANCE, "main");
|
|
|
|
|
// ...
|
|
|
|
|
|
|
|
|
|
addArgumentContext(new CommandArgumentContextBuilder()
|
|
|
|
|
.add(Boolean.TYPE, new CustomBooleanParser()) // 注册解析器
|
|
|
|
|
.build());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ...
|
|
|
|
|
@Handler
|
|
|
|
|
public void foo(CommandContext context, String arg, boolean b) {
|
|
|
|
|
System.out.println(b);
|
2022-03-31 02:13:16 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 选择 [`RawCommand`], [`SimpleCommand`] 或 [`CompositeCommand`]
|
|
|
|
|
|
|
|
|
|
若需要不限长度的,自由的参数列表,使用 [`RawCommand`]。
|
|
|
|
|
|
|
|
|
|
若需要子指令,使用 [`CompositeCommand`]。否则使用 [`SimpleCommand`]。
|
|
|
|
|
|
|
|
|
|
### 自行实现指令
|
|
|
|
|
|
|
|
|
|
Console 允许插件自行实现指令(不使用上述 `RawCommand`、`SimpleCommand`
|
|
|
|
|
和 `CompositeCommand`)。但注意,在实现时难免会需要使用到抽象指令描述器(如 `CommandArgument`
|
|
|
|
|
),而这些描述器是不稳定的。因此插件自行实现指令可能会导致不兼容未来的 Console 版本。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注册指令
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
|
|
所有指令都需要注册到指令管理器才能生效。要注册指令,在 `onEnable`
|
|
|
|
|
使用 `CommandManager.registerCommand(command)`。
|
|
|
|
|
|
|
|
|
|
### 查看已注册的所有指令
|
|
|
|
|
|
|
|
|
|
使用 `PluginManager.INSTANCE.getAllRegisteredCommands()`
|
|
|
|
|
。可以获得当前已经注册的所有 `Command` 实例列表。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
执行指令
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
|
|
指令既可以由插件执行,也可以在消息环境中由用户执行(需要 [chat-command](https://github.com/project-mirai/chat-command)
|
|
|
|
|
)。
|
|
|
|
|
|
|
|
|
|
### 在插件执行指令
|
|
|
|
|
|
2023-02-16 10:52:06 +08:00
|
|
|
|
若要通过字符串解析目标指令并执行,使用 `CommandManager.INSTANCE.executeCommand(CommandSender, Message)`
|
2022-06-17 20:11:35 +08:00
|
|
|
|
,其中 `Message` 为包含前缀(如果有必要)、指令名称、以及指令参数列表的完整消息。
|
|
|
|
|
|
2023-02-16 10:52:06 +08:00
|
|
|
|
若要通过字符串解析目标指令并执行,使用 `CommandManager.INSTANCE.executeCommand(CommandSender, Command, Message)`
|
2022-06-17 20:11:35 +08:00
|
|
|
|
,其中 `Message` 传递给指令的参数列表,不包含前缀或指令名称。注意,若要执行复合指令,需要包含子指令名称。
|
|
|
|
|
|
|
|
|
|
### 指令语法解析
|
|
|
|
|
|
|
|
|
|
一条消息可以被解析为指令,如果它满足:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
<指令前缀><任一指令名> <指令参数列表>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
指令参数列表由空格分隔。
|
|
|
|
|
|
|
|
|
|
### 指令解析流程
|
|
|
|
|
|
|
|
|
|
> 注意:该流程可能会变化,请不要依赖这个流程。
|
|
|
|
|
|
|
|
|
|
对于
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
@Handler suspend fun handle(context: CommandContext, target: User, message: String)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
指令 `/tell 123456 Hello` 的解析流程:
|
|
|
|
|
|
|
|
|
|
1. 被分割为 `/`, `"tell"`, `"123456"`, `"Hello"`
|
|
|
|
|
2. 根据 `/` 和 `"test"`,确定 `MySimpleCommand` 作为目标指令。`"123456"`, `"Hello"`
|
|
|
|
|
作为指令的原生参数。
|
|
|
|
|
3. 由于 `MySimpleCommand` 定义的 `handle` 需要两个参数, 即 `User` 和 `String`
|
|
|
|
|
,`"123456"` 需要转换成 `User`,`"Hello"` 需要转换成 `String`。
|
|
|
|
|
4. 指令寻找合适的解析器(`CommandValueArgumentParser`)
|
|
|
|
|
5. `"123456"` 通过 `ExistingUserValueArgumentParser` 变为 `User` 类型的参数
|
|
|
|
|
6. `"Hello"` 通过 `StringValueArgumentParser` 变为 `String` 类型的参数
|
|
|
|
|
7. 解析完成的参数传入 `handle`
|
|
|
|
|
|
|
|
|
|
文本参数转义
|
|
|
|
|
-----
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
|
|
|
|
不同的参数默认用空格分隔。有时用户希望在文字参数中包含空格本身,参数解析器可以接受三种表示方法。
|
|
|
|
|
|
|
|
|
|
以上文中定义的 `MySimpleCommand` 为例:
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 英文双引号
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
|
|
|
|
表示将其中内容作为一个参数,可以包括空格。
|
|
|
|
|
|
|
|
|
|
例如:用户输入 `/tell 123456 "Hello world!"` ,`message` 会收到 `Hello world!`。
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
注意:双引号仅在参数的首尾部生效。例如,用户输入 `/tell 123456 He"llo world!"`,`message`
|
|
|
|
|
只会得到 `He"llo`。
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 转义符
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
|
|
|
|
即英文反斜杠 `\`。表示忽略之后一个字符的特殊含义,仅看作字符本身。
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
|
|
|
|
- 用户输入 `/tell 123456 Hello\ world!`,`message` 得到 `Hello world!`;
|
|
|
|
|
- 用户输入 `/tell 123456 \"Hello world!\"`,`message` 得到 `"Hello`。
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 暂停解析标志
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
|
|
|
|
即连续两个英文短横线 `--`。表示从此处开始,到**这段文字内容**结束为止,都作为一个完整参数。
|
|
|
|
|
|
|
|
|
|
例如:
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
- 用户输入 `/tell 123456 -- Hello:::test\12""3`,`message`
|
|
|
|
|
得到 `Hello:::test\12""3`(`:` 表示空格);
|
|
|
|
|
- 用户输入 `/tell 123456 -- Hello @全体成员 test1 test2`,那么暂停解析的作用范围到 `@`
|
|
|
|
|
为止,之后的 `test1` 和 `test2` 是不同的参数。
|
|
|
|
|
- 用户输入 `/tell 123456 \-- Hello` 或 `/tell 123456 "--" Hello`
|
|
|
|
|
,这不是暂停解析标志,`message` 得到 `--` 本身。
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
|
|
|
|
注意:
|
|
|
|
|
|
|
|
|
|
`--` 的前后都应与其他参数有间隔,否则不认为这是暂停解析标志。
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
例如,用户输入 `/tell 123456--Hello world!`,`123456--Hello` 会被试图转换为 `User`
|
|
|
|
|
并出错。即使转换成功,`message` 也只会得到 `world!`。
|
2022-02-22 18:37:24 +08:00
|
|
|
|
|
|
|
|
|
### 非文本参数的转义
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
有时可能需要只用一个参数来接受各种消息内容,例如用户可以在 `/tell 123456` 后接图片、表情等,它们都是 `message`
|
|
|
|
|
的一部分。
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
对于这种定义方式,Mirai Console 的支持尚待实现,目前可以使用 [`RawCommand`] 替代。
|
2020-09-04 10:57:32 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
## 指令发送者
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
指令可能在聊天环境执行,也可能在控制台执行。
|
|
|
|
|
指令发送者即 `CommandSender`,是执行指令时的必须品之一。
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
|
|
|
|
### 类型
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
2020-09-04 15:48:20 +08:00
|
|
|
|
```text
|
|
|
|
|
CommandSender <---------+---------------+-------------------------------+
|
|
|
|
|
↑ | | |
|
|
|
|
|
| | | |
|
|
|
|
|
| UserCommandSender GroupAwareCommandSender CommandSenderOnMessage
|
|
|
|
|
| ↑ ↑ ↑
|
|
|
|
|
| | | |
|
|
|
|
|
AbstractCommandSender | | |
|
|
|
|
|
↑ | | |
|
|
|
|
|
| sealed | | |
|
|
|
|
|
+-------------+-------------+ | | |
|
|
|
|
|
| | | | |
|
|
|
|
|
| | | | | }
|
|
|
|
|
ConsoleCommandSender AbstractUserCommandSender | | } 一级子类
|
|
|
|
|
↑ | | }
|
|
|
|
|
| sealed | |
|
|
|
|
|
| | |
|
|
|
|
|
+----------------------+ | |
|
|
|
|
|
| | | |
|
|
|
|
|
| +------+------------+---------------+ |
|
|
|
|
|
| | | |
|
|
|
|
|
| | | | }
|
|
|
|
|
FriendCommandSender MemberCommandSender TempCommandSender | } 二级子类
|
|
|
|
|
↑ ↑ ↑ | }
|
|
|
|
|
| | | |
|
|
|
|
|
| | | | }
|
|
|
|
|
FriendCommandSenderOnMessage MemberCommandSenderOnMessage TempCommandSenderOnMessage | } 三级子类
|
|
|
|
|
| | | | }
|
|
|
|
|
| | | |
|
|
|
|
|
+-----------------------------+----------------------------+---------------+
|
|
|
|
|
```
|
|
|
|
|
|
2020-10-30 10:28:18 +08:00
|
|
|
|
有关类型的详细信息,请查看 [CommandSender.kt](../backend/mirai-console/src/command/CommandSender.kt#L48-L135)
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 获取控制台指令发送者
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
`ConsoleCommandSender` 表示以控制台身份执行指令。它是一个单例对象,在 Kotlin 可以直接通过类型获得类名获得实例,在
|
|
|
|
|
Java 可通过 `ConsoleCommandSender.INSTANCE` 获得。
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
### 获取其他指令发送者
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
在 Kotlin 可使用扩展函数:`Contact.asCommandSender()`
|
|
|
|
|
或 `MessageEvent.toCommandSender()`
|
|
|
|
|
。
|
2020-09-04 15:48:20 +08:00
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
在 Java 可使用 `CommandSender.from` 和 `CommandSender.of`。
|
2021-01-14 17:21:50 +08:00
|
|
|
|
|
|
|
|
|
|
2022-06-17 20:11:35 +08:00
|
|
|
|
|
|
|
|
|
[`MessageScope`]
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
表示几个消息对象的'域',即消息对象的集合。用于最小化将同一条消息发送给多个类型不同的目标的付出。示例:
|
|
|
|
|
|
|
|
|
|
*Kotlin*
|
|
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
// 在一个 CompositeCommand 内
|
|
|
|
|
@Handler
|
|
|
|
|
suspend fun CommandSender.handle(target: Member) {
|
|
|
|
|
val duration = Random.nextInt(1, 15)
|
|
|
|
|
target.mute(duration)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 不使用 MessageScope, 无用的样板代码
|
|
|
|
|
val thisGroup = this.getGroupOrNull()
|
|
|
|
|
val message = "${this.name} 禁言 ${target.nameCardOrNick} $duration 秒"
|
|
|
|
|
if (target.group != thisGroup) {
|
|
|
|
|
target.group.sendMessage(message)
|
|
|
|
|
}
|
|
|
|
|
sendMessage(message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 MessageScope, 清晰逻辑
|
|
|
|
|
// 表示至少发送给 `this`, 当 `this` 的真实发信对象与 `target.group` 不同时, 还额外发送给 `target.group`
|
|
|
|
|
this.scopeWith(target.group) {
|
|
|
|
|
sendMessage("${name} 禁言了 ${target.nameCardOrNick} $duration 秒")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 同样地, 可以扩展用法, 同时私聊指令执行者:
|
|
|
|
|
// this.scopeWith(
|
|
|
|
|
// target,
|
|
|
|
|
// target.group
|
|
|
|
|
// ) { ... }
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
*Java*
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
public class MyCommand extends SimpleCommand {
|
|
|
|
|
@Handler
|
|
|
|
|
public void handle(sender: CommandSender, target: Member) {
|
|
|
|
|
int duration = Random.nextInt(1, 15);
|
|
|
|
|
target.mute(duration);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 不使用 MessageScope
|
|
|
|
|
Group thisGroup = CommandSenderKt.getGroupOrNull(sender);
|
|
|
|
|
String message = "${this.name} 禁言 ${target.nameCardOrNick} $duration 秒";
|
|
|
|
|
if (!target.group.equals(thisGroup)) {
|
|
|
|
|
target.group.sendMessage(message);
|
|
|
|
|
}
|
|
|
|
|
sender.sendMessage(message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 MessageScope
|
|
|
|
|
// 表示至少发送给 `this`, 当 `this` 的真实发信对象与 `target.group` 不同时, 还额外发送给 `target.group`
|
|
|
|
|
MessageScope scope = MessageScopeKt.scopeWith(sender, target);
|
|
|
|
|
scope.sendMessage("${name} 禁言了 ${target.nameCardOrNick} $duration 秒");
|
|
|
|
|
|
|
|
|
|
// 或是只用一行:
|
|
|
|
|
MessageScopeKt.scopeWith(sender, target).sendMessage("${name} 禁言了 ${target.nameCardOrNick} $duration 秒");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-01-14 17:21:50 +08:00
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
> 下一步,[PluginData](PluginData.md#mirai-console-backend---plugindata)
|
|
|
|
|
>
|
|
|
|
|
> 返回 [开发文档索引](README.md#mirai-console)
|
|
|
|
|
|