Improve SendMessageHandler; Fix image not display in some group; #939

This commit is contained in:
Karlatemp 2021-01-31 18:55:02 +08:00
parent 8c88f0e44f
commit af034a0a00
No known key found for this signature in database
GPG Key ID: 21FBDDF664FF06F8
3 changed files with 87 additions and 14 deletions

View File

@ -156,6 +156,7 @@ internal class GroupImpl(
is ImgStore.GroupPicUp.Response.FileExists -> {
val resourceId = resource.calculateResourceId()
return OfflineGroupImage(imageId = resourceId)
.also { it.fileId = response.fileId.toInt() }
.also { ImageUploadEvent.Succeed(this@GroupImpl, resource, it).broadcast() }
}
is ImgStore.GroupPicUp.Response.RequireUpload -> {
@ -169,6 +170,7 @@ internal class GroupImpl(
)
return OfflineGroupImage(imageId = resource.calculateResourceId())
.also { it.fileId = response.fileId.toInt() }
.also { ImageUploadEvent.Succeed(this@GroupImpl, resource, it).broadcast() }
}
}

View File

@ -25,11 +25,11 @@ import net.mamoe.mirai.internal.network.protocol.packet.chat.image.ImgStore
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.*
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.createToFriend
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.createToGroup
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.castOrNull
import net.mamoe.mirai.utils.currentTimeSeconds
import java.lang.UnsupportedOperationException
/**
* 通用处理器
@ -105,7 +105,7 @@ internal abstract class SendMessageHandler<C : Contact> {
*/
suspend fun sendMessagePacket(
originalMessage: Message,
transformedMessage: Message,
transformedMessage: MessageChain,
finalMessage: MessageChain,
step: SendMessageStep,
): MessageReceipt<C> {
@ -125,10 +125,10 @@ internal abstract class SendMessageHandler<C : Contact> {
if (resp is MessageSvcPbSendMsg.Response.MessageTooLarge) {
return when (step) {
SendMessageStep.FIRST -> {
sendMessage(originalMessage, transformedMessage, SendMessageStep.LONG_MESSAGE)
sendMessageImpl(originalMessage, transformedMessage, SendMessageStep.LONG_MESSAGE)
}
SendMessageStep.LONG_MESSAGE -> {
sendMessage(originalMessage, transformedMessage, SendMessageStep.FRAGMENTED)
sendMessageImpl(originalMessage, transformedMessage, SendMessageStep.FRAGMENTED)
}
else -> {
@ -219,6 +219,8 @@ internal abstract class SendMessageHandler<C : Contact> {
)
}
open suspend fun preConversionTransformedMessage(message: Message): Message = message
open suspend fun conversionMessageChain(chain: MessageChain): MessageChain = chain
open suspend fun postTransformActions(chain: MessageChain) {
@ -255,15 +257,33 @@ internal suspend fun <C : Contact> SendMessageHandler<C>.transformSpecialMessage
}
/**
* Might be recalled with [transformedMessage] `is` [LongMessageInternal] if length estimation failed (sendMessagePacket)
* Send a message, and covert messages
*
* Don't recall this function.
*/
internal suspend fun <C : Contact> SendMessageHandler<C>.sendMessage(
originalMessage: Message,
transformedMessage: Message,
step: SendMessageStep,
): MessageReceipt<C> = sendMessageImpl(
originalMessage,
conversionMessageChain(
transformSpecialMessages(
preConversionTransformedMessage(transformedMessage)
)
),
step
)
/**
* Might be recalled with [transformedMessage] `is` [LongMessageInternal] if length estimation failed (sendMessagePacket)
*/
internal suspend fun <C : Contact> SendMessageHandler<C>.sendMessageImpl(
originalMessage: Message,
transformedMessage: MessageChain,
step: SendMessageStep,
): MessageReceipt<C> { // Result cannot be in interface.
val chain = transformSpecialMessages(transformedMessage)
.convertToLongMessageIfNeeded(step)
val chain = transformedMessage.convertToLongMessageIfNeeded(step)
chain.findIsInstance<QuoteReply>()?.source?.ensureSequenceIdAvailable()
@ -314,11 +334,19 @@ internal class GroupSendMessageHandler(
override val senderName: String
get() = contact.botAsMember.nameCardOrNick
override suspend fun postTransformActions(chain: MessageChain) {
chain.asSequence().filterIsInstance<FriendImage>().forEach { image ->
contact.updateFriendImageForGroupMessage(image)
override suspend fun conversionMessageChain(chain: MessageChain): MessageChain = chain.map { element ->
when (element) {
is OfflineGroupImage -> {
contact.fixImageFileId(element)
element
}
is FriendImage -> {
contact.updateFriendImageForGroupMessage(element)
}
else -> element
}
}
}.toMessageChain()
override suspend fun constructSourceFromMusicShareResponse(
finalMessage: MessageChain,
@ -341,18 +369,55 @@ internal class GroupSendMessageHandler(
}
companion object {
private suspend fun GroupImpl.fixImageFileId(image: OfflineGroupImage) {
if (image.fileId == null) {
val response: ImgStore.GroupPicUp.Response = ImgStore.GroupPicUp(
bot.client,
uin = bot.id,
groupCode = this.id,
md5 = image.md5,
size = 1,
).sendAndExpect(bot)
when (response) {
is ImgStore.GroupPicUp.Response.Failed -> {
image.fileId = 0 // Failed
}
is ImgStore.GroupPicUp.Response.FileExists -> {
image.fileId = response.fileId.toInt()
}
is ImgStore.GroupPicUp.Response.RequireUpload -> {
image.fileId = response.fileId.toInt()
}
}
}
}
/**
* Ensures server holds the cache
*/
private suspend fun GroupImpl.updateFriendImageForGroupMessage(image: FriendImage) {
private suspend fun GroupImpl.updateFriendImageForGroupMessage(image: FriendImage): OfflineGroupImage {
bot.network.run {
ImgStore.GroupPicUp(
val response = ImgStore.GroupPicUp(
bot.client,
uin = bot.id,
groupCode = id,
md5 = image.md5,
size = if (image is OnlineFriendImageImpl) image.delegate.fileLen else 0
).sendAndExpect<ImgStore.GroupPicUp.Response>()
return OfflineGroupImage(image.imageId).also { img ->
when (response) {
is ImgStore.GroupPicUp.Response.FileExists -> {
img.fileId = response.fileId.toInt()
}
is ImgStore.GroupPicUp.Response.RequireUpload -> {
img.fileId = response.fileId.toInt()
}
is ImgStore.GroupPicUp.Response.Failed -> {
img.fileId = 0
}
}
}
}
}
}

View File

@ -178,6 +178,7 @@ internal fun ImMsgBody.CustomFace.toNotOnlineImage(): ImMsgBody.NotOnlineImage {
@Suppress("DEPRECATION")
internal fun OfflineGroupImage.toJceData(): ImMsgBody.CustomFace {
return ImMsgBody.CustomFace(
fileId = this.fileId ?: 0,
filePath = this.imageId,
picMd5 = this.md5,
flag = ByteArray(4),
@ -185,7 +186,9 @@ internal fun OfflineGroupImage.toJceData(): ImMsgBody.CustomFace {
//_400Url = "/gchatpic_new/000000000/1041235568-2195821338-01E9451B70EDEAE3B37C101F1EEBF5B5/400?term=2",
//_400Width = 351,
oldData = oldData,
// pbReserve = CustomFaceExtPb.ResvAttr().toByteArray(CustomFaceExtPb.ResvAttr.serializer())
// pbReserve = "08 00 10 00 32 00 50 00 78 08".autoHexToBytes(),
// useful = 1,
// pbReserve = CustomFaceExtPb.ResvAttr().toByteArray(CustomFaceExtPb.ResvAttr.serializer())
)
}
@ -258,6 +261,9 @@ internal interface OfflineImage : Image
internal data class OfflineGroupImage(
override val imageId: String
) : GroupImage(), OfflineImage, DeferredOriginUrlAware {
@Transient
internal var fileId: Int? = null
object Serializer : Image.FallbackSerializer("OfflineGroupImage")
override fun getUrl(bot: Bot): String {