From 7c550bff7dcfb8b4981fd57d4d1b009899d6af36 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 20 Nov 2021 23:36:14 +0000 Subject: [PATCH] =?UTF-8?q?Add=20`Image.Factory`=20and=20`Image.Builder`?= =?UTF-8?q?=20for=20constructing=20`Image`=20inst=E2=80=A6=20(#1673)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add `Image.Factory` and `Image.Builder` for constructing `Image` instances with specific properties. close #1672 * Remove redundant `create`s * Add docs for `Image.Builder` * Remove Image.Factory, use Image.Builder in all places. * Fix cache & parameters Co-authored-by: Karlatemp --- ...binary-compatibility-validator-android.api | 29 ++++- .../api/binary-compatibility-validator.api | 29 ++++- .../src/commonMain/kotlin/IMirai.kt | 5 +- .../commonMain/kotlin/message/data/Image.kt | 117 ++++++++++++++++-- mirai-core/src/commonMain/kotlin/MiraiImpl.kt | 27 ---- .../message/InternalImageProtocolImpl.kt | 44 +++++++ .../commonMain/kotlin/message/imagesImpl.kt | 6 +- .../kotlin/message/ImageBuilderTest.kt | 107 ++++++++++++++++ 8 files changed, 322 insertions(+), 42 deletions(-) create mode 100644 mirai-core/src/commonTest/kotlin/message/ImageBuilderTest.kt 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 1518f082d..87d18698f 100644 --- a/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api +++ b/binary-compatibility-validator/android/api/binary-compatibility-validator-android.api @@ -86,7 +86,7 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve public fun calculateGroupUinByGroupCode (J)J 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 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; @@ -4453,6 +4453,7 @@ public abstract interface class net/mamoe/mirai/message/data/Image : net/mamoe/m public static fun isUploaded (Lnet/mamoe/mirai/Bot;[BJLkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;)Z public static fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; 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; } @@ -4466,6 +4467,29 @@ public final class net/mamoe/mirai/message/data/Image$AsStringSerializer : kotli public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/Image;)V } +public final class net/mamoe/mirai/message/data/Image$Builder { + public static final field Companion Lnet/mamoe/mirai/message/data/Image$Builder$Companion; + public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lnet/mamoe/mirai/message/data/Image; + public final fun getHeight ()I + public final fun getImageId ()Ljava/lang/String; + public final fun getSize ()J + public final fun getType ()Lnet/mamoe/mirai/message/data/ImageType; + public final fun getWidth ()I + public final fun isEmoji ()Z + public static final fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; + public final fun setEmoji (Z)V + public final fun setHeight (I)V + public final fun setImageId (Ljava/lang/String;)V + public final fun setSize (J)V + public final fun setType (Lnet/mamoe/mirai/message/data/ImageType;)V + public final fun setWidth (I)V +} + +public final class net/mamoe/mirai/message/data/Image$Builder$Companion { + public final fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; +} + public final class net/mamoe/mirai/message/data/Image$Key : net/mamoe/mirai/message/data/AbstractMessageKey { public static final field SERIAL_NAME Ljava/lang/String; public final fun calculateImageMd5ByImageId (Ljava/lang/String;)[B @@ -4477,6 +4501,7 @@ public final class net/mamoe/mirai/message/data/Image$Key : net/mamoe/mirai/mess public final fun isUploaded (Lnet/mamoe/mirai/Bot;[BJLkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;)Z public final fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; public final fun queryUrl (Lnet/mamoe/mirai/message/data/Image;)Ljava/lang/String; public final fun queryUrl (Lnet/mamoe/mirai/message/data/Image;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -4856,6 +4881,8 @@ 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 Image (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/message/data/Image; + public static synthetic fun Image$default (Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/message/data/Image; public static final synthetic fun OfflineAudio (Ljava/lang/String;[BJLnet/mamoe/mirai/message/data/AudioCodec;[B)Lnet/mamoe/mirai/message/data/OfflineAudio; public static final synthetic fun OfflineAudio (Lnet/mamoe/mirai/message/data/OnlineAudio;)Lnet/mamoe/mirai/message/data/OfflineAudio; public static final synthetic fun UnsupportedMessage ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; diff --git a/binary-compatibility-validator/api/binary-compatibility-validator.api b/binary-compatibility-validator/api/binary-compatibility-validator.api index ed909966c..3ff2b51dd 100644 --- a/binary-compatibility-validator/api/binary-compatibility-validator.api +++ b/binary-compatibility-validator/api/binary-compatibility-validator.api @@ -86,7 +86,7 @@ public abstract interface class net/mamoe/mirai/IMirai : net/mamoe/mirai/LowLeve public fun calculateGroupUinByGroupCode (J)J 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 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; @@ -4453,6 +4453,7 @@ public abstract interface class net/mamoe/mirai/message/data/Image : net/mamoe/m public static fun isUploaded (Lnet/mamoe/mirai/Bot;[BJLkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;)Z public static fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; 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; } @@ -4466,6 +4467,29 @@ public final class net/mamoe/mirai/message/data/Image$AsStringSerializer : kotli public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/Image;)V } +public final class net/mamoe/mirai/message/data/Image$Builder { + public static final field Companion Lnet/mamoe/mirai/message/data/Image$Builder$Companion; + public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun build ()Lnet/mamoe/mirai/message/data/Image; + public final fun getHeight ()I + public final fun getImageId ()Ljava/lang/String; + public final fun getSize ()J + public final fun getType ()Lnet/mamoe/mirai/message/data/ImageType; + public final fun getWidth ()I + public final fun isEmoji ()Z + public static final fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; + public final fun setEmoji (Z)V + public final fun setHeight (I)V + public final fun setImageId (Ljava/lang/String;)V + public final fun setSize (J)V + public final fun setType (Lnet/mamoe/mirai/message/data/ImageType;)V + public final fun setWidth (I)V +} + +public final class net/mamoe/mirai/message/data/Image$Builder$Companion { + public final fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; +} + public final class net/mamoe/mirai/message/data/Image$Key : net/mamoe/mirai/message/data/AbstractMessageKey { public static final field SERIAL_NAME Ljava/lang/String; public final fun calculateImageMd5ByImageId (Ljava/lang/String;)[B @@ -4477,6 +4501,7 @@ public final class net/mamoe/mirai/message/data/Image$Key : net/mamoe/mirai/mess public final fun isUploaded (Lnet/mamoe/mirai/Bot;[BJLkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;)Z public final fun isUploaded (Lnet/mamoe/mirai/message/data/Image;Lnet/mamoe/mirai/Bot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun newBuilder (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/Image$Builder; public final fun queryUrl (Lnet/mamoe/mirai/message/data/Image;)Ljava/lang/String; public final fun queryUrl (Lnet/mamoe/mirai/message/data/Image;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -4856,6 +4881,8 @@ 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 Image (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lnet/mamoe/mirai/message/data/Image; + public static synthetic fun Image$default (Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lnet/mamoe/mirai/message/data/Image; public static final synthetic fun OfflineAudio (Ljava/lang/String;[BJLnet/mamoe/mirai/message/data/AudioCodec;[B)Lnet/mamoe/mirai/message/data/OfflineAudio; public static final synthetic fun OfflineAudio (Lnet/mamoe/mirai/message/data/OnlineAudio;)Lnet/mamoe/mirai/message/data/OfflineAudio; public static final synthetic fun UnsupportedMessage ([B)Lnet/mamoe/mirai/message/data/UnsupportedMessage; diff --git a/mirai-core-api/src/commonMain/kotlin/IMirai.kt b/mirai-core-api/src/commonMain/kotlin/IMirai.kt index d3dcdcf88..a8b283f6d 100644 --- a/mirai-core-api/src/commonMain/kotlin/IMirai.kt +++ b/mirai-core-api/src/commonMain/kotlin/IMirai.kt @@ -180,12 +180,13 @@ public interface IMirai : LowLevelApiAccessor { public suspend fun sendNudge(bot: Bot, nudge: Nudge, receiver: Contact): Boolean /** - * 构造 [Image] + * 构造 [Image]. 请优先使用 [Image.Factory.create]. * * @see Image * @see Image.fromId + * @see Image.Factory.create */ - public fun createImage(imageId: String): Image + public fun createImage(imageId: String): Image = Image.Builder.newBuilder(imageId).build() /** * 创建一个 [FileMessage]. [name] 与 [size] 只供本地使用, 发送消息时只会使用 [id] 和 [internalId]. 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 2725ae560..08017cb35 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt @@ -14,7 +14,7 @@ "EXPERIMENTAL_API_USAGE", "unused", "UnusedImport", - "DEPRECATION_ERROR", "NOTHING_TO_INLINE" + "DEPRECATION_ERROR", "NOTHING_TO_INLINE", "MemberVisibilityCanBePrivate" ) package net.mamoe.mirai.message.data @@ -152,20 +152,100 @@ public interface Image : Message, MessageContent, CodableMessage { ) } + + /** + * [Image] 构建器. + * + * 示例: + * + * ```java + * Builder builder = Image.Builder.newBuilder("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.jpg") + * builder.setSize(123); + * builder.setType(ImageType.PNG); + * + * Image image = builder.build(); + * ``` + * + * @since 2.9.0 + */ + public class Builder private constructor( + /** + * @see Image.imageId + */ + public var imageId: String, + ) { + /** + * 图片大小字节数. 如果不提供改属性, 将无法 [Image.Key.isUploaded] + * + * @see Image.size + */ + public var size: Long = 0 + + /** + * @see Image.imageType + */ + public var type: ImageType = ImageType.UNKNOWN + + /** + * @see Image.width + */ + public var width: Int = 0 + + /** + * @see Image.height + */ + public var height: Int = 0 + + /** + * @see Image.isEmoji + */ + public var isEmoji: Boolean = false + + /** + * 使用当前参数构造 [Image]. + */ + public fun build(): Image = InternalImageProtocol.instance.createImage( + imageId = imageId, + size = size, + type = type, + width = width, + height = height, + isEmoji = isEmoji, + ) + + public companion object { + /** + * 创建一个 [Builder] + */ + @JvmStatic + public fun newBuilder(imageId: String): Builder = Builder(imageId) + } + } + @JvmBlockingBridge public companion object Key : AbstractMessageKey({ it.safeCast() }) { public const val SERIAL_NAME: String = "Image" /** - * 通过 [Image.imageId] 构造一个 [Image] 以便发送. 这个图片必须是服务器已经存在的图片. - * 图片 id 不一定会长时间保存, 因此不建议使用 id 发送图片. + * 通过 [Image.imageId] 构造一个 [Image] 以便发送. + * + * 图片 ID 不一定会长时间保存, 因此不建议使用 ID 发送图片. 建议使用 [Builder], 可以指定更多参数 (以及用于查询图片是否存在于服务器的必要参数 size). * * @see Image 获取更多说明 * @see Image.imageId 获取更多说明 + * @see Builder */ @JvmStatic public fun fromId(imageId: String): Image = Mirai.createImage(imageId) + /** + * 构造一个 [Image.Builder] 实例. + * + * @since 2.9.0 + */ + @JvmStatic + public fun newBuilder(imageId: String): Builder = Builder.newBuilder(imageId) + /** * 查询原图下载链接. * @@ -265,16 +345,27 @@ public interface Image : Message, MessageContent, CodableMessage { } /** - * 通过 [Image.imageId] 构造一个 [Image] 以便发送. 这个图片必须是服务器已经存在的图片. - * 图片 id 不一定会长时间保存, 因此不建议使用 id 发送图片. + * 通过 [Image.imageId] 构造一个 [Image] 以便发送. * - * @see Image 获取更多说明 - * @see Image.imageId 获取更多说明 + * 图片 ID 不一定会长时间保存, 因此不建议使用 ID 发送图片. 建议使用 [Image.Builder], 可以指定更多参数 (以及用于查询图片是否存在于服务器的必要参数 size). + * + * @see Image 获取更多关于 [Image] 的说明 + * @see Image.Builder 获取更多关于构造 [Image] 的方法 * * @see IMirai.createImage */ @JvmSynthetic -public inline fun Image(imageId: String): Image = Image.fromId(imageId) +public inline fun Image(imageId: String): Image = Image.Builder.newBuilder(imageId).build() + +/** + * 使用 [Image.Builder] 构建一个 [Image]. + * + * @see Image.Builder + * @since 2.9.0 + */ +@JvmSynthetic +public inline fun Image(imageId: String, builderAction: Image.Builder.() -> Unit = {}): Image = + Image.Builder.newBuilder(imageId).apply(builderAction).build() public enum class ImageType( /** @@ -286,7 +377,6 @@ public enum class ImageType( BMP("bmp"), JPG("jpg"), GIF("gif"), - //WEBP, //Unsupported by pc client APNG("png"), UNKNOWN("gif"); // bad design, should use `null` to represent unknown, but we cannot change it anymore. @@ -387,6 +477,15 @@ public abstract class GroupImage @MiraiInternalApi public constructor() : */ @MiraiInternalApi public interface InternalImageProtocol { // naming it Internal* to assign it a lower priority when resolving Image* + public fun createImage( + imageId: String, + size: Long, + type: ImageType = ImageType.UNKNOWN, + width: Int = 0, + height: Int = 0, + isEmoji: Boolean = false + ): Image + /** * @param context 用于检查的 [Contact]. 群图片与好友图片是两个通道, 建议使用欲发送到的 [Contact] 对象作为 [contact] 参数, 但目前不提供此参数时也可以检查. */ diff --git a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt index ec3eb5646..a294f923b 100644 --- a/mirai-core/src/commonMain/kotlin/MiraiImpl.kt +++ b/mirai-core/src/commonMain/kotlin/MiraiImpl.kt @@ -64,9 +64,6 @@ import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.message.MessageSerializers import net.mamoe.mirai.message.action.Nudge import net.mamoe.mirai.message.data.* -import net.mamoe.mirai.message.data.Image.Key.IMAGE_ID_REGEX -import net.mamoe.mirai.message.data.Image.Key.IMAGE_RESOURCE_ID_REGEX_1 -import net.mamoe.mirai.message.data.Image.Key.IMAGE_RESOURCE_ID_REGEX_2 import net.mamoe.mirai.utils.* internal fun getMiraiImpl() = Mirai as MiraiImpl @@ -761,30 +758,6 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor { } } - override fun createImage(imageId: String): Image { - return when { - imageId matches IMAGE_ID_REGEX -> { - Bot.instancesSequence.forEach { existsBot -> - runCatching { - val patcher = existsBot.asQQAndroidBot().components[ImagePatcher] - - patcher.findCacheByImageId(imageId)?.let { cache -> - val rsp = cache.cacheOGI.value0 - cache.accessLock.release() - if (rsp != null) return rsp - } - } - } - OfflineGroupImage(imageId) - } - imageId matches IMAGE_RESOURCE_ID_REGEX_1 -> OfflineFriendImage(imageId) - imageId matches IMAGE_RESOURCE_ID_REGEX_2 -> OfflineFriendImage(imageId) - else -> - @Suppress("INVISIBLE_MEMBER") - throw IllegalArgumentException("Illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE") - } - } - override fun createFileMessage(id: String, internalId: Int, name: String, size: Long): FileMessage { return FileMessageImpl(id, internalId, name, size) } diff --git a/mirai-core/src/commonMain/kotlin/message/InternalImageProtocolImpl.kt b/mirai-core/src/commonMain/kotlin/message/InternalImageProtocolImpl.kt index 373e41e49..9ae0acf0d 100644 --- a/mirai-core/src/commonMain/kotlin/message/InternalImageProtocolImpl.kt +++ b/mirai-core/src/commonMain/kotlin/message/InternalImageProtocolImpl.kt @@ -19,6 +19,9 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.Cmd0x352 import net.mamoe.mirai.internal.network.protocol.packet.chat.image.ImgStore import net.mamoe.mirai.internal.network.protocol.packet.chat.image.LongConn import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect +import net.mamoe.mirai.internal.utils.ImagePatcher +import net.mamoe.mirai.internal.utils.ImagePatcher.Companion.withCache +import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.ImageType import net.mamoe.mirai.message.data.InternalImageProtocol import net.mamoe.mirai.utils.cast @@ -138,6 +141,47 @@ internal class InternalImageProtocolImpl : InternalImageProtocol { } } + fun findExistImageByCache(imageId: String): Image? { + Bot.instancesSequence.forEach { existsBot -> + runCatching { + val patcher = existsBot.asQQAndroidBot().components[ImagePatcher] + + patcher.findCacheByImageId(imageId)?.withCache { cache -> + val rsp = cache.cacheOGI.value0 + if (rsp != null) return rsp + } + } + } + return null + } + + override fun createImage( + imageId: String, + size: Long, + type: ImageType, + width: Int, + height: Int, + isEmoji: Boolean + ): Image { + return when { + imageId matches Image.IMAGE_ID_REGEX -> { + if (size == 0L && width == 0 && height == 0) { + findExistImageByCache(imageId)?.let { return it } + } + OfflineGroupImage(imageId, width, height, size, type, isEmoji) + } + imageId matches Image.IMAGE_RESOURCE_ID_REGEX_1 -> { + OfflineFriendImage(imageId, width, height, size, type, isEmoji) + } + imageId matches Image.IMAGE_RESOURCE_ID_REGEX_2 -> { + OfflineFriendImage(imageId, width, height, size, type, isEmoji) + } + else -> + @Suppress("INVISIBLE_MEMBER") + throw IllegalArgumentException("Illegal imageId: $imageId. ${net.mamoe.mirai.message.data.ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE}") + } + } + override suspend fun isUploaded( bot: Bot, md5: ByteArray, diff --git a/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt b/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt index e84beff33..55f161ac2 100644 --- a/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt +++ b/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt @@ -334,7 +334,8 @@ internal data class OfflineGroupImage( override val width: Int = 0, override val height: Int = 0, override val size: Long = 0L, - override val imageType: ImageType = ImageType.UNKNOWN + override val imageType: ImageType = ImageType.UNKNOWN, + override val isEmoji: Boolean = false, ) : GroupImage(), OfflineImage, DeferredOriginUrlAware { @Transient internal var fileId: Int? = null @@ -380,7 +381,8 @@ internal data class OfflineFriendImage( override val width: Int = 0, override val height: Int = 0, override val size: Long = 0L, - override val imageType: ImageType = ImageType.UNKNOWN + override val imageType: ImageType = ImageType.UNKNOWN, + override val isEmoji: Boolean = false, ) : FriendImage(), OfflineImage, DeferredOriginUrlAware { object Serializer : Image.FallbackSerializer("OfflineFriendImage") diff --git a/mirai-core/src/commonTest/kotlin/message/ImageBuilderTest.kt b/mirai-core/src/commonTest/kotlin/message/ImageBuilderTest.kt new file mode 100644 index 000000000..ae799ed3c --- /dev/null +++ b/mirai-core/src/commonTest/kotlin/message/ImageBuilderTest.kt @@ -0,0 +1,107 @@ +/* + * 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 message + +import net.mamoe.mirai.Mirai +import net.mamoe.mirai.message.data.Image +import net.mamoe.mirai.message.data.ImageType +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class ImageBuilderTest { + companion object { + private const val IMAGE_ID = "{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.jpg" + } + + @Test + fun create() { + // five overloads + + Image(IMAGE_ID) { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, type) + assertEquals(false, isEmoji) + } + + Image.newBuilder(IMAGE_ID).run { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, type) + assertEquals(false, isEmoji) + } + + Image.Builder.newBuilder(IMAGE_ID).run { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, type) + assertEquals(false, isEmoji) + } + + Image.Builder.newBuilder(IMAGE_ID).build().run { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, imageType) + assertEquals(false, isEmoji) + } + } + + @Test + fun legacyMethods() { + // just make sure they work + + Mirai.createImage(IMAGE_ID).run { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, imageType) + assertEquals(false, isEmoji) + } + Image.fromId(IMAGE_ID).run { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, imageType) + assertEquals(false, isEmoji) + } + Image(IMAGE_ID).run { + assertEquals(IMAGE_ID, imageId) + assertEquals(0, width) + assertEquals(0, height) + assertEquals(0, size) + assertEquals(ImageType.UNKNOWN, imageType) + assertEquals(false, isEmoji) + } + Image(IMAGE_ID) { + width = 1 + height = 2 + size = 3 + type = ImageType.GIF + isEmoji = true + }.run { + assertEquals(IMAGE_ID, imageId) + assertEquals(1, width) + assertEquals(2, height) + assertEquals(3, size) + assertEquals(ImageType.GIF, imageType) + assertEquals(true, isEmoji) + } + } +} \ No newline at end of file