mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-03 15:10:14 +08:00
Unify image id
This commit is contained in:
parent
b7232182ae
commit
1d24a810fe
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
@ -36,13 +36,15 @@ import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Contact.Companion.sendImage
|
||||
import net.mamoe.mirai.contact.Contact.Companion.uploadImage
|
||||
import net.mamoe.mirai.message.code.CodableMessage
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_1
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
|
||||
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
|
||||
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.message.data.Image.Key.queryUrl
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import net.mamoe.mirai.utils.ExternalResource
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.sendAsImageTo
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage
|
||||
import net.mamoe.mirai.utils.MiraiInternalApi
|
||||
import net.mamoe.mirai.utils.safeCast
|
||||
import kotlin.LazyThreadSafetyMode.NONE
|
||||
|
||||
/**
|
||||
@ -56,15 +58,12 @@ import kotlin.LazyThreadSafetyMode.NONE
|
||||
* - [Image.fromId]. 在 Kotlin, 更推荐使用顶层函数 `val image = Image("id")`
|
||||
*
|
||||
* ### 上传和发送图片
|
||||
* - [Contact.uploadImage] 上传 [图片文件][ExternalImage] 并得到 [Image] 消息
|
||||
* - [Contact.sendImage] 上传 [图片文件][ExternalImage] 并发送返回的 [Image] 作为一条消息
|
||||
* - [Image.sendTo] 上传 [图片文件][ExternalImage] 并得到 [Image] 消息
|
||||
* - [Contact.uploadImage] 上传 [资源文件][ExternalResource] 并得到 [Image] 消息
|
||||
* - [Contact.sendImage] 上传 [资源文件][ExternalResource] 并发送返回的 [Image] 作为一条消息
|
||||
*
|
||||
* - [File.uploadAsImage]
|
||||
* - [InputStream.uploadAsImage]
|
||||
*
|
||||
* - [File.sendAsImageTo]
|
||||
* - [InputStream.sendAsImageTo]
|
||||
* - [ExternalResource.uploadAsImage]
|
||||
* - [ExternalResource.sendAsImageTo]
|
||||
* - [Contact.sendImage]
|
||||
*
|
||||
* ### 下载图片
|
||||
* - [Image.queryUrl] 扩展函数. 查询图片下载链接
|
||||
@ -85,12 +84,7 @@ public interface Image : Message, MessageContent, CodableMessage {
|
||||
* 图片 id 不一定会长时间保存, 也可能在将来改变格式, 因此不建议使用 id 发送图片.
|
||||
*
|
||||
* ### 格式
|
||||
* 群图片:
|
||||
* - [GROUP_IMAGE_ID_REGEX], 示例: `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.ext` (ext 为文件后缀, 如 png)
|
||||
*
|
||||
* 好友图片:
|
||||
* - [FRIEND_IMAGE_ID_REGEX_1], 示例: `/f8f1ab55-bf8e-4236-b55e-955848d7069f`
|
||||
* - [FRIEND_IMAGE_ID_REGEX_2], 示例: `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
|
||||
* 所有图片的 id 都满足正则表达式 [IMAGE_ID_REGEX]. 示例: `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.ext` (ext 为文件后缀, 如 png)
|
||||
*
|
||||
* @see Image 使用 id 构造图片
|
||||
*/
|
||||
@ -147,52 +141,40 @@ public interface Image : Message, MessageContent, CodableMessage {
|
||||
|
||||
|
||||
/**
|
||||
* 好友图片 ID 正则表达式
|
||||
*
|
||||
* `/f8f1ab55-bf8e-4236-b55e-955848d7069f`
|
||||
* @see FRIEND_IMAGE_ID_REGEX_2
|
||||
*/
|
||||
// Java: MessageUtils.FRIEND_IMAGE_ID_REGEX_1
|
||||
@JvmStatic
|
||||
@MiraiExperimentalApi
|
||||
@get:JvmName("getFriendImageIdRegex1")
|
||||
public val FRIEND_IMAGE_ID_REGEX_1: Regex = Regex("""/[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}""")
|
||||
|
||||
/**
|
||||
* 好友图片 ID 正则表达式 2
|
||||
*
|
||||
* `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
|
||||
* @see FRIEND_IMAGE_ID_REGEX_1
|
||||
*/
|
||||
// Java: MessageUtils.FRIEND_IMAGE_ID_REGEX_2
|
||||
@JvmStatic
|
||||
@MiraiExperimentalApi
|
||||
@get:JvmName("getFriendImageIdRegex2")
|
||||
public val FRIEND_IMAGE_ID_REGEX_2: Regex = Regex("""/[0-9]*-[0-9]*-[0-9a-fA-F]{32}""")
|
||||
|
||||
/**
|
||||
* 群图片 ID 正则表达式
|
||||
* 统一 ID 正则表达式
|
||||
*
|
||||
* `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.ext`
|
||||
*/
|
||||
@Suppress("RegExpRedundantEscape") // This is required on Android
|
||||
// Java: MessageUtils.GROUP_IMAGE_ID_REGEX
|
||||
@JvmStatic
|
||||
@MiraiExperimentalApi
|
||||
@get:JvmName("getGroupImageIdRegex")
|
||||
public val GROUP_IMAGE_ID_REGEX: Regex =
|
||||
@get:JvmName("getImageIdRegex")
|
||||
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 内部使用.
|
||||
*
|
||||
* `/f8f1ab55-bf8e-4236-b55e-955848d7069f`
|
||||
* @see IMAGE_RESOURCE_ID_REGEX_2
|
||||
*/
|
||||
@JvmStatic
|
||||
@MiraiInternalApi
|
||||
@get:JvmName("getImageResourceIdRegex1")
|
||||
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 内部使用.
|
||||
*
|
||||
* `/000000000-3814297509-BFB7027B9354B8F899A062061D74E206`
|
||||
* @see IMAGE_RESOURCE_ID_REGEX_1
|
||||
*/
|
||||
@JvmStatic
|
||||
@MiraiInternalApi
|
||||
@get:JvmName("getImageResourceIdRegex2")
|
||||
public val IMAGE_RESOURCE_ID_REGEX_2: Regex = Regex("""/[0-9]*-[0-9]*-[0-9a-fA-F]{32}""")
|
||||
}
|
||||
}
|
||||
|
||||
@MiraiExperimentalApi
|
||||
public val Image.isGroupImage: Boolean
|
||||
get() = GROUP_IMAGE_ID_REGEX matches imageId
|
||||
|
||||
@MiraiExperimentalApi
|
||||
public val Image.isFriendImage: Boolean
|
||||
get() = FRIEND_IMAGE_ID_REGEX_1 matches imageId || FRIEND_IMAGE_ID_REGEX_2 matches imageId
|
||||
|
||||
/**
|
||||
* 通过 [Image.imageId] 构造一个 [Image] 以便发送.
|
||||
* 这个图片必须是服务器已经存在的图片.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
@ -14,9 +14,9 @@
|
||||
package net.mamoe.mirai.message.data
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_1
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
|
||||
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
|
||||
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.MiraiExperimentalApi
|
||||
import kotlin.native.concurrent.SharedImmutable
|
||||
|
||||
@ -240,9 +240,9 @@ internal fun String.imageIdToMd5(offset: Int): ByteArray {
|
||||
internal fun calculateImageMd5ByImageId(imageId: String): ByteArray {
|
||||
@Suppress("DEPRECATION")
|
||||
return when {
|
||||
imageId matches FRIEND_IMAGE_ID_REGEX_2 -> imageId.imageIdToMd5(imageId.skipToSecondHyphen() + 1)
|
||||
imageId matches FRIEND_IMAGE_ID_REGEX_1 -> imageId.imageIdToMd5(1)
|
||||
imageId matches GROUP_IMAGE_ID_REGEX -> imageId.imageIdToMd5(1)
|
||||
imageId matches IMAGE_ID_REGEX -> imageId.imageIdToMd5(1)
|
||||
imageId matches IMAGE_RESOURCE_ID_REGEX_2 -> imageId.imageIdToMd5(imageId.skipToSecondHyphen() + 1)
|
||||
imageId matches IMAGE_RESOURCE_ID_REGEX_1 -> imageId.imageIdToMd5(1)
|
||||
|
||||
else -> error(
|
||||
"illegal imageId: $imageId. $ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE"
|
||||
@ -251,8 +251,8 @@ internal fun calculateImageMd5ByImageId(imageId: String): ByteArray {
|
||||
}
|
||||
|
||||
internal val ILLEGAL_IMAGE_ID_EXCEPTION_MESSAGE: String =
|
||||
"ImageId must match Regex `${FRIEND_IMAGE_ID_REGEX_1.pattern}`, " +
|
||||
"`${FRIEND_IMAGE_ID_REGEX_2.pattern}` or " +
|
||||
"`${GROUP_IMAGE_ID_REGEX.pattern}`"
|
||||
"ImageId must match Regex `${IMAGE_RESOURCE_ID_REGEX_1.pattern}`, " +
|
||||
"`${IMAGE_RESOURCE_ID_REGEX_2.pattern}` or " +
|
||||
"`${IMAGE_ID_REGEX.pattern}`"
|
||||
|
||||
// endregion
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
* 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.
|
||||
@ -25,10 +25,27 @@ public fun generateImageId(md5: ByteArray, format: String = "mirai"): String {
|
||||
return """{${generateUUID(md5)}}.$format"""
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
public fun generateImageIdFromResourceId(resourceId: String, format: String = "mirai"): String? {
|
||||
// friend image id: /1040400290-3666252994-EFF4427CE3D27DB6B1D9A8AB72E7A29C
|
||||
// friend image id: /1040400290-3666252994-EFF4427C E3D2 7DB6 B1D9 A8AB72E7A29C
|
||||
// group image id: {EF42A82D-8DB6-5D0F-4F11-68961D8DA5CB}.png
|
||||
|
||||
val md5String = resourceId.substringAfterLast("-").substringAfter("/").takeIf { it.length == 32 } ?: return null
|
||||
return "{${generateUUID(md5String)}}.$format"
|
||||
}
|
||||
|
||||
public fun generateUUID(md5: ByteArray): String {
|
||||
return "${md5[0, 3]}-${md5[4, 5]}-${md5[6, 7]}-${md5[8, 9]}-${md5[10, 15]}"
|
||||
}
|
||||
|
||||
public fun generateUUID(md5String: String): String {
|
||||
with(md5String) {
|
||||
check(length == 32) { "it should md5String.length == 32" }
|
||||
return "${substring(0, 8)}-${substring(8, 12)}-${substring(12, 16)}-${substring(16, 20)}-${substring(20, 32)}"
|
||||
}
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
public operator fun ByteArray.get(rangeStart: Int, rangeEnd: Int): String = buildString {
|
||||
for (it in rangeStart..rangeEnd) {
|
||||
|
@ -36,9 +36,9 @@ import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.action.Nudge
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_1
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
|
||||
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
|
||||
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.*
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
||||
import kotlin.math.absoluteValue
|
||||
@ -815,9 +815,9 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
|
||||
|
||||
override fun createImage(imageId: String): Image {
|
||||
return when {
|
||||
imageId matches FRIEND_IMAGE_ID_REGEX_1 -> OfflineFriendImage(imageId)
|
||||
imageId matches FRIEND_IMAGE_ID_REGEX_2 -> OfflineFriendImage(imageId)
|
||||
imageId matches GROUP_IMAGE_ID_REGEX -> OfflineGroupImage(imageId)
|
||||
imageId matches IMAGE_ID_REGEX -> 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")
|
||||
|
@ -21,12 +21,14 @@ import net.mamoe.mirai.event.events.BeforeImageUploadEvent
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
import net.mamoe.mirai.event.events.ImageUploadEvent
|
||||
import net.mamoe.mirai.internal.message.OfflineFriendImage
|
||||
import net.mamoe.mirai.internal.message.getImageType
|
||||
import net.mamoe.mirai.internal.network.highway.postImage
|
||||
import net.mamoe.mirai.internal.network.highway.sizeToString
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Cmd0x352
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.image.LongConn
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.utils.ExternalResource
|
||||
import net.mamoe.mirai.utils.generateImageIdFromResourceId
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
import net.mamoe.mirai.utils.verbose
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@ -71,10 +73,16 @@ internal abstract class AbstractUser(
|
||||
else -> "unknown"
|
||||
}
|
||||
return when (response) {
|
||||
is LongConn.OffPicUp.Response.FileExists -> OfflineFriendImage(response.resourceId)
|
||||
.also {
|
||||
ImageUploadEvent.Succeed(this, resource, it).broadcast()
|
||||
}
|
||||
is LongConn.OffPicUp.Response.FileExists -> OfflineFriendImage(
|
||||
imageId = generateImageIdFromResourceId(
|
||||
resourceId = response.resourceId,
|
||||
format = getImageType(response.imageInfo.fileType).takeIf { it != ExternalResource.DEFAULT_FORMAT_NAME }
|
||||
?: resource.formatName
|
||||
) ?: response.resourceId
|
||||
).also {
|
||||
ImageUploadEvent.Succeed(this, resource, it).broadcast()
|
||||
}
|
||||
|
||||
is LongConn.OffPicUp.Response.RequireUpload -> {
|
||||
bot.network.logger.verbose {
|
||||
"[Http] Uploading $kind image, size=${resource.size.sizeToString()}"
|
||||
@ -105,7 +113,9 @@ internal abstract class AbstractUser(
|
||||
)*/
|
||||
// 为什么不能 ??
|
||||
|
||||
OfflineFriendImage(response.resourceId).also {
|
||||
OfflineFriendImage(
|
||||
generateImageIdFromResourceId(response.resourceId, resource.formatName) ?: response.resourceId
|
||||
).also {
|
||||
ImageUploadEvent.Succeed(this, resource, it).broadcast()
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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("DEPRECATION_ERROR", "UnusedImport")
|
||||
|
||||
package net.mamoe.mirai.internal.message
|
||||
|
||||
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.io.serialization.toByteArray
|
||||
import net.mamoe.mirai.message.data.FlashImage
|
||||
import net.mamoe.mirai.message.data.isFriendImage
|
||||
import net.mamoe.mirai.message.data.isGroupImage
|
||||
import net.mamoe.mirai.message.data.md5
|
||||
|
||||
|
||||
internal fun FlashImage.toJceData(): ImMsgBody.Elem {
|
||||
return when {
|
||||
image.isFriendImage -> ImMsgBody.Elem(
|
||||
commonElem = ImMsgBody.CommonElem(
|
||||
serviceType = 3,
|
||||
businessType = 0,
|
||||
pbElem = HummerCommelem.MsgElemInfoServtype3(
|
||||
flashC2cPic = ImMsgBody.NotOnlineImage(
|
||||
filePath = image.imageId,
|
||||
resId = image.imageId,
|
||||
picMd5 = image.md5,
|
||||
oldPicMd5 = false,
|
||||
pbReserve = byteArrayOf(0x78, 0x06)
|
||||
)
|
||||
).toByteArray(HummerCommelem.MsgElemInfoServtype3.serializer())
|
||||
)
|
||||
)
|
||||
|
||||
image.isGroupImage -> ImMsgBody.Elem(
|
||||
commonElem = ImMsgBody.CommonElem(
|
||||
serviceType = 3,
|
||||
businessType = 0,
|
||||
pbElem = HummerCommelem.MsgElemInfoServtype3(
|
||||
flashTroopPic = ImMsgBody.CustomFace(
|
||||
filePath = image.imageId,
|
||||
picMd5 = image.md5,
|
||||
pbReserve = byteArrayOf(0x78, 0x06)
|
||||
)
|
||||
).toByteArray(HummerCommelem.MsgElemInfoServtype3.serializer())
|
||||
)
|
||||
)
|
||||
|
||||
else -> error("Internal error: an image is neither group image nor friend image.")
|
||||
}
|
||||
}
|
@ -177,8 +177,10 @@ internal fun MessageChain.toRichTextElems(
|
||||
}
|
||||
|
||||
|
||||
is FlashImage -> elements.add(currentMessage.toJceData())
|
||||
is FlashImage -> elements.add(currentMessage.toJceData(messageTarget))
|
||||
.also { transformOneMessage(UNSUPPORTED_FLASH_MESSAGE_PLAIN) }
|
||||
|
||||
|
||||
is AtAll -> elements.add(atAllData)
|
||||
is Face -> elements.add(
|
||||
if (currentMessage.id >= 260) {
|
||||
|
@ -16,17 +16,19 @@ import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.IMirai
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
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.message.data.FriendImage
|
||||
import net.mamoe.mirai.message.data.GroupImage
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_1
|
||||
import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
|
||||
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
|
||||
import net.mamoe.mirai.message.data.md5
|
||||
import net.mamoe.mirai.utils.*
|
||||
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
|
||||
import net.mamoe.mirai.utils.ExternalResource.Companion.DEFAULT_FORMAT_NAME
|
||||
import net.mamoe.mirai.utils.generateImageId
|
||||
import net.mamoe.mirai.utils.generateImageIdFromResourceId
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
|
||||
internal class OnlineGroupImageImpl(
|
||||
internal val delegate: ImMsgBody.CustomFace
|
||||
@ -36,7 +38,7 @@ OnlineGroupImage() {
|
||||
delegate.picMd5,
|
||||
delegate.filePath.substringAfterLast('.')
|
||||
).takeIf {
|
||||
GROUP_IMAGE_ID_REGEX.matches(it)
|
||||
IMAGE_ID_REGEX.matches(it)
|
||||
} ?: generateImageId(delegate.picMd5)
|
||||
|
||||
override val originUrl: String
|
||||
@ -60,7 +62,8 @@ internal class OnlineFriendImageImpl(
|
||||
internal val delegate: ImMsgBody.NotOnlineImage
|
||||
) : @Suppress("DEPRECATION")
|
||||
OnlineFriendImage() {
|
||||
override val imageId: String get() = delegate.resId
|
||||
override val imageId: String =
|
||||
generateImageIdFromResourceId(delegate.resId, getImageType(delegate.imgType)) ?: delegate.resId
|
||||
override val originUrl: String
|
||||
get() = if (delegate.origUrl.isNotBlank()) {
|
||||
"http://c2cpicdw.qpic.cn" + this.delegate.origUrl
|
||||
@ -96,7 +99,7 @@ internal fun getImageType(id: Int): String {
|
||||
1002 -> "webp"
|
||||
1005 -> "bmp"
|
||||
2000 -> "gif"
|
||||
2001 -> "png"
|
||||
2001, 3 -> "png"
|
||||
else -> DEFAULT_FORMAT_NAME
|
||||
}
|
||||
}
|
||||
@ -116,6 +119,7 @@ internal fun ImMsgBody.NotOnlineImage.toCustomFace(): ImMsgBody.CustomFace {
|
||||
)
|
||||
}
|
||||
|
||||
// aka friend image id
|
||||
internal fun ImMsgBody.NotOnlineImageOrCustomFace.calculateResId(): String {
|
||||
val url = origUrl.takeIf { it.isNotBlank() }
|
||||
?: thumbUrl.takeIf { it.isNotBlank() }
|
||||
@ -165,12 +169,13 @@ private val oldData: ByteArray =
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
internal fun OfflineFriendImage.toJceData(): ImMsgBody.NotOnlineImage {
|
||||
val friendImageId = this.friendImageId
|
||||
return ImMsgBody.NotOnlineImage(
|
||||
filePath = this.imageId,
|
||||
resId = this.imageId,
|
||||
filePath = friendImageId,
|
||||
resId = friendImageId,
|
||||
oldPicMd5 = false,
|
||||
picMd5 = this.md5,
|
||||
downloadPath = this.imageId,
|
||||
downloadPath = friendImageId,
|
||||
original = 1,
|
||||
pbReserve = byteArrayOf(0x78, 0x02)
|
||||
)
|
||||
@ -207,21 +212,6 @@ internal interface SuspendDeferredOriginUrlAware : Image {
|
||||
suspend fun getUrl(bot: Bot): String
|
||||
}
|
||||
|
||||
/**
|
||||
* 由 [ExternalImage] 委托的 [Image] 类型.
|
||||
*/
|
||||
@MiraiExperimentalApi("Will be renamed to OfflineImage on 1.2.0")
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
internal class ExperimentalDeferredImage internal constructor(
|
||||
@Suppress("CanBeParameter") private val externalImage: ExternalResource // for future use
|
||||
) : AbstractImage(), SuspendDeferredOriginUrlAware {
|
||||
override suspend fun getUrl(bot: Bot): String {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override val imageId: String = externalImage.calculateResourceId()
|
||||
}
|
||||
|
||||
@Suppress("EXPOSED_SUPER_INTERFACE")
|
||||
internal interface OnlineImage : Image, ConstOriginUrlAware {
|
||||
override val originUrl: String
|
||||
@ -236,8 +226,6 @@ internal interface OnlineImage : Image, ConstOriginUrlAware {
|
||||
internal interface OfflineImage : Image
|
||||
|
||||
/**
|
||||
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [IMirai.queryImageUrl]
|
||||
*
|
||||
* @param imageId 参考 [Image.imageId]
|
||||
*/
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@ -254,7 +242,7 @@ internal data class OfflineGroupImage(
|
||||
|
||||
init {
|
||||
@Suppress("DEPRECATION")
|
||||
require(imageId matches GROUP_IMAGE_ID_REGEX) {
|
||||
require(imageId matches IMAGE_ID_REGEX) {
|
||||
"Illegal imageId. It must matches GROUP_IMAGE_ID_REGEX"
|
||||
}
|
||||
}
|
||||
@ -266,6 +254,12 @@ internal data class OfflineGroupImage(
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
internal abstract class OnlineGroupImage : GroupImage(), OnlineImage
|
||||
|
||||
internal val Image.friendImageId: String
|
||||
get() {
|
||||
// /1234567890-3666252994-EFF4427CE3D27DB6B1D9A8AB72E7A29C
|
||||
return "/000000000-000000000-${md5.toUHexString("")}"
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 [Group.uploadImage] 上传得到的 [GroupImage]. 它的链接需要查询 [IMirai.queryImageUrl]
|
||||
*
|
||||
@ -276,13 +270,7 @@ internal data class OfflineFriendImage(
|
||||
override val imageId: String
|
||||
) : FriendImage(), OfflineImage, DeferredOriginUrlAware {
|
||||
override fun getUrl(bot: Bot): String {
|
||||
return "http://c2cpicdw.qpic.cn/offpic_new/${bot.id}/${this.imageId}/0?term=2"
|
||||
}
|
||||
|
||||
init {
|
||||
require(imageId matches FRIEND_IMAGE_ID_REGEX_1 || imageId matches FRIEND_IMAGE_ID_REGEX_2) {
|
||||
"Illegal imageId. It must matches either FRIEND_IMAGE_ID_REGEX_1 or FRIEND_IMAGE_ID_REGEX_2"
|
||||
}
|
||||
return "http://c2cpicdw.qpic.cn/offpic_new/${bot.id}${this.friendImageId}/0?term=2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,3 +280,38 @@ internal data class OfflineFriendImage(
|
||||
internal abstract class OnlineFriendImage : FriendImage(), OnlineImage
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
internal fun FlashImage.toJceData(messageTarget: ContactOrBot?): ImMsgBody.Elem {
|
||||
return if (messageTarget is User) {
|
||||
ImMsgBody.Elem(
|
||||
commonElem = ImMsgBody.CommonElem(
|
||||
serviceType = 3,
|
||||
businessType = 0,
|
||||
pbElem = HummerCommelem.MsgElemInfoServtype3(
|
||||
flashC2cPic = ImMsgBody.NotOnlineImage(
|
||||
filePath = image.friendImageId,
|
||||
resId = image.friendImageId,
|
||||
picMd5 = image.md5,
|
||||
oldPicMd5 = false,
|
||||
pbReserve = byteArrayOf(0x78, 0x06)
|
||||
)
|
||||
).toByteArray(HummerCommelem.MsgElemInfoServtype3.serializer())
|
||||
)
|
||||
)
|
||||
} else {
|
||||
ImMsgBody.Elem(
|
||||
commonElem = ImMsgBody.CommonElem(
|
||||
serviceType = 3,
|
||||
businessType = 0,
|
||||
pbElem = HummerCommelem.MsgElemInfoServtype3(
|
||||
flashTroopPic = ImMsgBody.CustomFace(
|
||||
filePath = image.imageId,
|
||||
picMd5 = image.md5,
|
||||
pbReserve = byteArrayOf(0x78, 0x06)
|
||||
)
|
||||
).toByteArray(HummerCommelem.MsgElemInfoServtype3.serializer())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user