diff --git a/.github/workflows/deploy-documentation.yml b/.github/workflows/deploy-documentation.yml new file mode 100644 index 0000000..6de7ff1 --- /dev/null +++ b/.github/workflows/deploy-documentation.yml @@ -0,0 +1,104 @@ +name: Deploy documentation + +on: + # If specified, the workflow will be triggered automatically once you push to the `main` branch. + # Replace `main` with your branch’s name + push: + branches: + - main + + # Specify to run a workflow manually from the Actions tab on GitHub + workflow_dispatch: + +# Gives the workflow permissions to clone the repo and create a page deployment +permissions: + id-token: write + pages: write + +env: + # Name of module and id separated by a slash + INSTANCE: Writerside/villa + # Replace HI with the ID of the instance in capital letters + ARTIFACT: webHelpVILLA2-all.zip + # Writerside docker image version + DOCKER_VERSION: 232.10275 + # Add the variable below to upload Algolia indexes + # Replace HI with the ID of the instance in capital letters +# ALGOLIA_ARTIFACT: algolia-indexes-HI.zip +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Build Writerside docs using Docker + uses: JetBrains/writerside-github-action@v4 + with: + instance: ${{ env.INSTANCE }} + artifact: ${{ env.ARTIFACT }} + docker-version: ${{ env.DOCKER_VERSION }} + + - name: Upload documentation + uses: actions/upload-artifact@v3 + with: + name: docs + path: | + artifacts/${{ env.ARTIFACT }} + artifacts/report.json + retention-days: 7 + + # Add the step below to upload Algolia indexes +# - name: Upload algolia-indexes +# uses: actions/upload-artifact@v3 +# with: +# name: algolia-indexes +# path: artifacts/${{ env.ALGOLIA_ARTIFACT }} +# retention-days: 7 + + # Add the job below and artifacts/report.json on Upload documentation step above if you want to fail the build when documentation contains errors + test: + # Requires build job results + needs: build + runs-on: ubuntu-latest + + steps: + - name: Download artifacts + uses: actions/download-artifact@v1 + with: + name: docs + path: artifacts + + - name: Test documentation + uses: JetBrains/writerside-checker-action@v1 + with: + instance: ${{ env.INSTANCE }} + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + # Requires the build job results + needs: test + runs-on: ubuntu-latest + steps: + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: docs + + - name: Unzip artifact + run: unzip -O UTF-8 -qq ${{ env.ARTIFACT }} -d dir + + - name: Setup Pages + uses: actions/configure-pages@v2 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: dir + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 diff --git a/Writerside/c.list b/Writerside/c.list new file mode 100644 index 0000000..b61cc60 --- /dev/null +++ b/Writerside/c.list @@ -0,0 +1,7 @@ + + + + + + diff --git a/Writerside/cfg/buildprofiles.xml b/Writerside/cfg/buildprofiles.xml new file mode 100644 index 0000000..1263cfa --- /dev/null +++ b/Writerside/cfg/buildprofiles.xml @@ -0,0 +1,34 @@ + + + + + + logo-icon.svg + logo-icon.svg + https://github.com/simple-robot/simbot-component-miyoushe-villa + GitHub + https://github.com/simple-robot/simbot-component-miyoushe-villa + true + https://github.com/simple-robot/simbot-component-miyoushe-villa/tree/main/Writerside/ + true + + + + + true + + + + + diff --git a/Writerside/cfg/glossary.xml b/Writerside/cfg/glossary.xml new file mode 100644 index 0000000..4c03b34 --- /dev/null +++ b/Writerside/cfg/glossary.xml @@ -0,0 +1,7 @@ + + + + 高性能全异步的bot风格事件调度框架 + 高性能全异步的bot风格事件调度框架,是Simple Robot的简称 + 基于simbot核心库对米游社大别野机器人的组件实现,也包括对API和事件订阅能力的底层库实现模块 + diff --git a/Writerside/help-versions.json b/Writerside/help-versions.json new file mode 100644 index 0000000..2a922b4 --- /dev/null +++ b/Writerside/help-versions.json @@ -0,0 +1,4 @@ +[ + {"version":"1.0","url":"/docs/1.0/","isCurrent":false}, + {"version":"2.0","url":"/docs/2.0","isCurrent":true} +] diff --git a/Writerside/images/logo-icon.svg b/Writerside/images/logo-icon.svg new file mode 100644 index 0000000..03a946a --- /dev/null +++ b/Writerside/images/logo-icon.svg @@ -0,0 +1,1205 @@ + + + + diff --git a/Writerside/topics/Home.md b/Writerside/topics/Home.md new file mode 100644 index 0000000..bda98b9 --- /dev/null +++ b/Writerside/topics/Home.md @@ -0,0 +1,84 @@ +# 首页 + +欢迎来到 [Simple Robot](https://github.com/simple-robot/simpler-robot) +(下文简称 simbot ) +的米游社大别野机器人组件 (下文简称 大别野组件 ) 文档。 + +大别野组件是基于 [simbot核心库](https://github.com/simple-robot/simpler-robot) +对 [米游社大别野机器人](https://open.miyoushe.com) 的组件实现, +也包括对API和事件订阅能力的底层库实现模块。 + +大别野组件由 Kotlin 语言编写,不同的模块分别基于 **KMP (Kotlin Multiplatform)** 或 **Kotlin/JVM** 构建。 +在JVM平台上对 Java 友好,并基于 KMP 提供更多平台的可能性。 + +> 对于simbot绝大多数的标准、基本功能的介绍都在 [simbot官网](https://simbot.forte.love/) 中。 +> {style="note"} + +## 模块简介 + +simbot的大别野机器人组件整个项目分为三个主要模块。它们分别是 **API模块**、**stdlib(标准库)模块**和**core(核心库)模块**。 + +### API模块 + + +

平台:JVM、JS、Native

+

+ API模块基于 KMP 构建项目,支持 JVM、JS、Native 平台, + 使用 Ktor 作为API请求(http请求)的解决方案。 +

+
+ +API模块的主要作用是提供针对大别野机器人开发平台中的各API和事件类型的底层封装。 +此模块 **不提供** 过度的功能性封装, +主要宗旨为在风格统一的情况下将API和事件 **描述** 为可供使用的依赖库。 + +### stdlib 标准库模块 + + +

平台:JVM、JS、Native

+

+ 标准库模块基于 KMP 构建项目,支持 JVM、JS、Native 平台, + 使用 Ktor 作为API请求(http请求)的解决方案。 +

