Support MarketFace (#761)

* Support MarketFace

* Change HummerMessage to interface

* Let MarketFace implement HummerMessage

* Move MessageKey implementation to MarketFace

* Chang baseKey to HummerMessage
This commit is contained in:
sandtechnology 2020-12-25 21:32:31 +08:00 committed by GitHub
parent 39db2c8533
commit ed289ed81d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 11 deletions

View File

@ -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())

View File

@ -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, HummerMessage>(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<HummerMessage>
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 码支持
* 格式: &#91;mirai:marketface:*[id]*,*[name]*&#93;
*/
public interface MarketFace : CodableMessage, HummerMessage {
public val name: String
public val id: Int
@ExperimentalMessageKey
override val key: MessageKey<MarketFace>
get() = Key
public companion object Key :
AbstractPolymorphicMessageKey<HummerMessage, MarketFace>(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<FlashImage>
get() = Key

View File

@ -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())
}
}

View File

@ -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<ImMsgBody.Elem>.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() }) {

View File

@ -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]"
}

View File

@ -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