Sfoglia il codice sorgente

Add `UnconsumedNoticesAlerter` and cleanup

Co-authored-by: Karlatemp <[email protected]>
Him188 4 anni fa
parent
commit
09265190e9

+ 2 - 2
mirai-core-utils/src/commonMain/kotlin/TypeSafeMap.kt

@@ -34,10 +34,10 @@ public value class TypeSafeMap(
         map[key] = value
     }
 
-    public fun <T> remove(key: TypeKey<T>): T? = map.remove(key).uncheckedCast()
+    public fun <T> remove(key: TypeKey<T>): T? = map.remove(key)?.uncheckedCast()
 }
 
 public inline fun buildTypeSafeMap(block: TypeSafeMap.() -> Unit): TypeSafeMap {
     contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
     return TypeSafeMap().apply(block)
-}
+}

+ 28 - 12
mirai-core/src/commonMain/kotlin/QQAndroidBot.kt

@@ -38,6 +38,8 @@ import net.mamoe.mirai.internal.network.handler.state.safe
 import net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException
 import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandlerFactory
 import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
+import net.mamoe.mirai.internal.network.notice.*
+import net.mamoe.mirai.internal.network.notice.decoders.MsgInfoDecoder
 import net.mamoe.mirai.internal.utils.subLogger
 import net.mamoe.mirai.utils.BotConfiguration
 import net.mamoe.mirai.utils.MiraiLogger
@@ -149,7 +151,20 @@ internal open class QQAndroidBot constructor(
 
         // There's no need to interrupt a broadcasting event when network handler closed.
         set(EventDispatcher, EventDispatcherImpl(bot.coroutineContext, logger.subLogger("EventDispatcher")))
-        set(NoticeProcessorPipeline, NoticeProcessorPipelineImpl(networkLogger.subLogger("NoticeProcessorPipeline")))
+
+        val pipelineLogger = networkLogger.subLogger("NoticeProcessor") //  shorten name
+        set(
+            NoticeProcessorPipeline,
+            NoticeProcessorPipelineImpl().apply {
+                registerProcessor(MsgInfoDecoder())
+                registerProcessor(FriendNoticeProcessor(pipelineLogger))
+                registerProcessor(GroupListNoticeProcessor(pipelineLogger))
+                registerProcessor(GroupMessageProcessor())
+                registerProcessor(PrivateMessageNoticeProcessor())
+                registerProcessor(OtherClientNoticeProcessor())
+                registerProcessor(UnconsumedNoticesAlerter(pipelineLogger))
+            },
+        )
 
         set(SsoProcessorContext, SsoProcessorContextImpl(bot))
         set(SsoProcessor, SsoProcessorImpl(get(SsoProcessorContext)))
@@ -164,34 +179,35 @@ internal open class QQAndroidBot constructor(
         set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger.subLogger("ContactUpdater")))
         set(
             BdhSessionSyncer,
-            BdhSessionSyncerImpl(configuration, components, networkLogger.subLogger("BotSessionSyncer"))
+            BdhSessionSyncerImpl(configuration, components, networkLogger.subLogger("BotSessionSyncer")),
         )
         set(
             MessageSvcSyncer,
-            MessageSvcSyncerImpl(bot, bot.coroutineContext, networkLogger.subLogger("MessageSvcSyncer"))
+            MessageSvcSyncerImpl(bot, bot.coroutineContext, networkLogger.subLogger("MessageSvcSyncer")),
         )
         set(
             EcdhInitialPublicKeyUpdater,
-            EcdhInitialPublicKeyUpdaterImpl(bot, networkLogger.subLogger("ECDHInitialPublicKeyUpdater"))
+            EcdhInitialPublicKeyUpdaterImpl(bot, networkLogger.subLogger("ECDHInitialPublicKeyUpdater")),
         )
         set(ServerList, ServerListImpl(networkLogger.subLogger("ServerList")))
         set(PacketLoggingStrategy, PacketLoggingStrategyImpl(bot))
         set(
-            PacketHandler, PacketHandlerChain(
+            PacketHandler,
+            PacketHandlerChain(
                 LoggingPacketHandlerAdapter(get(PacketLoggingStrategy), networkLogger),
                 EventBroadcasterPacketHandler(components),
-                CallPacketFactoryPacketHandler(bot)
-            )
+                CallPacketFactoryPacketHandler(bot),
+            ),
         )
         set(PacketCodec, PacketCodecImpl())
         set(
             OtherClientUpdater,
-            OtherClientUpdaterImpl(bot, components, networkLogger.subLogger("OtherClientUpdater"))
+            OtherClientUpdaterImpl(bot, components, networkLogger.subLogger("OtherClientUpdater")),
         )
         set(ConfigPushSyncer, ConfigPushSyncerImpl())
         set(
             AccountSecretsManager,
-            configuration.createAccountsSecretsManager(bot.logger.subLogger("AccountSecretsManager"))
+            configuration.createAccountsSecretsManager(bot.logger.subLogger("AccountSecretsManager")),
         )
     }
 
@@ -213,13 +229,13 @@ internal open class QQAndroidBot constructor(
                 val context = NetworkHandlerContextImpl(
                     bot,
                     networkLogger,
-                    createNetworkLevelComponents()
+                    createNetworkLevelComponents(),
                 )
                 NettyNetworkHandlerFactory.create(
                     context,
-                    context[ServerList].pollAny().toSocketAddress()
+                    context[ServerList].pollAny().toSocketAddress(),
                 )
-            }
+            },
         ) // We can move the factory to configuration but this is not necessary for now.
     }
 

+ 1 - 1
mirai-core/src/commonMain/kotlin/contact/StrangerImpl.kt

