From ed289ed81d631f044e01725bf769f2226c5c9570 Mon Sep 17 00:00:00 2001 From: sandtechnology <20417547+sandtechnology@users.noreply.github.com> Date: Fri, 25 Dec 2020 21:32:31 +0800 Subject: [PATCH] Support MarketFace (#761) * Support MarketFace * Change HummerMessage to interface * Let MarketFace implement HummerMessage * Move MessageKey implementation to MarketFace * Chang baseKey to HummerMessage --- .../kotlin/message/MessageSerializer.kt | 2 -- .../kotlin/message/data/HummerMessage.kt | 33 ++++++++++++++++--- mirai-core/src/commonMain/kotlin/MiraiImpl.kt | 1 + .../commonMain/kotlin/message/conversions.kt | 17 ++++++++-- .../src/commonMain/kotlin/message/faceImpl.kt | 14 ++++++++ .../kotlin/network/protocol/data/proto/Msg.kt | 2 +- 6 files changed, 58 insertions(+), 11 deletions(-) diff --git a/mirai-core-api/src/commonMain/kotlin/message/MessageSerializer.kt b/mirai-core-api/src/commonMain/kotlin/message/MessageSerializer.kt index 59fd525c5..2204f5678 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/MessageSerializer.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/MessageSerializer.kt @@ -112,8 +112,6 @@ private val builtInSerializersModule by lazy { contextual(PttMessage::class, PttMessage.serializer()) contextual(Voice::class, Voice.serializer()) - - contextual(HummerMessage::class, HummerMessage.serializer()) contextual(PokeMessage::class, PokeMessage.serializer()) contextual(VipFace::class, VipFace.serializer()) contextual(FlashImage::class, FlashImage.serializer()) diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt index 305d6aed5..ab372b67c 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt @@ -28,8 +28,7 @@ import net.mamoe.mirai.utils.safeCast * @see PokeMessage 戳一戳 * @see FlashImage 闪照 */ -@Serializable -public sealed class HummerMessage : MessageContent, ConstrainSingle { +public interface HummerMessage : MessageContent, ConstrainSingle { public companion object Key : AbstractPolymorphicMessageKey(MessageContent, { it.castOrNull() }) // has service type etc. @@ -56,7 +55,7 @@ public data class PokeMessage @MiraiInternalApi constructor( public val pokeType: Int, // 'type' is used by serialization public val id: Int -) : HummerMessage(), CodableMessage { +) : HummerMessage, CodableMessage { @ExperimentalMessageKey override val key: MessageKey get() = Key @@ -180,6 +179,30 @@ public data class PokeMessage @MiraiInternalApi constructor( //pbElem=08 01 18 00 20 FF FF FF FF 0F 2A 00 32 00 38 00 50 00 //serviceType=0x00000002(2) } +//////////////////////////////////// +////////// MARKET FACE ///////////// +//////////////////////////////////// +/** + * 商城表情 + * + * 目前不支持直接发送,可支持转发,但其取决于表情是否可使用. + * + * ## mirai 码支持 + * 格式: [mirai:marketface:*[id]*,*[name]*] + */ +public interface MarketFace : CodableMessage, HummerMessage { + public val name: String + public val id: Int + + @ExperimentalMessageKey + override val key: MessageKey + get() = Key + + public companion object Key : + AbstractPolymorphicMessageKey(HummerMessage, { it.safeCast() }) + + override fun contentToString(): String = name +} //////////////////////////////////// @@ -203,7 +226,7 @@ public data class VipFace @MiraiInternalApi constructor( */ public val kind: Kind, public val count: Int -) : HummerMessage(), CodableMessage { +) : HummerMessage, CodableMessage { @Serializable public data class Kind( val id: Int, @@ -297,7 +320,7 @@ public data class FlashImage( */ @Contextual public val image: Image -) : MessageContent, HummerMessage(), CodableMessage, ConstrainSingle { +) : MessageContent, HummerMessage, CodableMessage, ConstrainSingle { @ExperimentalMessageKey override val key: MessageKey get() = Key diff --git a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt index f4e61007d..bbeb8c2ea 100644 --- a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt +++ b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt @@ -55,6 +55,7 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor { private val _init = Mirai.let { Message.Serializer.registerSerializer(OfflineGroupImage::class, OfflineGroupImage.serializer()) Message.Serializer.registerSerializer(OfflineFriendImage::class, OfflineFriendImage.serializer()) + Message.Serializer.registerSerializer(MarketFaceImpl::class, MarketFaceImpl.serializer()) } } diff --git a/mirai-core/src/commonMain/kotlin/message/conversions.kt b/mirai-core/src/commonMain/kotlin/message/conversions.kt index 3d894bc0c..7d6440171 100644 --- a/mirai-core/src/commonMain/kotlin/message/conversions.kt +++ b/mirai-core/src/commonMain/kotlin/message/conversions.kt @@ -21,10 +21,8 @@ import net.mamoe.mirai.LowLevelApi import net.mamoe.mirai.contact.AnonymousMember import net.mamoe.mirai.contact.ContactOrBot import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.internal.network.protocol.data.proto.HummerCommelem +import net.mamoe.mirai.internal.network.protocol.data.proto.* import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody -import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm -import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush import net.mamoe.mirai.internal.utils.* import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.toByteArray @@ -170,6 +168,10 @@ internal fun MessageChain.toRichTextElems( } } } + //MarketFaceImpl继承于MarketFace 会自动添加兼容信息 + //如果有用户不慎/强行使用也会转换为文本信息 + is MarketFaceImpl -> elements.add(ImMsgBody.Elem(marketFace = it.delegate)) + is MarketFace -> transformOneMessage(PlainText(it.contentToString())) is VipFace -> transformOneMessage(PlainText(it.contentToString())) is PttMessage -> { elements.add( @@ -332,6 +334,12 @@ private fun MessageChain.cleanupRubbishMessageElements(): MessageChain { return@forEach } } + if (last is MarketFaceImpl && element is PlainText) { + if (element.content == (last as MarketFaceImpl).name) { + last = element + return@forEach + } + } if (last is PokeMessage && element is PlainText) { if (element == UNSUPPORTED_POKE_MESSAGE_PLAIN) { last = element @@ -406,6 +414,9 @@ internal fun List.joinToMessageChain(groupIdOrZero: Long, botId: } } } + element.marketFace != null -> { + list.add(MarketFaceImpl(element.marketFace)) + } element.lightApp != null -> { val content = runWithBugReport("解析 lightApp", { "resId=" + element.lightApp.msgResid + "data=" + element.lightApp.data.toUHexString() }) { diff --git a/mirai-core/src/commonMain/kotlin/message/faceImpl.kt b/mirai-core/src/commonMain/kotlin/message/faceImpl.kt index b65ae75c5..c5e85b646 100644 --- a/mirai-core/src/commonMain/kotlin/message/faceImpl.kt +++ b/mirai-core/src/commonMain/kotlin/message/faceImpl.kt @@ -10,12 +10,15 @@ package net.mamoe.mirai.internal.message import kotlinx.io.core.toByteArray +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient import net.mamoe.mirai.internal.network.protocol.data.proto.HummerCommelem import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.utils.hexToBytes import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.internal.utils.toByteArray import net.mamoe.mirai.message.data.Face +import net.mamoe.mirai.message.data.MarketFace internal val FACE_BUF = "00 01 00 04 52 CC F5 D0".hexToBytes() @@ -39,3 +42,14 @@ internal fun Face.toCommData(): ImMsgBody.CommonElem { ) } + +@Serializable +internal data class MarketFaceImpl internal constructor( + internal val delegate: ImMsgBody.MarketFace, +) : MarketFace { + @Transient + override val name: String = delegate.faceName.decodeToString() + @Transient + override val id: Int = delegate.tabId + override fun toString() = "[mirai:marketface:$id,$name]" +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Msg.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Msg.kt index 2e2c19df5..791138cac 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Msg.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/Msg.kt @@ -575,7 +575,7 @@ internal class ImMsgBody : ProtoBuf { @ProtoNumber(9) @JvmField val mediaType: Int = 0, @ProtoNumber(10) @JvmField val imageWidth: Int = 0, @ProtoNumber(11) @JvmField val imageHeight: Int = 0, - @ProtoNumber(12) @JvmField val mobileparam: ByteArray = EMPTY_BYTE_ARRAY, + @ProtoNumber(12) @JvmField val mobileParam: ByteArray = EMPTY_BYTE_ARRAY, @ProtoNumber(13) @JvmField val pbReserve: ByteArray = EMPTY_BYTE_ARRAY ) : ProtoBuf