[core] Fix sending FileMessage on uploadNewFile (regression in 2.12.0), fix #2195

This commit is contained in:
Him188 2022-08-16 10:54:55 +08:00
parent a51f55124c
commit 2e4cab4365
No known key found for this signature in database
GPG Key ID: BA439CDDCF652375
6 changed files with 72 additions and 11 deletions

View File

@ -18,7 +18,7 @@ import net.mamoe.mirai.contact.file.AbsoluteFolder
import net.mamoe.mirai.contact.isOperator import net.mamoe.mirai.contact.isOperator
import net.mamoe.mirai.internal.contact.GroupImpl import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.contact.file.RemoteFilesImpl.Companion.findFileByPath import net.mamoe.mirai.internal.contact.file.RemoteFilesImpl.Companion.findFileByPath
import net.mamoe.mirai.internal.message.flags.MiraiInternalMessageFlag import net.mamoe.mirai.internal.message.flags.AllowSendFileMessage
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.components.ClockHolder.Companion.clock import net.mamoe.mirai.internal.network.components.ClockHolder.Companion.clock
import net.mamoe.mirai.internal.network.highway.Highway import net.mamoe.mirai.internal.network.highway.Highway
@ -181,7 +181,7 @@ internal abstract class CommonAbsoluteFolderImpl(
// 当为 true 时跳过上传, 但仍然需要完成 `sendMessage(FileMessage)` 才是正常逻辑 // 当为 true 时跳过上传, 但仍然需要完成 `sendMessage(FileMessage)` 才是正常逻辑
callback?.onBegin(file, content) callback?.onBegin(file, content)
val result = kotlin.runCatching { val result = kotlin.runCatching {
folder.contact.sendMessage(file.toMessage() + MiraiInternalMessageFlag) folder.contact.sendMessage(AllowSendFileMessage + file.toMessage())
}.map { content.size } }.map { content.size }
callback?.onFinished(file, content, result) callback?.onFinished(file, content, result)
return file return file
@ -245,7 +245,7 @@ internal abstract class CommonAbsoluteFolderImpl(
) )
}.let { result0 -> }.let { result0 ->
val result = result0.onSuccessCatching { val result = result0.onSuccessCatching {
folder.contact.sendMessage(file.toMessage() + MiraiInternalMessageFlag) folder.contact.sendMessage(AllowSendFileMessage + file.toMessage())
} }
callback?.onFinished(file, content, result.map { content.size }) callback?.onFinished(file, content, result.map { content.size })
} }

View File

@ -92,4 +92,17 @@ internal object MiraiInternalMessageFlag : MessageMetadata, ConstrainSingle, Int
data data
) )
} }
}
internal object AllowSendFileMessage : MessageMetadata, ConstrainSingle, InternalFlagOnlyMessage,
AbstractMessageKey<AllowSendFileMessage>({ it.safeCast() }) {
override val key: MessageKey<AllowSendFileMessage> get() = this
override fun toString(): String = ""
override fun <D, R> accept(visitor: MessageVisitor<D, R>, data: D): R {
return visitor.ex()?.visitAllowSendFileMessage(this, data) ?: super<InternalFlagOnlyMessage>.accept(
visitor,
data
)
}
} }

View File

@ -15,6 +15,7 @@ import kotlinx.coroutines.coroutineScope
import net.mamoe.mirai.internal.contact.SendMessageStep import net.mamoe.mirai.internal.contact.SendMessageStep
import net.mamoe.mirai.internal.message.data.FileMessageImpl import net.mamoe.mirai.internal.message.data.FileMessageImpl
import net.mamoe.mirai.internal.message.data.checkIsImpl import net.mamoe.mirai.internal.message.data.checkIsImpl
import net.mamoe.mirai.internal.message.flags.AllowSendFileMessage
import net.mamoe.mirai.internal.message.protocol.MessageProtocol import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.internal.message.protocol.ProcessorCollector import net.mamoe.mirai.internal.message.protocol.ProcessorCollector
import net.mamoe.mirai.internal.message.protocol.decode.MessageDecoder import net.mamoe.mirai.internal.message.protocol.decode.MessageDecoder
@ -28,6 +29,7 @@ import net.mamoe.mirai.internal.message.protocol.outgoing.OutgoingMessageSender
import net.mamoe.mirai.internal.message.protocol.outgoing.OutgoingMessageTransformer import net.mamoe.mirai.internal.message.protocol.outgoing.OutgoingMessageTransformer
import net.mamoe.mirai.internal.message.protocol.serialization.MessageSerializer import net.mamoe.mirai.internal.message.protocol.serialization.MessageSerializer
import net.mamoe.mirai.internal.message.source.createMessageReceipt import net.mamoe.mirai.internal.message.source.createMessageReceipt
import net.mamoe.mirai.internal.message.visitor.MessageVisitorEx
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.ObjMsg import net.mamoe.mirai.internal.network.protocol.data.proto.ObjMsg
import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement
@ -69,19 +71,37 @@ internal class FileMessageProtocol : MessageProtocol() {
private val ALLOW_SENDING_FILE_MESSAGE = systemProp("mirai.message.allow.sending.file.message", false) private val ALLOW_SENDING_FILE_MESSAGE = systemProp("mirai.message.allow.sending.file.message", false)
fun verifyFileMessage(message: MessageChain) { fun verifyFileMessage(message: MessageChain) {
message.acceptChildren(object : RecursiveMessageVisitor<Unit>() { var hasFileMessage = false
var hasAllowSendFileMessage = false
message.acceptChildren(object : RecursiveMessageVisitor<Unit>(), MessageVisitorEx<Unit, Unit> {
override fun isFinished(): Boolean {
return hasAllowSendFileMessage // finish early if allow send
}
override fun visitAllowSendFileMessage(message: AllowSendFileMessage, data: Unit) {
hasAllowSendFileMessage = true
}
override fun visitFileMessage(message: FileMessage, data: Unit) { override fun visitFileMessage(message: FileMessage, data: Unit) {
if (ALLOW_SENDING_FILE_MESSAGE) return if (ALLOW_SENDING_FILE_MESSAGE) return
// #1715 // #1715
if (message !is FileMessageImpl) error("Customized FileMessage cannot be send") if (message !is FileMessageImpl) error("Customized FileMessage cannot be send")
if (!message.allowSend) error( if (!message.allowSend) {
"Sending FileMessage is not allowed, as it may cause unexpected results. " + hasFileMessage = true
"Add JVM argument `-Dmirai.message.allow.sending.file.message=true` to disable this check. " + }
"Do this only for compatibility!"
)
} }
}) })
if (hasAllowSendFileMessage) {
// allowing
return
}
if (hasFileMessage) {
throw IllegalStateException(
"Sending FileMessage is not allowed, as it may cause unexpected results. " +
"Add JVM argument `-Dmirai.message.allow.sending.file.message=true` to disable this check. " +
"Do this only for compatibility!"
)
}
} }
} }

