From fc7ece1ce29f58bc8448abf220b6a01477644a0c Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Thu, 20 Jun 2024 22:45:53 +0800 Subject: [PATCH 1/4] =?UTF-8?q?pref:=20=E5=BD=93=E9=81=87=E5=88=B0?= =?UTF-8?q?=E9=A2=84=E6=9C=9F=E5=86=85=E4=BD=86=E6=97=A0=E6=B3=95=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E8=A7=A3=E6=9E=90=E7=9A=84=E4=BA=8B=E4=BB=B6=E6=97=B6?= =?UTF-8?q?=E4=B9=9F=E5=8C=85=E8=A3=85=E5=88=B0=20UnknownEvent=20=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- buildSrc/src/main/kotlin/P.kt | 2 +- gradle/libs.versions.toml | 3 ++ .../build.gradle.kts | 2 + .../v11/core/bot/internal/OneBotBotImpl.kt | 41 ++++++++++++++++--- .../onebot/v11/event/UnknownEvent.kt | 35 ++++++++++++++-- 5 files changed, 72 insertions(+), 11 deletions(-) diff --git a/buildSrc/src/main/kotlin/P.kt b/buildSrc/src/main/kotlin/P.kt index 70e3c1b..5e5bd27 100644 --- a/buildSrc/src/main/kotlin/P.kt +++ b/buildSrc/src/main/kotlin/P.kt @@ -41,7 +41,7 @@ object P { override val homepage: String get() = HOMEPAGE - private val baseVersion = v(0, 6, 0) + private val baseVersion = v(0, 7, 0) val snapshotVersion = baseVersion - Version.SNAPSHOT override val version = if (isSnapshot()) snapshotVersion else baseVersion diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6c86dc7..29c5786 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -71,6 +71,9 @@ ktor-client-winhttp = { group = "io.ktor", name = "ktor-client-winhttp", version # see https://ktor.io/docs/http-client-engines.html#darwin ktor-client-darwin = { group = "io.ktor", name = "ktor-client-darwin", version.ref = "ktor" } +ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" } +ktor-server-ws = { module = "io.ktor:ktor-server-websockets", version.ref = "ktor" } + # log4j log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/build.gradle.kts b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/build.gradle.kts index cc24753..a8b9e11 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/build.gradle.kts +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/build.gradle.kts @@ -100,6 +100,8 @@ kotlin { implementation(libs.kotlinPoet) implementation(libs.kotlinx.coroutines.reactor) api(libs.ktor.client.java) + implementation(libs.ktor.server.netty) + implementation(libs.ktor.server.ws) } } } diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt index 8c7299b..80165db 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonPrimitive @@ -369,7 +370,11 @@ internal class OneBotBotImpl( } } - receiveEvent(currentSession) + kotlin.runCatching { + receiveEvent(currentSession) + }.onFailure { ex -> + logger.error("Event reception is interrupted: {}", ex.message, ex) + } // The Session is done or dead, // or the job is done. @@ -448,6 +453,8 @@ internal class OneBotBotImpl( } } ?: continue + logger.debug("Received raw event: {}", eventRaw) + val event = kotlin.runCatching { resolveRawEvent(eventRaw) }.getOrElse { e -> @@ -460,9 +467,9 @@ internal class OneBotBotImpl( ) // 接收的事件解析出现错误, // 这应该是预期外的情况, - // 直接终止 session 和 Bot + // 直接终止 session, 但是不终止 Bot, + // 只有当重连次数用尽才考虑终止 Bot。 session.closeExceptionally(ex) - job.cancel(exMsg, ex) throw ex } @@ -489,10 +496,10 @@ internal class OneBotBotImpl( val subTypeFieldName = resolveEventSubTypeFieldName(postType) ?: "${postType}_type" val subType = obj[subTypeFieldName]?.jsonPrimitive?.content - fun toUnknown(): UnknownEvent { + fun toUnknown(reason: Throwable? = null): UnknownEvent { val time = obj["time"]?.jsonPrimitive?.long ?: -1L val selfId = obj["self_id"]?.jsonPrimitive?.long?.ID ?: 0L.ID - return UnknownEvent(time, selfId, postType, text) + return UnknownEvent(time, selfId, postType, text, reason) } if (subType == null) { @@ -501,7 +508,29 @@ internal class OneBotBotImpl( } resolveEventSerializer(postType, subType)?.let { - return OneBot11.DefaultJson.decodeFromJsonElement(it, obj) + return try { + OneBot11.DefaultJson.decodeFromJsonElement(it, obj) + } catch (serEx: SerializationException) { + logger.error( + "Received raw event '{}' decode failed because of serialization: {}" + + "It will be pushed as an UnknownEvent", + text, + serEx.message, + serEx + ) + + toUnknown(serEx) + } catch (argEx: IllegalArgumentException) { + logger.error( + "Received raw event '{}' decode failed because of illegal argument: {}" + + "It will be pushed as an UnknownEvent", + text, + argEx.message, + argEx + ) + + toUnknown(argEx) + } } ?: run { return toUnknown() } diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt index bc3fc30..8b811a2 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt @@ -17,9 +17,10 @@ package love.forte.simbot.component.onebot.v11.event +import kotlinx.serialization.SerializationException import love.forte.simbot.annotations.FragileSimbotAPI import love.forte.simbot.common.id.LongID - +import love.forte.simbot.component.onebot.common.annotations.InternalOneBotAPI /** * 用于“兜底”的 [RawEvent] 类型实现。 @@ -28,6 +29,9 @@ import love.forte.simbot.common.id.LongID * * [UnknownEvent] 要求事件体必须包括 [time], [selfId] 和 [postType]。 * + * 如果 [UnknownEvent] 是由于某些异常而产生(例如原本事件进行序列化但是失败了), + * 那么失败的原因则会通过 [reason] 提供。 + * * ### FragileAPI * * 这是一个具有**特殊规则**的事件类型。 @@ -37,12 +41,35 @@ import love.forte.simbot.common.id.LongID * @author ForteScarlet */ @FragileSimbotAPI -public data class UnknownEvent( +public class UnknownEvent @InternalOneBotAPI constructor( override val time: Long, override val selfId: LongID, override val postType: String, /** - * 原始的JSON字符串 + * 原始的JSON字符串, + * 也是判断 [UnknownEvent] 之间是否相同的**唯一依据**。 */ public val raw: String, -) : RawEvent + + /** + * 如果是由于异常而产生,则此处为异常的原因。 + * 通常会是 [SerializationException]。 + */ + public val reason: Throwable? = null +) : RawEvent { + override fun toString(): String = + "UnknownEvent(time=$time, selfId=$selfId, postType='$postType')" + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is UnknownEvent) return false + + if (raw != other.raw) return false + + return true + } + + override fun hashCode(): Int { + return raw.hashCode() + } +} From cfd43e4d3313623a30c9b0a5783fea546215e7de Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Thu, 20 Jun 2024 22:53:40 +0800 Subject: [PATCH 2/4] =?UTF-8?q?pref:=20UnknownEvent=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20rawJson=20=E6=9D=A5=E7=9B=B4=E6=8E=A5=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=90=8E=E7=9A=84=20JsonObject?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onebot/v11/core/bot/internal/OneBotBotImpl.kt | 2 +- .../build.gradle.kts | 1 + .../component/onebot/v11/event/UnknownEvent.kt | 15 ++++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt index 80165db..fa725a4 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/bot/internal/OneBotBotImpl.kt @@ -499,7 +499,7 @@ internal class OneBotBotImpl( fun toUnknown(reason: Throwable? = null): UnknownEvent { val time = obj["time"]?.jsonPrimitive?.long ?: -1L val selfId = obj["self_id"]?.jsonPrimitive?.long?.ID ?: 0L.ID - return UnknownEvent(time, selfId, postType, text, reason) + return UnknownEvent(time, selfId, postType, text, obj, reason) } if (subType == null) { diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/build.gradle.kts b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/build.gradle.kts index a0583f0..b1ba4de 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/build.gradle.kts +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/build.gradle.kts @@ -61,6 +61,7 @@ kotlin { commonMain.dependencies { implementation(libs.simbot.api) implementation(libs.simbot.common.annotations) + implementation(libs.kotlinx.serialization.json) implementation(project(":simbot-component-onebot-common")) api(project(":simbot-component-onebot-v11:simbot-component-onebot-v11-common")) diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt index 8b811a2..b41c4e8 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-event/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/event/UnknownEvent.kt @@ -18,6 +18,7 @@ package love.forte.simbot.component.onebot.v11.event import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.JsonObject import love.forte.simbot.annotations.FragileSimbotAPI import love.forte.simbot.common.id.LongID import love.forte.simbot.component.onebot.common.annotations.InternalOneBotAPI @@ -32,6 +33,12 @@ import love.forte.simbot.component.onebot.common.annotations.InternalOneBotAPI * 如果 [UnknownEvent] 是由于某些异常而产生(例如原本事件进行序列化但是失败了), * 那么失败的原因则会通过 [reason] 提供。 * + * ### 内部构造 + * + * [UnknownEvent] 应当始终由内部使用、构造, + * 不要在其他地方自行构造 [UnknownEvent], + * 它的构造函数不保证任何源码或二进制兼容。 + * * ### FragileAPI * * 这是一个具有**特殊规则**的事件类型。 @@ -51,11 +58,17 @@ public class UnknownEvent @InternalOneBotAPI constructor( */ public val raw: String, + /** + * [raw] 对应解析的 [JsonObject] 对象。 + */ + public val rawJson: JsonObject, + /** * 如果是由于异常而产生,则此处为异常的原因。 * 通常会是 [SerializationException]。 */ - public val reason: Throwable? = null + public val reason: Throwable? = null, + ) : RawEvent { override fun toString(): String = "UnknownEvent(time=$time, selfId=$selfId, postType='$postType')" From 0208e6607ef704157d149faf49e87424a80556a5 Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Thu, 20 Jun 2024 23:04:27 +0800 Subject: [PATCH 3/4] =?UTF-8?q?pref:=20=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=85=AC=E5=BC=80=E7=9A=84=E5=86=85=E9=83=A8=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E8=A7=A3=E6=9E=90API=EF=BC=8C=E5=B9=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0JVM=E5=B9=B3=E5=8F=B0=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E6=A1=A5=E6=8E=A5API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v11/message/MessageElementResolvers.kt | 3 + .../src/jvmMain/java/module-info.java | 2 + .../message/MessageElementResolvers.jvm.kt | 80 +++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/MessageElementResolvers.kt b/simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/MessageElementResolvers.kt index e343486..9ba6f4d 100644 --- a/simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/MessageElementResolvers.kt +++ b/simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/MessageElementResolvers.kt @@ -32,6 +32,7 @@ import love.forte.simbot.resource.toStringResource import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.jvm.JvmName +import kotlin.jvm.JvmSynthetic /** * 将事件中接收到的 [OneBotMessageSegment] 解析为 [Message.Element]。 @@ -57,6 +58,7 @@ public fun OneBotMessageSegment.resolveToMessageElement(): Message.Element { * @see resolveToOneBotSegment */ @InternalOneBotAPI +@JvmSynthetic public suspend fun Message.resolveToOneBotSegmentList(): List { return when (this) { is Message.Element -> resolveToOneBotSegment() @@ -71,6 +73,7 @@ public suspend fun Message.resolveToOneBotSegmentList(): List = + runInNoScopeBlocking { resolveToOneBotSegmentList() } + +/** + * 将 [Message] 解析为一用于API请求的 [OneBotMessageSegment] 列表。 + * + * @see resolveToOneBotSegmentList + */ +@OptIn(InternalSimbotAPI::class) +@InternalOneBotAPI +@Api4J +public fun Message.resolveToOneBotSegmentListAsync(): CompletableFuture> = + runInAsync { resolveToOneBotSegmentList() } + +/** + * 将 [Message] 解析为一用于API请求的 [OneBotMessageSegment] 列表。 + * + * @see resolveToOneBotSegmentList + */ +@OptIn(InternalSimbotAPI::class, DelicateCoroutinesApi::class) +@InternalOneBotAPI +@Api4J +public fun Message.resolveToOneBotSegmentListReserve(): SuspendReserve> = + suspendReserve( + GlobalScope, + EmptyCoroutineContext + ) { resolveToOneBotSegmentList() } + +/** + * 将一个 [Message.Element] 转化为用于API请求的 [OneBotMessageSegment]。 + * @see resolveToOneBotSegment + */ +@InternalOneBotAPI +@Api4J +public fun Message.Element.resolveToOneBotSegmentBlocking(): OneBotMessageSegment? = + runInNoScopeBlocking { resolveToOneBotSegment() } + +/** + * 将一个 [Message.Element] 转化为用于API请求的 [OneBotMessageSegment]。 + * @see resolveToOneBotSegment + */ +@OptIn(InternalSimbotAPI::class) +@InternalOneBotAPI +@Api4J +public fun Message.Element.resolveToOneBotSegmentAsync(): CompletableFuture = + runInAsync { resolveToOneBotSegment() } + +/** + * 将一个 [Message.Element] 转化为用于API请求的 [OneBotMessageSegment]。 + * @see resolveToOneBotSegment + */ +@OptIn(DelicateCoroutinesApi::class, InternalSimbotAPI::class) +@InternalOneBotAPI +@Api4J +public fun Message.Element.resolveToOneBotSegmentReserve(): SuspendReserve = + suspendReserve( + GlobalScope, + EmptyCoroutineContext + ) { resolveToOneBotSegment() } + + internal actual fun offlineImageResolver(): OfflineImageValueResolver> = object : JvmOfflineImageValueResolver>() { override fun resolveUnknownInternal(image: OfflineImage, context: Continuation) { From e9da669a5200139fb085d0c990405e5decf2ae71 Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Thu, 20 Jun 2024 23:30:27 +0800 Subject: [PATCH 4/4] release: v0.7.0 --- .changelog/v0.7.0.md | 7 +++++++ Writerside/v.list | 4 ++-- gradle/libs.versions.toml | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 .changelog/v0.7.0.md diff --git a/.changelog/v0.7.0.md b/.changelog/v0.7.0.md new file mode 100644 index 0000000..2529b95 --- /dev/null +++ b/.changelog/v0.7.0.md @@ -0,0 +1,7 @@ +> 对应核心版本: [**v4.0.1**](https://github.com/simple-robot/simpler-robot/releases/tag/v4.0.1) + + +我们欢迎并期望着您的的[反馈](https://github.com/simple-robot/simbot-component-onebot/issues)或[协助](https://github.com/simple-robot/simbot-component-onebot/pulls), +感谢您的贡献与支持! + +也欢迎您为我们献上一颗 `star`,这是对我们最大的鼓励与认可! diff --git a/Writerside/v.list b/Writerside/v.list index d79b912..1f9fc75 100644 --- a/Writerside/v.list +++ b/Writerside/v.list @@ -7,8 +7,8 @@ - + - + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 29c5786..1a6abfa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ ktor = "2.3.11" openjdk-jmh = "1.35" log4j = "2.20.0" # simbot -simbot = "4.0.0" +simbot = "4.0.1" suspendTransform = "0.9.0" gradleCommon = "0.4.0" # ksp