@@ -54,7 +54,7 @@ internal class StrangerImpl(
         }
         bot.network.run {
             StrangerList.DelStranger(bot.client, this@StrangerImpl)
-                .sendAndExpect<StrangerList.DelStranger.Response>().also {
+                .sendAndExpect().also {
                     check(it.isSuccess) { "delete Stranger failed: ${it.result}" }
                 }
         }

+ 31 - 9
mirai-core/src/commonMain/kotlin/network/components/NoticeProcessorPipeline.kt

@@ -24,9 +24,10 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMs
 import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
 import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetMsg
 import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.OnlinePushPbPushTransMsg
-import net.mamoe.mirai.utils.MiraiLogger
+import net.mamoe.mirai.utils.TypeKey
 import net.mamoe.mirai.utils.TypeSafeMap
 import net.mamoe.mirai.utils.uncheckedCast
+import java.util.*
 import java.util.concurrent.ConcurrentLinkedQueue
 import java.util.concurrent.locks.ReentrantReadWriteLock
 import kotlin.concurrent.read
@@ -54,14 +55,24 @@ internal interface PipelineContext {
     val isConsumed: Boolean
 
     /**
-     * Mark the input as consumed so that there will not be warnings like 'Unknown type xxx'. This will not stop the pipeline.
+     * Marks the input as consumed so that there will not be warnings like 'Unknown type xxx'. This will not stop the pipeline.
      *
      * If this is executed, make sure you provided all information important for debugging.
      *
      * You need to invoke [markAsConsumed] if your implementation includes some `else` branch which covers all situations,
      * and throws a [contextualBugReportException] or logs something.
      */
-    fun markAsConsumed()
+    @ConsumptionMarker
+    fun NoticeProcessor.markAsConsumed()
+
+    /**
+     * Marks the input as not consumed, if it was marked by this [NoticeProcessor].
+     */
+    @ConsumptionMarker
+    fun NoticeProcessor.markNotConsumed()
+
+    @DslMarker
+    annotation class ConsumptionMarker // to give an explicit color.
 
 
     val collected: Collection<Packet>
@@ -89,13 +100,16 @@ internal interface PipelineContext {
      * @return result collected from processors. This would also have been collected to this context (where you call [fire]).
      */
     suspend fun fire(data: Any?): Collection<Packet>
+
+    companion object {
+        val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync")
+        val PipelineContext.fromSync get() = attributes[KEY_FROM_SYNC]
+    }
 }
 
 internal inline val PipelineContext.context get() = this
 
-internal class NoticeProcessorPipelineImpl(
-    private val logger: MiraiLogger,
-) : NoticeProcessorPipeline {
+internal class NoticeProcessorPipelineImpl : NoticeProcessorPipeline {
     private val processors = ArrayList<NoticeProcessor>()
     private val processorsLock = ReentrantReadWriteLock()
 
@@ -110,9 +124,17 @@ internal class NoticeProcessorPipelineImpl(
         override val bot: QQAndroidBot, override val attributes: TypeSafeMap,
     ) : PipelineContext {
 
-        override var isConsumed: Boolean = false
-        override fun markAsConsumed() {
-            isConsumed = true
+        private val consumers: Stack<NoticeProcessor> = Stack()
+
+        override val isConsumed: Boolean = consumers.isNotEmpty()
+        override fun NoticeProcessor.markAsConsumed() {
+            consumers.push(this)
+        }
+
+        override fun NoticeProcessor.markNotConsumed() {
+            if (consumers.peek() === this) {
+                consumers.pop()
+            }
         }
 
         override val collected = ConcurrentLinkedQueue<Packet>()

+ 0 - 45
mirai-core/src/commonMain/kotlin/network/notice/BinaryMessageProcessor.kt

@@ -1,45 +0,0 @@
-/*
- * Copyright 2019-2021 Mamoe Technologies and contributors.
- *
- *  此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
- *  Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
- *
- *  https://github.com/mamoe/mirai/blob/master/LICENSE
- */
-
-package net.mamoe.mirai.internal.network.notice
-
-import net.mamoe.mirai.internal.message.contextualBugReportException
-import net.mamoe.mirai.internal.network.components.PipelineContext
-import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
-import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans.PbMsgInfo
-import net.mamoe.mirai.internal.utils._miraiContentToString
-import net.mamoe.mirai.utils.read
-
-internal class BinaryMessageProcessor : SimpleNoticeProcessor<PbMsgInfo>(type()), NewContactSupport {
-    override suspend fun PipelineContext.processImpl(data: PbMsgInfo) {
-        data.msgData.read<Unit> {
-            when (data.msgType) {
-                44 -> {
-                    TODO("removed")
-                }
-                34 -> {
-                    TODO("removed")
-                }
-                else -> {
-                    when {
-                        data.msgType == 529 && data.msgSubtype == 9 -> {
-                            TODO("removed")
-                        }
-                    }
-                    throw contextualBugReportException(
-                        "解析 OnlinePush.PbPushTransMsg, msgType=${data.msgType}",
-                        data._miraiContentToString(),
-                        null,
-                        "并描述此时机器人是否被踢出, 或是否有成员列表变更等动作."
-                    )
-                }
-            }
-        }
-    }
-}

+ 2 - 2
mirai-core/src/commonMain/kotlin/network/notice/FriendNoticeProcessor.kt

@@ -86,6 +86,7 @@ internal class FriendNoticeProcessor(
     }
 
     override suspend fun PipelineContext.processImpl(data: MsgType0x210) = data.context {
+        markAsConsumed()
         when (data.uSubMsgType) {
             0xB3L -> {
                 // 08 01 12 52 08 A2 FF 8C F0 03 10 00 1D 15 3D 90 5E 22 2E E6 88 91 E4 BB AC E5 B7 B2 E7 BB 8F E6 98 AF E5 A5 BD E5 8F 8B E5 95 A6 EF BC 8C E4 B8 80 E8 B5 B7 E6 9D A5 E8 81 8A E5 A4 A9 E5 90 A7 21 2A 09 48 69 6D 31 38 38 6D 6F 65 30 07 38 03 48 DD F1 92 B7 07
@@ -111,9 +112,8 @@ internal class FriendNoticeProcessor(
                 val body = vProtobuf.loadAs(SubMsgType0x115.MsgBody.serializer())
                 handleInputStatusChanged(body)
             }
-            else -> return
+            else -> markNotConsumed()
         }
-        markAsConsumed()
     }
 
     private fun PipelineContext.handleInputStatusChanged(body: SubMsgType0x115.MsgBody) {

+ 50 - 28
mirai-core/src/commonMain/kotlin/network/notice/GroupListNoticeProcessor.kt

@@ -60,6 +60,7 @@ internal class GroupListNoticeProcessor(
 
     override suspend fun PipelineContext.processImpl(data: MsgType0x210) {
         if (data.uSubMsgType != 0x44L) return
+        markAsConsumed()
         val msg = data.vProtobuf.loadAs(Submsgtype0x44.Submsgtype0x44.MsgBody.serializer())
         if (msg.msgGroupMsgSync == null) return
 
@@ -328,34 +329,7 @@ internal class GroupListNoticeProcessor(
                     handleLeave(target, kind, operator, groupUin)
                 }
             }
-            else -> {
-                when {
-                    data.msgType == 529 && data.msgSubtype == 9 -> {
-                        /*
-                        PbMsgInfo#1773430973 {
-fromUin=0x0000000026BA1173(649728371)
-generalFlag=0x00000001(1)
-msgData=0A 07 70 72 69 6E 74 65 72 10 02 1A CD 02 0A 1F 53 61 6D 73 75 6E 67 20 4D 4C 2D 31 38 36 30 20 53 65 72 69 65 73 20 28 55 53 42 30 30 31 29 0A 16 4F 6E 65 4E 6F 74 65 20 66 6F 72 20 57 69 6E 64 6F 77 73 20 31 30 0A 19 50 68 61 6E 74 6F 6D 20 50 72 69 6E 74 20 74 6F 20 45 76 65 72 6E 6F 74 65 0A 11 4F 6E 65 4E 6F 74 65 20 28 44 65 73 6B 74 6F 70 29 0A 1D 4D 69 63 72 6F 73 6F 66 74 20 58 50 53 20 44 6F 63 75 6D 65 6E 74 20 57 72 69 74 65 72 0A 16 4D 69 63 72 6F 73 6F 66 74 20 50 72 69 6E 74 20 74 6F 20 50 44 46 0A 15 46 6F 78 69 74 20 50 68 61 6E 74 6F 6D 20 50 72 69 6E 74 65 72 0A 03 46 61 78 32 09 0A 03 6A 70 67 10 01 18 00 32 0A 0A 04 6A 70 65 67 10 01 18 00 32 09 0A 03 70 6E 67 10 01 18 00 32 09 0A 03 67 69 66 10 01 18 00 32 09 0A 03 62 6D 70 10 01 18 00 32 09 0A 03 64 6F 63 10 01 18 01 32 0A 0A 04 64 6F 63 78 10 01 18 01 32 09 0A 03 74 78 74 10 00 18 00 32 09 0A 03 70 64 66 10 01 18 01 32 09 0A 03 70 70 74 10 01 18 01 32 0A 0A 04 70 70 74 78 10 01 18 01 32 09 0A 03 78 6C 73 10 01 18 01 32 0A 0A 04 78 6C 73 78 10 01 18 01
-msgSeq=0x00001AFF(6911)
-msgSubtype=0x00000009(9)
-msgTime=0x5FDF21A3(1608458659)
-msgType=0x00000211(529)
-msgUid=0x010000005FDEE04C(72057595646369868)
-realMsgTime=0x5FDF21A3(1608458659)
-svrIp=0x3E689409(1047041033)
-toUin=0x0000000026BA1173(649728371)
-}
-                         */
-                        return
-                    }
-                }
-                throw contextualBugReportException(
-                    "解析 OnlinePush.PbPushTransMsg, msgType=${data.msgType}",
-                    data._miraiContentToString(),
-                    null,
-                    "并描述此时机器人是否被踢出, 或是否有成员列表变更等动作."
-                )
-            }
+            else -> markNotConsumed()
         }
     }
 
@@ -476,4 +450,52 @@ toUin=0x0000000026BA1173(649728371)
             }
         }
     }
+
+
+    // backup, copied from old code
+    /*
+    34 -> { // 主动入群
+
+        // 回答了问题, 还需要管理员审核
+        // msgContent=27 0B 60 E7 01 76 E4 B8 DD 82 00 30 45 41 31 30 35 35 42 44 39 39 42 35 37 46 44 31 41 31 46 36 42 43 42 43 33 43 42 39 34 34 38 31 33 34 42 36 31 46 38 45 43 39 38 38 43 39 37 33
+        // msgContent=27 0B 60 E7 01 76 E4 B8 DD 02 00 30 44 44 41 43 44 33 35 43 31 39 34 30 46 42 39 39 34 46 43 32 34 43 39 32 33 39 31 45 42 35 32 33 46 36 30 37 35 42 41 38 42 30 30 37 42 36 42 41
+        // 回答正确问题, 直接加入
+
+        //            27 0B 60 E7 01 76 E4 B8 DD 82 00 30 43 37 37 39 41 38 32 44 38 33 30 35 37 38 31 33 37 45 42 39 35 43 42 45 36 45 43 38 36 34 38 44 34 35 44 42 33 44 45 37 34 41 36 30 33 37 46 45
+        // 提交验证消息加入, 需要审核
+
+        // 被踢了??
+        // msgContent=27 0B 60 E7 01 76 E4 B8 DD 83 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 46 46 32 33 36 39 35 33 31 37 42 44 46 37 43 36 39 34 37 41 45 38 39 43 45 43 42 46 33 41 37 35 39 34 39 45 36 37 33 37 31 41 39 44 33 33 45 33
+
+        /*
+        // 搜索后直接加入群
+
+        soutv 17:43:32 : 33类型的content = 27 0B 60 E7 01 07 6E 47 BA 82 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 32 30 39 39 42 39 41 46 32 39 41 35 42 33 46 34 32 30 44 36 44 36 39 35 44 38 45 34 35 30 46 30 45 30 38 45 31 41 39 42 46 46 45 32 30 32 34 35
+        soutv 17:43:32 : 主动入群content = 2A 3D F5 69 01 35 D7 10 EA 83 4C EF 4F DD 06 B9 DC C0 ED D4 B1 00 30 37 41 39 31 39 34 31 41 30 37 46 38 32 31 39 39 43 34 35 46 39 30 36 31 43 37 39 37 33 39 35 43 34 44 36 31 33 43 31 35 42 37 32 45 46 43 43 36
+         */
+
+        val group = bot.getGroupByUinOrNull(msgHead.fromUin)
+        group ?: return
+
+        msgBody.msgContent.soutv("主动入群content")
+
+        if (msgBody.msgContent.read {
+                discardExact(4) // group code
+                discardExact(1) // 1
+                discardExact(4) // requester uin
+                readByte().toInt().and(0xff)
+                // 0x02: 回答正确问题直接加入
+                // 0x82: 回答了问题, 或者有验证消息, 需要管理员审核
+                // 0x83: 回答正确问题直接加入
+            } != 0x82) {
+
+            if (group.members.contains(msgHead.authUin)) {
+                return
+            }
+            @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
+            return MemberJoinEvent.Active(group.newMember(getNewMemberInfo())
+                .also { group.members.delegate.addLast(it) })
+        } else return
+    }
+    */
 }

+ 7 - 1
mirai-core/src/commonMain/kotlin/network/notice/OtherClientNoticeProcessor.kt

@@ -109,8 +109,14 @@ internal class OtherClientNoticeProcessor : MixedNoticeProcessor() {
      */
     override suspend fun PipelineContext.processImpl(data: MsgComm.Msg) = data.context {
         if (msgHead.msgType != 529) return
+
+        // top_package/awbk.java:3765
         markAsConsumed() // todo check
-        if (msgHead.c2cCmd != 7) return
+        if (msgHead.c2cCmd != 7) {
+            // 各种垃圾
+            // 08 04 12 1E 08 E9 07 10 B7 F7 8B 80 02 18 E9 07 20 00 28 DD F1 92 B7 07 30 DD F1 92 B7 07 48 02 50 03 32 1E 08 88 80 F8 92 CD 84 80 80 10 10 01 18 00 20 01 2A 0C 0A 0A 08 01 12 06 E5 95 8A E5 95 8A
+            return
+        }
         val body = msgBody.msgContent.loadAs(SubMsgType0x7.MsgBody.serializer())
 
         val textMsg =

+ 5 - 3
mirai-core/src/commonMain/kotlin/network/notice/PrivateMessageNoticeProcessor.kt

@@ -15,9 +15,9 @@ import net.mamoe.mirai.internal.contact.*
 import net.mamoe.mirai.internal.getGroupByUin
 import net.mamoe.mirai.internal.message.toMessageChainOnline
 import net.mamoe.mirai.internal.network.components.PipelineContext
+import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.fromSync
 import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
 import net.mamoe.mirai.internal.network.components.SsoProcessor
-import net.mamoe.mirai.internal.network.notice.SystemMessageProcessor.Companion.fromSync
 import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
 import net.mamoe.mirai.utils.context
 
@@ -35,6 +35,7 @@ import net.mamoe.mirai.utils.context
  */
 internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg>(type()) {
     override suspend fun PipelineContext.processImpl(data: MsgComm.Msg) = data.context {
+        markAsConsumed()
         if (msgHead.fromUin == bot.id && fromSync) {
             // Bot send message to himself? or from other client? I am not the implementer.
             bot.client.sendFriendMessageSeq.updateIfSmallerThan(msgHead.msgSeq)
@@ -47,7 +48,6 @@ internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg
             208, // friend ptt, maybe also support stranger
             -> {
                 handlePrivateMessage(data, bot.getFriend(senderUin) ?: bot.getStranger(senderUin) ?: return)
-                markAsConsumed()
             }
 
             141, // group temp
@@ -55,7 +55,9 @@ internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg
                 val tmpHead = msgHead.c2cTmpMsgHead ?: return
                 val group = bot.getGroupByUin(tmpHead.groupUin) ?: return
                 handlePrivateMessage(data, group[senderUin] ?: return)
-                markAsConsumed()
+            }
+            else -> {
+                markNotConsumed()
             }
         }
 

+ 0 - 161
mirai-core/src/commonMain/kotlin/network/notice/SystemMessageProcessor.kt

@@ -1,161 +0,0 @@
-/*
- * Copyright 2019-2021 Mamoe Technologies and contributors.
- *
- *  此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
- *  Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
- *
- *  https://github.com/mamoe/mirai/blob/master/LICENSE
- */
-
-package net.mamoe.mirai.internal.network.notice
-
-import kotlinx.coroutines.sync.withLock
-import net.mamoe.mirai.internal.network.components.ContactUpdater
-import net.mamoe.mirai.internal.network.components.MsgCommonMsgProcessor
-import net.mamoe.mirai.internal.network.components.PipelineContext
-import net.mamoe.mirai.internal.network.components.SsoProcessor
-import net.mamoe.mirai.internal.network.handler.logger
-import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
-import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
-import net.mamoe.mirai.utils.TypeKey
-import net.mamoe.mirai.utils.debug
-import net.mamoe.mirai.utils.toUHexString
-
-internal class SystemMessageProcessor : MsgCommonMsgProcessor(), NewContactSupport {
-    companion object {
-        val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync")
-        val PipelineContext.fromSync get() = attributes[KEY_FROM_SYNC]
-    }
-
-    override suspend fun PipelineContext.processImpl(data: MsgComm.Msg): Unit = data.run {
-        // TODO: 2021/6/26 extract logic into multiple processors
-        when (msgHead.msgType) {
-            33 -> bot.components[ContactUpdater].groupListModifyLock.withLock {
-            }
-
-            34 -> { // 与 33 重复
-                return
-            }
-
-            38 -> bot.components[ContactUpdater].groupListModifyLock.withLock { // 建群
-                TODO("removed")
-            }
-
-            85 -> bot.components[ContactUpdater].groupListModifyLock.withLock { // 其他客户端入群
-                TODO("removed")
-            }
-
-            /*
-            34 -> { // 主动入群
-
-                // 回答了问题, 还需要管理员审核
-                // msgContent=27 0B 60 E7 01 76 E4 B8 DD 82 00 30 45 41 31 30 35 35 42 44 39 39 42 35 37 46 44 31 41 31 46 36 42 43 42 43 33 43 42 39 34 34 38 31 33 34 42 36 31 46 38 45 43 39 38 38 43 39 37 33
-                // msgContent=27 0B 60 E7 01 76 E4 B8 DD 02 00 30 44 44 41 43 44 33 35 43 31 39 34 30 46 42 39 39 34 46 43 32 34 43 39 32 33 39 31 45 42 35 32 33 46 36 30 37 35 42 41 38 42 30 30 37 42 36 42 41
-                // 回答正确问题, 直接加入
-
-                //            27 0B 60 E7 01 76 E4 B8 DD 82 00 30 43 37 37 39 41 38 32 44 38 33 30 35 37 38 31 33 37 45 42 39 35 43 42 45 36 45 43 38 36 34 38 44 34 35 44 42 33 44 45 37 34 41 36 30 33 37 46 45
-                // 提交验证消息加入, 需要审核
-
-                // 被踢了??
-                // msgContent=27 0B 60 E7 01 76 E4 B8 DD 83 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 46 46 32 33 36 39 35 33 31 37 42 44 46 37 43 36 39 34 37 41 45 38 39 43 45 43 42 46 33 41 37 35 39 34 39 45 36 37 33 37 31 41 39 44 33 33 45 33
-
-                /*
-                // 搜索后直接加入群
-
-                soutv 17:43:32 : 33类型的content = 27 0B 60 E7 01 07 6E 47 BA 82 3E 03 3F A2 06 B4 B4 BD A8 D5 DF 00 30 32 30 39 39 42 39 41 46 32 39 41 35 42 33 46 34 32 30 44 36 44 36 39 35 44 38 45 34 35 30 46 30 45 30 38 45 31 41 39 42 46 46 45 32 30 32 34 35
-                soutv 17:43:32 : 主动入群content = 2A 3D F5 69 01 35 D7 10 EA 83 4C EF 4F DD 06 B9 DC C0 ED D4 B1 00 30 37 41 39 31 39 34 31 41 30 37 46 38 32 31 39 39 43 34 35 46 39 30 36 31 43 37 39 37 33 39 35 43 34 44 36 31 33 43 31 35 42 37 32 45 46 43 43 36
-                 */
-
-                val group = bot.getGroupByUinOrNull(msgHead.fromUin)
-                group ?: return
-
-                msgBody.msgContent.soutv("主动入群content")
-
-                if (msgBody.msgContent.read {
-                        discardExact(4) // group code
-                        discardExact(1) // 1
-                        discardExact(4) // requester uin
-                        readByte().toInt().and(0xff)
-                        // 0x02: 回答正确问题直接加入
-                        // 0x82: 回答了问题, 或者有验证消息, 需要管理员审核
-                        // 0x83: 回答正确问题直接加入
-                    } != 0x82) {
-
-                    if (group.members.contains(msgHead.authUin)) {
-                        return
-                    }
-                    @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
-                    return MemberJoinEvent.Active(group.newMember(getNewMemberInfo())
-                        .also { group.members.delegate.addLast(it) })
-                } else return
-            }
-            */
-
-            //167 单向好友
-            166, 167 -> {
-                TODO("removed")
-            }
-            208 -> {
-                // friend ptt
-                TODO("removed")
-            }
-            529 -> {
-
-                // top_package/awbk.java:3765
-
-                when (msgHead.c2cCmd) {
-                    // other client sync
-                    7 -> {
-                        TODO("removed")
-                    }
-                }
-
-                // 各种垃圾
-                // 08 04 12 1E 08 E9 07 10 B7 F7 8B 80 02 18 E9 07 20 00 28 DD F1 92 B7 07 30 DD F1 92 B7 07 48 02 50 03 32 1E 08 88 80 F8 92 CD 84 80 80 10 10 01 18 00 20 01 2A 0C 0A 0A 08 01 12 06 E5 95 8A E5 95 8A
-            }
-            141 -> {
-
-                if (!bot.components[SsoProcessor].firstLoginSucceed || msgHead.fromUin == bot.id && !fromSync) {
-                    return
-                }
-                TODO("removed")
-            }
-            84, 87 -> { // 请求入群验证 和 被要求入群
-                bot.network.run {
-                    NewContact.SystemMsgNewGroup(bot.client).sendWithoutExpect()
-                }
-                return
-            }
-            187 -> { // 请求加好友验证
-                bot.network.run {
-                    NewContact.SystemMsgNewFriend(bot.client).sendWithoutExpect()
-                }
-                return
-            }
-            732 -> {
-                // unknown
-                // 前 4 byte 是群号
-                return
-            }
-            //陌生人添加信息
-            191 -> {
-                TODO("removed")
-            }
-            // 732:  27 0B 60 E7 0C 01 3E 03 3F A2 5E 90 60 E2 00 01 44 71 47 90 00 00 02 58
-            // 732:  27 0B 60 E7 11 00 40 08 07 20 E7 C1 AD B8 02 5A 36 08 B4 E7 E0 F0 09 1A 1A 08 9C D4 16 10 F7 D2 D8 F5 05 18 D0 E2 85 F4 06 20 00 28 00 30 B4 E7 E0 F0 09 2A 0E 08 00 12 0A 08 9C D4 16 10 00 18 01 20 00 30 00 38 00
-            // 732:  27 0B 60 E7 11 00 33 08 07 20 E7 C1 AD B8 02 5A 29 08 EE 97 85 E9 01 1A 19 08 EE D6 16 10 FF F2 D8 F5 05 18 E9 E7 A3 05 20 00 28 00 30 EE 97 85 E9 01 2A 02 08 00 30 00 38 00
-            else -> {
-                bot.network.logger.debug { "unknown PbGetMsg type ${msgHead.msgType}, data=${msgBody.msgContent.toUHexString()}" }
-                return
-            }
-        }
-    }
-
-    // kotlin bug, don't remove
-    private inline fun kotlinx.atomicfu.AtomicInt.loop(action: (Int) -> Unit): Nothing {
-        while (true) {
-            action(value)
-        }
-    }
-
-}

+ 135 - 0
mirai-core/src/commonMain/kotlin/network/notice/UnconsumedNoticesAlerter.kt

@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019-2021 Mamoe Technologies and contributors.
+ *
+ *  此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
+ *  Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
+ *
+ *  https://github.com/mamoe/mirai/blob/master/LICENSE
+ */
+
+package net.mamoe.mirai.internal.network.notice
+
+import net.mamoe.mirai.internal.message.contextualBugReportException
+import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
+import net.mamoe.mirai.internal.network.components.PipelineContext
+import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC
+import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
+import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
+import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus
+import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
+import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
+import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans
+import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
+import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
+import net.mamoe.mirai.internal.utils._miraiContentToString
+import net.mamoe.mirai.utils.MiraiLogger
+import net.mamoe.mirai.utils.debug
+import net.mamoe.mirai.utils.toUHexString
+
+internal class UnconsumedNoticesAlerter(
+    private val logger: MiraiLogger,
+) : MixedNoticeProcessor() {
+    override suspend fun PipelineContext.processImpl(data: MsgInfo) {
+        if (isConsumed) return
+        logger.debug { "Unknown kind ${data.shMsgType.toInt()}, data=${data.vMsg.toUHexString()}" }
+    }
+
+    override suspend fun PipelineContext.processImpl(data: MsgType0x210) {
+        if (isConsumed) return
+        when (data.uSubMsgType) {
+            0x26L, // VIP 进群提示
+            0x111L, // 提示共同好友
+            0xD4L, // bot 在其他客户端被踢或主动退出而同步情况
+            -> {
+                // Network(1994701021) 16:03:54 : unknown group 528 type 0x0000000000000026, data: 08 01 12 40 0A 06 08 F4 EF BB 8F 04 10 E7 C1 AD B8 02 18 01 22 2C 10 01 1A 1A 18 B4 DC F8 9B 0C 20 E7 C1 AD B8 02 28 06 30 02 A2 01 04 08 93 D6 03 A8 01 08 20 00 28 00 32 08 18 01 20 FE AF AF F5 05 28 00
+
+            }
+
+            0xE2L -> {
+                // unknown
+
+                // 0A 35 08 00 10 A2 FF 8C F0 03 1A 1B E5 90 8C E6 84 8F E4 BD A0 E7 9A 84 E5 8A A0 E5 A5 BD E5 8F 8B E8 AF B7 E6 B1 82 22 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B 28 01
+                // vProtobuf.loadAs(Msgtype0x210.serializer())
+            }
+
+        }
+        logger.debug { "Unknown group 528 type 0x${data.uSubMsgType.toUHexString("")}, data: " + data.vProtobuf.toUHexString() }
+    }
+
+    override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {
+        if (isConsumed) return
+        logger.debug { "Unknown group 732 type ${data.kind}, data: " + data.buf.toUHexString() }
+    }
+
+    override suspend fun PipelineContext.processImpl(data: OnlinePushTrans.PbMsgInfo) {
+        if (isConsumed) return
+        when {
+            data.msgType == 529 && data.msgSubtype == 9 -> {
+                /*
+                PbMsgInfo#1773430973 {
+                    fromUin=0x0000000026BA1173(649728371)
+                    generalFlag=0x00000001(1)
+                    msgData=0A 07 70 72 69 6E 74 65 72 10 02 1A CD 02 0A 1F 53 61 6D 73 75 6E 67 20 4D 4C 2D 31 38 36 30 20 53 65 72 69 65 73 20 28 55 53 42 30 30 31 29 0A 16 4F 6E 65 4E 6F 74 65 20 66 6F 72 20 57 69 6E 64 6F 77 73 20 31 30 0A 19 50 68 61 6E 74 6F 6D 20 50 72 69 6E 74 20 74 6F 20 45 76 65 72 6E 6F 74 65 0A 11 4F 6E 65 4E 6F 74 65 20 28 44 65 73 6B 74 6F 70 29 0A 1D 4D 69 63 72 6F 73 6F 66 74 20 58 50 53 20 44 6F 63 75 6D 65 6E 74 20 57 72 69 74 65 72 0A 16 4D 69 63 72 6F 73 6F 66 74 20 50 72 69 6E 74 20 74 6F 20 50 44 46 0A 15 46 6F 78 69 74 20 50 68 61 6E 74 6F 6D 20 50 72 69 6E 74 65 72 0A 03 46 61 78 32 09 0A 03 6A 70 67 10 01 18 00 32 0A 0A 04 6A 70 65 67 10 01 18 00 32 09 0A 03 70 6E 67 10 01 18 00 32 09 0A 03 67 69 66 10 01 18 00 32 09 0A 03 62 6D 70 10 01 18 00 32 09 0A 03 64 6F 63 10 01 18 01 32 0A 0A 04 64 6F 63 78 10 01 18 01 32 09 0A 03 74 78 74 10 00 18 00 32 09 0A 03 70 64 66 10 01 18 01 32 09 0A 03 70 70 74 10 01 18 01 32 0A 0A 04 70 70 74 78 10 01 18 01 32 09 0A 03 78 6C 73 10 01 18 01 32 0A 0A 04 78 6C 73 78 10 01 18 01
+                    msgSeq=0x00001AFF(6911)
+                    msgSubtype=0x00000009(9)
+                    msgTime=0x5FDF21A3(1608458659)
+                    msgType=0x00000211(529)
+                    msgUid=0x010000005FDEE04C(72057595646369868)
+                    realMsgTime=0x5FDF21A3(1608458659)
+                    svrIp=0x3E689409(1047041033)
+                    toUin=0x0000000026BA1173(649728371)
+                }
+                 */
+                return
+            }
+        }
+        throw contextualBugReportException(
+            "解析 OnlinePush.PbPushTransMsg, msgType=${data.msgType}",
+            data._miraiContentToString(),
+            null,
+            "并描述此时机器人是否被踢出, 或是否有成员列表变更等动作.",
+        )
+    }
+
+    override suspend fun PipelineContext.processImpl(data: MsgOnlinePush.PbPushMsg) {
+        if (isConsumed) return
+
+    }
+
+    override suspend fun PipelineContext.processImpl(data: MsgComm.Msg) {
+        if (isConsumed) return
+        when (data.msgHead.msgType) {
+            732 -> {
+                // 732:  27 0B 60 E7 0C 01 3E 03 3F A2 5E 90 60 E2 00 01 44 71 47 90 00 00 02 58
+                // 732:  27 0B 60 E7 11 00 40 08 07 20 E7 C1 AD B8 02 5A 36 08 B4 E7 E0 F0 09 1A 1A 08 9C D4 16 10 F7 D2 D8 F5 05 18 D0 E2 85 F4 06 20 00 28 00 30 B4 E7 E0 F0 09 2A 0E 08 00 12 0A 08 9C D4 16 10 00 18 01 20 00 30 00 38 00
+                // 732:  27 0B 60 E7 11 00 33 08 07 20 E7 C1 AD B8 02 5A 29 08 EE 97 85 E9 01 1A 19 08 EE D6 16 10 FF F2 D8 F5 05 18 E9 E7 A3 05 20 00 28 00 30 EE 97 85 E9 01 2A 02 08 00 30 00 38 00
+
+                // unknown
+                // 前 4 byte 是群号
+            }
+            84, 87 -> { // 请求入群验证 和 被要求入群
+                bot.network.run {
+                    NewContact.SystemMsgNewGroup(bot.client).sendWithoutExpect()
+                }
+            }
+            187 -> { // 请求加好友验证
+                bot.network.run {
+                    NewContact.SystemMsgNewFriend(bot.client).sendWithoutExpect()
+                }
+            }
+            else -> {
+                logger.debug { "unknown PbGetMsg type ${data.msgHead.msgType}, data=${data.msgBody.msgContent.toUHexString()}" }
+            }
+        }
+    }
+
+    override suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) {
+        if (isConsumed) return
+        TODO("Not yet implemented")
+    }
+
+    override suspend fun PipelineContext.processImpl(data: RequestPushStatus) {
+        if (isConsumed) return
+        TODO("Not yet implemented")
+    }
+}

+ 4 - 11
mirai-core/src/commonMain/kotlin/network/notice/decoders/MsgInfoDecoder.kt

@@ -19,18 +19,14 @@ import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
 import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
 import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
 import net.mamoe.mirai.internal.utils.io.serialization.loadAs
-import net.mamoe.mirai.utils.MiraiLogger
-import net.mamoe.mirai.utils.debug
 import net.mamoe.mirai.utils.read
-import net.mamoe.mirai.utils.toUHexString
 
 /**
  * Decodes [MsgInfo] and re-fire [MsgType0x210] or [MsgType0x2DC]
  */
-internal class MsgInfoDecoder(
-    private val logger: MiraiLogger,
-) : SimpleNoticeProcessor<MsgInfo>(type()) {
+internal class MsgInfoDecoder : SimpleNoticeProcessor<MsgInfo>(type()) {
     override suspend fun PipelineContext.processImpl(data: MsgInfo) {
+        markAsConsumed()
         when (data.shMsgType.toUShort().toInt()) {
             // 528
             0x210 -> fire(data.vMsg.loadAs(MsgType0x210.serializer()))
@@ -47,10 +43,7 @@ internal class MsgInfoDecoder(
                     fire(MsgType0x2DC(kind, group, this.readBytes()))
                 }
             }
-
-            else -> {
-                logger.debug { "Unknown kind ${data.shMsgType.toInt()}, data=${data.vMsg.toUHexString()}" }
-            }
+            else -> markNotConsumed()
         }
     }
 }
@@ -58,5 +51,5 @@ internal class MsgInfoDecoder(
 internal class MsgType0x2DC(
     val kind: Int, // inner kind, read from vMsg
     val group: GroupImpl,
-    val buf: ByteArray
+    val buf: ByteArray,
 )

+ 0 - 25
mirai-core/src/commonMain/kotlin/network/notice/decoders/MsgType0x210Decoder.kt

@@ -1,25 +0,0 @@
-/*
- * Copyright 2019-2021 Mamoe Technologies and contributors.
- *
- *  此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
- *  Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
- *
- *  https://github.com/mamoe/mirai/blob/master/LICENSE
- */
-
-package net.mamoe.mirai.internal.network.notice.decoders
-
-import net.mamoe.mirai.internal.network.components.PipelineContext
-import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
-import net.mamoe.mirai.internal.network.protocol.data.jce.MsgType0x210
-
-internal class MsgType0x210Decoder : SimpleNoticeProcessor<MsgType0x210>(type()) {
-    override suspend fun PipelineContext.processImpl(data: MsgType0x210) {
-        when (data.uSubMsgType) {
-            0x8AL -> {
-            }
-            else -> {
-            }
-        }
-    }
-}

+ 5 - 8
mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt

@@ -24,8 +24,7 @@ import net.mamoe.mirai.internal.QQAndroidBot
 import net.mamoe.mirai.internal.network.MultiPacket
 import net.mamoe.mirai.internal.network.Packet
 import net.mamoe.mirai.internal.network.QQAndroidClient
-import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline
-import net.mamoe.mirai.internal.network.notice.SystemMessageProcessor
+import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.KEY_FROM_SYNC
 import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
 import net.mamoe.mirai.internal.network.protocol.data.proto.MsgSvc
 import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
@@ -152,14 +151,12 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
                     QQAndroidClient.MessageSvcSyncData.PbGetMessageSyncId(
                         uid = msg.msgHead.msgUid,
                         sequence = msg.msgHead.msgSeq,
-                        time = msg.msgHead.msgTime
-                    )
+                        time = msg.msgHead.msgTime,
+                    ),
                 )
             }
-            .flatMapConcat { msg ->
-                bot.components.noticeProcessorPipeline
-                    .process(bot, msg, SystemMessageProcessor.KEY_FROM_SYNC to false)
-                    .asFlow()
+            .map { msg ->
+                bot.processPacketThroughPipeline(msg, KEY_FROM_SYNC to false)
             }
 
         val list: List<Packet> = messages.toList()

+ 2 - 2
mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/OnlinePush.PbC2CMsgSync.kt

@@ -13,7 +13,7 @@ import kotlinx.io.core.ByteReadPacket
 import net.mamoe.mirai.internal.QQAndroidBot
 import net.mamoe.mirai.internal.network.Packet
 import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline
-import net.mamoe.mirai.internal.network.notice.SystemMessageProcessor
+import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.KEY_FROM_SYNC
 import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
 import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
 import net.mamoe.mirai.internal.network.toPacket
@@ -26,7 +26,7 @@ internal object PbC2CMsgSync : IncomingPacketFactory<Packet>(
         return bot.components.noticeProcessorPipeline.process(
             bot = bot,
             data = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer()).msg,
-            attributes = SystemMessageProcessor.KEY_FROM_SYNC to true
+            attributes = KEY_FROM_SYNC to true,
         ).toPacket()
     }
 }

