Jelajahi Sumber

Support receive nested ForwardMessages (#1196)

* Support receive nested ForwardMessages

* Tests
Karlatemp 4 tahun lalu
induk
melakukan
28a8b8303a

+ 19 - 4
mirai-core/src/commonMain/kotlin/MiraiImpl.kt

@@ -974,12 +974,27 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
     }
 
     override suspend fun downloadForwardMessage(bot: Bot, resourceId: String): List<ForwardMessage.Node> {
-        return downloadMultiMsgTransmit(bot, resourceId, ResourceKind.FORWARD_MESSAGE).msg.map { msg ->
-            msg.toNode(bot)
+        return downloadMultiMsgTransmit(bot, resourceId, ResourceKind.FORWARD_MESSAGE).toForwardMessageNodes(bot)
+    }
+
+    internal open suspend fun MsgTransmit.PbMultiMsgNew.toForwardMessageNodes(
+        bot: Bot,
+        context: RefineContext
+    ): List<ForwardMessage.Node> {
+        return msg.map { it.toNode(bot, context) }
+    }
+
+    internal open suspend fun MsgTransmit.PbMultiMsgTransmit.toForwardMessageNodes(bot: Bot): List<ForwardMessage.Node> {
+        val pbs = this.pbItemList.associate {
+            it.fileName to it.buffer.loadAs(MsgTransmit.PbMultiMsgNew.serializer())
         }
+        val main = pbs["MultiMsg"] ?: return this.msg.map { it.toNode(bot, EmptyRefineContext) }
+        val context = SimpleRefineContext(mutableMapOf())
+        context[ForwardMessageInternal.MsgTransmits] = pbs
+        return main.toForwardMessageNodes(bot, context)
     }
 
-    protected open suspend fun MsgComm.Msg.toNode(bot: Bot): ForwardMessage.Node {
+    protected open suspend fun MsgComm.Msg.toNode(bot: Bot, refineContext: RefineContext): ForwardMessage.Node {
         val msg = this
         return ForwardMessage.Node(
             senderId = msg.msgHead.fromUin,
@@ -989,7 +1004,7 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
                 ?: msg.msgHead.fromUin.toString(),
             messageChain = listOf(msg)
                 .toMessageChainNoSource(bot, 0, MessageSourceKind.GROUP)
-                .refineDeep(bot)
+                .refineDeep(bot, refineContext)
         )
     }
 

+ 1 - 1
mirai-core/src/commonMain/kotlin/QQAndroidBot.kt

@@ -310,5 +310,5 @@ internal fun RichMessage.Key.forwardMessage(
             <source name="${source.take(50)}" icon="" action="" appid="-1"/>
         </msg>
     """.trimIndent().replace("\n", " ").trim()
-    return ForwardMessageInternal(template, resId)
+    return ForwardMessageInternal(template, resId, null)
 }

+ 28 - 3
mirai-core/src/commonMain/kotlin/message/LongMessageInternal.kt

@@ -11,9 +11,11 @@ package net.mamoe.mirai.internal.message
 
 import net.mamoe.mirai.Bot
 import net.mamoe.mirai.Mirai
+import net.mamoe.mirai.internal.MiraiImpl
 import net.mamoe.mirai.internal.asQQAndroidBot
-import net.mamoe.mirai.internal.message.DeepMessageRefiner.refineDeep
+import net.mamoe.mirai.internal.network.protocol.data.proto.MsgTransmit
 import net.mamoe.mirai.message.data.*
+import net.mamoe.mirai.utils.cast
 import net.mamoe.mirai.utils.safeCast
 
 // internal runtime value, not serializable
@@ -34,7 +36,11 @@ internal data class LongMessageInternal internal constructor(override val conten
 
 // internal runtime value, not serializable
 @Suppress("RegExpRedundantEscape", "UnnecessaryVariable")
-internal data class ForwardMessageInternal(override val content: String, val resId: String) : AbstractServiceMessage(),
+internal data class ForwardMessageInternal(
+    override val content: String,
+    val resId: String?,
+    val fileName: String?,
+) : AbstractServiceMessage(),
     RefinableMessage {
     override val serviceId: Int get() = 35
 
@@ -60,6 +66,23 @@ internal data class ForwardMessageInternal(override val content: String, val res
         val preview = titles
         val source = xmlFoot.findField("name")
 
+        if (fileName != null) { // nested
+            val transmits = refineContext.getNotNull(MsgTransmits)[fileName]
+                ?: return SimpleServiceMessage(serviceId, content) // Refine failed
+            return MessageOrigin(
+                SimpleServiceMessage(serviceId, content),
+                null, // Nested don't have resource id
+                MessageOriginKind.FORWARD
+            ) + ForwardMessage(
+                preview = preview,
+                title = title,
+                brief = brief,
+                source = source,
+                summary = summary.trim(),
+                nodeList = Mirai.cast<MiraiImpl>().run { transmits.toForwardMessageNodes(bot, refineContext) }
+            )
+        }
+
         return MessageOrigin(
             SimpleServiceMessage(serviceId, content),
             resId,
@@ -70,7 +93,7 @@ internal data class ForwardMessageInternal(override val content: String, val res
             brief = brief,
             source = source,
             summary = summary.trim(),
-            nodeList = Mirai.downloadForwardMessage(bot, resId)
+            nodeList = Mirai.downloadForwardMessage(bot, resId!!)
         )
     }
 
@@ -87,6 +110,8 @@ internal data class ForwardMessageInternal(override val content: String, val res
             return substringAfter("$type=\"", "")
                 .substringBefore("\"", "")
         }
+
+        val MsgTransmits = RefineContextKey<Map<String, MsgTransmit.PbMultiMsgNew>>("MsgTransmit")
     }
 }
 

+ 9 - 3
mirai-core/src/commonMain/kotlin/message/ReceiveMessageHandler.kt

@@ -482,14 +482,20 @@ internal object ReceiveMessageTransformer {
                 val resId = findStringProperty("m_resid")
 
                 val msg = if (resId.isEmpty()) {
-                    SimpleServiceMessage(35, content)
+                    // Nested ForwardMessage
+                    val fileName = findStringProperty("m_fileName")
+                    if (fileName.isNotEmpty() && findStringProperty("action") == "viewMultiMsg") {
+                        ForwardMessageInternal(content, null, fileName)
+                    } else {
+                        SimpleServiceMessage(35, content)
+                    }
                 } else when (findStringProperty("multiMsgFlag").toIntOrNull()) {
                     1 -> LongMessageInternal(content, resId)
-                    0 -> ForwardMessageInternal(content, resId)
+                    0 -> ForwardMessageInternal(content, resId, null)
                     else -> {
                         // from PC QQ
                         if (findStringProperty("action") == "viewMultiMsg") {
-                            ForwardMessageInternal(content, resId)
+                            ForwardMessageInternal(content, resId, null)
                         } else {
                             SimpleServiceMessage(35, content)
                         }

File diff ditekan karena terlalu besar
+ 6 - 0
mirai-core/src/jvmTest/kotlin/message/data/MessageRefineTest.kt


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini