diff --git a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api index 9dad21614..67f0a130a 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -90,6 +90,7 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve public abstract fun constructMessageSource (JLnet/mamoe/mirai/message/data/MessageSourceKind;JJ[II[ILnet/mamoe/mirai/message/data/MessageChain;)Lnet/mamoe/mirai/message/data/OfflineMessageSource; public abstract fun createFileMessage (Ljava/lang/String;ILjava/lang/String;J)Lnet/mamoe/mirai/message/data/FileMessage; public abstract fun createImage (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image; + public abstract fun createUnsupportedMessage ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; public fun downloadForwardMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;)Ljava/util/List; public abstract fun downloadForwardMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun downloadLongMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/MessageChain; @@ -4727,6 +4728,7 @@ public final class net/mamoe/mirai/message/data/MessageUtils { public static final synthetic fun At (Lnet/mamoe/mirai/contact/UserOrBot;)Lnet/mamoe/mirai/message/data/At; public static final synthetic fun FileMessage (Ljava/lang/String;ILjava/lang/String;J)Lnet/mamoe/mirai/message/data/FileMessage; public static final synthetic fun Image (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image; + public static final synthetic fun UnsupportedMessage ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; public static final synthetic fun at (Lnet/mamoe/mirai/contact/Member;)Lnet/mamoe/mirai/message/data/At; public static final fun buildMessageChain (ILkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/message/data/MessageChain; public static final fun buildMessageChain (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/message/data/MessageChain; @@ -5258,6 +5260,28 @@ public final class net/mamoe/mirai/message/data/SingleMessage$Serializer : kotli public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/SingleMessage;)V } +public abstract interface class net/mamoe/mirai/message/data/UnsupportedMessage : net/mamoe/mirai/message/data/MessageContent { + public static final field Companion Lnet/mamoe/mirai/message/data/UnsupportedMessage$Companion; + public static final field SERIAL_NAME Ljava/lang/String; + public fun contentToString ()Ljava/lang/String; + public static fun create ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; + public abstract fun getStruct ()[B +} + +public final class net/mamoe/mirai/message/data/UnsupportedMessage$Companion { + public static final field SERIAL_NAME Ljava/lang/String; + public final fun create ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; +} + +public final class net/mamoe/mirai/message/data/UnsupportedMessage$Serializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/data/UnsupportedMessage$Serializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/data/UnsupportedMessage; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/UnsupportedMessage;)V +} + public final class net/mamoe/mirai/message/data/VipFace : net/mamoe/mirai/message/code/CodableMessage, net/mamoe/mirai/message/data/HummerMessage { public static final field AiXin Lnet/mamoe/mirai/message/data/VipFace$Kind; public static final field BianBian Lnet/mamoe/mirai/message/data/VipFace$Kind; diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index c7925502e..298a44093 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -90,6 +90,7 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve public abstract fun constructMessageSource (JLnet/mamoe/mirai/message/data/MessageSourceKind;JJ[II[ILnet/mamoe/mirai/message/data/MessageChain;)Lnet/mamoe/mirai/message/data/OfflineMessageSource; public abstract fun createFileMessage (Ljava/lang/String;ILjava/lang/String;J)Lnet/mamoe/mirai/message/data/FileMessage; public abstract fun createImage (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image; + public abstract fun createUnsupportedMessage ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; public fun downloadForwardMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;)Ljava/util/List; public abstract fun downloadForwardMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun downloadLongMessage (Lnet/mamoe/mirai/Bot;Ljava/lang/String;)Lnet/mamoe/mirai/message/data/MessageChain; @@ -4727,6 +4728,7 @@ public final class net/mamoe/mirai/message/data/MessageUtils { public static final synthetic fun At (Lnet/mamoe/mirai/contact/UserOrBot;)Lnet/mamoe/mirai/message/data/At; public static final synthetic fun FileMessage (Ljava/lang/String;ILjava/lang/String;J)Lnet/mamoe/mirai/message/data/FileMessage; public static final synthetic fun Image (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image; + public static final synthetic fun UnsupportedMessage ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; public static final synthetic fun at (Lnet/mamoe/mirai/contact/Member;)Lnet/mamoe/mirai/message/data/At; public static final fun buildMessageChain (ILkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/message/data/MessageChain; public static final fun buildMessageChain (Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/message/data/MessageChain; @@ -5258,6 +5260,28 @@ public final class net/mamoe/mirai/message/data/SingleMessage$Serializer : kotli public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/SingleMessage;)V } +public abstract interface class net/mamoe/mirai/message/data/UnsupportedMessage : net/mamoe/mirai/message/data/MessageContent { + public static final field Companion Lnet/mamoe/mirai/message/data/UnsupportedMessage$Companion; + public static final field SERIAL_NAME Ljava/lang/String; + public fun contentToString ()Ljava/lang/String; + public static fun create ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; + public abstract fun getStruct ()[B +} + +public final class net/mamoe/mirai/message/data/UnsupportedMessage$Companion { + public static final field SERIAL_NAME Ljava/lang/String; + public final fun create ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; +} + +public final class net/mamoe/mirai/message/data/UnsupportedMessage$Serializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/data/UnsupportedMessage$Serializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/data/UnsupportedMessage; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/UnsupportedMessage;)V +} + public final class net/mamoe/mirai/message/data/VipFace : net/mamoe/mirai/message/code/CodableMessage, net/mamoe/mirai/message/data/HummerMessage { public static final field AiXin Lnet/mamoe/mirai/message/data/VipFace$Kind; public static final field BianBian Lnet/mamoe/mirai/message/data/VipFace$Kind; diff --git a/mirai-core-api/src/commonMain/kotlin/IMirai.kt b/mirai-core-api/src/commonMain/kotlin/IMirai.kt index 3441ee804..6ddefce12 100644 --- a/mirai-core-api/src/commonMain/kotlin/IMirai.kt +++ b/mirai-core-api/src/commonMain/kotlin/IMirai.kt @@ -145,6 +145,12 @@ public interface IMirai : LowLevelApiAccessor { */ public fun createFileMessage(id: String, internalId: Int, name: String, size: Long): FileMessage + /** + * 创建 [UnsupportedMessage] + * @since 2.6 + */ + public fun createUnsupportedMessage(struct: ByteArray): UnsupportedMessage + /** * 获取图片下载链接 * diff --git a/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt b/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt index e7a99ed28..53aaddd38 100644 --- a/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt +++ b/mirai-core-api/src/commonMain/kotlin/internal/message/MessageSerializersImpl.kt @@ -130,6 +130,7 @@ private val builtInSerializersModule by lazy { subclass(MusicShare::class, MusicShare.serializer()) subclass(Dice::class, Dice.serializer()) + subclass(UnsupportedMessage::class, UnsupportedMessage.Serializer) } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt new file mode 100644 index 000000000..69e3bb606 --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2019-2021 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + + +@file:Suppress("NOTHING_TO_INLINE") +@file:JvmMultifileClass +@file:JvmName("MessageUtils") + +package net.mamoe.mirai.message.data + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import net.mamoe.mirai.IMirai +import net.mamoe.mirai.Mirai +import net.mamoe.mirai.internal.message.map +import net.mamoe.mirai.utils.chunkedHexToBytes +import net.mamoe.mirai.utils.copy +import net.mamoe.mirai.utils.toUHexString + +/** + * mirai 尚未支持的消息类型. + * + * [UnsupportedMessage] 可以发送, 接收, 或序列化保存 + * @since 2.6 + */ +@SerialName(UnsupportedMessage.SERIAL_NAME) +@Serializable(UnsupportedMessage.Serializer::class) +public interface UnsupportedMessage : MessageContent { + override fun contentToString(): String = "[不支持的消息#${struct.contentHashCode()}]" // to produce 'stable' and reliable text + + /** + * 原生消息数据 + */ + public val struct: ByteArray + + public companion object { + public const val SERIAL_NAME: String = "UnsupportedMessage" + + /** + * 创建 [UnsupportedMessage] + * @see IMirai.createUnsupportedMessage + */ + @JvmStatic + public fun create(struct: ByteArray): UnsupportedMessage = Mirai.createUnsupportedMessage(struct) + } + + public object Serializer : KSerializer by Surrogate.serializer().map( + resultantDescriptor = Surrogate.serializer().descriptor.copy(SERIAL_NAME), + deserialize = { Mirai.createUnsupportedMessage(struct.chunkedHexToBytes()) }, + serialize = { Surrogate(struct.toUHexString("")) } + ) { + @Suppress("RemoveRedundantQualifierName") + @Serializable + @SerialName(UnsupportedMessage.SERIAL_NAME) + private class Surrogate( + val struct: String // hex + ) + } +} + +/** + * 创建 [UnsupportedMessage] + * @since 2.6 + * @see UnsupportedMessage.create + */ +@JvmSynthetic +public inline fun UnsupportedMessage(struct: ByteArray): UnsupportedMessage = UnsupportedMessage.create(struct) \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt index 2b3ffca77..256b0a2cd 100644 --- a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt +++ b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt @@ -30,6 +30,7 @@ import net.mamoe.mirai.internal.contact.info.MemberInfoImpl import net.mamoe.mirai.internal.message.* import net.mamoe.mirai.internal.network.highway.* import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo +import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.LongMsg import net.mamoe.mirai.internal.network.protocol.data.proto.MsgTransmit import net.mamoe.mirai.internal.network.protocol.packet.chat.* @@ -109,6 +110,10 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor { OfflineMessageSourceImplData::class, OfflineMessageSourceImplData.serializer() ) + MessageSerializers.registerSerializer( + UnsupportedMessageImpl::class, + UnsupportedMessageImpl.serializer() + ) } } @@ -903,6 +908,9 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor { return FileMessageImpl(id, internalId, name, size) } + override fun createUnsupportedMessage(struct: ByteArray): UnsupportedMessage = + UnsupportedMessageImpl(struct.loadAs(ImMsgBody.Elem.serializer())) + @Suppress("DEPRECATION", "OverridingDeprecatedMember") override suspend fun queryImageUrl(bot: Bot, image: Image): String = when (image) { is ConstOriginUrlAware -> image.originUrl diff --git a/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt b/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt index f789d8085..cb8ef2b53 100644 --- a/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt +++ b/mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt @@ -154,6 +154,7 @@ private object ReceiveMessageTransformer { // ignore } else -> { + builder.add(UnsupportedMessageImpl(element)) // println(it._miraiContentToString()) } } diff --git a/mirai-core/src/commonMain/kotlin/message/UnsupportedMessageImpl.kt b/mirai-core/src/commonMain/kotlin/message/UnsupportedMessageImpl.kt new file mode 100644 index 000000000..db8d03dbe --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/message/UnsupportedMessageImpl.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2019-2021 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + + +package net.mamoe.mirai.internal.message + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody +import net.mamoe.mirai.internal.utils.io.serialization.toByteArray +import net.mamoe.mirai.message.data.UnsupportedMessage +import net.mamoe.mirai.message.data.content +import net.mamoe.mirai.utils.copy + +@SerialName(UnsupportedMessage.SERIAL_NAME) +@Serializable(UnsupportedMessageImpl.Serializer::class) +internal data class UnsupportedMessageImpl( + val structElem: ImMsgBody.Elem +) : UnsupportedMessage { + override val struct: ByteArray by lazy { structElem.toByteArray(ImMsgBody.Elem.serializer()) } + override fun toString(): String = content + override fun hashCode(): Int { + return struct.contentHashCode() + } + + override fun equals(other: Any?): Boolean { + if (other === this) return true + if (other !is UnsupportedMessageImpl) return false + if (other.structElem == this.structElem) return true + return other.struct.contentEquals(this.struct) + } + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor = + UnsupportedMessage.Serializer.descriptor.copy(UnsupportedMessage.SERIAL_NAME) + + override fun deserialize(decoder: Decoder): UnsupportedMessageImpl = + UnsupportedMessage.Serializer.deserialize(decoder) as UnsupportedMessageImpl + + override fun serialize(encoder: Encoder, value: UnsupportedMessageImpl) = + UnsupportedMessage.Serializer.serialize(encoder, value) + } +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/message/messageToElems.kt b/mirai-core/src/commonMain/kotlin/message/messageToElems.kt index 15f02fb81..006b4e807 100644 --- a/mirai-core/src/commonMain/kotlin/message/messageToElems.kt +++ b/mirai-core/src/commonMain/kotlin/message/messageToElems.kt @@ -239,6 +239,7 @@ internal fun MessageChain.toRichTextElems( is InternalFlagOnlyMessage, is ShowImageFlag -> { // ignore } + is UnsupportedMessageImpl -> elements.add(currentMessage.structElem) else -> { // unrecognized types are ignored // error("unsupported message type: ${currentMessage::class.simpleName}") diff --git a/mirai-core/src/jvmTest/kotlin/message/data/MessageSerializationTest.kt b/mirai-core/src/jvmTest/kotlin/message/data/MessageSerializationTest.kt index 2191de289..d2b2d54f7 100644 --- a/mirai-core/src/jvmTest/kotlin/message/data/MessageSerializationTest.kt +++ b/mirai-core/src/jvmTest/kotlin/message/data/MessageSerializationTest.kt @@ -19,6 +19,7 @@ import kotlinx.serialization.serializer import net.mamoe.mirai.Mirai import net.mamoe.mirai.internal.message.FileMessageImpl import net.mamoe.mirai.internal.message.MarketFaceImpl +import net.mamoe.mirai.internal.message.UnsupportedMessageImpl import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.message.MessageSerializers import net.mamoe.mirai.message.data.* @@ -75,6 +76,7 @@ internal class MessageSerializationTest { AtAll, image, Face(Face.AI_NI), + UnsupportedMessageImpl(ImMsgBody.Elem()) ) private val emptySource = Mirai.constructMessageSource(