From fc7ece1ce29f58bc8448abf220b6a01477644a0c Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Thu, 20 Jun 2024 22:45:53 +0800 Subject: [PATCH 1/2] =?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/2] =?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')"