mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-27 08:50:15 +08:00
Update docs
This commit is contained in:
parent
59eea052be
commit
4fa7867e6a
@ -37,4 +37,5 @@ Bot bot = BotFactory.INSTANCE.newBot( );
|
||||
|
||||
|
||||
> 下一步,[Contacts](Contacts.md)
|
||||
>
|
||||
> [回到 Mirai 文档索引](README.md)
|
@ -7,4 +7,5 @@
|
||||
可通过 `Bot.getFriend` 或 `Bot.getGroup` 获取相关对象。
|
||||
|
||||
> 下一步,[Events](Events.md)
|
||||
>
|
||||
> [回到 Mirai 文档索引](README.md)
|
191
docs/Events.md
191
docs/Events.md
@ -1,25 +1,39 @@
|
||||
# Mirai - Events
|
||||
|
||||
## 目录
|
||||
- [使用 `ListenerHost` 监听事件](#使用-listenerhost-监听事件)
|
||||
- [在 Kotlin 函数式监听](#在-kotlin-函数式监听)
|
||||
- [事件列表](#事件列表)
|
||||
|
||||
- [事件系统](#事件系统)
|
||||
- [监听事件](#监听事件)
|
||||
- [使用 `ListenerHost` 监听事件](#使用-listenerhost-监听事件)
|
||||
- [在 Kotlin 函数式监听](#在-kotlin-函数式监听)
|
||||
- [实现事件](#实现事件)
|
||||
- [工具函数(Kotlin)](#工具函数kotlin)
|
||||
|
||||
|
||||
## 事件系统
|
||||
|
||||
Mirai 以事件驱动,使用者需要监听如 `收到消息`,`收到入群申请` 等事件。
|
||||
|
||||
[`Event`]: ../mirai-core-api/src/commonMain/kotlin/event/Event.kt#L21-L62
|
||||
|
||||
每个事件都实现接口 [`Event`],且继承 `AbstractEvent`。
|
||||
实现 `CancellableEvent` 的事件可以被取消(`CancellableEvent.cancel`)。
|
||||
|
||||
[事件列表](../mirai-core-api/src/commonMain/kotlin/event/events/README.md#事件)
|
||||
|
||||
## 监听事件
|
||||
|
||||
有两种方法监听事件:
|
||||
- [使用 `ListenerHost` 监听事件](#使用-listenerhost-监听事件)
|
||||
- [在 Kotlin 函数式监听](#在-kotlin-函数式监听)
|
||||
|
||||
## 使用 `ListenerHost` 监听事件
|
||||
### 使用 `ListenerHost` 监听事件
|
||||
|
||||
标注一个函数(方法)为事件监听器。mirai 通过反射获取他们并为之注册事件。
|
||||
|
||||
> 详见 [EventHandler](../mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt#L27-L168)
|
||||
|
||||
### Kotlin 函数
|
||||
#### Kotlin 函数
|
||||
|
||||
Kotlin 函数要求:
|
||||
- 接收者 (英 receiver) 和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在)
|
||||
@ -89,7 +103,7 @@ object MyEvents : SimpleListenerHost( /* override coroutineContext here */ ) {
|
||||
}
|
||||
MyEvents.registerEvents()
|
||||
```
|
||||
### Java 方法
|
||||
#### Java 方法
|
||||
|
||||
所有 Java 方法都会在 `Dispatchers.IO` 中调用,因此在 Java 可以调用阻塞方法。
|
||||
|
||||
@ -127,15 +141,15 @@ public class MyEventHandlers extends SimpleListenerHost {
|
||||
// Events.registerEvents(new MyEventHandlers())
|
||||
```
|
||||
|
||||
## 在 Kotlin 函数式监听
|
||||
### 在 Kotlin 函数式监听
|
||||
[CoroutineScope.subscribe](../mirai-core-api/src/commonMain/kotlin/event/subscriber.kt#L137-L220)
|
||||
|
||||
用法示例:
|
||||
```kotlin
|
||||
object YourApplication : CoroutineScope by CoroutineScope(SupervisorJob())
|
||||
object MyApplication : CoroutineScope by CoroutineScope(SupervisorJob())
|
||||
|
||||
// 启动事件监听器
|
||||
YourApplication.subscribeAlways<GroupMessageEvent> {
|
||||
MyApplication.subscribeAlways<GroupMessageEvent> {
|
||||
// this: GroupMessageEvent
|
||||
// it: GroupMessageEvent
|
||||
// lambda 的 this 和参数都是 GroupMessageEvent
|
||||
@ -148,7 +162,7 @@ YourApplication.subscribeAlways<GroupMessageEvent> {
|
||||
|
||||
Mirai 也支持传递函数引用:
|
||||
```kotlin
|
||||
YourApplication.subscribeAlways<GroupMessageEvent> {
|
||||
MyApplication.subscribeAlways<GroupMessageEvent> {
|
||||
// this: GroupMessageEvent
|
||||
// it: GroupMessageEvent
|
||||
// lambda 的 this 和参数都是 GroupMessageEvent
|
||||
@ -157,6 +171,159 @@ YourApplication.subscribeAlways<GroupMessageEvent> {
|
||||
}
|
||||
```
|
||||
|
||||
## 事件列表
|
||||
### 在 Kotlin 使用 DSL 监听事件
|
||||
> **警告:此节内容需要坚实的 Kotlin 技能,盲目使用会导致问题**
|
||||
|
||||
[事件列表](../mirai-core-api/src/commonMain/kotlin/event/events/README.md#事件)
|
||||
[subscribeMessages](../mirai-core-api/src/commonMain/kotlin/event/subscribeMessages.kt#L37-L64)
|
||||
|
||||
示例:
|
||||
```
|
||||
MyApplication.subscribeMessages {
|
||||
"test" {
|
||||
// 当消息内容为 "test" 时执行
|
||||
// this: MessageEvent
|
||||
reply("test!")
|
||||
}
|
||||
|
||||
"Hello" reply "Hi" // 当消息内容为 "Hello" 时回复 "Hi"
|
||||
"quote me" quoteReply "ok" // 当消息内容为 "quote me" 时引用该消息并回复 "ok"
|
||||
"quote me2" quoteReply {
|
||||
// lambda 也是允许的:
|
||||
// 返回值接受 Any?
|
||||
// 为 Unit 时不发送任何内容;
|
||||
// 为 Message 时直接发送;
|
||||
// 为 String 时发送为 PlainText;
|
||||
// 否则 toString 并发送为 PlainText
|
||||
|
||||
"ok"
|
||||
}
|
||||
|
||||
case("iGNorECase", ignoreCase=true) reply "OK" // 忽略大小写
|
||||
startsWith("-") reply { cmd ->
|
||||
// 当消息内容以 "-" 开头时执行
|
||||
// cmd 为消息去除开头 "-" 的内容
|
||||
}
|
||||
|
||||
|
||||
val listener: Listener<MessageEvent> = "1" reply "2"
|
||||
// 每个语句都会被注册为事件监听器,可以这样获取监听器
|
||||
|
||||
listener.complete() // 停止 "1" reply "2" 这个事件监听
|
||||
}
|
||||
```
|
||||
|
||||
## 实现事件
|
||||
|
||||
只要实现接口 `Event` 并继承 `AbstractEvent` 的对象就可以被广播。
|
||||
|
||||
要广播一个事件,使用 `Event.broadcast()`(Kotlin)或 `EventKt.broadcast(Event)`(Java)。
|
||||
|
||||
## 工具函数(Kotlin)
|
||||
|
||||
*可能需要较好的 Kotlin 技能才能理解以下内容。*
|
||||
|
||||
基于 Kotlin 协程特性,mirai 提供 `
|
||||
|
||||
### 线性同步(`syncFromEvent`)
|
||||
[linear.kt](../mirai-core-api/src/commonMain/kotlin/event/linear.kt)
|
||||
|
||||
挂起协程并获取下一个戳 Bot 的对象:
|
||||
```kotlin
|
||||
val target: UserOrBot = syncFromEvent<BotNudgedEvent> { sender }
|
||||
```
|
||||
|
||||
带超时版本:
|
||||
```kotlin
|
||||
val target: UserOrBot = syncFromEvent<BotNudgedEvent>(5000) { sender } // 5000ms
|
||||
```
|
||||
|
||||
异步 `async` 版本:
|
||||
|
||||
```kotlin
|
||||
val target: Deferred<UserOrBot> = coroutineScope.asyncFromEvent<BotNudgedEvent> { sender }
|
||||
```
|
||||
|
||||
### 线性同步(`nextEvent`)
|
||||
[nextEvent.kt](../mirai-core-api/src/commonMain/kotlin/event/nextEvent.kt)
|
||||
|
||||
挂起协程并获取下一个指定事件:
|
||||
|
||||
```kotlin
|
||||
val event: BotNudgedEvent = nextEvent<BotNudgedEvent>()
|
||||
```
|
||||
|
||||
带超时和过滤器版本:
|
||||
|
||||
```kotlin
|
||||
val event: BotNudgedEvent = nextEvent<BotNudgedEvent>(5000) { it.bot.id == 123456L }
|
||||
```
|
||||
|
||||
### 条件选择(`selectMessages`)
|
||||
> **警告:此节内容需要坚实的 Kotlin 技能,盲目使用会导致问题**
|
||||
|
||||
[select.kt](../mirai-core-api/src/commonMain/kotlin/event/select.kt)
|
||||
|
||||
类似于 Kotlin 协程 `select`,mirai 也提供类似的功能。
|
||||
|
||||
`selectMessages`:挂起当前协程,等待任意一个事件监听器触发后返回其返回值。
|
||||
|
||||
```kotlin
|
||||
MyCoroutineScope.subscribeAlways<GroupMessageEvent> {
|
||||
if (message.contentEquals("ocr")) {
|
||||
reply("请发送你要进行 OCR 的图片或图片链接")
|
||||
val image: InputStream = selectMessages {
|
||||
has<Image> { URL(it.queryUrl()).openStream() }
|
||||
has<PlainText> { URL(it.content).openStream() }
|
||||
defaultReply { "请发送图片或图片链接" }
|
||||
timeout(30_000) { event.quoteReply("请在 30 秒内发送图片或图片链接"); null }
|
||||
} ?: return@subscribeAlways
|
||||
|
||||
val result = ocr(image)
|
||||
quoteReply(result)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这种语法就相当于(伪代码):
|
||||
```
|
||||
val image = when (下一条消息) {
|
||||
包含图片 { 查询图片链接() }
|
||||
包含纯文本 { 下载图片() }
|
||||
其他情况 { 引用回复() }
|
||||
超时 { 引用回复() }
|
||||
}
|
||||
```
|
||||
|
||||
### 循环条件选择(`whileSelectMessages`)
|
||||
> **警告:此节内容需要坚实的 Kotlin 技能,盲目使用会导致问题**
|
||||
|
||||
[select.kt](../mirai-core-api/src/commonMain/kotlin/event/select.kt)
|
||||
|
||||
类似于 Kotlin 协程 `whileSelect`,mirai 也提供类似的功能。
|
||||
|
||||
`whileSelectMessages`:挂起当前协程,等待任意一个事件监听器返回 `false` 后返回。
|
||||
|
||||
```kotlin
|
||||
reply("开启复读模式")
|
||||
whileSelectMessages {
|
||||
"stop" {
|
||||
reply("已关闭复读")
|
||||
false // 停止循环
|
||||
}
|
||||
// 也可以使用 startsWith("") { true } 等 DSL
|
||||
default {
|
||||
reply(message)
|
||||
true // 继续循环
|
||||
}
|
||||
timeout(3000) {
|
||||
// on
|
||||
true
|
||||
}
|
||||
} // 等待直到 `false`
|
||||
reply("复读模式结束")
|
||||
```
|
||||
|
||||
|
||||
> 下一步,[Messages](Messages.md)
|
||||
>
|
||||
> [回到 Mirai 文档索引](README.md)
|
@ -66,5 +66,6 @@ mirai 官方提供 Kotlin/Java 等 JVM 平台语言开发支持。如果你不
|
||||
|
||||
***本文档正在更新中***
|
||||
|
||||
- [创建 Bot](CreatingBots.md)
|
||||
- [Bots](Bots.md)
|
||||
- [Contacts](Contacts.md)
|
||||
- [Events](Events.md)
|
||||
|
Loading…
Reference in New Issue
Block a user