Him188 4 rokov pred
rodič
commit
bcea5c229e

+ 6 - 6
mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt

@@ -33,8 +33,8 @@ import net.mamoe.mirai.internal.network.highway.ResourceKind.GROUP_AUDIO
 import net.mamoe.mirai.internal.network.highway.ResourceKind.GROUP_IMAGE
 import net.mamoe.mirai.internal.network.highway.postPtt
 import net.mamoe.mirai.internal.network.highway.tryServersUpload
+import net.mamoe.mirai.internal.network.message.MessagePipelineConfiguration
 import net.mamoe.mirai.internal.network.message.MessagePipelineContextImpl
-import net.mamoe.mirai.internal.network.message.OutgoingMessagePhasesCommon
 import net.mamoe.mirai.internal.network.message.OutgoingMessagePhasesGroup
 import net.mamoe.mirai.internal.network.message.buildPhaseConfiguration
 import net.mamoe.mirai.internal.network.protocol.data.proto.Cmd0x388
@@ -151,12 +151,12 @@ internal class GroupImpl constructor(
         return bot.id == id || members.firstOrNull { it.id == id } != null
     }
 
-    val sendMessagePipeline = OutgoingMessagePhasesGroup.run {
+    val sendMessagePipeline: MessagePipelineConfiguration<GroupImpl> = OutgoingMessagePhasesGroup.run {
         buildPhaseConfiguration {
             Begin then
                     Preconditions then
                     MessageToMessageChain then
-                    OutgoingMessagePhasesCommon.BroadcastPreSendEvent(::GroupMessagePreSendEvent) then
+                    BroadcastPreSendEvent(::GroupMessagePreSendEvent) then
                     CheckLength then
                     EnsureSequenceIdAvailable then
                     UploadForwardMessages then
@@ -166,15 +166,15 @@ internal class GroupImpl constructor(
 
                     ConvertToLongMessage onFailureJumpTo 1 then
                     StartCreatePackets then
-                    OutgoingMessagePhasesCommon.CreatePacketsForMusicShare(specialMessageSourceStrategy) then
-                    OutgoingMessagePhasesCommon.CreatePacketsForFileMessage(specialMessageSourceStrategy) then
+                    CreatePacketsForMusicShare(specialMessageSourceStrategy) then
+                    CreatePacketsForFileMessage(specialMessageSourceStrategy) then
                     CreatePacketsNormal() then
                     LogMessageSent() then
                     SendPacketsAndCreateReceipt() onFailureJumpTo 1 then
 
                     Finish finally
 
-                    OutgoingMessagePhasesCommon.BroadcastPostSendEvent(::GroupMessagePostSendEvent) finally
+                    BroadcastPostSendEvent(::GroupMessagePostSendEvent) finally
                     CloseContext() finally
                     ThrowExceptions()
         }

+ 18 - 15
mirai-core/src/commonMain/kotlin/network/message/OutgoingMessagePhasesCommon.kt

@@ -29,6 +29,7 @@ import net.mamoe.mirai.internal.network.message.MessagePipelineContext.Companion
 import net.mamoe.mirai.internal.network.message.MessagePipelineContext.Companion.KEY_FINAL_MESSAGE_CHAIN
 import net.mamoe.mirai.internal.network.message.MessagePipelineContext.Companion.KEY_MESSAGE_SOURCE_RESULT
 import net.mamoe.mirai.internal.network.message.MessagePipelineContext.Companion.KEY_ORIGINAL_MESSAGE
+import net.mamoe.mirai.internal.network.message.MessagePipelineContext.Companion.KEY_PACKET_TRACE
 import net.mamoe.mirai.internal.network.message.MessagePipelineContext.Companion.KEY_SENDING_AS_FRAGMENTED
 import net.mamoe.mirai.internal.network.pipeline.*
 import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
@@ -142,18 +143,19 @@ internal abstract class OutgoingMessagePhasesCommon {
         }
 
     @PhaseMarker
-    class BroadcastPreSendEvent<C : AbstractContact> @PhaseMarker constructor(
-        private val constructor: (C, Message) -> MessagePreSendEvent
-    ) : AbstractPhase<MessagePipelineContext<C>, MessageChain, MessageChain>("BroadcastPreSendEvent") {
+    fun <C : AbstractContact> BroadcastPreSendEvent(
+        constructor: (C, Message) -> MessagePreSendEvent
+    ) = object : AbstractPhase<MessagePipelineContext<C>, MessageChain, MessageChain>("BroadcastPreSendEvent") {
         override suspend fun MessagePipelineContext<C>.doPhase(input: MessageChain): MessageChain {
             constructor(contact, input).broadcast()
             return input
         }
     }
 
-    class BroadcastPostSendEvent<C : AbstractContact> @PhaseMarker constructor(
-        private val constructor: (C, MessageChain, Throwable?, MessageReceipt<C>?) -> MessagePostSendEvent<in C>
-    ) : Node.Finally<MessagePipelineContext<C>>("BroadcastPreSendEvent") {
+    @PhaseMarker
+    fun <C : AbstractContact> BroadcastPostSendEvent(
+        constructor: (C, MessageChain, Throwable?, MessageReceipt<C>?) -> MessagePostSendEvent<in C>
+    ) = object : Node.Finally<MessagePipelineContext<C>>("BroadcastPreSendEvent") {
         override suspend fun MessagePipelineContext<C>.doFinally() {
             val result = executionResult
             val chain = attributes[KEY_FINAL_MESSAGE_CHAIN]
@@ -198,10 +200,9 @@ internal abstract class OutgoingMessagePhasesCommon {
                 input.forEach {
                     if (it is OfflineGroupImage) contact.fixImageFileId(it)
                 }
-                input.replaced<FriendImage> {
+                return input.replaced<FriendImage> {
                     contact.updateFriendImageForGroupMessage(it)
                 }
-                return input
             }
 
             suspend fun GroupImpl.fixImageFileId(image: OfflineGroupImage) {
@@ -337,16 +338,18 @@ internal abstract class OutgoingMessagePhasesCommon {
         name: String
     ) : AbstractPhase<MessagePipelineContext<C>, List<OutgoingPacket>?, List<OutgoingPacket>?>(name) {
         override suspend fun MessagePipelineContext<C>.doPhase(input: List<OutgoingPacket>?): List<OutgoingPacket>? {
-            return input ?: createPacketsImpl(attributes[KEY_FINAL_MESSAGE_CHAIN])
+            return input ?: createPacketsImpl(attributes[KEY_FINAL_MESSAGE_CHAIN])?.also {
+                attributes[KEY_PACKET_TRACE] = name
+            }
         }
 
         protected abstract suspend fun MessagePipelineContext<C>.createPacketsImpl(chain: MessageChain): List<OutgoingPacket>?
     }
 
     @PhaseMarker
-    class CreatePacketsForMusicShare<in C : AbstractContact> @PhaseMarker constructor(
-        private val specialMessageSourceStrategy: SpecialMessageSourceStrategy<C>
-    ) : CreatePacketsPhase<C>("CreatePacketsForMusicShare") {
+    fun <C : AbstractContact> CreatePacketsForMusicShare(
+        specialMessageSourceStrategy: SpecialMessageSourceStrategy<C>
+    ) = object : CreatePacketsPhase<C>("CreatePacketsForMusicShare") {
         override suspend fun MessagePipelineContext<C>.createPacketsImpl(chain: MessageChain): List<OutgoingPacket>? {
             val musicShare = chain[MusicShare] ?: return null
             attributes[KEY_MESSAGE_SOURCE_RESULT] =
@@ -369,9 +372,9 @@ internal abstract class OutgoingMessagePhasesCommon {
     }
 
     @PhaseMarker
-    class CreatePacketsForFileMessage<in C : AbstractContact> @PhaseMarker constructor(
-        private val specialMessageSourceStrategy: SpecialMessageSourceStrategy<C>
-    ) : CreatePacketsPhase<C>("CreatePacketsForFileMessage") {
+    fun <C : AbstractContact> CreatePacketsForFileMessage(
+        specialMessageSourceStrategy: SpecialMessageSourceStrategy<C>
+    ) = object : CreatePacketsPhase<C>("CreatePacketsForFileMessage") {
         override suspend fun MessagePipelineContext<C>.createPacketsImpl(chain: MessageChain): List<OutgoingPacket>? {
             val file = chain[FileMessage] ?: return null
             file.checkIsImpl()

+ 1 - 1
mirai-core/src/commonMain/kotlin/network/message/OutgoingMessagePhasesGroup.kt

@@ -48,7 +48,7 @@ internal object OutgoingMessagePhasesGroup : OutgoingMessagePhasesCommon(), Outg
     @Suppress("FunctionName")
     @PhaseMarker
     fun CreatePacketsNormal() = object : CreatePacketsFallback<GroupImpl>() {
-        override suspend fun MessagePipelineContext<GroupImpl>.createPacketsImpl(chain: MessageChain): List<OutgoingPacket>? {
+        override suspend fun MessagePipelineContext<GroupImpl>.createPacketsImpl(chain: MessageChain): List<OutgoingPacket> {
             return MessageSvcPbSendMsg.createToGroupImpl(
                 bot.client,
                 contact,

+ 6 - 0
mirai-core/src/commonMain/kotlin/network/message/OutgoingMessagePipeline.kt

@@ -93,6 +93,12 @@ internal interface MessagePipelineContext<out C : AbstractContact> : PipelineCon
 
         @JvmField
         val KEY_MESSAGE_SOURCE_RESULT = TypeKey<Deferred<OnlineMessageSource.Outgoing>>("messageSourceResult")
+
+        /**
+         * Origin phase name
+         */
+        @JvmField
+        val KEY_PACKET_TRACE = TypeKey<String>("packetTrace")
     }
 }
 

+ 52 - 0
mirai-core/src/commonMain/kotlin/network/pipeline/PipelineConfiguration.kt

@@ -9,6 +9,7 @@
 
 package net.mamoe.mirai.internal.network.pipeline
 
+import net.mamoe.mirai.utils.TestOnly
 import net.mamoe.mirai.utils.cast
 import net.mamoe.mirai.utils.forEachWithIndexer
 import net.mamoe.mirai.utils.uncheckedCast
@@ -101,6 +102,57 @@ internal class PipelineConfiguration<C : PipelineContext, InitialIn, FinalOut> {
     }
 }
 
+@TestOnly
+internal fun <C : PipelineContext, InitialIn, FinalOut> PipelineConfiguration<C, InitialIn, FinalOut>.replaceNode(
+    target: (node: Node<C, *, *>) -> Boolean,
+    node: Node<C, *, *>
+): Boolean {
+    mutableNodes.forEachIndexed { index, old ->
+        if (target(old)) {
+            mutableNodes.removeAt(index)
+            mutableNodes.add(index, node)
+            return true
+        }
+    }
+    return false
+}
+
+@TestOnly
+internal fun <C : PipelineContext, InitialIn, FinalOut> PipelineConfiguration<C, InitialIn, FinalOut>.replacePhase(
+    target: (node: Node<C, *, *>) -> Boolean,
+    name: String,
+    doPhase: suspend C.(input: Any?) -> Any?
+): Boolean = replaceNode(target, object : AbstractPhase<C, Any?, Any?>(name) {
+    override suspend fun C.doPhase(input: Any?): Any? {
+        return doPhase.invoke(this, input)
+    }
+})
+
+@TestOnly
+internal fun <C : PipelineContext, InitialIn, FinalOut> PipelineConfiguration<C, InitialIn, FinalOut>.insertPhase(
+    before: (node: Node<C, *, *>) -> Boolean,
+    name: String,
+    doPhase: suspend C.(input: Any?) -> Any?
+): Boolean = insertNode(before, object : AbstractPhase<C, Any?, Any?>(name) {
+    override suspend fun C.doPhase(input: Any?): Any? {
+        return doPhase.invoke(this, input)
+    }
+})
+
+@TestOnly
+internal fun <C : PipelineContext, InitialIn, FinalOut> PipelineConfiguration<C, InitialIn, FinalOut>.insertNode(
+    before: (node: Node<C, *, *>) -> Boolean,
+    node: Node<C, *, *>
+): Boolean {
+    mutableNodes.forEachIndexed { index, old ->
+        if (before(old)) {
+            mutableNodes.add(index, node)
+            return true
+        }
+    }
+    return false
+}
+
 internal fun PipelineConfiguration<*, *, *>.validate() {
     if (this.nodes.none() { it is Node.Finally<*> }) error("There is no Finally node in the configuration $this")
 }