diff --git a/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt b/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt index f8cbc4226..39f45668e 100644 --- a/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/file/AbsoluteFolderImpl.kt @@ -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 }) } diff --git a/mirai-core/src/commonMain/kotlin/message/flags/InternalFlagOnlyMessage.kt b/mirai-core/src/commonMain/kotlin/message/flags/InternalFlagOnlyMessage.kt index bc78ff6e4..d5c399056 100644 --- a/mirai-core/src/commonMain/kotlin/message/flags/InternalFlagOnlyMessage.kt +++ b/mirai-core/src/commonMain/kotlin/message/flags/InternalFlagOnlyMessage.kt @@ -92,4 +92,17 @@ internal object MiraiInternalMessageFlag : MessageMetadata, ConstrainSingle, Int data ) } +} + +internal object AllowSendFileMessage : MessageMetadata, ConstrainSingle, InternalFlagOnlyMessage, + AbstractMessageKey({ it.safeCast() }) { + override val key: MessageKey get() = this + override fun toString(): String = "" + + override fun accept(visitor: MessageVisitor, data: D): R { + return visitor.ex()?.visitAllowSendFileMessage(this, data) ?: super.accept( + visitor, + data + ) + } } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/message/protocol/impl/FileMessageProtocol.kt b/mirai-core/src/commonMain/kotlin/message/protocol/impl/FileMessageProtocol.kt index cac90926c..f2ec5aeec 100644 --- a/mirai-core/src/commonMain/kotlin/message/protocol/impl/FileMessageProtocol.kt +++ b/mirai-core/src/commonMain/kotlin/message/protocol/impl/FileMessageProtocol.kt @@ -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() { + var hasFileMessage = false + var hasAllowSendFileMessage = false + message.acceptChildren(object : RecursiveMessageVisitor(), MessageVisitorEx { + 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!" + ) + } } } diff --git a/mirai-core/src/commonMain/kotlin/message/visitor/MessageVisitorEx.kt b/mirai-core/src/commonMain/kotlin/message/visitor/MessageVisitorEx.kt index 463718ec5..8202510e0 100644 --- a/mirai-core/src/commonMain/kotlin/message/visitor/MessageVisitorEx.kt +++ b/mirai-core/src/commonMain/kotlin/message/visitor/MessageVisitorEx.kt @@ -64,4 +64,8 @@ internal interface MessageVisitorEx : MessageVisitor { fun visitMiraiInternalMessageFlag(message: MiraiInternalMessageFlag, data: D): R { return visitInternalFlagOnlyMessage(message, data) } + + fun visitAllowSendFileMessage(message: AllowSendFileMessage, data: D): R { + return visitInternalFlagOnlyMessage(message, data) + } } \ No newline at end of file diff --git a/mirai-core/src/commonTest/kotlin/message/protocol/impl/FileMessageProtocolTest.kt b/mirai-core/src/commonTest/kotlin/message/protocol/impl/FileMessageProtocolTest.kt index 23f9c8f58..8f3035656 100644 --- a/mirai-core/src/commonTest/kotlin/message/protocol/impl/FileMessageProtocolTest.kt +++ b/mirai-core/src/commonTest/kotlin/message/protocol/impl/FileMessageProtocolTest.kt @@ -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 = 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 { + 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) + } } \ No newline at end of file diff --git a/mirai-core/src/jvmBaseMain/kotlin/utils/RemoteFileImpl.kt b/mirai-core/src/jvmBaseMain/kotlin/utils/RemoteFileImpl.kt index 26a2f6d17..bfdce8742 100644 --- a/mirai-core/src/jvmBaseMain/kotlin/utils/RemoteFileImpl.kt +++ b/mirai-core/src/jvmBaseMain/kotlin/utils/RemoteFileImpl.kt @@ -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 { @Suppress("DEPRECATION") - return contact.sendMessage(uploadInternal(resource, null) + MiraiInternalMessageFlag) + return contact.sendMessage(AllowSendFileMessage + uploadInternal(resource, null)) } override suspend fun getDownloadInfo(): RemoteFile.DownloadInfo? {