From e8c0ef192cc4645b2d2def83188cfc211a5a4de3 Mon Sep 17 00:00:00 2001 From: Him188 Date: Mon, 11 Jan 2021 22:05:04 +0800 Subject: [PATCH] Update docs --- docs/Bots.md | 73 +++++++++++++------ docs/Contacts.md | 5 +- docs/Events.md | 39 +++++----- docs/Messages.md | 11 ++- .../kotlin/event/JvmMethodListeners.kt | 4 +- 5 files changed, 80 insertions(+), 52 deletions(-) diff --git a/docs/Bots.md b/docs/Bots.md index 5315796cd..34bd6bab0 100644 --- a/docs/Bots.md +++ b/docs/Bots.md @@ -9,6 +9,8 @@ 一个机器人被以 `Bot` 对象描述。mirai 的交互入口点是 `Bot`。`Bot` 只可通过 [`BotFactory`](../mirai-core-api/src/commonMain/kotlin/BotFactory.kt#L22-L87) 内的 `newBot` 方法获得: +> 你现在还不需要知道 `Bot` 可以干什么。 + ```kotlin interface BotFactory { fun newBot(qq: Long, password: String, configuration: BotConfiguration): Bot @@ -29,6 +31,8 @@ val bot = BotFactory.newBot( ) Bot bot = BotFactory.INSTANCE.newBot( ); ``` +> Scala 使用者请查看 [#834](https://github.com/mamoe/mirai/issues/834) + ### 配置 Bot 可以切换使用的协议、控制日志输出等。 @@ -47,19 +51,31 @@ Bot bot = BotFactory.INSTANCE.newBot(qq, password, new BotConfiguration() {{ }}) ``` -下文示例代码都要放入 `// config` 中。 +下文示例代码都要放入 `// 配置` 中。 - -### 常用配置 > 可在 [BotConfiguration.kt](../mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt#L23) 查看完整配置列表 -#### 设备信息 -Bot 默认使用全随机的设备信息。在更换账号地点时候使用随机设备信息可能会导致无法登录。 +### 常用配置 + +#### 修改运行目录 +默认为 `File(".")` -要使用 `deviceInfo.json` 存储设备信息: ``` -fileBasedDeviceInfo() // "myDeviceInfo.json" -fileBasedDeviceInfo("myDeviceInfo.json") // "myDeviceInfo.json" +// Kotlin +workingDir = File("C:/mirai") + +// Java +setWorkingDir(File("C:/mirai")) +``` + +#### 设备信息 +Bot 默认使用全随机的设备信息。**在更换账号地点时候使用随机设备信息可能会导致无法登录**,当然,**成功登录时使用的设备信息也可以保存后在新的设备使用**。 + +要使用 `device.json` 存储设备信息: +``` +fileBasedDeviceInfo() // 存储为 "device.json" +// 或 +fileBasedDeviceInfo("myDeviceInfo.json") // 存储为 "myDeviceInfo.json" ``` 要自定义设备信息: @@ -76,7 +92,7 @@ setDeviceInfo(bot -> /* create device info */) #### 切换登录协议 Mirai 支持多种登录协议:`ANDROID_PHONE`,`ANDROID_PAD`,`ANDROID_WATCH`,默认使用 `ANDROID_PHONE`。 -若登录失败,可尝试切换协议。但注意,部分功能在部分协议上不受支持,详见源码内注释。 +若登录失败,可尝试切换协议。**但注意部分功能在部分协议上不受支持**,详见源码内注释。 要切换协议: ``` @@ -93,7 +109,10 @@ Bot 有两个日志类别,`Bot` 或 `Net`。`Bot` 为通常日志,如收到 重定向日志到文件: ``` redirectBotLogToFile() +redirectBotLogToDirectory() + redirectNetworkLogToFile() +redirectNetworkLogToDirectory() ``` 手动覆盖日志: @@ -107,11 +126,17 @@ setNetworkLoggerSupplier(bot -> /* create logger */) setBotLoggerSupplier(bot -> /* create logger */) ``` +关闭日志: +``` +noNetworkLog() +noBotLog() +``` + #### 覆盖登录解决器 -在遇到验证码时,Mirai 会寻找 `LoginSolver` 以解决验证码。 +Mirai 会使用 `LoginSolver` 解决验证码。 - 在 Android 需要手动提供 `LoginSolver` -- 在 JVM, Mirai 会根据环境支持情况选择 Swing/CLI 实现 +- 在 JVM, Mirai 会根据环境支持情况选择 Swing/CLI 实现,通常不需要手动提供 覆盖默认的 `LoginSolver`: ``` @@ -122,35 +147,35 @@ loginSolver = YourLoginSolver setLoginSolver(new YourLoginSolver()) ``` -要获取更多有关验证码解决器的信息,查看 [LoginSolver.kt](../mirai-core-api/src/commonMain/kotlin/utils/LoginSolver.kt#L32) +> 要获取更多有关 `LoginSolver` 的信息,查看 [LoginSolver.kt](../mirai-core-api/src/commonMain/kotlin/utils/LoginSolver.kt#L32) ### 获取当前所有 `Bot` 实例 -在登录后,`Bot` 实例会被自动记录。可在 `Bot.instances` 获取到当前在线的所有 `Bot` 列表。当 `Bot` 离线,其实例就会被删除。 +在登录后 `Bot` 实例会被自动记录。可在 `Bot.instances` 获取到当前**在线**的所有 `Bot` 列表。 ## 2. 登录 -创建 `Bot` 后不会自动登录,需要手动调用其 `login()` 方法。在 Kotlin 还可以使用 `Bot.alsoLogin()` 扩展,相当于 `bot.apply { login() }`。 +创建 `Bot` 后不会自动登录,需要手动调用其 `login()` 方法。只需要调用一次 `login()` 即可,`Bot` 掉线时会自动重连。 ### 处理滑动验证码 -由于服务器正在大力推广滑块验证码,登录时可能需要解决滑动验证码。部分账号可以跳过滑块验证码直接重新登录,服务器就会要求图片验证码。 +[project-mirai/mirai-login-solver-selenium]: https://github.com/project-mirai/mirai-login-solver-selenium -处理验证码需要浏览器支持,可在 [project-mirai/mirai-login-solver-selenium](https://github.com/project-mirai/mirai-login-solver-selenium) 查看详细处理方案。 +服务器正在大力推广滑块验证码。 + +部分账号可以跳过滑块验证码,Mirai 会自动尝试。 +若你的账号无法跳过验证,可在 [project-mirai/mirai-login-solver-selenium] 查看处理方案。 ### 常见登录失败原因 -| 错误信息 | 可能的原因 | 可能的解决方案 | -|:--------------|:---------|:----------------------| -| 当前版本过低 | 密码错误 | 检查密码 | -| 当前上网环境异常 | 设备锁 | 开启或关闭设备锁后重试登录 | +| 错误信息 | 可能的原因 | 可能的解决方案 | +|:--------------|:---------------|:----------------------| +| 当前版本过低 | 密码错误 | 检查密码 | +| 当前上网环境异常 | 设备锁 | 开启或关闭设备锁后重试登录 | +| 禁止登录 | 需要处理滑块验证码 | [project-mirai/mirai-login-solver-selenium] | 若以上方案无法解决问题,请尝试 [切换登录协议](#切换登录协议) 和 **[处理滑动验证码](#处理滑动验证码)**。 -### 重新登录 - -可以再次调用 `Bot.login()` 以重新登录 `Bot`。这一般没有必要——`Bot` 运行时会自动与服务器同步事件(如群成员变化,好友数量变化)。 - > 下一步,[Contacts](Contacts.md) > diff --git a/docs/Contacts.md b/docs/Contacts.md index 3731b4652..20af0b5dd 100644 --- a/docs/Contacts.md +++ b/docs/Contacts.md @@ -3,10 +3,11 @@ [![](https://mermaid.ink/img/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5cbmNsYXNzIEJvdCB7XG4gICAgK2ZyaWVuZHM6IENvbnRhY3RMaXN0XG4gICAgK2dyb3VwczogQ29udGFjdExpc3RcbiAgICArZ2V0RnJpZW5kKExvbmcpIEZyaWVuZD9cbiAgICArZ2V0RnJpZW5kT3JOdWxsKExvbmcpIEZyaWVuZFxuICAgICtnZXRHcm91cChMb25nKSBHcm91cD9cbiAgICArZ2V0R3JvdXBPckZhaWwoTG9uZykgR3JvdXBcbiAgICArbG9naW4oKVxuICAgICtjbG9zZSgpXG59XG5cbmNsYXNzIENvbnRhY3RPckJvdCB7XG4gICAgK2lkOiBJbnRcbiAgICArYXZhdGFyVXJsOiBTdHJpbmdcbn1cblxuY2xhc3MgVXNlck9yQm90IHtcbiAgICArbnVkZ2UoKSBOdWRnZVxufVxuXG5jbGFzcyBDb250YWN0IHtcbiAgICArYm90OiBCb3RcbiAgICArc2VuZE1lc3NhZ2UoTWVzc2FnZSkgTWVzc2FnZVJlY2VpcHRcbiAgICArc2VuZE1lc3NhZ2UoU3RyaW5nKSBNZXNzYWdlUmVjZWlwdFxuICAgICt1cGxvYWRJbWFnZShFeHRlcm5hbEltYWdlKSBJbWFnZVxufVxuXG5jbGFzcyBVc2VyIHtcbiAgICArbmljazogU3RyaW5nXG4gICAgK3JlbWFyazogU3RyaW5nXG59XG5cbmNsYXNzIEdyb3VwIHtcbiAgICArbWVtYmVyczogQ29udGFjdExpc3RcbiAgICArbmFtZTogU3RyaW5nXG4gICAgK3NldHRpbmdzOiBHcm91cFNldHRpbmdzXG4gICAgK293bmVyOiBOb3JtYWxNZW1iZXJcbiAgICArYm90TXV0ZVJlbWFpbmluZzogTG9uZ1xuICAgICtib3RQZXJtaXNzaW9uOiBNZW1iZXJQZXJtaXNzaW9uXG4gICAgK3F1aXQoKSBCb29sZWFuXG4gICAgK3VwbG9hZFZvaWNlKCkgVm9pY2Vcbn1cblxuY2xhc3MgTm9ybWFsTWVtYmVyIHtcbiAgICArbXV0ZSgpXG4gICAgK2tpY2soKVxufVxuXG5jbGFzcyBBbm9ueW1vdXNNZW1iZXIge1xuICAgICthbm9ueW1vdXNJZDogU3RyaW5nXG59XG5cbmNsYXNzIE1lbWJlciB7XG4gICAgK2dyb3VwOiBHcm91cFxufVxuXG5Db250YWN0T3JCb3Q8fC0tQ29udGFjdFxuQ29udGFjdE9yQm90PHwtLVVzZXJPckJvdFxuXG5Vc2VyT3JCb3Q8fC0tQm90XG5Vc2VyT3JCb3Q8fC0tVXNlclxuXG5Db250YWN0PHwtLVVzZXJcbkNvbnRhY3Q8fC0tR3JvdXBcblxuVXNlcjx8LS1NZW1iZXJcblVzZXI8fC0tRnJpZW5kXG5cbk1lbWJlcjx8LS1Ob3JtYWxNZW1iZXJcbk1lbWJlcjx8LS1Bbm9ueW1vdXNNZW1iZXIiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlfQ)](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5cbmNsYXNzIEJvdCB7XG4gICAgK2ZyaWVuZHM6IENvbnRhY3RMaXN0XG4gICAgK2dyb3VwczogQ29udGFjdExpc3RcbiAgICArZ2V0RnJpZW5kKExvbmcpIEZyaWVuZD9cbiAgICArZ2V0RnJpZW5kT3JOdWxsKExvbmcpIEZyaWVuZFxuICAgICtnZXRHcm91cChMb25nKSBHcm91cD9cbiAgICArZ2V0R3JvdXBPckZhaWwoTG9uZykgR3JvdXBcbiAgICArbG9naW4oKVxuICAgICtjbG9zZSgpXG59XG5cbmNsYXNzIENvbnRhY3RPckJvdCB7XG4gICAgK2lkOiBJbnRcbiAgICArYXZhdGFyVXJsOiBTdHJpbmdcbn1cblxuY2xhc3MgVXNlck9yQm90IHtcbiAgICArbnVkZ2UoKSBOdWRnZVxufVxuXG5jbGFzcyBDb250YWN0IHtcbiAgICArYm90OiBCb3RcbiAgICArc2VuZE1lc3NhZ2UoTWVzc2FnZSkgTWVzc2FnZVJlY2VpcHRcbiAgICArc2VuZE1lc3NhZ2UoU3RyaW5nKSBNZXNzYWdlUmVjZWlwdFxuICAgICt1cGxvYWRJbWFnZShFeHRlcm5hbEltYWdlKSBJbWFnZVxufVxuXG5jbGFzcyBVc2VyIHtcbiAgICArbmljazogU3RyaW5nXG4gICAgK3JlbWFyazogU3RyaW5nXG59XG5cbmNsYXNzIEdyb3VwIHtcbiAgICArbWVtYmVyczogQ29udGFjdExpc3RcbiAgICArbmFtZTogU3RyaW5nXG4gICAgK3NldHRpbmdzOiBHcm91cFNldHRpbmdzXG4gICAgK293bmVyOiBOb3JtYWxNZW1iZXJcbiAgICArYm90TXV0ZVJlbWFpbmluZzogTG9uZ1xuICAgICtib3RQZXJtaXNzaW9uOiBNZW1iZXJQZXJtaXNzaW9uXG4gICAgK3F1aXQoKSBCb29sZWFuXG4gICAgK3VwbG9hZFZvaWNlKCkgVm9pY2Vcbn1cblxuY2xhc3MgTm9ybWFsTWVtYmVyIHtcbiAgICArbXV0ZSgpXG4gICAgK2tpY2soKVxufVxuXG5jbGFzcyBBbm9ueW1vdXNNZW1iZXIge1xuICAgICthbm9ueW1vdXNJZDogU3RyaW5nXG59XG5cbmNsYXNzIE1lbWJlciB7XG4gICAgK2dyb3VwOiBHcm91cFxufVxuXG5Db250YWN0T3JCb3Q8fC0tQ29udGFjdFxuQ29udGFjdE9yQm90PHwtLVVzZXJPckJvdFxuXG5Vc2VyT3JCb3Q8fC0tQm90XG5Vc2VyT3JCb3Q8fC0tVXNlclxuXG5Db250YWN0PHwtLVVzZXJcbkNvbnRhY3Q8fC0tR3JvdXBcblxuVXNlcjx8LS1NZW1iZXJcblVzZXI8fC0tRnJpZW5kXG5cbk1lbWJlcjx8LS1Ob3JtYWxNZW1iZXJcbk1lbWJlcjx8LS1Bbm9ueW1vdXNNZW1iZXIiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlfQ) +基于面向对象的设计,可直接获取 `Contact` 的属性如 `nick`,`permission`。 -要主动发送一条消息,调用 `Contact.sendMessage()` 即可。 +要主动发送一条消息,调用 `Contact.sendMessage()` 即可*(后文介绍)*。 -可通过 `Bot.getFriend` 或 `Bot.getGroup` 获取相关对象,也可以通过事件获取。 +可通过 `Bot.getFriend` 或 `Bot.getGroup` 获取相关对象,也可以通过事件获取*(后文介绍)*。 > 下一步,[Events](Events.md) > diff --git a/docs/Events.md b/docs/Events.md index 6efb758e7..66db503c3 100644 --- a/docs/Events.md +++ b/docs/Events.md @@ -5,7 +5,7 @@ - [事件系统](#事件系统) - [事件通道](#事件通道) - [通道操作](#通道操作) - - [缩窄(过滤)](#缩窄过滤) + - [过滤](#过滤) - [添加 `CoroutineContext`](#添加-coroutinecontext) - [限制作用域](#限制作用域) - [链式调用](#链式调用) @@ -22,7 +22,7 @@ ## 事件系统 -Mirai 以事件驱动,使用者需要监听如 `收到消息`,`收到入群申请` 等事件。 +Mirai 以事件驱动。 [`Event`]: ../mirai-core-api/src/commonMain/kotlin/event/Event.kt#L21-L62 @@ -39,13 +39,13 @@ Mirai 以事件驱动,使用者需要监听如 `收到消息`,`收到入群 [事件通道][`EventChannel`]是监听事件的入口。 **在不同的事件通道中可以监听到不同类型的事件**。 -> 对通道的转换操作可以在使用时查看源码内注释 ([`EventChannel`])。 - ### 获取事件通道 -`GlobalEventChannel` 是最大的通道:所有的事件都可以在 `GlobalEventChannel` 监听到。**因此,`GlobalEventChannel` 会包含来自所有 `Bot` 实例的事件。** +[`GlobalEventChannel`]: ../mirai-core-api/src/commonMain/kotlin/event/GlobalEventChannel.kt -通常不会直接使用 `GlobalEventChannel`,而是使用经过 [通道操作](#通道操作) 操作的子通道。 +[`GlobalEventChannel`] 是最大的通道:所有的事件都可以在 [`GlobalEventChannel`] 监听到。**因此,[`GlobalEventChannel`] 会包含来自所有 `Bot` 实例的事件。** + +通常不会直接使用 [`GlobalEventChannel`],而是使用经过 [通道操作](#通道操作) 操作的子通道。 > 回到 [目录](#目录) @@ -55,7 +55,7 @@ Mirai 以事件驱动,使用者需要监听如 `收到消息`,`收到入群 **一个通道的属性都是*不变的*:每个转换操作都会创建一个新的通道而不会修改原通道。** -### 缩窄(过滤) +### 过滤 `GlobalEventChannel` 包含任何 `Event`,可以通过 `EventChannel.filter` 过滤得到一个只包含期望的事件的 `EventChannel`。 @@ -68,11 +68,13 @@ EventChannel channel = GlobalEventChannel.INSTANCE.filter(ev -> ev instanceof Bo > 回到 [通道操作](#通道操作) +> 你可以选择跳过下文介绍的协程属性和作用域,直接阅读 [在 `EventChannel` 监听事件](#在-eventchannel-监听事件) + ### 添加 `CoroutineContext` 一个通道持有属性 `defaultCoroutineContext`,将会自动添加给每个事件监听器(见后文)。 -可以为通道添加一些 `CoroutineContext`,如 `CoroutineExceptionHandler`。 +可以为通道添加一些 `CoroutineContext`,如 `CoroutineExceptionHandler`(用于处理监听时产生的异常)。 ```kotlin channel.exceptionHandler { exception -> logger.error(exception) @@ -171,7 +173,7 @@ bot.eventChannel.subscribeAlways(GroupMessageEvent.class, event -> { }) ``` -> 有关监听事件的实现细节可在使用时查看源码内注释。 +> 实现细节可查看源码内注释。 > 回到 [目录](#目录) @@ -180,25 +182,21 @@ bot.eventChannel.subscribeAlways(GroupMessageEvent.class, event -> { 监听都需要在*事件通道*中进行。如下几种方法都本质上会调用上述 `EventChannel.subscribe` 等方法。 -- [使用 `ListenerHost` 监听事件](#使用-eventhandler-注解标注的方法监听事件) +- [使用 `@EventHandler` 注解标注的方法监听事件](#使用-eventhandler-注解标注的方法监听事件) - [在 Kotlin 使用 DSL 监听事件](#在-kotlin-使用-dsl-监听事件) ### 使用 `@EventHandler` 注解标注的方法监听事件 标注一个函数(方法)为事件监听器。mirai 通过反射获取他们并为之注册事件。 -> 详见 [EventHandler](../mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt#L22-L144) - - [Kotlin 函数](#kotlin-函数) - [Java 方法](#java-方法) #### Kotlin 函数 Kotlin 函数要求: -- 接收者 (英 receiver) 和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在) +- 接收者和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在) 接收者或函数参数的类型都必须为 `Event` 或其子类. -- 返回值: 为 `Unit` 或不指定返回值时将注册为 `EventChannel.subscribeAlways`, 为 `ListeningStatus` 时将注册为 `EventChannel.subscribe`. - 任何其他类型的返回值将会在注册时抛出异常. 所有 Kotlin 非 `suspend` 的函数都将会在 `Dispatchers.IO` 中调用 @@ -266,14 +264,14 @@ eventChannel.registerListenerHost(MyEvents) #### Java 方法 -所有 Java 方法都会在 `Dispatchers.IO` 中调用,因此在 Java 可以调用阻塞方法。 +所有 Java 方法都会在 `Dispatchers.IO` 中调用,因此在 Java 也可以调用阻塞方法。 支持的方法类型: ``` // T 表示任何 Event 类型. void onEvent(T) Void onEvent(T) -ListeningStatus onEvent(T) // 返回 null 时将抛出异常 +ListeningStatus onEvent(T) // 禁止返回 null ``` Java 使用示例: @@ -356,13 +354,13 @@ eventChannel.subscribeMessages { > 回到 [目录](#目录) ## 工具函数(Kotlin) - -*可能需要较好的 Kotlin 技能才能理解以下内容。* +> *可能需要较好的 Kotlin 技能才能理解以下内容。* +> **可以[跳过本节](# )** 基于 Kotlin 协程特性,mirai 提供 ` ### 线性同步(`syncFromEvent`) -[linear.kt](../mirai-core-api/src/commonMain/kotlin/event/linear.kt) +[syncFromEvent.kt](../mirai-core-api/src/commonMain/kotlin/event/syncFromEvent.kt) 挂起协程并获取下一个戳 Bot 的对象: ```kotlin @@ -462,6 +460,7 @@ reply("复读模式结束") > 回到 [目录](#目录) +######   > 下一步,[Messages](Messages.md) > diff --git a/docs/Messages.md b/docs/Messages.md index c962e629d..cf701fae5 100644 --- a/docs/Messages.md +++ b/docs/Messages.md @@ -10,19 +10,19 @@ - [由 `CodableMessage` 取得 mirai 码字符串](#由-codablemessage-取得-mirai-码字符串) - [由 mirai 码字符串取得 `MessageChain` 实例](#由-mirai-码字符串取得-messagechain-实例) - [消息链](#消息链) + - [发送消息](#发送消息) - [构造消息链](#构造消息链) - [元素唯一性](#元素唯一性) - [获取消息链中的消息元素](#获取消息链中的消息元素) ## 消息系统 -在 Contacts 章节提到,要发送消息,使用 `Contact.sendMessage(Message)`。 +在 Contacts 章节提到,要发送消息,使用 `Contact.sendMessage(Message)`。`Message` 架构如下图所示。 [![](https://mermaid.ink/img/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5cbmNsYXNzIE1lc3NhZ2VDaGFpblxuTWVzc2FnZUNoYWluIDogTGlzdH5TaW5nbGVNZXNzYWdlflxuXG5NZXNzYWdlPHwtLU1lc3NhZ2VDaGFpblxuTWVzc2FnZTx8LS1TaW5nbGVNZXNzYWdlXG5cbk1lc3NhZ2VDaGFpbiBvLS0gU2luZ2xlTWVzc2FnZVxuXG5TaW5nbGVNZXNzYWdlPHwtLU1lc3NhZ2VDb250ZW50XG5TaW5nbGVNZXNzYWdlPHwtLU1lc3NhZ2VNZXRhZGF0YVxuXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlfQ)](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5cbmNsYXNzIE1lc3NhZ2VDaGFpblxuTWVzc2FnZUNoYWluIDogTGlzdH5TaW5nbGVNZXNzYWdlflxuXG5NZXNzYWdlPHwtLU1lc3NhZ2VDaGFpblxuTWVzc2FnZTx8LS1TaW5nbGVNZXNzYWdlXG5cbk1lc3NhZ2VDaGFpbiBvLS0gU2luZ2xlTWVzc2FnZVxuXG5TaW5nbGVNZXNzYWdlPHwtLU1lc3NhZ2VDb250ZW50XG5TaW5nbGVNZXNzYWdlPHwtLU1lc3NhZ2VNZXRhZGF0YVxuXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlfQ) `SingleMessage` 表示单个消息元素,`MessageChain`(消息链) 是 `List`。主动发送的消息和从服务器接收消息都是 `MessageChain`。 -mirai 提供大量消息链的扩展:[MessageChain.kt](../mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt#L59)。 > 回到 [目录](#目录) @@ -130,6 +130,7 @@ at.toMiraiCode() // 结果为 `[mirai:at:123]` | [`PokeMessage`] | `[mirai:poke:$name,$pokeType,$id]` | | [`VipFace`] | `[mirai:vipface:${kind.id},${kind.name},$count]` | | [`LightApp`] | `[mirai:app:$content]` | +| [`SimpleServiceMessage`] | `[mirai:service:$serviceId,$content]` | ### 由 mirai 码字符串取得 `MessageChain` 实例 @@ -150,6 +151,8 @@ MessageChain chain = MiraiCode.parseMiraiCode("[mirai:atall]"); 前文已经介绍消息链,这里介绍消息链的使用。 +### 发送消息 + 在 [Contacts 章节](Contacts.md) 提到,要发送消息使用 `Contact.sendMessage`。`Contact.sendMessage` 的定义是: ```kotlin suspend fun sendMessage(message: Message): MessageReceipt @@ -226,7 +229,7 @@ MessageChain chain = new MessageChainBuilder() ### 元素唯一性 [`MessageKey`]: ../mirai-core-api/src/commonMain/kotlin/message/data/MessageKey.kt -[`ConstrainSingle`]: ../mirai-core-api/src/commonMain/kotlin/message/data/Message.kt#L350-L370 +[`ConstrainSingle`]: ../mirai-core-api/src/commonMain/kotlin/message/data/Message.kt#L273-L287 [`HummerMessage`]: ../mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt 部分元素只能单一存在于消息链中。这样的元素实现接口 [`ConstrainSingle`]。 @@ -270,7 +273,7 @@ val image: Image? = chain.filterIsInstance().firstOrNull() Image image = (Image) chain.stream().filter(Image.class::isInstance).findFirst().orElse(null); ``` -在 Kotlin 要获取第一个指定类型实例还可以使用扩展。 +在 Kotlin 要获取第一个指定类型实例还可以使用快捷扩展。 ```kotlin val image: Image? = chain.findIsInstance() val image: Image = chain.firstIsInstance() // 不存在时 NoSuchElementException diff --git a/mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt b/mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt index 62a1d2565..a76c2bdea 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt +++ b/mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt @@ -23,7 +23,7 @@ import kotlin.coroutines.EmptyCoroutineContext * * ### Kotlin 函数 * Kotlin 函数要求: - * - 接收者 (英 receiver) 和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在) + * - 接收者和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在) * 接收者或函数参数的类型都必须为 [Event] 或其子类. * - 返回值: 为 [Unit] 或不指定返回值时将注册为 [EventChannel.subscribeAlways], 为 [ListeningStatus] 时将注册为 [EventChannel.subscribe]. * 任何其他类型的返回值将会在注册时抛出异常. @@ -108,7 +108,7 @@ import kotlin.coroutines.EmptyCoroutineContext * // T 表示任何 Event 类型. * void onEvent(T) * Void onEvent(T) - * @NotNull ListeningStatus onEvent(T) // 返回 null 时将抛出异常 + * @NotNull ListeningStatus onEvent(T) // 禁止返回 null * ``` * *