View File

@ -64,4 +64,8 @@ internal interface MessageVisitorEx<in D, out R> : MessageVisitor<D, R> {
fun visitMiraiInternalMessageFlag(message: MiraiInternalMessageFlag, data: D): R { fun visitMiraiInternalMessageFlag(message: MiraiInternalMessageFlag, data: D): R {
return visitInternalFlagOnlyMessage(message, data) return visitInternalFlagOnlyMessage(message, data)
} }
fun visitAllowSendFileMessage(message: AllowSendFileMessage, data: D): R {
return visitInternalFlagOnlyMessage(message, data)
}
} }

View File

@ -10,14 +10,17 @@
package net.mamoe.mirai.internal.message.protocol.impl package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.flags.AllowSendFileMessage
import net.mamoe.mirai.internal.message.protocol.MessageProtocol import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.internal.testFramework.DynamicTestsResult import net.mamoe.mirai.internal.testFramework.DynamicTestsResult
import net.mamoe.mirai.internal.testFramework.TestFactory import net.mamoe.mirai.internal.testFramework.TestFactory
import net.mamoe.mirai.internal.testFramework.runDynamicTests import net.mamoe.mirai.internal.testFramework.runDynamicTests
import net.mamoe.mirai.message.data.FileMessage import net.mamoe.mirai.message.data.FileMessage
import net.mamoe.mirai.message.data.toMessageChain
import net.mamoe.mirai.utils.hexToBytes import net.mamoe.mirai.utils.hexToBytes
import kotlin.test.BeforeTest import kotlin.test.BeforeTest
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertFailsWith
internal class FileMessageProtocolTest : AbstractMessageProtocolTest() { internal class FileMessageProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> = arrayOf(FileMessageProtocol(), TextProtocol()) override val protocols: Array<out MessageProtocol> = arrayOf(FileMessageProtocol(), TextProtocol())
@ -76,4 +79,24 @@ internal class FileMessageProtocolTest : AbstractMessageProtocolTest() {
testContextual(data, serialName), testContextual(data, serialName),
) )
} }
@Test
fun `test manual send forbidden`() {
val data = FileMessage("id", 1, "name", 2)
assertFailsWith<IllegalStateException> {
FileMessageProtocol.verifyFileMessage(data.toMessageChain())
}
}
@Test
fun `test auto send allowed`() {
val data = FileMessage("id", 1, "name", 2)
FileMessageProtocol.verifyFileMessage(AllowSendFileMessage + data)
}
@Test
fun `test auto send allowed2`() {
val data = FileMessage("id", 1, "name", 2)
FileMessageProtocol.verifyFileMessage(data + AllowSendFileMessage)
}
} }

View File

@ -20,6 +20,7 @@ import net.mamoe.mirai.contact.isOperator
import net.mamoe.mirai.internal.asQQAndroidBot import net.mamoe.mirai.internal.asQQAndroidBot
import net.mamoe.mirai.internal.contact.groupCode import net.mamoe.mirai.internal.contact.groupCode
import net.mamoe.mirai.internal.message.data.FileMessageImpl import net.mamoe.mirai.internal.message.data.FileMessageImpl
import net.mamoe.mirai.internal.message.flags.AllowSendFileMessage
import net.mamoe.mirai.internal.message.flags.MiraiInternalMessageFlag import net.mamoe.mirai.internal.message.flags.MiraiInternalMessageFlag
import net.mamoe.mirai.internal.network.highway.Highway import net.mamoe.mirai.internal.network.highway.Highway
import net.mamoe.mirai.internal.network.highway.ResourceKind import net.mamoe.mirai.internal.network.highway.ResourceKind
@ -551,7 +552,7 @@ internal abstract class CommonRemoteFileImpl(
override suspend fun uploadAndSend(resource: ExternalResource): MessageReceipt<Contact> { override suspend fun uploadAndSend(resource: ExternalResource): MessageReceipt<Contact> {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
return contact.sendMessage(uploadInternal(resource, null) + MiraiInternalMessageFlag) return contact.sendMessage(AllowSendFileMessage + uploadInternal(resource, null))
} }
override suspend fun getDownloadInfo(): RemoteFile.DownloadInfo? { override suspend fun getDownloadInfo(): RemoteFile.DownloadInfo? {