diff --git a/docs/ConfiguringProjects.md b/docs/ConfiguringProjects.md index 4880d1b4f..3ee45288c 100644 --- a/docs/ConfiguringProjects.md +++ b/docs/ConfiguringProjects.md @@ -4,7 +4,7 @@ mirai 使用纯 Kotlin 开发,最低要求 `JDK 1.8`,`Kotlin 1.4`。 -如果你熟悉构建工具,只需要添加 `jcenter` 仓库和依赖 `net.mamoe:mirai-core:VERSION` 即可而不需要继续阅读。下文将详细解释这些步骤。 +如果你熟悉 Gradle,只需要添加 `jcenter` 仓库和依赖 `net.mamoe:mirai-core:VERSION` 即可而不需要继续阅读。下文将详细解释其他方法。 本文提供如下三种配置方法,但更推荐使用 Gradle 构建。 @@ -86,7 +86,7 @@ dependencies { net.mamoe - mirai-core + mirai-core-jvm 1.3.3 diff --git a/docs/Contacts.md b/docs/Contacts.md index ce0c6707f..48c5671af 100644 --- a/docs/Contacts.md +++ b/docs/Contacts.md @@ -1 +1,10 @@ -# Mirai - Contacts \ No newline at end of file +# Mirai - Contacts + +[![](https://mermaid.ink/img/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5cbmNsYXNzIEJvdCB7XG4gICAgK2ZyaWVuZHM6IENvbnRhY3RMaXN0XG4gICAgK2dyb3VwczogQ29udGFjdExpc3RcbiAgICArZ2V0RnJpZW5kKExvbmcpIEZyaWVuZD9cbiAgICArZ2V0RnJpZW5kT3JOdWxsKExvbmcpIEZyaWVuZFxuICAgICtnZXRHcm91cChMb25nKSBHcm91cD9cbiAgICArZ2V0R3JvdXBPckZhaWwoTG9uZykgR3JvdXBcbiAgICArbG9naW4oKVxuICAgICtjbG9zZSgpXG59XG5cbmNsYXNzIENvbnRhY3RPckJvdCB7XG4gICAgK2lkOiBJbnRcbn1cblxuY2xhc3MgVXNlck9yQm90IHtcbiAgICArbnVkZ2UoKSBOdWRnZVxufVxuXG5jbGFzcyBDb250YWN0IHtcbiAgICArYm90OiBCb3RcbiAgICArc2VuZE1lc3NhZ2UoTWVzc2FnZSkgTWVzc2FnZVJlY2VpcHRcbiAgICArc2VuZE1lc3NhZ2UoU3RyaW5nKSBNZXNzYWdlUmVjZWlwdFxuICAgICt1cGxvYWRJbWFnZShFeHRlcm5hbEltYWdlKSBJbWFnZVxufVxuXG5jbGFzcyBVc2VyIHtcbiAgICArbmljazogU3RyaW5nXG4gICAgK3JlbWFyazogU3RyaW5nXG4gICAgK2F2YXRhclVybDogU3RyaW5nXG59XG5cbmNsYXNzIEdyb3VwIHtcbiAgICArbWVtYmVyczogQ29udGFjdExpc3RcbiAgICArbmFtZTogU3RyaW5nXG4gICAgK3NldHRpbmdzOiBHcm91cFNldHRpbmdzXG4gICAgK293bmVyOiBOb3JtYWxNZW1iZXJcbiAgICArYm90TXV0ZVJlbWFpbmluZzogTG9uZ1xuICAgICtib3RQZXJtaXNzaW9uOiBNZW1iZXJQZXJtaXNzaW9uXG4gICAgK3F1aXQoKSBCb29sZWFuXG4gICAgK3VwbG9hZFZvaWNlKCkgVm9pY2Vcbn1cblxuY2xhc3MgTm9ybWFsTWVtYmVyIHtcbiAgICArbXV0ZSgpXG4gICAgK2tpY2soKVxufVxuXG5jbGFzcyBBbm9ueW1vdXNNZW1iZXIge1xuICAgICthbm9ueW1vdXNJZDogU3RyaW5nXG59XG5cbmNsYXNzIE1lbWJlciB7XG4gICAgK2dyb3VwOiBHcm91cFxufVxuXG5Db250YWN0T3JCb3Q8LS1Db250YWN0XG5Db250YWN0T3JCb3Q8LS1Vc2VyT3JCb3RcblxuVXNlck9yQm90PC0tQm90XG5Vc2VyT3JCb3Q8LS1Vc2VyXG5cbkNvbnRhY3Q8LS1Vc2VyXG5Db250YWN0PC0tR3JvdXBcblxuVXNlcjwtLU1lbWJlclxuVXNlcjwtLUZyaWVuZFxuXG5NZW1iZXI8LS1Ob3JtYWxNZW1iZXJcbk1lbWJlcjwtLUFub255bW91c01lbWJlciIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In0sInVwZGF0ZUVkaXRvciI6ZmFsc2V9)](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5cbmNsYXNzIEJvdCB7XG4gICAgK2ZyaWVuZHM6IENvbnRhY3RMaXN0XG4gICAgK2dyb3VwczogQ29udGFjdExpc3RcbiAgICArZ2V0RnJpZW5kKExvbmcpIEZyaWVuZD9cbiAgICArZ2V0RnJpZW5kT3JOdWxsKExvbmcpIEZyaWVuZFxuICAgICtnZXRHcm91cChMb25nKSBHcm91cD9cbiAgICArZ2V0R3JvdXBPckZhaWwoTG9uZykgR3JvdXBcbiAgICArbG9naW4oKVxuICAgICtjbG9zZSgpXG59XG5cbmNsYXNzIENvbnRhY3RPckJvdCB7XG4gICAgK2lkOiBJbnRcbn1cblxuY2xhc3MgVXNlck9yQm90IHtcbiAgICArbnVkZ2UoKSBOdWRnZVxufVxuXG5jbGFzcyBDb250YWN0IHtcbiAgICArYm90OiBCb3RcbiAgICArc2VuZE1lc3NhZ2UoTWVzc2FnZSkgTWVzc2FnZVJlY2VpcHRcbiAgICArc2VuZE1lc3NhZ2UoU3RyaW5nKSBNZXNzYWdlUmVjZWlwdFxuICAgICt1cGxvYWRJbWFnZShFeHRlcm5hbEltYWdlKSBJbWFnZVxufVxuXG5jbGFzcyBVc2VyIHtcbiAgICArbmljazogU3RyaW5nXG4gICAgK3JlbWFyazogU3RyaW5nXG4gICAgK2F2YXRhclVybDogU3RyaW5nXG59XG5cbmNsYXNzIEdyb3VwIHtcbiAgICArbWVtYmVyczogQ29udGFjdExpc3RcbiAgICArbmFtZTogU3RyaW5nXG4gICAgK3NldHRpbmdzOiBHcm91cFNldHRpbmdzXG4gICAgK293bmVyOiBOb3JtYWxNZW1iZXJcbiAgICArYm90TXV0ZVJlbWFpbmluZzogTG9uZ1xuICAgICtib3RQZXJtaXNzaW9uOiBNZW1iZXJQZXJtaXNzaW9uXG4gICAgK3F1aXQoKSBCb29sZWFuXG4gICAgK3VwbG9hZFZvaWNlKCkgVm9pY2Vcbn1cblxuY2xhc3MgTm9ybWFsTWVtYmVyIHtcbiAgICArbXV0ZSgpXG4gICAgK2tpY2soKVxufVxuXG5jbGFzcyBBbm9ueW1vdXNNZW1iZXIge1xuICAgICthbm9ueW1vdXNJZDogU3RyaW5nXG59XG5cbmNsYXNzIE1lbWJlciB7XG4gICAgK2dyb3VwOiBHcm91cFxufVxuXG5Db250YWN0T3JCb3Q8LS1Db250YWN0XG5Db250YWN0T3JCb3Q8LS1Vc2VyT3JCb3RcblxuVXNlck9yQm90PC0tQm90XG5Vc2VyT3JCb3Q8LS1Vc2VyXG5cbkNvbnRhY3Q8LS1Vc2VyXG5Db250YWN0PC0tR3JvdXBcblxuVXNlcjwtLU1lbWJlclxuVXNlcjwtLUZyaWVuZFxuXG5NZW1iZXI8LS1Ob3JtYWxNZW1iZXJcbk1lbWJlcjwtLUFub255bW91c01lbWJlciIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In0sInVwZGF0ZUVkaXRvciI6ZmFsc2V9) + +要主动发送一条消息,调用 `Contact.sendMessage()` 即可。 + +可通过 `Bot.getFriend` 或 `Bot.getGroup` 获取相关对象。 + +> 下一步,[Events](Events.md) +> [回到 Mirai 文档索引](README.md) \ No newline at end of file diff --git a/docs/Events.md b/docs/Events.md new file mode 100644 index 000000000..107856dc3 --- /dev/null +++ b/docs/Events.md @@ -0,0 +1,162 @@ +# Mirai - Events + +## 目录 +- [使用 `ListenerHost` 监听事件](#使用-listenerhost-监听事件) +- [在 Kotlin 函数式监听](#在-kotlin-函数式监听) +- [事件列表](#事件列表) + +## 事件系统 + +Mirai 以事件驱动,使用者需要监听如 `收到消息`,`收到入群申请` 等事件。 + +有两种方法监听事件: +- [使用 `ListenerHost` 监听事件](#使用-listenerhost-监听事件) +- [在 Kotlin 函数式监听](#在-kotlin-函数式监听) + +## 使用 `ListenerHost` 监听事件 + +标注一个函数(方法)为事件监听器。mirai 通过反射获取他们并为之注册事件。 + +> 详见 [EventHandler](../mirai-core-api/src/commonMain/kotlin/event/JvmMethodListeners.kt#L27-L168) + +### Kotlin 函数 + +Kotlin 函数要求: +- 接收者 (英 receiver) 和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在) + 接收者或函数参数的类型都必须为 `Event` 或其子类. +- 返回值: 为 `Unit` 或不指定返回值时将注册为 `CoroutineScope.subscribeAlways`, 为 `ListeningStatus` 时将注册为 `CoroutineScope.subscribe`. + 任何其他类型的返回值将会在注册时抛出异常. + +所有 Kotlin 非 `suspend` 的函数都将会在 `Dispatchers.IO` 中调用 + +支持的函数类型: +```kotlin +// 所有函数参数, 函数返回值都不允许标记为可空 (带有 '?' 符号) +// T 表示任何 Event 类型. +suspend fun T.onEvent(T) +suspend fun T.onEvent(T): ListeningStatus +suspend fun T.onEvent(T): Nothing +suspend fun onEvent(T) +suspend fun onEvent(T): ListeningStatus +suspend fun onEvent(T): Nothing +suspend fun T.onEvent() +suspend fun T.onEvent(): ListeningStatus +suspend fun T.onEvent(): Nothing +fun T.onEvent(T) +fun T.onEvent(T): ListeningStatus +fun T.onEvent(T): Nothing +fun onEvent(T) +fun onEvent(T): ListeningStatus +fun onEvent(T): Nothing +fun T.onEvent() +fun T.onEvent(): ListeningStatus +fun T.onEvent(): Nothing +``` + +Kotlin 使用示例: + +- 独立 `CoroutineScope` 和 `ListenerHost` +```kotlin +object MyEvents : ListenerHost { + override val coroutineContext = SupervisorJob() + // 可以抛出任何异常, 将在 this.coroutineContext 或 registerEvents 时提供的 CoroutineScope.coroutineContext 中的 CoroutineExceptionHandler 处理. + @EventHandler + suspend fun MessageEvent.onMessage() { + reply("received") + } +} +myCoroutineScope.registerEvents(MyEvents) +``` +`onMessage` 抛出的异常将会交给 `myCoroutineScope` 处理 + +- 合并 `CoroutineScope` 和 `ListenerHost`: 使用 `SimpleListenerHost` +```kotlin +object MyEvents : SimpleListenerHost( /* override coroutineContext here */ ) { + override fun handleException(context: CoroutineContext, exception: Throwable) { + // 处理 onMessage 中未捕获的异常 + } + @EventHandler + suspend fun MessageEvent.onMessage() { // 可以抛出任何异常, 将在 handleException 处理 + reply("received") + // 无返回值 (或者返回 Unit), 表示一直监听事件. + } + @EventHandler + suspend fun MessageEvent.onMessage(): ListeningStatus { // 可以抛出任何异常, 将在 handleException 处理 + reply("received") + return ListeningStatus.LISTENING // 表示继续监听事件 + // return ListeningStatus.STOPPED // 表示停止监听事件 + } +} +MyEvents.registerEvents() +``` +### Java 方法 + +所有 Java 方法都会在 `Dispatchers.IO` 中调用,因此在 Java 可以调用阻塞方法。 + +支持的方法类型: +``` +// T 表示任何 Event 类型. +void onEvent(T) +Void onEvent(T) +ListeningStatus onEvent(T) // 返回 null 时将抛出异常 +``` + +Java 使用示例: + +```java +public class MyEventHandlers extends SimpleListenerHost { + @Override + public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception){ + // 处理事件处理时抛出的异常 + } + @EventHandler + public void onMessage(@NotNull MessageEvent event) throws Exception { // 可以抛出任何异常, 将在 handleException 处理 + event.subject.sendMessage("received"); + // 无返回值, 表示一直监听事件. + } + @NotNull + @EventHandler + public ListeningStatus onMessage(@NotNull MessageEvent event) throws Exception { // 可以抛出任何异常, 将在 handleException 处理 + event.subject.sendMessage("received"); + return ListeningStatus.LISTENING; // 表示继续监听事件 + // return ListeningStatus.STOPPED; // 表示停止监听事件 + } +} + +// 注册: +// Events.registerEvents(new MyEventHandlers()) +``` + +## 在 Kotlin 函数式监听 +[CoroutineScope.subscribe](../mirai-core-api/src/commonMain/kotlin/event/subscriber.kt#L137-L220) + +用法示例: +```kotlin +object YourApplication : CoroutineScope by CoroutineScope(SupervisorJob()) + +// 启动事件监听器 +YourApplication.subscribeAlways { + // this: GroupMessageEvent + // it: GroupMessageEvent + // lambda 的 this 和参数都是 GroupMessageEvent + + group.sendMessage(sender.at() + "Hello! ${sender.nick}") +} + +// YouApplication[Job]!!.cancel() // +``` + +Mirai 也支持传递函数引用: +```kotlin +YourApplication.subscribeAlways { + // this: GroupMessageEvent + // it: GroupMessageEvent + // lambda 的 this 和参数都是 GroupMessageEvent + + group.sendMessage(sender.at() + "Hello! ${sender.nick}") +} +``` + +## 事件列表 + +[事件列表](../mirai-core-api/src/commonMain/kotlin/event/events/README.md#事件) \ No newline at end of file diff --git a/docs/src/Contacts.mermaid.md b/docs/src/Contacts.mermaid.md new file mode 100644 index 000000000..513fcd7cc --- /dev/null +++ b/docs/src/Contacts.mermaid.md @@ -0,0 +1,74 @@ +```mermaid +classDiagram + +class Bot { + +friends: ContactList + +groups: ContactList + +getFriend(Long) Friend? + +getFriendOrNull(Long) Friend + +getGroup(Long) Group? + +getGroupOrFail(Long) Group + +login() + +close() +} + +class ContactOrBot { + +id: Int +} + +class UserOrBot { + +nudge() Nudge +} + +class Contact { + +bot: Bot + +sendMessage(Message) MessageReceipt + +sendMessage(String) MessageReceipt + +uploadImage(ExternalImage) Image +} + +class User { + +nick: String + +remark: String + +avatarUrl: String +} + +class Group { + +members: ContactList + +name: String + +settings: GroupSettings + +owner: NormalMember + +botMuteRemaining: Long + +botPermission: MemberPermission + +quit() Boolean + +uploadVoice() Voice +} + +class NormalMember { + +mute() + +kick() +} + +class AnonymousMember { + +anonymousId: String +} + +class Member { + +group: Group +} + +ContactOrBot<--Contact +ContactOrBot<--UserOrBot + +UserOrBot<--Bot +UserOrBot<--User + +Contact<--User +Contact<--Group + +User<--Member +User<--Friend + +Member<--NormalMember +Member<--AnonymousMember +``` \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/event/events/README.md b/mirai-core-api/src/commonMain/kotlin/event/events/README.md index 02167d9ce..9cf4e000a 100644 --- a/mirai-core-api/src/commonMain/kotlin/event/events/README.md +++ b/mirai-core-api/src/commonMain/kotlin/event/events/README.md @@ -25,9 +25,10 @@ - (`1.3.0+`) Bot 被戳: BotNudgedEvent ### [消息](message.kt) -- (`1.1.0-`) 主动发送消息: MessageSendEvent - - 群消息: GroupMessageSendEvent - - 好友消息: FriendMessageSendEvent +- 被动收到消息:MessageEvent + - 群消息:GroupMessageEvent + - 好友消息:FriendMessageEvent + - 群临时会话消息:TempMessageEvent - (`1.1.0+`) 主动发送消息前: MessagePreSendEvent - 群消息: GroupMessagePreSendEvent - 好友消息: FriendMessagePreSendEvent @@ -44,6 +45,9 @@ - 图片上传完成: ImageUploadEvent - 图片上传成功: Succeed - 图片上传失败: Failed +- (`1.1.0-`) ~~主动发送消息: MessageSendEvent~~ + - ~~群消息: GroupMessageSendEvent~~ + - ~~好友消息: FriendMessageSendEvent~~ ### [群](group.kt) - 机器人被踢出群或在其他客户端主动退出一个群: BotLeaveEvent @@ -60,7 +64,7 @@ - 入群公告改变: GroupEntranceAnnouncementChangeEvent - 全员禁言状态改变: GroupMuteAllEvent - 匿名聊天状态改变: GroupAllowAnonymousChatEvent - - 坦白说状态改变: GroupAllowConfessTalkEvent + - (`1.3.0-`) ~~坦白说状态改变: GroupAllowConfessTalkEvent~~ - 允许群员邀请好友加群状态改变: GroupAllowMemberInviteEvent #### 群成员