+
+ +标准库模块依赖API模块,在此基础上额外提供大别野中 **Bot** 概念的封装与能力实现, +达到对一个 Bot 的事件订阅、消息发送等能力。 +与API模块类型,标准库模块的主要宗旨同样是在风格统一的情况下将Bot与事件订阅的能力 **描述** 为可供使用的依赖库。 + +> **API模块** 和 **标准库模块** 与 **simbot** 的关系主要体现在较为统一的 **风格** 上。 +> 实质上这两个模块 **不直接依赖** 与simbot相关的库。(可能存在部分仅编译依赖或编译器插件依赖) +> +> 它们两个是可以完全作为独立的底层API依赖库使用的。 +{style="note"} + + +### core 核心库 + + +

平台:JVM

+

+ 核心库模块基于 Kotlin/JVM 构建项目,支持 JVM 平台, + 兼容并提供友好的Java API。 +

+
+ + +核心库模块是对 **simbot核心库** 的大别野机器人实现,也是此项目作为 **“simbot组件”** 的主要体现。 + +核心库模块依赖并实现 **simbot API**,针对其定义的各类型来提供simbot风格的大别野组件实现。例如实现 simbot 提供的 `Bot` +类型为 `VillaBot` 并提供大别野组件下的各种独特能力。 + +核心库模块是一种高级封装,它会借助 simbot API 强大的能力来提供大量高级功能,例如对事件的订阅和更便捷的消息发送、对 Spring +Boot 的支持等。 + +核心库模块会尽可能屏蔽掉**底层API**(上述两个模块),使其对开发者透明,取而代之的是更加清晰明了的API。 + +> 当然,对于一些特殊场景或不得已的情况,开发者依旧可以很轻松的使用底层API来达成所求目的。 + + + + 大别野开放平台 + 大别野机器人开发文档 + + diff --git "a/Writerside/topics/\344\275\277\347\224\250-Spring-Boot.md" "b/Writerside/topics/\344\275\277\347\224\250-Spring-Boot.md" new file mode 100644 index 0000000..cce2632 --- /dev/null +++ "b/Writerside/topics/\344\275\277\347\224\250-Spring-Boot.md" @@ -0,0 +1,3 @@ +# 使用 Spring Boot + +Start typing here... \ No newline at end of file diff --git "a/Writerside/topics/\344\275\277\347\224\250API.md" "b/Writerside/topics/\344\275\277\347\224\250API.md" new file mode 100644 index 0000000..86a80bf --- /dev/null +++ "b/Writerside/topics/\344\275\277\347\224\250API.md" @@ -0,0 +1,218 @@ +--- +switcher-label: JavaAPI风格 +--- + + + + +# 使用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% + +``` + + + + +## 使用 + +大别野组件 的API模块提供了针对 +[米游社大别野API](https://webstatic.mihoyo.com/vila/bot/doc/) 的基本对应封装。 + +API封装的命名与API具有一定关联,例如 [`获取大别野信息`](https://webstatic.mihoyo.com/vila/bot/doc/villa_api/get_villa.html): + + + +```HTTP +GET /vila/api/bot/platform/getVilla +``` + +``` +love.forte.simbot.miyoushe.api.villa.GetVillaApi +``` + + +> 所有的API实现均在包路径 `love.forte.simbot.miyoushe.api` 中。 + +API的应用大差不差,因此此处仅使用部分类型作为示例, +不会演示所有API。 + + + + +```kotlin +// 准备 bot 的必要信息 +val botId = "bot_xxxx" +val botSecret = "xxxx" +// 大别野ID,请求时作为token的一员。 +val villaId = "1234" +// 构建请求用的 token +val token = MiyousheVillaApiToken(botId, botSecret, villaId) + +// 准备一个用于 HTTP 请求的 [[[HttpClient|https://ktor.io/docs/create-client.html]]] +// 如果使用 JVM,你需要确保 classpath 环境中添加了合适的 [[[引擎|https://ktor.io/docs/http-client-engines.html]]] +// 如果使用其他平台,例如 JS 或 native,则可能需要添加了合适的引擎依赖后手动填入它们,以 mingwx64 平台为例:`HttpClient(WinHttp)`。 +val httpClient = HttpClient() + +// 构建需要请求的 API 示例,此处为 [[[获取房间信息|https://webstatic.mihoyo.com/vila/bot/doc/room_api/get_room.html]]] API +val roomId: ULong = 1234u // 假设房间ID是 1234 +val api = GetRoomApi.create(roomId) + +// 发起请求并得到结果。在 API 模块中有三种请求方式(均为挂起函数): +// 1️⃣ 使用 api.request, 得到 Ktor 进行 HTTP 请求的原始响应类型 HttpResponse +val response: HttpResponse = api.request(httpClient, token) + +// 2️⃣ 使用 api.requestResult, 得到请求结果的统一响应体结构。假如此响应代表成功(result.retcode == 0), 则可以通过 result.data 获取响应结果。 +val result: ApiResult = api.requestResult(httpClient, token) + +// 3️⃣ 使用 api.requestData, 得到当响应体代表成功时的响应数据。如果响应体不为成功则会抛出异常。 +val requestData: GetRoomResult = api.requestData(httpClient, token) +``` + + + + +```java +// 准备 bot 的必要信息 +var botId = "bot_xxxx"; +var botSecret = "xxxx"; +// 大别野ID,请求时作为token的一员。 +var villaId = "1234"; +// 构建请求用的 token +var token = new MiyousheVillaApiToken(botId, botSecret, villaId); + +// 准备一个用于 HTTP 请求的 [[[HttpClient|https://ktor.io/docs/create-client.html]]] +// 你需要确保 classpath 环境中添加了合适的 [[[引擎|https://ktor.io/docs/http-client-engines.html]]] +var client = HttpClientJvmKt.HttpClient((config) -> Unit.INSTANCE); + +// 构建需要请求的 API 示例,此处为 [[[获取房间信息|https://webstatic.mihoyo.com/vila/bot/doc/room_api/get_room.html]]] API +// 假设房间ID是 1234 +var api = GetRoomApi.create(Long.parseUnsignedLong("1234")); +// Java 中操作无符号数字比较麻烦,因此面向Java的大部分相关操作也会提供基于字符串操作的重载、扩展API +var api = GetRoomApi.create("1234"); + +// 发起请求并得到结果。在 API 模块中有三种请求方式(均使用 `APIRequests` 的静态方法): +// 1️⃣ 使用 api.request, 得到 Ktor 进行 HTTP 请求的原始响应类型 HttpResponse +HttpResponse response = APIRequests.requestBlocking(api, client, token); + +// 2️⃣ 使用 api.requestResult, 得到请求结果的统一响应体结构。假如此响应代表成功(result.retcode == 0), 则可以通过 result.data 获取响应结果。 +ApiResult result = APIRequests.requestResultBlocking(api, client, token); + +// 3️⃣ 使用 api.requestData, 得到当响应体代表成功时的响应数据。如果响应体不为成功则会抛出异常。 +GetRoomResult requestData = APIRequests.requestDataBlocking(api, client, token); +``` +{switcher-key="%jb%"} + +```java +import java.util.concurrent.CompletableFuture;// 准备 bot 的必要信息 +var botId = "bot_xxxx"; +var botSecret = "xxxx"; +// 大别野ID,请求时作为token的一员。 +var villaId = "1234"; +// 构建请求用的 token +var token = new MiyousheVillaApiToken(botId, botSecret, villaId); + +// 准备一个用于 HTTP 请求的 [[[HttpClient|https://ktor.io/docs/create-client.html]]] +// 你需要确保 classpath 环境中添加了合适的 [[[引擎|https://ktor.io/docs/http-client-engines.html]]] +var client = HttpClientJvmKt.HttpClient((config) -> Unit.INSTANCE); + +// 构建需要请求的 API 示例,此处为 [[[获取房间信息|https://webstatic.mihoyo.com/vila/bot/doc/room_api/get_room.html]]] API +// 假设房间ID是 1234 +var api = GetRoomApi.create(Long.parseUnsignedLong("1234")); +// Java 中操作无符号数字比较麻烦,因此面向Java的大部分相关操作也会提供基于字符串操作的重载、扩展API +var api = GetRoomApi.create("1234"); + +// 发起请求并得到结果。在 API 模块中有三种请求方式(均使用 `APIRequests` 的静态方法): +// 1️⃣ 使用 api.request, 得到 Ktor 进行 HTTP 请求的原始响应类型 HttpResponse +CompletableFuture response = APIRequests.requestAsync(api, client, token); + +// 2️⃣ 使用 api.requestResult, 得到请求结果的统一响应体结构。假如此响应代表成功(result.retcode == 0), 则可以通过 result.data 获取响应结果。 +CompletableFuture> result = APIRequests.requestResultAsync(api, client, token); + +// 3️⃣ 使用 api.requestData, 得到当响应体代表成功时的响应数据。如果响应体不为成功则会抛出异常。 +CompletableFuture requestData = APIRequests.requestDataAsync(api, client, token); +``` +{switcher-key="%ja%"} + + +异步API的响应结果都是 CompletableFuture 类型的, +在处理它们的时候需要注意尽可能避免使用任何会造成阻塞的方法, +例如 getjoin 。 + +```java +// ↓ CompletableFuture +var requestData = APIRequests.requestDataAsync(api, client, token); +// 使用 CompletableFuture 的 thenAccept 或诸如此类的流程化API来接收、处理你的结果 +requestData.thenAccept(result -> System.out.println("Result: " + result)); +``` + +当然,你也可以选择配合使用一些与 CompletableFuture 兼容的其他异步/响应式框架, +例如 reactor。 + +同样的,异步结果的 异常 也需要特别处理,否则你可能会在不经意间错过它: + +```java +// ↓ CompletableFuture +var requestData = APIRequests.requestDataAsync(api, client, token); +requestData.exceptionally(ex -> { + // 生产环境里应该使用更好的处理方法或可靠的日志输出 + ex.printStackTrace(); + return null; +}) +.thenAccept(...); +``` + + + + + + diff --git "a/Writerside/topics/\344\275\277\347\224\250\346\240\207\345\207\206\345\272\223.md" "b/Writerside/topics/\344\275\277\347\224\250\346\240\207\345\207\206\345\272\223.md" new file mode 100644 index 0000000..2b5abc7 --- /dev/null +++ "b/Writerside/topics/\344\275\277\347\224\250\346\240\207\345\207\206\345\272\223.md" @@ -0,0 +1,3 @@ +# 使用标准库 + +Start typing here... \ No newline at end of file diff --git "a/Writerside/topics/\344\275\277\347\224\250\346\240\270\345\277\203\345\272\223.md" "b/Writerside/topics/\344\275\277\347\224\250\346\240\270\345\277\203\345\272\223.md" new file mode 100644 index 0000000..b0980b6 --- /dev/null +++ "b/Writerside/topics/\344\275\277\347\224\250\346\240\270\345\277\203\345\272\223.md" @@ -0,0 +1,3 @@ +# 使用核心库 + +Start typing here... \ No newline at end of file diff --git "a/Writerside/topics/\345\277\253\351\200\237\345\274\200\345\247\213.md" "b/Writerside/topics/\345\277\253\351\200\237\345\274\200\345\247\213.md" new file mode 100644 index 0000000..9d12f0c --- /dev/null +++ "b/Writerside/topics/\345\277\253\351\200\237\345\274\200\345\247\213.md" @@ -0,0 +1,6 @@ +# 快速开始 + + + +本章节下的内容将会根据不同的模块提供一些快速构建项目的示例代码。 diff --git a/Writerside/v.list b/Writerside/v.list new file mode 100644 index 0000000..d8ac115 --- /dev/null +++ b/Writerside/v.list @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Writerside/villa.tree b/Writerside/villa.tree new file mode 100644 index 0000000..f814569 --- /dev/null +++ b/Writerside/villa.tree @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/Writerside/writerside.cfg b/Writerside/writerside.cfg new file mode 100644 index 0000000..d3de1fd --- /dev/null +++ b/Writerside/writerside.cfg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/buildSrc/src/main/kotlin/SuspendTransforms.kt b/buildSrc/src/main/kotlin/SuspendTransforms.kt index 515a3ab..e80b778 100644 --- a/buildSrc/src/main/kotlin/SuspendTransforms.kt +++ b/buildSrc/src/main/kotlin/SuspendTransforms.kt @@ -37,7 +37,7 @@ object SuspendTransforms { */ val jvmAsyncTransformer = SuspendTransformConfiguration.jvmAsyncTransformer.copy( syntheticFunctionIncludeAnnotations = includeAnnotations, - transformFunctionInfo = FunctionInfo("love.forte.simbot.utils", null, "$\$runInAsync"), + transformFunctionInfo = FunctionInfo("love.forte.simbot.utils", null, "$\$runInAsyncNullable"), copyAnnotationExcludes = SuspendTransformConfiguration.jvmAsyncTransformer.copyAnnotationExcludes + SuspendTransformConfiguration.jvmAsyncTransformer.markAnnotation.classInfo ) diff --git a/simbot-component-miyoushe-villa-api/build.gradle.kts b/simbot-component-miyoushe-villa-api/build.gradle.kts index a2a40b3..f7b8a30 100644 --- a/simbot-component-miyoushe-villa-api/build.gradle.kts +++ b/simbot-component-miyoushe-villa-api/build.gradle.kts @@ -7,7 +7,7 @@ plugins { kotlin("multiplatform") // `miyoushe-multiplatform-maven-publish` kotlin("plugin.serialization") -// `miyoushe-dokka-partial-configure` + `miyoushe-dokka-partial-configure` } setup(P) diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/audit/AuditApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/audit/AuditApi.kt index d26c48d..3a9c482 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/audit/AuditApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/audit/AuditApi.kt @@ -22,6 +22,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.ApiResult import love.forte.simbot.miyoushe.api.MiyousheVillaPostApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.js.JsName import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -70,7 +71,10 @@ public class AuditApi private constructor(override val body: Body) : MiyousheVil public data class Body( @SerialName("audit_content") val auditContent: String, @SerialName("pass_through") val passThrough: String?, - @SerialName("room_id") val roomId: ULong?, + @SerialName("room_id") + @Serializable(ULongWriteStringSerializer::class) + val roomId: ULong?, + @Serializable(ULongWriteStringSerializer::class) val uid: ULong, /** diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/member/DeleteVillaMemberApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/member/DeleteVillaMemberApi.kt index 6cb372b..fc986ac 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/member/DeleteVillaMemberApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/member/DeleteVillaMemberApi.kt @@ -19,6 +19,7 @@ package love.forte.simbot.miyoushe.api.member import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmStatic @@ -64,7 +65,7 @@ public class DeleteVillaMemberApi private constructor(override val body: Body) : * */ @Serializable - public data class Body(val uid: ULong) + public data class Body(@Serializable(ULongWriteStringSerializer::class) val uid: ULong) override fun toString(): String { return "DeleteVillaMemberApi(body=$body)" diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/MsgContent.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/MsgContent.kt index 13502d4..951ac7a 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/MsgContent.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/MsgContent.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.msg import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.msg.TextMsgContent.EntityContent.Style.Factory.STYLE_BOLD +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmField import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -128,7 +129,10 @@ public data class TextMsgContent( @Serializable @SerialName(MentionedUser.TYPE) public data class MentionedUser( - @SerialName("user_id") @get:JvmName("getUserId") val userId: ULong + @SerialName("user_id") + @get:JvmName("getUserId") + @Serializable(ULongWriteStringSerializer::class) + val userId: ULong ) : EntityContent() { val userIdStrValue: String get() = userId.toString() @@ -192,9 +196,11 @@ public data class TextMsgContent( public data class VillaRoomLink( @SerialName("villa_id") @get:JvmName("getVillaId") + @Serializable(ULongWriteStringSerializer::class) val villaId: ULong, @SerialName("room_id") @get:JvmName("getRoomId") + @Serializable(ULongWriteStringSerializer::class) val roomId: ULong, ) : EntityContent() { val villaIdStrValue: String get() = villaId.toString() @@ -260,6 +266,7 @@ public data class TextMsgContent( @SerialName(MentionAll.TYPE) public data object MentionAll : EntityContent() { public const val TYPE: String = "mention_all" + public const val CONTENT: String = "@全体成员" /** * Factory for [Builder]. diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/Panel.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/Panel.kt index 0fdc1e6..75c6d08 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/Panel.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/Panel.kt @@ -23,6 +23,7 @@ import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.* import love.forte.simbot.miyoushe.api.msg.ButtonComponent.Companion.C_TYPE_CALLBACK +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -39,6 +40,7 @@ public data class Panel( */ @SerialName("template_id") @get:JvmName("getTemplateIdUnsignedSource") + @Serializable(ULongWriteStringSerializer::class) val templateId: ULong? = null, /** diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/PinMessageApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/PinMessageApi.kt index 5db6c9e..b13da04 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/PinMessageApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/PinMessageApi.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.msg import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -66,7 +67,9 @@ public class PinMessageApi private constructor(override val body: Body) : Miyous public data class Body( @SerialName("msg_uid") val msgUid: String, @SerialName("is_cancel") val isCancel: Boolean, - @SerialName("room_id") val roomId: ULong, + @SerialName("room_id") + @Serializable(ULongWriteStringSerializer::class) + val roomId: ULong, @SerialName("send_at") val sendAt: Long ) diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/RecallMessageApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/RecallMessageApi.kt index 926b18a..967fa0a 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/RecallMessageApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/RecallMessageApi.kt @@ -17,11 +17,13 @@ package love.forte.simbot.miyoushe.api.msg -import io.ktor.http.* import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import kotlinx.serialization.builtins.serializer import love.forte.simbot.miyoushe.api.ApiResult -import love.forte.simbot.miyoushe.api.MiyousheVillaGetApi +import love.forte.simbot.miyoushe.api.MiyousheVillaPostApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -33,11 +35,7 @@ import kotlin.jvm.JvmStatic * * @author ForteScarlet */ -public class RecallMessageApi private constructor( - private val msgUid: String, - private val roomId: ULong, - private val msgTime: Long? -) : MiyousheVillaGetApi() { +public class RecallMessageApi private constructor(override val body: Body) : MiyousheVillaPostApi() { public companion object Factory { private const val PATH = "/vila/api/bot/platform/recallMessage" @@ -52,16 +50,19 @@ public class RecallMessageApi private constructor( @JvmName("create") @JvmStatic public fun create(msgUid: String, roomId: ULong, msgTime: Long?): RecallMessageApi = - RecallMessageApi(msgUid, roomId, msgTime) + RecallMessageApi(Body(msgUid, roomId, msgTime)) } - override fun URLBuilder.prepareUrl(): URLBuilder = apply { - with(parameters) { - append("msg_uid", msgUid) - append("room_id", roomId.toString()) - msgTime?.also { append("msg_time", it.toString()) } - } - } + @Serializable + public data class Body( + @SerialName("msg_uid") + val msgUid: String, + @SerialName("room_id") + @Serializable(ULongWriteStringSerializer::class) + val roomId: ULong, + @SerialName("msg_time") + val msgTime: Long? + ) override val path: String get() = PATH @@ -71,25 +72,20 @@ public class RecallMessageApi private constructor( get() = ApiResult.emptySerializer() override fun toString(): String { - return "RecallMessageApi(msgUid='$msgUid', roomId=$roomId, msgTime=$msgTime)" + return "RecallMessageApi(body=$body)" } override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is RecallMessageApi) return false - if (msgUid != other.msgUid) return false - if (roomId != other.roomId) return false - if (msgTime != other.msgTime) return false + if (body != other.body) return false return true } override fun hashCode(): Int { - var result = msgUid.hashCode() - result = 31 * result + roomId.hashCode() - result = 31 * result + msgTime.hashCode() - return result + return body.hashCode() } diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/SendMessageApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/SendMessageApi.kt index 13ad15c..15dbed6 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/SendMessageApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/msg/SendMessageApi.kt @@ -25,6 +25,7 @@ import love.forte.simbot.ExperimentalSimbotApi import love.forte.simbot.miyoushe.MiyousheVilla import love.forte.simbot.miyoushe.api.ApiResult import love.forte.simbot.miyoushe.api.MiyousheVillaPostApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmStatic @@ -138,7 +139,9 @@ public class SendMessageApi private constructor(override val body: Body) : Miyou */ @Serializable public data class Body( - @SerialName("room_id") val roomId: ULong, + @SerialName("room_id") + @Serializable(ULongWriteStringSerializer::class) + val roomId: ULong, @SerialName("object_name") val objectName: String, @SerialName("msg_content") val msgContent: String, ) diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/DeleteMemberRoleApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/DeleteMemberRoleApi.kt index ff881be..fe31ccd 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/DeleteMemberRoleApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/DeleteMemberRoleApi.kt @@ -19,6 +19,7 @@ package love.forte.simbot.miyoushe.api.role import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -64,7 +65,7 @@ public class DeleteMemberRoleApi private constructor(override val body: Body) : * @property id 身份组 id */ @Serializable - public data class Body(val id: ULong) + public data class Body(@Serializable(ULongWriteStringSerializer::class) val id: ULong) override fun toString(): String { return "DeleteMemberRoleApi(body=$body)" diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/EditMemberRoleApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/EditMemberRoleApi.kt index 1d2293b..3963d9c 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/EditMemberRoleApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/EditMemberRoleApi.kt @@ -19,6 +19,7 @@ package love.forte.simbot.miyoushe.api.role import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -194,7 +195,8 @@ public class EditMemberRoleApi private constructor(override val body: Body) : Mi */ @Serializable public data class Body( - val id: ULong, val name: String, val color: String, val permissions: Collection + @Serializable(ULongWriteStringSerializer::class) val id: ULong, + val name: String, val color: String, val permissions: Collection ) override fun toString(): String { diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/OperateMemberToRoleApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/OperateMemberToRoleApi.kt index ba5e206..9139d44 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/OperateMemberToRoleApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/role/OperateMemberToRoleApi.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.role import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -120,8 +121,12 @@ public class OperateMemberToRoleApi private constructor(override val body: Body) */ @Serializable public data class Body( - @SerialName("role_id") val roleId: ULong, + @SerialName("role_id") + @Serializable(ULongWriteStringSerializer::class) + val roleId: ULong, + @Serializable(ULongWriteStringSerializer::class) val uid: ULong, + @SerialName("is_add") val isAdd: Boolean ) diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteGroupApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteGroupApi.kt index 7213ce1..ae5ef73 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteGroupApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteGroupApi.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.room import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -66,7 +67,7 @@ public class DeleteGroupApi private constructor(override val body: Body) : Miyou * @property groupId 分组 id */ @Serializable - public data class Body(@SerialName("group_id") val groupId: ULong) + public data class Body(@SerialName("group_id") @Serializable(ULongWriteStringSerializer::class) val groupId: ULong) override fun toString(): String { return "DeleteGroupApi(body=$body)" diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteRoomApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteRoomApi.kt index 6b8cfeb..8c0f584 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteRoomApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/DeleteRoomApi.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.room import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -66,7 +67,7 @@ public class DeleteRoomApi private constructor(override val body: Body) : Miyous * @property roomId 房间 id */ @Serializable - public data class Body(@SerialName("room_id") val roomId: ULong) + public data class Body(@SerialName("room_id") @Serializable(ULongWriteStringSerializer::class) val roomId: ULong) override fun toString(): String { return "DeleteRoomApi(body=$body)" diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditGroupApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditGroupApi.kt index d3d4165..af687ee 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditGroupApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditGroupApi.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.room import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -69,7 +70,12 @@ public class EditGroupApi private constructor(override val body: Body) : Miyoush * @property groupName 大别野 名称 */ @Serializable - public data class Body(@SerialName("group_id") val groupId: ULong, @SerialName("group_name") val groupName: String) + public data class Body( + @SerialName("group_id") + @Serializable(ULongWriteStringSerializer::class) + val groupId: ULong, + @SerialName("group_name") val groupName: String + ) override fun toString(): String { return "EditGroupApi(body=$body)" diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditRoomApi.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditRoomApi.kt index 7a31a20..ae295be 100644 --- a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditRoomApi.kt +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/api/room/EditRoomApi.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.api.room import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.miyoushe.api.MiyousheVillaPostEmptyResultApi +import love.forte.simbot.miyoushe.utils.serialization.ULongWriteStringSerializer import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -72,7 +73,9 @@ public class EditRoomApi private constructor(override val body: Body) : Miyoushe */ @Serializable public data class Body( - @SerialName("room_id") val roomId: ULong, + @SerialName("room_id") + @Serializable(ULongWriteStringSerializer::class) + val roomId: ULong, @SerialName("room_name") val roomName: String, ) diff --git a/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/utils/serialization/ULongWriteStringSerializer.kt b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/utils/serialization/ULongWriteStringSerializer.kt new file mode 100644 index 0000000..fa51afb --- /dev/null +++ b/simbot-component-miyoushe-villa-api/src/commonMain/kotlin/love/forte/simbot/miyoushe/utils/serialization/ULongWriteStringSerializer.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023. ForteScarlet. + * + * This file is part of simbot-component-miyoushe. + * + * simbot-component-miyoushe is free software: you can redistribute it and/or modify it under the terms of + * the GNU Lesser General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * simbot-component-miyoushe is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with simbot-component-miyoushe, + * If not, see . + */ + +package love.forte.simbot.miyoushe.utils.serialization + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * 将 [ULong] 写为字符串格式的序列化器。 + * + */ +public object ULongWriteStringSerializer : KSerializer { + private val source = ULong.serializer() + + override fun deserialize(decoder: Decoder): ULong = source.deserialize(decoder) + override val descriptor: SerialDescriptor get() = source.descriptor + + override fun serialize(encoder: Encoder, value: ULong) { + encoder.encodeString(value.toString()) + } +} diff --git a/simbot-component-miyoushe-villa-api/src/jvmMain/kotlin/love/forte/simbot/miyoushe/api/apiRequests.jvm.kt b/simbot-component-miyoushe-villa-api/src/jvmMain/kotlin/love/forte/simbot/miyoushe/api/apiRequests.jvm.kt index 8f0eadc..dbe5030 100644 --- a/simbot-component-miyoushe-villa-api/src/jvmMain/kotlin/love/forte/simbot/miyoushe/api/apiRequests.jvm.kt +++ b/simbot-component-miyoushe-villa-api/src/jvmMain/kotlin/love/forte/simbot/miyoushe/api/apiRequests.jvm.kt @@ -52,6 +52,7 @@ public fun MiyousheVillaApi.requestBlocking( * @throws HttpStatusException 如果 http 结果不是成功 ([HttpStatusCode.isSuccess] == false) */ @Api4J +@JvmOverloads public fun MiyousheVillaApi.requestResultBlocking( client: HttpClient, token: MiyousheVillaApiToken, @@ -66,6 +67,7 @@ public fun MiyousheVillaApi.requestResultBlocking( * @throws ApiResultNotSuccessException 如果结果不是成功 (see [ApiResult.dataIfSuccess]) */ @Api4J +@JvmOverloads public fun MiyousheVillaApi.requestDataBlocking( client: HttpClient, token: MiyousheVillaApiToken, diff --git a/simbot-component-miyoushe-villa-core/build.gradle.kts b/simbot-component-miyoushe-villa-core/build.gradle.kts index 0f16ac2..6d75ba8 100644 --- a/simbot-component-miyoushe-villa-core/build.gradle.kts +++ b/simbot-component-miyoushe-villa-core/build.gradle.kts @@ -4,7 +4,8 @@ plugins { kotlin("jvm") // `miyoushe-multiplatform-maven-publish` kotlin("plugin.serialization") -// `miyoushe-dokka-partial-configure` + `miyoushe-dokka-partial-configure` + `simbot-miyoushe-suspend-transform` } setup(P) diff --git a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/VillaRoomImpl.kt b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/VillaRoomImpl.kt index acabe36..9c5fa3b 100644 --- a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/VillaRoomImpl.kt +++ b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/VillaRoomImpl.kt @@ -26,7 +26,7 @@ import love.forte.simbot.component.miyoushe.VillaRoomGroup import love.forte.simbot.component.miyoushe.internal.bot.VillaBotImpl import love.forte.simbot.component.miyoushe.internal.message.toReceipt import love.forte.simbot.component.miyoushe.message.VillaSendMessageReceipt -import love.forte.simbot.component.miyoushe.message.sendTo +import love.forte.simbot.component.miyoushe.message.sendToReceipt import love.forte.simbot.component.miyoushe.requestDataBy import love.forte.simbot.definition.GuildMember import love.forte.simbot.definition.Role @@ -78,16 +78,14 @@ internal class VillaRoomImpl( override suspend fun send(message: Message): VillaSendMessageReceipt { val roomId = room.roomId - return message.sendTo(bot, villaId, roomId, null) - .toReceipt(bot, villaId, roomId, null) + return message.sendToReceipt(bot, villaId, roomId, null) } @OptIn(InternalSimbotApi::class) override suspend fun send(message: MessageContent): VillaSendMessageReceipt { val roomId = room.roomId - return message.sendTo(bot, villaId, roomId, null) - .toReceipt(bot, villaId, roomId, null) + return message.sendToReceipt(bot, villaId, roomId, null) } override suspend fun send(text: String): VillaSendMessageReceipt { @@ -96,6 +94,6 @@ internal class VillaRoomImpl( val result = SendMessageApi.create(roomId, MsgContentInfo(TextMsgContent(text = text))).requestDataBy(bot, villaId) - return result.toReceipt(bot, villaId, roomId, null) + return result.toReceipt(bot, villaId, roomId, System.currentTimeMillis()) } } diff --git a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/event/VillaSendMessageEventImpl.kt b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/event/VillaSendMessageEventImpl.kt index 47a66b1..98bbab1 100644 --- a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/event/VillaSendMessageEventImpl.kt +++ b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/event/VillaSendMessageEventImpl.kt @@ -26,7 +26,7 @@ import love.forte.simbot.component.miyoushe.internal.message.VillaReceivedMessag import love.forte.simbot.component.miyoushe.internal.message.toReceipt import love.forte.simbot.component.miyoushe.message.VillaReceivedMessageContent import love.forte.simbot.component.miyoushe.message.VillaSendMessageReceipt -import love.forte.simbot.component.miyoushe.message.sendTo +import love.forte.simbot.component.miyoushe.message.sendToReceipt import love.forte.simbot.component.miyoushe.requestDataBy import love.forte.simbot.message.Message import love.forte.simbot.message.MessageContent @@ -63,8 +63,7 @@ internal class VillaSendMessageEventImpl( val villaIdStr = sourceEventExtend.villaIdStrValue val roomId = sourceEventExtend.roomId - return message.sendTo(bot, villaIdStr, roomId, autoQuote) - .toReceipt(bot, villaIdStr, roomId, null) + return message.sendToReceipt(bot, villaIdStr, roomId, autoQuote) } @OptIn(InternalSimbotApi::class) @@ -73,8 +72,7 @@ internal class VillaSendMessageEventImpl( val villaIdStr = sourceEventExtend.villaIdStrValue val roomId = sourceEventExtend.roomId - return message.sendTo(bot, villaIdStr, roomId, autoQuote) - .toReceipt(bot, villaIdStr, roomId, null) + return message.sendToReceipt(bot, villaIdStr, roomId, autoQuote) } override suspend fun reply(text: String): VillaSendMessageReceipt { @@ -91,6 +89,6 @@ internal class VillaSendMessageEventImpl( decoder = bot.source.apiDecoder ).requestDataBy(bot, villaIdStr) - return result.toReceipt(bot, villaIdStr, roomId, null) + return result.toReceipt(bot, villaIdStr, roomId, System.currentTimeMillis()) } } diff --git a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/message/VillaSendMessageReceiptImpls.kt b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/message/VillaSendMessageReceiptImpls.kt index 635cb6c..ab4eab7 100644 --- a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/message/VillaSendMessageReceiptImpls.kt +++ b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/internal/message/VillaSendMessageReceiptImpls.kt @@ -34,17 +34,16 @@ internal class VillaSendSingleMessageReceiptImpl( override val result: SendMessageResult ) : VillaSendSingleMessageReceipt() { override suspend fun delete(): Boolean { - val result = RecallMessageApi.create(result.botMsgId, roomId, msgTime).requestResultBy(bot, villaId) + val api = RecallMessageApi.create(result.botMsgId, roomId, msgTime) + bot.logger.trace("Delete api: {}", api) + val result = api.requestResultBy(bot, villaId) + bot.logger.trace("Delete result: {}", result) return result.isSuccess } } internal class VillaSendAggregatedMessageReceiptImpl( - private val bot: VillaBotImpl, - private val villaId: String, - private val roomId: ULong, - private val msgTime: Long?, private val receipts: List ) : VillaSendAggregatedMessageReceipt() { override val size: Int get() = receipts.size @@ -59,5 +58,12 @@ internal fun List.toReceipt(bot: VillaBotImpl, villaId: Strin check(isNotEmpty()) { "List of `SendMessageResult` is empty" } if (size == 1) return first().toReceipt(bot, villaId, roomId, msgTime) - return VillaSendAggregatedMessageReceiptImpl(bot, villaId, roomId, msgTime, map { it.toReceipt(bot, villaId, roomId, msgTime) }) + return VillaSendAggregatedMessageReceiptImpl(map { it.toReceipt(bot, villaId, roomId, msgTime) }) +} + +internal fun List.toReceipt(): VillaSendMessageReceipt { + check(isNotEmpty()) { "List of `VillaSendSingleMessageReceipt` is empty" } + if (size == 1) return first() + + return VillaSendAggregatedMessageReceiptImpl(toList()) } diff --git a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaMessages.kt b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaMessages.kt index ddf6c1e..2e68ce4 100644 --- a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaMessages.kt +++ b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaMessages.kt @@ -21,13 +21,17 @@ package love.forte.simbot.component.miyoushe.message import love.forte.simbot.InternalSimbotApi import love.forte.simbot.component.miyoushe.bot.VillaBot +import love.forte.simbot.component.miyoushe.internal.bot.VillaBotImpl +import love.forte.simbot.component.miyoushe.internal.message.toReceipt import love.forte.simbot.component.miyoushe.requestDataBy import love.forte.simbot.component.miyoushe.uploadToOssData +import love.forte.simbot.component.miyoushe.utils.toULong import love.forte.simbot.literal import love.forte.simbot.message.* import love.forte.simbot.miyoushe.api.image.GetUploadImageParamsApi import love.forte.simbot.miyoushe.api.msg.* import love.forte.simbot.miyoushe.api.msg.QuoteInfo.Companion.toQuoteInfo +import love.forte.simbot.miyoushe.api.msg.TextMsgContent.EntityContent import love.forte.simbot.miyoushe.event.SendMessage import love.forte.simbot.resources.ByteArrayResource import love.forte.simbot.resources.FileResource @@ -53,7 +57,6 @@ public suspend fun Message.sendTo( check(apiList.isNotEmpty()) { "Nothing to reply: the list of APIs ready to be used for sending is empty" } return apiList.map { - println("api: $it") it.requestDataBy(bot, villaId) } } @@ -70,11 +73,50 @@ public suspend fun MessageContent.sendTo( check(apiList.isNotEmpty()) { "Nothing to reply: the list of APIs ready to be used for sending is empty" } return apiList.map { - println("api: $it") it.requestDataBy(bot, villaId) } } +@InternalSimbotApi +internal suspend fun Message.sendToReceipt( + bot: VillaBotImpl, + villaId: String, + roomId: ULong, + autoQuote: QuoteInfo? = null +): VillaSendMessageReceipt { + val apiList = toSendApi(bot, villaId, roomId, autoQuote) + // 没有可回复的内容:准备用于发送的API列表为空 + check(apiList.isNotEmpty()) { "Nothing to reply: the list of APIs ready to be used for sending is empty" } + + val result = apiList.map { + it.requestDataBy(bot, villaId).toReceipt(bot, villaId, roomId, System.currentTimeMillis()) + } + + if (result.size == 1) return result.first() + + return result.toReceipt() +} + +@InternalSimbotApi +internal suspend fun MessageContent.sendToReceipt( + bot: VillaBotImpl, + villaId: String, + roomId: ULong, + autoQuote: QuoteInfo? = null +): VillaSendMessageReceipt { + val apiList = toSendApi(bot, villaId, roomId, autoQuote) + // 没有可回复的内容:准备用于发送的API列表为空 + check(apiList.isNotEmpty()) { "Nothing to reply: the list of APIs ready to be used for sending is empty" } + + val result = apiList.map { + it.requestDataBy(bot, villaId).toReceipt(bot, villaId, roomId, System.currentTimeMillis()) + } + + if (result.size == 1) return result.first() + + return result.toReceipt() +} + @InternalSimbotApi public suspend fun MessageContent.toSendApi( @@ -241,7 +283,16 @@ private suspend fun Message.Element<*>.toMsgContents0( is At -> return returnListOf( MsgContentInfo( - content = TextMsgContent.EMPTY, + content = TextMsgContent( + text = originContent, + entities = listOf( + TextMsgContent.Entity( + offset = 0, + length = originContent.length, + EntityContent.MentionedUser(target.toULong()) + ) + ) + ), mentionedInfo = MentionedInfo.mentionMembers(listOf(target.literal)), quoteInfo = autoQuote ) @@ -249,7 +300,16 @@ private suspend fun Message.Element<*>.toMsgContents0( AtAll -> return returnListOf( MsgContentInfo( - content = TextMsgContent.EMPTY, + content = TextMsgContent( + text = EntityContent.MentionAll.CONTENT, + entities = listOf( + TextMsgContent.Entity( + offset = 0, + length = EntityContent.MentionAll.CONTENT.length, + EntityContent.MentionAll + ) + ) + ), mentionedInfo = MentionedInfo.mentionAll(), quoteInfo = autoQuote ) @@ -289,6 +349,15 @@ private suspend fun Message.Element<*>.toMsgContents0( } is VillaStyleText -> { + // `VillaStyleText` 不能单独发送,你需要配合 `PlainText` (例如 `text.toText()`) 使用。 + // 在发送时,`VillaStyleText.text` 是无效的。 + // 未来可能会真的让它无效,所以请及时改正。 + bot.logger.warn( + "`VillaStyleText` ({}) cannot be sent alone, you need to use it with `PlainText` (e.g. `text.toText()`). When sent, `VillaStyleText.text` is not valid." + + "In the future, separately sent `VillaStyleText` will be ignored, so please check and correct it in time.", + this + ) + return returnListOf( MsgContentInfo( content = TextMsgContent( @@ -462,8 +531,22 @@ private suspend fun toMsgContents0( } text.mentionedInfo { + type = MentionedInfo.TYPE_MENTION_MEMBER userIdList.add(message.target.literal) } + + text.content { + entity { + val currentLen = textBuilder.length + val atContent = message.originContent + appendText(atContent) + content(EntityContent.MentionedUser) { + userId = message.target.toULong() + } + offset = currentLen + length = atContent.length + } + } } AtAll -> { @@ -475,6 +558,17 @@ private suspend fun toMsgContents0( text.mentionedInfo { type = MentionedInfo.TYPE_MENTION_ALL } + + text.content { + entity { + val currentLen = textBuilder.length + val atContent = EntityContent.MentionAll.CONTENT + appendText(atContent) + content = EntityContent.MentionAll + offset = currentLen + length = EntityContent.MentionAll.CONTENT.length + } + } } is PlainText -> { diff --git a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaStyleText.kt b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaStyleText.kt index dca3e35..73291e8 100644 --- a/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaStyleText.kt +++ b/simbot-component-miyoushe-villa-core/src/main/kotlin/love/forte/simbot/component/miyoushe/message/VillaStyleText.kt @@ -30,8 +30,12 @@ import love.forte.simbot.miyoushe.api.msg.TextMsgContent * 更多文本样式消息。 * 文本样式不会作为 [PlainText] 使用(因为其对应的 [text] 已经直接作为 [Text] 被追加了) * + * ### 发送 + * * [VillaStyleText] 在作为用于发送的消息时,[text] **无效**, * 且 [offset] 与 [length] 会直接相对于当前解析过程中的正文信息。 + * 因此,如果一定要使用 [VillaStyleText] 发送具有样式的文本,那么一定是要配合 [PlainText] 进行的。 + * * 而当前解析过程中的文本信息除了 [PlainText] 以外,还可能由其他消息类型进行填充(例如 [VillaVillaRoomLink] 会填充房间名称信息), * 因此 [VillaStyleText] 作为发送用的消息(且不是直接使用 [VillaReceivedMessageContent] 原样发送时)需要仔细确认其参数是否正确。 * @@ -60,12 +64,14 @@ public data class VillaStyleText( /** * 构建一个**用于发送**的 [VillaStyleText]。 - * 发送时 [text] 无效因此无需填写,默认为空字符串。 + * 在作为多个消息元素的消息链发送时 [text] 无效,可选择默认为空字符串。 + * * * @param fontStyle 参考 [TextMsgContent.EntityContent.Style.fontStyle] */ @JvmStatic - public fun create(offset: Int, length: Int, fontStyle: String): VillaStyleText = + @JvmOverloads + public fun create(text: String = "", offset: Int, length: Int, fontStyle: String): VillaStyleText = VillaStyleText("", offset, length, TextMsgContent.EntityContent.Style(fontStyle)) } } diff --git a/simbot-component-miyoushe-villa-stdlib/build.gradle.kts b/simbot-component-miyoushe-villa-stdlib/build.gradle.kts index 8eb46c0..025e810 100644 --- a/simbot-component-miyoushe-villa-stdlib/build.gradle.kts +++ b/simbot-component-miyoushe-villa-stdlib/build.gradle.kts @@ -7,7 +7,8 @@ plugins { kotlin("multiplatform") // `miyoushe-multiplatform-maven-publish` kotlin("plugin.serialization") -// `miyoushe-dokka-partial-configure` + `miyoushe-dokka-partial-configure` + `simbot-miyoushe-suspend-transform` } setup(P) diff --git a/simbot-component-miyoushe-villa-stdlib/src/commonMain/kotlin/love/forte/simbot/miyoushe/stdlib/bot/Bot.kt b/simbot-component-miyoushe-villa-stdlib/src/commonMain/kotlin/love/forte/simbot/miyoushe/stdlib/bot/Bot.kt index 242be4c..73380f9 100644 --- a/simbot-component-miyoushe-villa-stdlib/src/commonMain/kotlin/love/forte/simbot/miyoushe/stdlib/bot/Bot.kt +++ b/simbot-component-miyoushe-villa-stdlib/src/commonMain/kotlin/love/forte/simbot/miyoushe/stdlib/bot/Bot.kt @@ -20,6 +20,7 @@ package love.forte.simbot.miyoushe.stdlib.bot import io.ktor.client.* import kotlinx.coroutines.CoroutineScope import kotlinx.serialization.json.Json +import love.forte.simbot.JST import love.forte.simbot.miyoushe.event.Event import love.forte.simbot.miyoushe.event.EventExtendData import love.forte.simbot.miyoushe.event.EventSource @@ -124,7 +125,7 @@ public interface Bot : CoroutineScope { * @throws IllegalArgumentException 如果 bot 已经被关闭或已经结束 * @throws PLoginFailedException 如果登录时失败 */ - @JvmSynthetic // TODO JST? + @JST public suspend fun start() /** @@ -138,7 +139,7 @@ public interface Bot : CoroutineScope { * 挂起直到此 bot 的协程被终止。 * 可能会通过 [logout]、[cancel] 主动终止,或收到了 [PKickOff] 数据包而被动终止。 */ - @JvmSynthetic // TODO JST? + @JST(asyncBaseName = "asFuture", asyncSuffix = "") public suspend fun join() /**