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

View File

@ -92,4 +92,17 @@ internal object MiraiInternalMessageFlag : MessageMetadata, ConstrainSingle, Int
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.message.data.FileMessageImpl
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.ProcessorCollector
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.serialization.MessageSerializer
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.ObjMsg
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)
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) {
if (ALLOW_SENDING_FILE_MESSAGE) return
// #1715
if (message !is FileMessageImpl) error("Customized FileMessage cannot be send")
if (!message.allowSend) error(
"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!"
)
if (!message.allowSend) {
hasFileMessage = true
}
}
})
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 {
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
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.testFramework.DynamicTestsResult
import net.mamoe.mirai.internal.testFramework.TestFactory
import net.mamoe.mirai.internal.testFramework.runDynamicTests
import net.mamoe.mirai.message.data.FileMessage
import net.mamoe.mirai.message.data.toMessageChain
import net.mamoe.mirai.utils.hexToBytes
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertFailsWith
internal class FileMessageProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> = arrayOf(FileMessageProtocol(), TextProtocol())
@ -76,4 +79,24 @@ internal class FileMessageProtocolTest : AbstractMessageProtocolTest() {
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.contact.groupCode
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.network.highway.Highway
import net.mamoe.mirai.internal.network.highway.ResourceKind
@ -551,7 +552,7 @@ internal abstract class CommonRemoteFileImpl(
override suspend fun uploadAndSend(resource: ExternalResource): MessageReceipt<Contact> {
@Suppress("DEPRECATION")
return contact.sendMessage(uploadInternal(resource, null) + MiraiInternalMessageFlag)
return contact.sendMessage(AllowSendFileMessage + uploadInternal(resource, null))
}
override suspend fun getDownloadInfo(): RemoteFile.DownloadInfo? {