+ 0 - 44
mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/OnlinePush.ReqPush.kt

@@ -446,8 +446,6 @@ private object Transformers732 : Map<Int, Lambda732> by mapOf(
     }
 )
 
-internal val ignoredLambda528: Lambda528 = lambda528 { _, _ -> emptySequence() }
-
 internal interface Lambda528 {
     suspend operator fun invoke(msg: MsgType0x210, bot: QQAndroidBot, msgInfo: MsgInfo): Sequence<Packet>
 }
@@ -526,44 +524,6 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
             }
     },
 
-    // Network(1994701021) 16:03:54 : unknown group 528 type 0x0000000000000026, data: 08 01 12 40 0A 06 08 F4 EF BB 8F 04 10 E7 C1 AD B8 02 18 01 22 2C 10 01 1A 1A 18 B4 DC F8 9B 0C 20 E7 C1 AD B8 02 28 06 30 02 A2 01 04 08 93 D6 03 A8 01 08 20 00 28 00 32 08 18 01 20 FE AF AF F5 05 28 00
-    // VIP 进群提示
-    0x26L to ignoredLambda528,
-    // 提示共同好友
-    0x111L to ignoredLambda528,
-    // 新好友
-    0xB3L to lambda528 { bot ->
-        TODO("removed")
-    },
-    0xE2L to lambda528 { _ ->
-        // TODO: unknown. maybe messages.
-        // 0A 35 08 00 10 A2 FF 8C F0 03 1A 1B E5 90 8C E6 84 8F E4 BD A0 E7 9A 84 E5 8A A0 E5 A5 BD E5 8F 8B E8 AF B7 E6 B1 82 22 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B 28 01
-        // vProtobuf.loadAs(Msgtype0x210.serializer())
-
-        return@lambda528 emptySequence()
-    },
-    0x44L to lambda528 { bot ->
-        TODO("removed")
-    },
-    // bot 在其他客户端被踢或主动退出而同步情况
-    0xD4L to lambda528 { _ ->
-        // this.soutv("0x210")
-        /* @Serializable
-         data class SubD4(
-             // ok
-             val uin: Long
-         ) : ProtoBuf
-
-         val uin = vProtobuf.loadAs(SubD4.serializer()).uin
-         val group = bot.getGroupByUinOrNull(uin) ?: bot.getGroupOrNull(uin)
-         return@lambda528 if (group != null && bot.groups.delegate.remove(group)) {
-             group.cancel(CancellationException("Being kicked"))
-             sequenceOf(BotLeaveEvent.Active(group))
-         } else emptySequence()*/
-
-        //ignore
-        return@lambda528 emptySequence()
-    },
     //戳一戳信息等
     0x122L to lambda528 { bot, msgInfo ->
         val body = vProtobuf.loadAs(Submsgtype0x122.Submsgtype0x122.MsgBody.serializer())
@@ -618,10 +578,6 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
             }
         }
     },
-    //好友输入状态
-    0x115L to lambda528 { bot ->
-        TODO("removed")
-    },
     // 群相关,  ModFriendRemark, DelFriend, ModGroupProfile
     0x27L to lambda528 { bot ->
         fun ModGroupProfile.transform(bot: QQAndroidBot): Sequence<Packet> {