From 0b6bccff31fc8a2ed1b8ba1d586a7a6b6d6b393d Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Sun, 31 Dec 2023 23:24:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Writerside/topics/Home.md | 6 +- Writerside/topics/Welcome.topic | 10 +- Writerside/topics/bot-config.md | 148 ++++++++++++++ Writerside/topics/snippets.md | 268 ++++++++++++++++++++++++++ Writerside/topics/use-api.md | 69 ++----- Writerside/topics/use-core.md | 2 +- Writerside/topics/use-spring-boot.md | 276 ++++++++++++++++++++++++++- Writerside/topics/use-stdlib.md | 230 +++++++++++++++++++++- Writerside/villa.tree | 1 + 9 files changed, 947 insertions(+), 63 deletions(-) create mode 100644 Writerside/topics/bot-config.md create mode 100644 Writerside/topics/snippets.md diff --git a/Writerside/topics/Home.md b/Writerside/topics/Home.md index c4e220a..8f548b0 100644 --- a/Writerside/topics/Home.md +++ b/Writerside/topics/Home.md @@ -1,8 +1,8 @@ # 前言&简介 - -

文档当前目标版本: v%version%

-
+ + + 欢迎来到 [Simple Robot](https://github.com/simple-robot/simpler-robot) (下文简称 simbot ) diff --git a/Writerside/topics/Welcome.topic b/Writerside/topics/Welcome.topic index 18e8483..81eb6a8 100644 --- a/Writerside/topics/Welcome.topic +++ b/Writerside/topics/Welcome.topic @@ -24,17 +24,17 @@ - 欢迎! + 欢迎! 快速开始 - - - - + + + + diff --git a/Writerside/topics/bot-config.md b/Writerside/topics/bot-config.md new file mode 100644 index 0000000..8ed836a --- /dev/null +++ b/Writerside/topics/bot-config.md @@ -0,0 +1,148 @@ +# Bot配置文件 + + +

在使用 Spring Boot 时自动注册 bot 所需的配置文件。

+
+ +## 简单示例 + +```json +{ + "component": "simbot.villa", + "ticket": { + "botId": "你的botId", + "botSecret": "你的botSecret" + } +} +``` +{collapsible="true" default-state="expanded" collapsed-title="简单示例"} + +```json +{ + "component": "simbot.villa", + "ticket": { + "botId": "你的botId", + "botSecret": "你的botSecret" + }, + "config": { + "loginVillaId": "0", + "loginMeta": null, + "loginRegion": null, + "timeout": null + } +} +``` +{collapsible="true" default-state="collapsed" collapsed-title="完整示例"} + +## 属性描述 + + + + +固定值:`simbot.villa` + + + + +bot用于登录的票据信息,必填。 + + + + +`String` + +bot开发配置中的 `bot_id` + + + + +`String` + +bot开发配置中的 `secret` + + + + + + + +可选项,提供一些额外的可配置属性。 + + + + +`String` + +创建连接(获取 ws 连接信息)时提供给 API 的 token 中的 `villa_id` 属性。 + +机器人未上线时,`villa_id` 使用测试别野,上线后可传 `0`。 + +默认为 `0`。 + + + + +`Map?` + +应用在 `PLogin.meta` 上的属性。 + +默认为 `null`。 + + + + +`String?` + +应用在 `PLogin.region` 上的属性。如果为 `null` 则会使用一个随机值。 + +默认为 `null`。 + + + + +`TimeoutConfig?` + +与部分超时相关的配置信息。 +当任意属性不为 `null` 时会为 bot 中用于请求API的 `HttpClient` +配置 [HttpTimeout][HttpTimeout] 插件。 + +默认为 `null`。 + + + + +`Long?` + +API请求中的超时请求配置。参考 [HttpTimeout][HttpTimeout] 中的相关说明。 + +默认为 `null`。 + + + + +`Long?` + +API请求中的超时请求配置。参考 [HttpTimeout][HttpTimeout] 中的相关说明。 + +默认为 `null`。 + + + + +`Long?` + +API请求中的超时请求配置。参考 [HttpTimeout][HttpTimeout] 中的相关说明。 + +默认为 `null`。 + + + + + + + + + + + +[HttpTimeout]: https://ktor.io/docs/timeout.html diff --git a/Writerside/topics/snippets.md b/Writerside/topics/snippets.md new file mode 100644 index 0000000..8fcc365 --- /dev/null +++ b/Writerside/topics/snippets.md @@ -0,0 +1,268 @@ +[//]: # (Ktor 引擎选择) + + + + + +你可以前往 [Ktor文档](https://ktor.io/docs/http-client-engines.html) +处选择一个对应所用平台下合适的 `Client Engine`。 +这里会根据不同平台提供几个示例,你可以选择其他可用目标。 + + + +
+ +[CIO](https://ktor.io/docs/http-client-engines.html#cio) 是一个比较通用的引擎。 +在不知道选什么的情况下,可以考虑使用它。 + + + + +```kotlin +runtimeOnly("io.ktor:ktor-client-cio-jvm:$ktor_version") +``` + + + + +```groovy +runtimeOnly 'io.ktor:ktor-client-cio-jvm:$ktor_version' +``` + + + + +```xml + + io.ktor + ktor-client-cio-jvm + ${ktor_version} + runtime + +``` + + + + +
+ +如果你打算使用 Java11+,也可以选择 [Java](https://ktor.io/docs/http-client-engines.html#java) 引擎。 + +
+ + + + +```kotlin +runtimeOnly("io.ktor:ktor-client-java:$ktor_version") +``` + +
+ +> 如果你想要显式配置引擎,那么就不能使用 `runtimeOnly` 了。 + +
+ + +```groovy +runtimeOnly 'io.ktor:ktor-client-java:$ktor_version' +``` + +
+ +> 如果你想要显式配置引擎,那么就不能使用 `runtimeOnly` 了。 + +
+ + +```xml + + io.ktor + ktor-client-java-jvm + ${ktor_version} + runtime + +``` + +
+ +> 如果你想要显式配置引擎,那么就不能使用 `runtime scope` 了。 + +
+
+ +
+ + +
+ +JavaScript 平台下可以选择 [Js](https://ktor.io/docs/http-client-engines.html#js) 引擎。 + + + + +```kotlin +implementation("io.ktor:ktor-client-js:$ktor_version") +``` + + + + +```groovy +implementation 'io.ktor:ktor-client-js:$ktor_version' +``` + + + + +
+ + +
+ +native 平台目标下,可能需要根据不同的平台类型选择不同的引擎。 + + + +
+ +可以选择 [WinHttp](https://ktor.io/docs/http-client-engines.html#winhttp) 引擎。 + + + + +```kotlin +implementation("io.ktor:ktor-client-winhttp:$ktor_version") +``` + + + + +```groovy +implementation 'io.ktor:ktor-client-winhttp:$ktor_version' +``` + + + + +
+ +
+ +Linux 下依旧可以选择 [CIO](https://ktor.io/docs/http-client-engines.html#cio) 引擎。 + + + + +```kotlin +implementation("io.ktor:ktor-client-cio:$ktor_version") +``` + + + + +```groovy +implementation 'io.ktor:ktor-client-cio:$ktor_version' +``` + + + + +
+ +
+ +可以选择 [Darwin](https://ktor.io/docs/http-client-engines.html#darwin) 引擎。 + + + + +```kotlin +implementation("io.ktor:ktor-client-darwin:$ktor_version") +``` + + + + +```groovy +implementation 'io.ktor:ktor-client-darwin:$ktor_version' +``` + + + + +
+
+ +
+
+ +
+
+ + +
+ +[//]: # (文档描述信息) + +

文档描述版本: v%version%

+ + +[//]: # (依赖安装描述. 需要参数 %name%) + + + + + +```kotlin +plugins { + // 或使用 kotlin("multiplatform") + // 但是不管是什么,你都需要 kotlin 插件来支持自动选择对应平台的依赖。 + kotlin("jvm") version "%kt-version%" + // 其他一些插件, 随你喜欢 + `[[[java|https://docs.gradle.org/current/userguide/java_plugin.html#header]]]` // 你依旧可以使用 Java 编写代码 + `[[[application|https://docs.gradle.org/current/userguide/application_plugin.html]]]` // 使用 application 可以打包你的应用程序 +} +// 其他配置... +dependencies { + implementation("love.forte.simbot.component:simbot-component-miyoushe-villa-%name%:%version%") + // 其他依赖.. +} +``` + + + + +```groovy +plugins { + // 或使用 org.jetbrains.kotlin.multiplatform, + // 但是不管是什么,你都需要 kotlin 插件来支持自动选择对应平台的依赖。 + id 'org.jetbrains.kotlin.jvm' version '%kt-version%' + // 其他一些插件, 随你喜欢 + id '[[[java|https://docs.gradle.org/current/userguide/java_plugin.html#header]]]' // 你依旧可以使用 Java 编写代码 + id '[[[application|https://docs.gradle.org/current/userguide/application_plugin.html]]]' // 使用 application 可以打包你的应用程序 +} +// 其他配置... +dependencies { + implementation 'love.forte.simbot.component:simbot-component-miyoushe-villa-%name%:%version%' + // 其他依赖.. +} + +``` + + + + +```xml + + love.forte.simbot.component + + simbot-component-miyoushe-villa-%name%%maven-name-suffix% + %version% + +``` + + + + + diff --git a/Writerside/topics/use-api.md b/Writerside/topics/use-api.md index 86a80bf..a681a26 100644 --- a/Writerside/topics/use-api.md +++ b/Writerside/topics/use-api.md @@ -2,66 +2,31 @@ switcher-label: JavaAPI风格 --- + # 使用API -## 安装 - - + +本章节介绍如何使用 API 模块来构建、请求一个米游社大别野的API。 + -```kotlin -plugins { - // 或使用 kotlin("multiplatform") - // 但是不管是什么,你都需要 kotlin 插件来支持自动选择对应平台的依赖。 - kotlin("jvm") version "%kt-version%" - // 其他一些插件, 随你喜欢 - [[[java|https://docs.gradle.org/current/userguide/java_plugin.html#header]]] // 你依旧可以使用 Java 编写代码 - [[[application|https://docs.gradle.org/current/userguide/application_plugin.html]]] // 使用 application 可以打包你的应用程序 -} -// 其他配置... -dependencies { - implementation 'love.forte.simbot.component:simbot-component-miyoushe-villa-api:%version%' - // 其他依赖.. -} -``` + + + - - - -```groovy -plugins { - // 或使用 org.jetbrains.kotlin.multiplatform, - // 但是不管是什么,你都需要 kotlin 插件来支持自动选择对应平台的依赖。 - id 'org.jetbrains.kotlin.jvm' version '%kt-version%' - // 其他一些插件, 随你喜欢 - id '[[[java|https://docs.gradle.org/current/userguide/java_plugin.html#header]]]' // 你依旧可以使用 Java 编写代码 - id '[[[application|https://docs.gradle.org/current/userguide/application_plugin.html]]]' // 使用 application 可以打包你的应用程序 -} -// 其他配置... -dependencies { - implementation 'love.forte.simbot.component:simbot-component-miyoushe-villa-api:%version%' - // 其他依赖.. -} +## 安装 -``` + + + + - - - -```xml - - love.forte.simbot.component - - simbot-component-miyoushe-villa-api-jvm - %version% - -``` +然后选择一个合适的 Ktor 引擎。 - - + ## 使用 @@ -70,7 +35,7 @@ dependencies { API封装的命名与API具有一定关联,例如 [`获取大别野信息`](https://webstatic.mihoyo.com/vila/bot/doc/villa_api/get_villa.html): - + ```HTTP GET /vila/api/bot/platform/getVilla @@ -87,7 +52,7 @@ API的应用大差不差,因此此处仅使用部分类型作为示例, 不会演示所有API。 - + ```kotlin // 准备 bot 的必要信息 @@ -119,7 +84,7 @@ val requestData: GetRoomResult = api.requestData(httpClient, token) ``` - + ```java // 准备 bot 的必要信息 diff --git a/Writerside/topics/use-core.md b/Writerside/topics/use-core.md index b0980b6..c907cc1 100644 --- a/Writerside/topics/use-core.md +++ b/Writerside/topics/use-core.md @@ -1,3 +1,3 @@ # 使用核心库 -Start typing here... \ No newline at end of file +你可以先参考 [使用 Spring Boot](use-spring-boot.md)。 diff --git a/Writerside/topics/use-spring-boot.md b/Writerside/topics/use-spring-boot.md index cce2632..9b55b0e 100644 --- a/Writerside/topics/use-spring-boot.md +++ b/Writerside/topics/use-spring-boot.md @@ -1,3 +1,277 @@ +--- +switcher-label: JavaAPI风格 +--- + + + + + + # 使用 Spring Boot -Start typing here... \ No newline at end of file + +本章节介绍如何在 Spring Boot 中使用大别野组件。 + + +## 安装 + +首先你需要选择使用一个 [`simboot-core-spring-boot-starter`](https://central.sonatype.com/artifact/love.forte.simbot.boot/simboot-core-spring-boot-starter/versions) +的 3.x 版本(下文以 `simbot_version` 代表之)。 + + + + +```kotlin +implementation("love.forte.simbot.boot:simboot-core-spring-boot-starter:$simbot_version") +``` + + + + +```groovy +implementation 'love.forte.simbot.boot:simboot-core-spring-boot-starter:$simbot_version' +``` + + + + +```xml + + love.forte.simbot.boot + + simboot-core-spring-boot-starter + ${simbot_version} + +``` + + + + +然后安装大别野组件的core模块依赖。 + + + + +```kotlin +implementation("love.forte.simbot.component:simbot-component-miyoushe-villa-core:%version%") +``` + + + + +```groovy +implementation 'love.forte.simbot.component:simbot-component-miyoushe-villa-core:%version%' +``` + + + + +```xml + + love.forte.simbot.component + + simbot-component-miyoushe-villa-core + %version% + +``` + + + + +然后选择一个合适的 Ktor 引擎。 + +> 你只能选择 JVM 平台的引擎 —— Spring Boot Starter 并没有其他平台。 + + + +## BOT配置 + +接下来,在项目资源文件目录下的 `simbot-bots` 文件夹中创建一个用于配置bot的配置文件 `xxx.bot.json` +(文件名随意,扩展名应为 `.bot` 或 `.bot.json`), +而配置文件的内容则参考章节 [BOT配置文件](bot-config.md) 。 + +``` +${PROJECT_SRC}/main/resources/simbot-bots/xxx.bot.json +``` + + +如果想要修改此路径,可在 Spring Boot 的配置文件中进行配置: + + + + +``` +# 自定义配置bot资源文件的扫描路径。 +# 默认为 classpath:simbot-bots/*.bot* +# 如果要使用本地文件可以使用 `file:` 开头 +simbot.bot-configuration-resources[0]=classpath:simbot-bots/*.bot* +``` +{noinject=true} + + + + +```yaml +simbot: + # 自定义配置bot资源文件的扫描路径。 + # 默认为 classpath:simbot-bots/*.bot* + # 如果要使用本地文件可以使用 `file:` 开头 + bot-configuration-resources: + - 'classpath:simbot-bots/*.bot*' +``` + + + + + + +## 启动类 + +像每一个 Spring Boot 应用一样,你需要一个启动类,并通过标注 `@EnableSimbot` 来启用 simbot : + + + + +```kotlin +@EnableSimbot +@SpringBootApplication +class App + +fun main(vararg args: String) { + runApplication(args = args) +} +``` + + + + +```java +@EnableSimbot +@SpringBootApplication +public class App { + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } +} +``` + +> 如果你在 Java 中遇到了无法引用 `@EnableSimbot` 的情况, +> 或许可以参考 [这篇FAQ](https://simbot.forte.love/faq/包引用异常)。 + + + + +## 监听事件 + +接下来就是逻辑代码所在的地方了,编写一个监听函数并监听一个事件。 + +此处我们监听 `ChannelMessageEvent`,也就是 **子频道的消息事件**。 + +假设:要求 bot 必须 **被AT**,并且说一句 `你好`,此时 bot 会引用用户发送的消息并回复 `你也好!` ,类似于: + + +@BOT 你好 + + +_\> 用户: @BOT 你好_ + +你也好! + + + + + + + +```kotlin +import love.forte.simboot.annotation.ContentTrim +import love.forte.simboot.annotation.Filter +import love.forte.simboot.annotation.Listener +import love.forte.simbot.event.ChannelMessageEvent + +@Component +class ExampleListener { + + @Listener + @Filter(value = "你好", targets = Filter.Targets(atBot = true)) + @ContentTrim // 当匹配被at时,将'at'这个特殊消息移除后,剩余的文本消息大概率存在前后空格,通过此注解在匹配的时候忽略前后空格 + suspend fun onChannelMessage(event: ChannelMessageEvent) { // 将要监听的事件类型放在参数里,即代表监听此类型的消息 + event.reply("你也好!") + } +} +``` + + + + +```java +import love.forte.simboot.annotation.ContentTrim +import love.forte.simboot.annotation.Filter +import love.forte.simboot.annotation.Listener +import love.forte.simbot.event.ChannelMessageEvent + +@Component +public class ExampleListener { + @Listener + @Filter(value = "你好", targets = @Filter.Targets(atBot = true)) + @ContentTrim // 当匹配被at时,将'at'这个特殊消息移除后,剩余的文本消息大概率存在前后空格,通过此注解在匹配的时候忽略前后空格 + public void onChannelMessage(ChannelMessageEvent event) { // 将要监听的事件类型放在参数里,即代表监听此类型的消息 + // Java中的阻塞式API + event.replyBlocking("你也好!"); + } +} +``` +{switcher-key="%jb%"} + +```java +import love.forte.simboot.annotation.ContentTrim +import love.forte.simboot.annotation.Filter +import love.forte.simboot.annotation.Listener +import love.forte.simbot.event.ChannelMessageEvent + +@Component +public class ExampleListener { + @Listener + @Filter(value = "你好", targets = @Filter.Targets(atBot = true)) + @ContentTrim // 当匹配被at时,将'at'这个特殊消息移除后,剩余的文本消息大概率存在前后空格,通过此注解在匹配的时候忽略前后空格 + public CompletableFuture onChannelMessage(ChannelMessageEvent event) { // 将要监听的事件类型放在参数里,即代表监听此类型的消息 + // 将 CompletableFuture 作为返回值,simbot会以非阻塞的形式处理它 + return event.replyAsync("你也好!"); + } +} +``` +{switcher-key="%ja%"} + +```java +import love.forte.simboot.annotation.ContentTrim +import love.forte.simboot.annotation.Filter +import love.forte.simboot.annotation.Listener +import love.forte.simbot.event.ChannelMessageEvent + +@Component +public class ExampleListener { + + @Listener + @Filter(value = "你好", targets = @Filter.Targets(atBot = true)) + @ContentTrim // 当匹配被at时,将'at'这个特殊消息移除后,剩余的文本消息大概率存在前后空格,通过此注解在匹配的时候忽略前后空格 + public Mono onChannelMessage(ChannelMessageEvent event) { // 将要监听的事件类型放在参数里,即代表监听此类型的消息 + // 将 Mono 等响应式类型作为返回值,simbot会以非阻塞的形式处理它 + return Mono.fromCompletionStage(event.replyAsync("你也好!")); + } + +} +``` +{switcher-key="%jr%"} + + + +如果返回值是需要第三方库的响应式类型,那么你的项目环境依赖中必须存在 `Kotlin Coroutines` 对其的支持库才可使用。 +你可以参考文档中 [响应式的处理结果](https://simbot.forte.love/docs/basic/event-listener#可响应式的处理结果) 的内容。 + + + + + + +## 启动 + diff --git a/Writerside/topics/use-stdlib.md b/Writerside/topics/use-stdlib.md index 2b5abc7..2502eec 100644 --- a/Writerside/topics/use-stdlib.md +++ b/Writerside/topics/use-stdlib.md @@ -1,3 +1,231 @@ +--- +switcher-label: JavaAPI风格 +--- + + + + + # 使用标准库 -Start typing here... \ No newline at end of file + +本章节介绍如何使用标准库模块来实现构建、启动一个 Bot,以及订阅、处理事件。 + + + + + + +## 安装 + + + + + + +然后选择一个合适的 Ktor 引擎。 + + + +## 使用 + +大别野组件 +的标准库模块在 [API模块](use-api.md) 之上提供了构建 Bot、订阅并处理事件的能力。 + + + + +```kotlin +// 准备 bot 的必要信息 +val botId = "bot_xxxx" +val botSecret = "xxxx" +// 用于注册 bot 的 “票据” 信息。 +val ticket = Bot.Ticket(botId, botSecret) +// 登录时获取 ws 连接信息时所需的 villa_id 信息。 +// 根据文档描述,如果bot处于测试阶段,可以使用测试大别野的id,如果已经上线,则可以使用 "0" +val villaId = "0" + +// 构建一个 Bot,并可选的进行一些配置。 +val bot = BotFactory.create(ticket) { + loginVillaId = villaId + loginRegion = null + // 其他配置... +} + +// 注册事件有一些不同但类似的方式 +// 1️⃣ 通过 registerProcessor 注册一个普通的事件处理器,此处理器会接收并处理所有类型的事件 +// registerProcessor 是最基本的注册方式,也是其他方式的最终汇集点 +bot.registerProcessor { source -> + // source 代表事件的来源以及它的原始样貌,比如通过 ws 获取到的原始样貌就是接收到的二进制数据以及解析出来的含有 protobuf 格式body的协议包 + // this: Event, 事件的统一结构体以及它内部的具体事件结构体 + println("event: $this") + println("event.extendData: $extendData") + println("eventSource: $source") +} + +// 2️⃣ 通过 processEvent 注册一个针对具体 extendData 类型的事件处理器,它只有在 extendData 与目标类型一致时才会处理。 +// 此示例展示处理 SendMessage 也就是消息事件,并在对方发送了包含 'stop' 的文本时终止 bot。 +bot.processEvent { source -> + val content = extendData.content + println("extendData.content: $content") + // 如果是文本类型消息的话 + if (extendData.objectName == SendMessage.OBJECT_NAME_TEXT) { + // 解析 content 中的文本消息为 MsgContentInfo,并在之后进一步判断文本消息的内容 + val msgContentInfo = + MsgContentInfo.decode(content = content, deserializationStrategy = MsgContentInfo.TextSerializer) + println(msgContentInfo) + println(msgContentInfo.content) + println(msgContentInfo.content.text) + println(msgContentInfo.content.entities) + + if ("stop" in msgContentInfo.content.text) { + bot.cancel() + } + } +} + +// 启动 bot, 此时会开始获取ws、连接并接收消息。 +bot.start() + +// 挂起 bot,直到它结束(被终止) +bot.join() +``` + + + + +```java +// 准备 bot 的必要信息 +var botId = "bot_xxxx"; +var botSecret = "xxxx"; +// 用于注册 bot 的 “票据” 信息。 +var ticket = new Bot.Ticket(botId, botSecret); + +// 准备配置类,当然,也可以不准备,即省略配置。 +var conf = new BotConfiguration(); +// 登录时获取 ws 连接信息时所需的 villa_id 信息。 +// 根据文档描述,如果bot处于测试阶段,可以使用测试大别野的id,如果已经上线,则可以使用 "0" +conf.setLoginVillaId("0"); +// 其他配置... + +// 构建一个 Bot +var bot = BotFactory.create(ticket, conf); + +// 注册事件有一些不同但类似的方式 +// 1️⃣ 通过 registerProcessor 注册一个普通的事件处理器,此处理器会接收并处理所有类型的事件 +// 使用 EventProcessors.blocking 可以构建一个阻塞的事件处理器示例 +bot.registerProcessor( + EventProcessors.blocking((event, source) -> { + System.out.println("event: " + event); + System.out.println("event.data: " + event.getExtendData()); + System.out.println("eventSource: " + source); + })); + +// 2️⃣ 通过 registerProcessor 注册一个针对具体 extendData 类型的事件处理器,它只有在 extendData 与目标类型一致时才会处理。 +// 使用 EventProcessors.blocking 可以构建一个阻塞的事件处理器实例, 并在开头指定目标事件的类型 +// 此示例展示处理 SendMessage 也就是消息事件,并在对方发送了包含 'stop' 的文本时终止 bot。 +bot.registerProcessor( + EventProcessors.blocking(SendMessage.class, (event, source) -> { + var extendData = event.getExtendData(); + var content = extendData.getContent(); + System.out.println("extendData.content: " + content); + // 如果是文本类型消息的话 + if (extendData.getObjectName() == SendMessage.OBJECT_NAME_TEXT) { + // 解析 content 中的文本消息为 MsgContentInfo,并在之后进一步判断文本消息的内容 + var msgContentInfo = MsgContentInfo.decode(content, MsgContentInfo.TextSerializer); + System.out.println(msgContentInfo); + System.out.println(msgContentInfo.getContent()); + System.out.println(msgContentInfo.getContent().getText()); + System.out.println(msgContentInfo.getContent().getEntities()); + if (msgContentInfo.getContent().getText().contains("stop")) { + bot.cancel(); + } + } + })); + +// 阻塞地启动bot +bot.startBlocking(); +// 阻塞当前线程,直到它结束(被终止) +bot.joinBlocking(); +``` + +{switcher-key="%jb%"} + +```java +// 准备 bot 的必要信息 +var botId = "bot_xxxx"; +var botSecret = "xxxx"; +// 用于注册 bot 的 “票据” 信息。 +var ticket = new Bot.Ticket(botId, botSecret); + +// 准备配置类,当然,也可以不准备,即省略配置。 +var conf = new BotConfiguration(); +// 登录时获取 ws 连接信息时所需的 villa_id 信息。 +// 根据文档描述,如果bot处于测试阶段,可以使用测试大别野的id,如果已经上线,则可以使用 "0" +conf.setLoginVillaId("0"); +// 其他配置... + +// 构建一个 Bot +var bot = BotFactory.create(ticket, conf); + +// 注册事件有一些不同但类似的方式 +// 1️⃣ 通过 registerProcessor 注册一个普通的事件处理器,此处理器会接收并处理所有类型的事件 +// 使用 EventProcessors.async 可以构建一个异步的事件处理器示例 +// 所有异步API都需要以 CompletableFuture 作为结果,且不建议在其中执行任何阻塞API —— 那样的话使用异步风格就没有意义了。 +bot.registerProcessor( + EventProcessors.async((event, source) -> { + System.out.println("event: " + event); + System.out.println("event.data: " + event.getExtendData()); + System.out.println("eventSource: " + source); + + // 因为上述代码没有什么必须真正异步的内容,所以直接返回一个空的 future 即可。 + // 实际应用中可以配合请求 API 时的异步API来做到真正的异步结果。 + return CompletableFuture.completedFuture(null); + })); + +// 2️⃣ 通过 registerProcessor 注册一个针对具体 extendData 类型的事件处理器,它只有在 extendData 与目标类型一致时才会处理。 +// 使用 EventProcessors.async 可以构建一个异步的事件处理器实例, 并在开头指定目标事件的类型 +// 此示例展示处理 SendMessage 也就是消息事件,并在对方发送了包含 'stop' 的文本时终止 bot。 +bot.registerProcessor( + EventProcessors.async(SendMessage.class, (event, source) -> { + var extendData = event.getExtendData(); + var content = extendData.getContent(); + System.out.println("extendData.content: " + content); + // 如果是文本类型消息的话 + if (extendData.getObjectName() == SendMessage.OBJECT_NAME_TEXT) { + // 解析 content 中的文本消息为 MsgContentInfo,并在之后进一步判断文本消息的内容 + var msgContentInfo = MsgContentInfo.decode(content, MsgContentInfo.TextSerializer); + System.out.println(msgContentInfo); + System.out.println(msgContentInfo.getContent()); + System.out.println(msgContentInfo.getContent().getText()); + System.out.println(msgContentInfo.getContent().getEntities()); + if (msgContentInfo.getContent().getText().contains("stop")) { + bot.cancel(); + } + } + + return CompletableFuture.completedFuture(null); + })); + +// 异步地启动bot,并在启动后将 bot 转化为 Future。 +// 转化后的 Future 会直到 bot 结束(被终止)时完成,因此可通过此 future 监测 bot 是否终止 +var botAsFuture = bot.startAsync().thenCompose(unit -> bot.asFuture()); + +botAsFuture.thenAccept(unit -> { + // 通过常规的 future API 操作结束后的行为,比如输出日志。 + System.out.println("Bot 终止"); +}); + +// ⚠ 不建议,但是最简单粗暴的方式就是直接 join 它,就像阻塞API一样 +botAsFuture.join(); +``` +{switcher-key="%ja%"} + + +正如上述示例中注释描述所说,当使用异步API时候,请尽可能避免在异步的事件处理器中使用任何阻塞API。 + + + + + +> 封装的事件的结构、属性以及属性类型都基本与大别野文档中的一致或具有对应关系。 diff --git a/Writerside/villa.tree b/Writerside/villa.tree index d9d98a5..524244c 100644 --- a/Writerside/villa.tree +++ b/Writerside/villa.tree @@ -14,4 +14,5 @@ +