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 c7ef6976f..9691f9abc 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -4357,6 +4357,7 @@ public abstract interface class net/mamoe/mirai/message/data/Image : net/mamoe/m public abstract fun getImageType ()Lnet/mamoe/mirai/message/data/ImageType; public abstract fun getSize ()J public abstract fun getWidth ()I + public fun isEmoji ()Z public static fun queryUrl (Lnet/mamoe/mirai/message/data/Image;)Ljava/lang/String; public static fun queryUrl (Lnet/mamoe/mirai/message/data/Image;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index 2b511354d..ec677c124 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -4357,6 +4357,7 @@ public abstract interface class net/mamoe/mirai/message/data/Image : net/mamoe/m public abstract fun getImageType ()Lnet/mamoe/mirai/message/data/ImageType; public abstract fun getSize ()J public abstract fun getWidth ()I + public fun isEmoji ()Z public static fun queryUrl (Lnet/mamoe/mirai/message/data/Image;)Ljava/lang/String; public static fun queryUrl (Lnet/mamoe/mirai/message/data/Image;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt index 359e68416..11625e3e2 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt @@ -107,6 +107,13 @@ public interface Image : Message, MessageContent, CodableMessage { */ public val imageType: ImageType + /** + * 判断该图片是否为 `动画表情` + * + * @since 2.8.0 + */ + public val isEmoji: Boolean get() = false + public object AsStringSerializer : KSerializer by String.serializer().mapPrimitive( SERIAL_NAME, serialize = { imageId }, @@ -166,9 +173,8 @@ public interface Image : Message, MessageContent, CodableMessage { @Suppress("RegExpRedundantEscape") // This is required on Android @JvmStatic @get:JvmName("getImageIdRegex") - // inline because compilation error - public inline val IMAGE_ID_REGEX: Regex - get() = Regex("""\{[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\}\..{3,5}""") + public val IMAGE_ID_REGEX: Regex = + Regex("""\{[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\}\..{3,5}""") /** * 图片资源 ID 正则表达式 1. mirai 内部使用. @@ -179,9 +185,8 @@ public interface Image : Message, MessageContent, CodableMessage { @JvmStatic @MiraiInternalApi @get:JvmName("getImageResourceIdRegex1") - // inline because compilation error - public inline val IMAGE_RESOURCE_ID_REGEX_1: Regex - get() = Regex("""/[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}""") + public val IMAGE_RESOURCE_ID_REGEX_1: Regex = + Regex("""/[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}""") /** * 图片资源 ID 正则表达式 2. mirai 内部使用. @@ -192,9 +197,8 @@ public interface Image : Message, MessageContent, CodableMessage { @JvmStatic @MiraiInternalApi @get:JvmName("getImageResourceIdRegex2") - // inline because compilation error - public inline val IMAGE_RESOURCE_ID_REGEX_2: Regex - get() = Regex("""/[0-9]*-[0-9]*-[0-9a-fA-F]{32}""") + public val IMAGE_RESOURCE_ID_REGEX_2: Regex = + Regex("""/[0-9]*-[0-9]*-[0-9a-fA-F]{32}""") } } @@ -266,7 +270,12 @@ public sealed class AbstractImage : Image { get() = ImageType.UNKNOWN final override fun toString(): String = _stringValue!! - final override fun contentToString(): String = "[图片]" + final override fun contentToString(): String = if (isEmoji) { + "[动画表情]" + } else { + "[图片]" + } + override fun appendMiraiCodeTo(builder: StringBuilder) { builder.append("[mirai:image:").append(imageId).append("]") } diff --git a/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt b/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt index 9a6e6322e..49a327e1d 100644 --- a/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt +++ b/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt @@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.message +import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import net.mamoe.mirai.Bot import net.mamoe.mirai.IMirai @@ -19,9 +20,9 @@ import net.mamoe.mirai.contact.Contact.Companion.uploadImage import net.mamoe.mirai.contact.ContactOrBot import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.User -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.network.protocol.data.proto.* import net.mamoe.mirai.internal.utils._miraiContentToString +import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.Image.Key.IMAGE_ID_REGEX @@ -63,6 +64,18 @@ internal class OnlineGroupImageImpl( }/0?term=2" } else "http://gchat.qpic.cn" + delegate.origUrl + override val isEmoji: Boolean by lazy { + delegate.pbReserve.pbImageResv_checkIsEmoji(CustomFaceExtPb.ResvAttr.serializer()) + } +} + +private fun ByteArray.pbImageResv_checkIsEmoji(serializer: KSerializer): Boolean { + val data = this + return kotlin.runCatching { + data.takeIf { it.isNotEmpty() }?.loadAs(serializer)?.let { ext -> + ext.imageBizType == 1 || ext.textSummary.encodeToString() == "[动画表情]" + } + }.getOrNull() ?: false } private val imageLogger: MiraiLogger by lazy { MiraiLogger.Factory.create(Image::class) } @@ -108,6 +121,9 @@ OnlineFriendImage() { "http://c2cpicdw.qpic.cn/offpic_new/0/" + delegate.resId + "/0?term=2" } + override val isEmoji: Boolean by lazy { + delegate.pbReserve.pbImageResv_checkIsEmoji(NotOnlineImageExtPb.ResvAttr.serializer()) + } } /* diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv3.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv3.kt index 2074bf118..23efb4c8b 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv3.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv3.kt @@ -29,14 +29,14 @@ internal class CustomFaceExtPb : ProtoBuf { @Serializable internal class ResvAttr( - @JvmField @ProtoNumber(1) val imageBizType: Int = 0, + @ProtoNumber(1) override val imageBizType: Int = 0, @JvmField @ProtoNumber(2) val customfaceType: Int = 0, @JvmField @ProtoNumber(3) val emojiPackageid: Int = 0, @JvmField @ProtoNumber(4) val emojiId: Int = 0, @JvmField @ProtoNumber(5) val text: String = "", @JvmField @ProtoNumber(6) val doutuSuppliers: String = "", @JvmField @ProtoNumber(7) val msgImageShow: AnimationImageShow? = null, - @JvmField @ProtoNumber(9) val textSummary: ByteArray = EMPTY_BYTE_ARRAY, + @ProtoNumber(9) override val textSummary: ByteArray = EMPTY_BYTE_ARRAY, @JvmField @ProtoNumber(10) val emojiFrom: Int = 0, @JvmField @ProtoNumber(11) val emojiSource: String = "", @JvmField @ProtoNumber(12) val emojiWebUrl: String = "", @@ -47,6 +47,6 @@ internal class CustomFaceExtPb : ProtoBuf { @JvmField @ProtoNumber(17) val cameraCaptureMaterialname: String = "", @JvmField @ProtoNumber(18) val adEmoJumpUrl: String = "", @JvmField @ProtoNumber(19) val adEmoDescStr: String = "", - ) : ProtoBuf + ) : ProtoBuf, ImgExtPbResvAttrCommon } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv6.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv6.kt new file mode 100644 index 000000000..fa4403da7 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/HummerResv6.kt @@ -0,0 +1,37 @@ +/* + * 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("unused", "SpellCheckingInspection") + +package net.mamoe.mirai.internal.network.protocol.data.proto + +import kotlinx.serialization.Serializable +import kotlinx.serialization.protobuf.ProtoNumber +import net.mamoe.mirai.internal.utils.io.ProtoBuf +import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY + +@Serializable +internal class NotOnlineImageExtPb : ProtoBuf { + @Serializable + internal class ResvAttr( + @ProtoNumber(1) override val imageBizType: Int = 0, + @JvmField @ProtoNumber(2) val customfaceType: Int = 0, + @JvmField @ProtoNumber(3) val emojiPackageid: Int = 0, + @JvmField @ProtoNumber(4) val emojiId: Int = 0, + @JvmField @ProtoNumber(5) val text: String = "", + @JvmField @ProtoNumber(6) val doutuSuppliers: String = "", + @ProtoNumber(8) override val textSummary: ByteArray = EMPTY_BYTE_ARRAY, + @JvmField @ProtoNumber(10) val emojiFrom: Int = 0, + @JvmField @ProtoNumber(11) val emojiSource: String = "", + @JvmField @ProtoNumber(12) val emojiWebUrl: String = "", + @JvmField @ProtoNumber(13) val emojiIconUrl: String = "", + @JvmField @ProtoNumber(14) val emojiMarketFaceName: String = "", + @JvmField @ProtoNumber(15) val source: Int = 0 + ) : ProtoBuf, ImgExtPbResvAttrCommon +} + \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/ImgExtPbResvAttrCommon.kt b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/ImgExtPbResvAttrCommon.kt new file mode 100644 index 000000000..651977674 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/protocol/data/proto/ImgExtPbResvAttrCommon.kt @@ -0,0 +1,17 @@ +/* + * 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/dev/LICENSE + */ + +package net.mamoe.mirai.internal.network.protocol.data.proto + +import net.mamoe.mirai.internal.utils.io.ProtoBuf + +internal interface ImgExtPbResvAttrCommon: ProtoBuf { + val textSummary: ByteArray + val imageBizType: Int +} \ No newline at end of file