diff --git a/buildSrc/src/main/kotlin/P.kt b/buildSrc/src/main/kotlin/P.kt index be11ab34..d5fa9bbb 100644 --- a/buildSrc/src/main/kotlin/P.kt +++ b/buildSrc/src/main/kotlin/P.kt @@ -56,8 +56,8 @@ object P { override val homepage: String get() = HOMEPAGE - const val VERSION = "4.0.0-beta7" - const val NEXT_VERSION = "4.0.0-beta8" + const val VERSION = "4.0.0-beta8" + const val NEXT_VERSION = "4.0.0-beta9" override val snapshotVersion = "$NEXT_VERSION-SNAPSHOT" override val version = if (isSnapshot()) snapshotVersion else VERSION diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a5f6d1ca..04e30922 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ ktor = "2.3.11" openjdk-jmh = "1.37" log4j = "2.23.1" # simbot -simbot = "4.1.0" +simbot = "4.3.0" suspendTransform = "0.9.0" gradleCommon = "0.6.0" # ksp diff --git a/simbot-component-qq-guild-core/api/simbot-component-qq-guild-core.api b/simbot-component-qq-guild-core/api/simbot-component-qq-guild-core.api index 3053af77..25c817c6 100644 --- a/simbot-component-qq-guild-core/api/simbot-component-qq-guild-core.api +++ b/simbot-component-qq-guild-core/api/simbot-component-qq-guild-core.api @@ -1616,11 +1616,12 @@ public final class love/forte/simbot/component/qguild/message/QGAtChannel$Compan public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class love/forte/simbot/component/qguild/message/QGAttachmentMessage : love/forte/simbot/component/qguild/message/QGMessageElement { +public final class love/forte/simbot/component/qguild/message/QGAttachmentMessage : love/forte/simbot/component/qguild/message/QGMessageElement, love/forte/simbot/message/BinaryDataAwareMessage { public static final field Companion Llove/forte/simbot/component/qguild/message/QGAttachmentMessage$Companion; public fun (Ljava/lang/String;)V public fun (Ljava/lang/String;Ljava/util/Map;)V public synthetic fun (Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun binaryData (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/util/Map; public final fun copy (Ljava/lang/String;Ljava/util/Map;)Llove/forte/simbot/component/qguild/message/QGAttachmentMessage; diff --git a/simbot-component-qq-guild-core/src/commonMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.kt b/simbot-component-qq-guild-core/src/commonMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.kt index 4adced7c..05e9536a 100644 --- a/simbot-component-qq-guild-core/src/commonMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.kt +++ b/simbot-component-qq-guild-core/src/commonMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.kt @@ -21,13 +21,16 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import love.forte.simbot.common.id.ID import love.forte.simbot.common.id.StringID.Companion.ID +import love.forte.simbot.component.qguild.bot.QGBot import love.forte.simbot.logger.LoggerFactory import love.forte.simbot.logger.logger +import love.forte.simbot.message.BinaryDataAwareMessage import love.forte.simbot.message.Messages import love.forte.simbot.qguild.model.Message import kotlin.jvm.JvmName import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmStatic +import kotlin.jvm.JvmSynthetic import love.forte.simbot.message.Message as SimbotMessage @@ -43,8 +46,12 @@ import love.forte.simbot.message.Message as SimbotMessage @SerialName("qg.attachment") @Serializable public data class QGAttachmentMessage -@JvmOverloads constructor(public val url: String, public val properties: Map = emptyMap()) : - QGMessageElement { +@JvmOverloads constructor( + public val url: String, + public val properties: Map = emptyMap() +) : QGMessageElement, BinaryDataAwareMessage { + + internal var bot: QGBot? = null private lateinit var _source: Message.Attachment @@ -60,6 +67,16 @@ public data class QGAttachmentMessage @Deprecated("Just get url", ReplaceWith("url.ID", "love.forte.simbot.ID")) public val id: ID get() = url.ID + /** + * 尝试通过 [url] 读取二进制资源。 + * + * @throws IllegalStateException 如果无法读取(例如因序列化而丢失了 HttpClient) + * @throws Exception 请求过程中产生的任何异常 + */ + @JvmSynthetic + override suspend fun binaryData(): ByteArray = + readBinaryData(bot, url) + public companion object { /** @@ -77,6 +94,11 @@ public data class QGAttachmentMessage } } +internal expect suspend fun readBinaryData( + bot: QGBot?, + url: String +): ByteArray + /** * @suppress */ diff --git a/simbot-component-qq-guild-core/src/jsMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.js.kt b/simbot-component-qq-guild-core/src/jsMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.js.kt new file mode 100644 index 00000000..0b4451ed --- /dev/null +++ b/simbot-component-qq-guild-core/src/jsMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.js.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-qq-guild. + * + * simbot-component-qq-guild 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-qq-guild 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-qq-guild. + * If not, see . + */ + +package love.forte.simbot.component.qguild.message + +import io.ktor.client.request.* +import io.ktor.client.statement.* +import love.forte.simbot.component.qguild.bot.QGBot + +internal actual suspend fun readBinaryData( + bot: QGBot?, + url: String +): ByteArray { + val client = bot?.source?.apiClient ?: error("api Http client from bot is missing") + return client.get(url).readBytes() +} diff --git a/simbot-component-qq-guild-core/src/jvmMain/java/module-info.java b/simbot-component-qq-guild-core/src/jvmMain/java/module-info.java index 80ae9253..a244fdeb 100644 --- a/simbot-component-qq-guild-core/src/jvmMain/java/module-info.java +++ b/simbot-component-qq-guild-core/src/jvmMain/java/module-info.java @@ -29,6 +29,8 @@ requires transitive simbot.component.qqguild.api; requires kotlinx.datetime; + requires io.ktor.client.core; + requires io.ktor.utils; // exports diff --git a/simbot-component-qq-guild-core/src/jvmMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.jvm.kt b/simbot-component-qq-guild-core/src/jvmMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.jvm.kt new file mode 100644 index 00000000..51351b23 --- /dev/null +++ b/simbot-component-qq-guild-core/src/jvmMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.jvm.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-qq-guild. + * + * simbot-component-qq-guild 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-qq-guild 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-qq-guild. + * If not, see . + */ + +package love.forte.simbot.component.qguild.message + +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.util.cio.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import love.forte.simbot.component.qguild.bot.QGBot +import java.io.IOException +import java.net.URI + +internal actual suspend fun readBinaryData( + bot: QGBot?, + url: String +): ByteArray { + val client = bot?.source?.apiClient + if (client != null) { + return client.get(url).readBytes() + } + + try { + val jUrl = URI.create(url).toURL() + return withContext(Dispatchers.IO) { + jUrl.openStream() + .toByteReadChannel(context = Dispatchers.IO) + .toByteArray() + } + } catch (io: IOException) { + throw IllegalStateException(io.localizedMessage, io) + } +} diff --git a/simbot-component-qq-guild-core/src/nativeMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.native.kt b/simbot-component-qq-guild-core/src/nativeMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.native.kt new file mode 100644 index 00000000..939187d3 --- /dev/null +++ b/simbot-component-qq-guild-core/src/nativeMain/kotlin/love/forte/simbot/component/qguild/message/QGAttachmentMessage.native.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024. ForteScarlet. + * + * This file is part of simbot-component-qq-guild. + * + * simbot-component-qq-guild 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-qq-guild 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-qq-guild. + * If not, see . + */ + +package love.forte.simbot.component.qguild.message + +import io.ktor.client.request.* +import io.ktor.client.statement.* +import love.forte.simbot.component.qguild.bot.QGBot + +internal actual suspend fun readBinaryData( + bot: QGBot?, + url: String +): ByteArray { + val client = bot?.source?.apiClient ?: error("api Http client from bot is missing") + return client.get(url).readBytes() +} +