Redesign notice handling and introduce NoticeProcessorPipeline part 3:

- Extract `SyncController`;
- Add super type `ProtocolStruct` to `ProtoBuf` and `JceStruct` to standardize `NoticeProcessorPipeline.process`
- and other implementations for pipeline
This commit is contained in:
Him188 2021-06-28 19:44:33 +08:00
parent be4423c993
commit 1b80fbc1e6
27 changed files with 436 additions and 436 deletions

View File

@ -241,6 +241,12 @@ public fun String.truncated(length: Int, truncated: String = "..."): String {
} else this } else this
} }
/**
* Similar to [run] bot with [Unit] return type.
*
* You should not reference to [T] directly in the [block].
*/
// can convert to contextual receiver in the future, or there might be a stdlib function which we can delegate to.
public inline fun <T> T.context(block: T.() -> Unit) { public inline fun <T> T.context(block: T.() -> Unit) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return block() return block()

View File

@ -156,7 +156,8 @@ internal open class QQAndroidBot constructor(
set( set(
NoticeProcessorPipeline, NoticeProcessorPipeline,
NoticeProcessorPipelineImpl().apply { NoticeProcessorPipelineImpl().apply {
registerProcessor(MsgInfoDecoder()) registerProcessor(MsgInfoDecoder(pipelineLogger))
registerProcessor(FriendNoticeProcessor(pipelineLogger)) registerProcessor(FriendNoticeProcessor(pipelineLogger))
registerProcessor(GroupListNoticeProcessor(pipelineLogger)) registerProcessor(GroupListNoticeProcessor(pipelineLogger))
registerProcessor(GroupMessageProcessor()) registerProcessor(GroupMessageProcessor())
@ -217,6 +218,7 @@ internal open class QQAndroidBot constructor(
open fun createNetworkLevelComponents(): ComponentStorage { open fun createNetworkLevelComponents(): ComponentStorage {
return ConcurrentComponentStorage { return ConcurrentComponentStorage {
set(BotClientHolder, BotClientHolderImpl(bot, networkLogger.subLogger("BotClientHolder"))) set(BotClientHolder, BotClientHolderImpl(bot, networkLogger.subLogger("BotClientHolder")))
set(SyncController, SyncControllerImpl())
}.withFallback(defaultBotLevelComponents) }.withFallback(defaultBotLevelComponents)
} }

View File

@ -9,26 +9,26 @@
package net.mamoe.mirai.internal.message package net.mamoe.mirai.internal.message
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
internal data class ContextualBugReportException(
override val message: String,
override val cause: Throwable?,
) : IllegalStateException()
internal fun contextualBugReportException( internal fun contextualBugReportException(
context: String, context: String,
forDebug: String, forDebug: String,
e: Throwable? = null, e: Throwable? = null,
additional: String = "", additional: String = "",
): IllegalStateException { ): ContextualBugReportException {
return IllegalStateException( return ContextualBugReportException(
"$context 时遇到了意料之中的问题. 请完整复制此日志提交给 mirai: https://github.com/mamoe/mirai/issues/new $additional 调试信息: $forDebug", "$context 时遇到了意料之中的问题. 请完整复制此日志提交给 mirai: https://github.com/mamoe/mirai/issues/new $additional 调试信息: $forDebug",
e e,
) )
} }
@OptIn(ExperimentalContracts::class)
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "RESULT_CLASS_IN_RETURN_TYPE")
@kotlin.internal.InlineOnly
internal inline fun <R> runWithBugReport(context: String, forDebug: () -> String, block: () -> R): R { internal inline fun <R> runWithBugReport(context: String, forDebug: () -> String, block: () -> R): R {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)

View File

@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.network
import net.mamoe.mirai.internal.AbstractBot import net.mamoe.mirai.internal.AbstractBot
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
/* /*
@ -42,9 +43,11 @@ internal fun Collection<Packet>.toPacket(): Packet {
} }
internal fun MultiPacket(delegate: Collection<Packet>): MultiPacket = MultiPacketImpl(delegate) internal fun MultiPacket(delegate: Collection<Packet>): MultiPacket = MultiPacketImpl(delegate)
internal fun MultiPacket(delegate: Packet): MultiPacket =
if (delegate is MultiPacket) delegate else MultiPacket(listOf(delegate))
internal open class MultiPacketImpl( internal open class MultiPacketImpl(
val delegate: Collection<Packet> val delegate: Collection<Packet>,
) : MultiPacket, Collection<Packet> by delegate { ) : MultiPacket, Collection<Packet> by delegate {
override fun toString(): String = delegate.joinToString( override fun toString(): String = delegate.joinToString(
@ -56,6 +59,7 @@ internal open class MultiPacketImpl(
internal class ParseErrorPacket( internal class ParseErrorPacket(
val data: ProtocolStruct,
val error: Throwable, val error: Throwable,
val direction: Direction = Direction.TO_BOT_LOGGER, val direction: Direction = Direction.TO_BOT_LOGGER,
) : Packet, Packet.NoLog { ) : Packet, Packet.NoLog {

View File

@ -11,7 +11,6 @@
package net.mamoe.mirai.internal.network package net.mamoe.mirai.internal.network
import kotlinx.atomicfu.AtomicBoolean
import kotlinx.atomicfu.AtomicInt import kotlinx.atomicfu.AtomicInt
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic
import kotlinx.io.core.String import kotlinx.io.core.String
@ -21,7 +20,6 @@ import net.mamoe.mirai.internal.BotAccount
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.components.AccountSecrets import net.mamoe.mirai.internal.network.components.AccountSecrets
import net.mamoe.mirai.internal.network.components.SsoSession import net.mamoe.mirai.internal.network.components.SsoSession
import net.mamoe.mirai.internal.network.protocol.SyncingCacheList
import net.mamoe.mirai.internal.network.protocol.data.jce.FileStoragePushFSSvcList import net.mamoe.mirai.internal.network.protocol.data.jce.FileStoragePushFSSvcList
import net.mamoe.mirai.internal.network.protocol.packet.Tlv import net.mamoe.mirai.internal.network.protocol.packet.Tlv
import net.mamoe.mirai.internal.utils.AtomicIntSeq import net.mamoe.mirai.internal.utils.AtomicIntSeq
@ -142,60 +140,6 @@ internal open class QQAndroidClient(
} }
} }
class MessageSvcSyncData {
val firstNotify: AtomicBoolean = atomic(true)
var latestMsgNewGroupTime: Long = currentTimeSeconds()
var latestMsgNewFriendTime: Long = currentTimeSeconds()
@Volatile
var syncCookie: ByteArray? = null
var pubAccountCookie = EMPTY_BYTE_ARRAY
var msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY
internal data class PbGetMessageSyncId(
val uid: Long,
val sequence: Int,
val time: Int
)
val pbGetMessageCacheList = SyncingCacheList<PbGetMessageSyncId>()
internal data class SystemMsgNewSyncId(
val sequence: Long,
val time: Long
)
val systemMsgNewGroupCacheList = SyncingCacheList<SystemMsgNewSyncId>(10)
val systemMsgNewFriendCacheList = SyncingCacheList<SystemMsgNewSyncId>(10)
internal data class PbPushTransMsgSyncId(
val uid: Long,
val sequence: Int,
val time: Int
)
val pbPushTransMsgCacheList = SyncingCacheList<PbPushTransMsgSyncId>(10)
internal data class OnlinePushReqPushSyncId(
val uid: Long,
val sequence: Short,
val time: Long
)
val onlinePushReqPushCacheList = SyncingCacheList<OnlinePushReqPushSyncId>(50)
internal data class PendingGroupMessageReceiptSyncId(
val messageRandom: Int,
)
val pendingGroupMessageReceiptCacheList = SyncingCacheList<PendingGroupMessageReceiptSyncId>(50)
}
val syncingController = MessageSvcSyncData()
var t150: Tlv? = null var t150: Tlv? = null
var rollbackSig: ByteArray? = null var rollbackSig: ByteArray? = null
var ipFromT149: ByteArray? = null var ipFromT149: ByteArray? = null

View File

@ -12,10 +12,10 @@ package net.mamoe.mirai.internal.network.components
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.message.contextualBugReportException import net.mamoe.mirai.internal.message.contextualBugReportException
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.ParseErrorPacket
import net.mamoe.mirai.internal.network.component.ComponentKey import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.component.ComponentStorage import net.mamoe.mirai.internal.network.component.ComponentStorage
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC 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.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus 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.MsgComm
@ -24,8 +24,11 @@ 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.data.proto.Structmsg
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetMsg 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.internal.network.protocol.packet.chat.receive.OnlinePushPbPushTransMsg
import net.mamoe.mirai.internal.network.toPacket
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
import net.mamoe.mirai.utils.TypeKey import net.mamoe.mirai.utils.TypeKey
import net.mamoe.mirai.utils.TypeSafeMap import net.mamoe.mirai.utils.TypeSafeMap
import net.mamoe.mirai.utils.toDebugString
import net.mamoe.mirai.utils.uncheckedCast import net.mamoe.mirai.utils.uncheckedCast
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
@ -34,21 +37,35 @@ import kotlin.concurrent.read
import kotlin.concurrent.write import kotlin.concurrent.write
import kotlin.reflect.KClass import kotlin.reflect.KClass
internal typealias ProcessResult = Collection<Packet>
/** /**
* Centralized processor pipeline for [MessageSvcPbGetMsg] and [OnlinePushPbPushTransMsg] * Centralized processor pipeline for [MessageSvcPbGetMsg] and [OnlinePushPbPushTransMsg]
*/ */
internal interface NoticeProcessorPipeline { internal interface NoticeProcessorPipeline {
fun registerProcessor(processor: NoticeProcessor) fun registerProcessor(processor: NoticeProcessor)
suspend fun process(bot: QQAndroidBot, data: Any?, attributes: TypeSafeMap = TypeSafeMap()): Collection<Packet> /**
* Process [data] into [Packet]s. Exceptions are wrapped into [ParseErrorPacket]
*/
suspend fun process(bot: QQAndroidBot, data: ProtocolStruct, attributes: TypeSafeMap = TypeSafeMap()): ProcessResult
companion object : ComponentKey<NoticeProcessorPipeline> { companion object : ComponentKey<NoticeProcessorPipeline> {
val ComponentStorage.noticeProcessorPipeline get() = get(NoticeProcessorPipeline) val ComponentStorage.noticeProcessorPipeline get() = get(NoticeProcessorPipeline)
@JvmStatic
suspend inline fun QQAndroidBot.processPacketThroughPipeline(
data: ProtocolStruct,
attributes: TypeSafeMap = TypeSafeMap(),
): Packet {
return components.noticeProcessorPipeline.process(this, data, attributes).toPacket()
}
} }
} }
internal interface PipelineContext { internal interface PipelineContext {
val bot: QQAndroidBot val bot: QQAndroidBot
val attributes: TypeSafeMap val attributes: TypeSafeMap
@ -99,7 +116,7 @@ internal interface PipelineContext {
* *
* @return result collected from processors. This would also have been collected to this context (where you call [fire]). * @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> suspend fun fire(data: ProtocolStruct): ProcessResult
companion object { companion object {
val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync") val KEY_FROM_SYNC = TypeKey<Boolean>("fromSync")
@ -109,7 +126,7 @@ internal interface PipelineContext {
internal inline val PipelineContext.context get() = this internal inline val PipelineContext.context get() = this
internal class NoticeProcessorPipelineImpl : NoticeProcessorPipeline { internal open class NoticeProcessorPipelineImpl : NoticeProcessorPipeline {
private val processors = ArrayList<NoticeProcessor>() private val processors = ArrayList<NoticeProcessor>()
private val processorsLock = ReentrantReadWriteLock() private val processorsLock = ReentrantReadWriteLock()
@ -147,22 +164,37 @@ internal class NoticeProcessorPipelineImpl : NoticeProcessorPipeline {
this.collected.addAll(packets) this.collected.addAll(packets)
} }
override suspend fun fire(data: Any?): Collection<Packet> { override suspend fun fire(data: ProtocolStruct): ProcessResult {
return process(bot, data, attributes) return process(bot, data, attributes)
} }
} }
override suspend fun process(bot: QQAndroidBot, data: Any?, attributes: TypeSafeMap): Collection<Packet> { override suspend fun process(bot: QQAndroidBot, data: ProtocolStruct, attributes: TypeSafeMap): ProcessResult {
processorsLock.read { processorsLock.read {
val context = ContextImpl(bot, attributes) val context = ContextImpl(bot, attributes)
for (processor in processors) { for (processor in processors) {
kotlin.runCatching {
processor.process(context, data) processor.process(context, data)
}.onFailure { e ->
context.collect(
ParseErrorPacket(
data,
IllegalStateException(
"Exception in $processor while processing packet ${packetToString(data)}.",
e,
),
),
)
}
} }
return context.collected return context.collected
} }
} }
protected open fun packetToString(data: Any?): String =
data.toDebugString("mirai.network.debug.notice.pipeline.log.full")
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -203,7 +235,6 @@ internal abstract class MsgCommonMsgProcessor : SimpleNoticeProcessor<MsgComm.Ms
internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() { internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
final override suspend fun PipelineContext.processImpl(data: Any) { final override suspend fun PipelineContext.processImpl(data: Any) {
when (data) { when (data) {
is MsgInfo -> processImpl(data)
is PbMsgInfo -> processImpl(data) is PbMsgInfo -> processImpl(data)
is MsgOnlinePush.PbPushMsg -> processImpl(data) is MsgOnlinePush.PbPushMsg -> processImpl(data)
is MsgComm.Msg -> processImpl(data) is MsgComm.Msg -> processImpl(data)
@ -214,7 +245,6 @@ internal abstract class MixedNoticeProcessor : AnyNoticeProcessor() {
} }
} }
protected open suspend fun PipelineContext.processImpl(data: MsgInfo) {}
protected open suspend fun PipelineContext.processImpl(data: MsgType0x210) {} // 528 protected open suspend fun PipelineContext.processImpl(data: MsgType0x210) {} // 528
protected open suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {} // 732 protected open suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {} // 732
protected open suspend fun PipelineContext.processImpl(data: PbMsgInfo) {} protected open suspend fun PipelineContext.processImpl(data: PbMsgInfo) {}

View File

@ -54,7 +54,7 @@ internal class PacketLoggingStrategyImpl(
packet ?: return packet ?: return
if (!bot.logger.isEnabled && !logger.isEnabled) return if (!bot.logger.isEnabled && !logger.isEnabled) return
if (packet is ParseErrorPacket) { if (packet is ParseErrorPacket) {
packet.direction.getLogger(bot).error("Exception in parsing packet.", packet.error) packet.direction.getLogger(bot).error("Exception on parsing packet.", packet.error)
} }
if (packet is MultiPacket) { if (packet is MultiPacket) {
@ -64,7 +64,7 @@ internal class PacketLoggingStrategyImpl(
} }
logReceivedImpl(packet, incomingPacket, logger) logReceivedImpl(packet, incomingPacket, logger)
} },
) )
} }

View File

@ -0,0 +1,143 @@
/*
* 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.components
import kotlinx.atomicfu.AtomicBoolean
import kotlinx.atomicfu.atomic
import net.mamoe.mirai.internal.AbstractBot
import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.protocol.SyncingCacheList
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans
import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.utils.currentTimeSeconds
internal interface SyncController {
val firstNotify: AtomicBoolean
var latestMsgNewGroupTime: Long
var latestMsgNewFriendTime: Long
var syncCookie: ByteArray?
var pubAccountCookie: ByteArray
var msgCtrlBuf: ByteArray
fun syncOnlinePush(uid: Long, sequence: Short, time: Long): Boolean
fun syncNewFriend(sequence: Long, time: Long): Boolean
fun syncNewGroup(sequence: Long, time: Long): Boolean
fun syncGetMessage(uid: Long, sequence: Int, time: Int): Boolean
fun syncPushTrans(uid: Long, sequence: Int, time: Int): Boolean
fun syncGroupMessageReceipt(messageRandom: Int): Boolean
fun containsGroupMessageReceipt(messageRandom: Int): Boolean
companion object : ComponentKey<SyncController> {
val AbstractBot.syncController get() = this.components[SyncController]
val QQAndroidClient.syncController get() = bot.syncController
var QQAndroidClient.syncCookie
get() = bot.syncController.syncCookie
set(value) {
bot.syncController.syncCookie = value
}
}
}
internal fun SyncController.syncPushTrans(content: OnlinePushTrans.PbMsgInfo): Boolean =
syncPushTrans(content.msgUid, content.msgSeq, content.msgTime)
internal fun SyncController.syncGetMessage(
msgHead: MsgComm.MsgHead,
) = msgHead.run {
syncGetMessage(msgUid, msgSeq, msgTime)
}
internal fun SyncController.syncOnlinePush(
msgInfo: MsgInfo,
) = syncOnlinePush(
uid = msgInfo.lMsgUid ?: 0,
sequence = msgInfo.shMsgSeq,
time = msgInfo.uMsgTime,
)
internal class SyncControllerImpl : SyncController {
override val firstNotify: AtomicBoolean = atomic(true)
@Volatile
override var latestMsgNewGroupTime: Long = currentTimeSeconds()
@Volatile
override var latestMsgNewFriendTime: Long = currentTimeSeconds()
@Volatile
override var syncCookie: ByteArray? = null
@Volatile
override var pubAccountCookie = EMPTY_BYTE_ARRAY
@Volatile
override var msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY
private val pbGetMessageCacheList = SyncingCacheList<PbGetMessageSyncId>()
private val systemMsgNewGroupCacheList = SyncingCacheList<SystemMsgNewSyncId>(10)
private val systemMsgNewFriendCacheList = SyncingCacheList<SystemMsgNewSyncId>(10)
private val pbPushTransMsgCacheList = SyncingCacheList<PbPushTransMsgSyncId>(10)
private val onlinePushReqPushCacheList = SyncingCacheList<OnlinePushReqPushSyncId>(50)
private val pendingGroupMessageReceiptCacheList = SyncingCacheList<PendingGroupMessageReceiptSyncId>(50)
override fun syncOnlinePush(uid: Long, sequence: Short, time: Long): Boolean =
onlinePushReqPushCacheList.addCache(OnlinePushReqPushSyncId(uid, sequence, time))
override fun syncNewFriend(sequence: Long, time: Long): Boolean =
systemMsgNewFriendCacheList.addCache(SystemMsgNewSyncId(sequence, time))
override fun syncNewGroup(sequence: Long, time: Long): Boolean =
systemMsgNewGroupCacheList.addCache(SystemMsgNewSyncId(sequence, time))
override fun syncGetMessage(uid: Long, sequence: Int, time: Int): Boolean =
pbGetMessageCacheList.addCache(PbGetMessageSyncId(uid, sequence, time))
override fun syncPushTrans(uid: Long, sequence: Int, time: Int): Boolean =
pbPushTransMsgCacheList.addCache(PbPushTransMsgSyncId(uid, sequence, time))
override fun syncGroupMessageReceipt(messageRandom: Int): Boolean =
pendingGroupMessageReceiptCacheList.addCache(PendingGroupMessageReceiptSyncId(messageRandom))
override fun containsGroupMessageReceipt(messageRandom: Int): Boolean =
pendingGroupMessageReceiptCacheList.contains { it.messageRandom == messageRandom }
data class PbGetMessageSyncId(
val uid: Long,
val sequence: Int,
val time: Int,
)
data class SystemMsgNewSyncId(
val sequence: Long,
val time: Long,
)
data class PbPushTransMsgSyncId(
val uid: Long,
val sequence: Int,
val time: Int,
)
data class OnlinePushReqPushSyncId(
val uid: Long,
val sequence: Short,
val time: Long,
)
data class PendingGroupMessageReceiptSyncId(
val messageRandom: Int,
)
}

View File

@ -197,8 +197,8 @@ internal class GroupListNoticeProcessor(
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
override suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) = data.msg.context { override suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) = data.msg.context {
markAsConsumed()
if (this == null) return if (this == null) return
markAsConsumed()
when (subType) { when (subType) {
// 处理被邀请入群 或 处理成员入群申请 // 处理被邀请入群 或 处理成员入群申请
1 -> when (groupMsgType) { 1 -> when (groupMsgType) {
@ -259,16 +259,12 @@ internal class GroupListNoticeProcessor(
"解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=$groupMsgType", "解析 NewContact.SystemMsgNewGroup, subType=5, groupMsgType=$groupMsgType",
this._miraiContentToString(), this._miraiContentToString(),
null, null,
"并描述此时机器人是否被踢出群等" "并描述此时机器人是否被踢出群等",
) )
} }
} }
} }
else -> throw contextualBugReportException( else -> markNotConsumed()
"解析 NewContact.SystemMsgNewGroup, subType=$subType, groupMsgType=$groupMsgType",
forDebug = this._miraiContentToString(),
additional = "并尽量描述此时机器人是否正被邀请加入群, 或者是有有新群员加入此群"
)
} }
} }

View File

@ -25,6 +25,7 @@ import net.mamoe.mirai.internal.message.toMessageChainOnline
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.PipelineContext import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.notice.GroupMessageProcessor.MemberNick.Companion.generateMemberNickFromMember import net.mamoe.mirai.internal.network.notice.GroupMessageProcessor.MemberNick.Companion.generateMemberNickFromMember
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
@ -71,8 +72,9 @@ internal class GroupMessageProcessor : SimpleNoticeProcessor<MsgOnlinePush.PbPus
if (isFromSelfAccount) { if (isFromSelfAccount) {
val messageRandom = data.msg.msgBody.richText.attr?.random ?: return val messageRandom = data.msg.msgBody.richText.attr?.random ?: return
if (bot.client.syncingController.pendingGroupMessageReceiptCacheList.contains { it.messageRandom == messageRandom } if (bot.syncController.containsGroupMessageReceipt(messageRandom)
|| msgHead.fromAppid == 3116 || msgHead.fromAppid == 2021) { || msgHead.fromAppid == 3116 || msgHead.fromAppid == 2021
) {
// 3116=group music share // 3116=group music share
// 2021=group file // 2021=group file
// message sent by bot // message sent by bot

View File

@ -94,11 +94,7 @@ internal class OtherClientNoticeProcessor : MixedNoticeProcessor() {
collected += OtherClientOfflineEvent(client) collected += OtherClientOfflineEvent(client)
} }
else -> throw contextualBugReportException( else -> markNotConsumed()
"decode SvcRequestPushStatus (PC Client status change)",
data._miraiContentToString(),
additional = "unknown status=${data.status}",
)
} }
} }
} }

View File

@ -56,9 +56,7 @@ internal class PrivateMessageNoticeProcessor : SimpleNoticeProcessor<MsgComm.Msg
val group = bot.getGroupByUin(tmpHead.groupUin) ?: return val group = bot.getGroupByUin(tmpHead.groupUin) ?: return
handlePrivateMessage(data, group[senderUin] ?: return) handlePrivateMessage(data, group[senderUin] ?: return)
} }
else -> { else -> markNotConsumed()
markNotConsumed()
}
} }
} }

View File

@ -13,7 +13,6 @@ import net.mamoe.mirai.internal.message.contextualBugReportException
import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor import net.mamoe.mirai.internal.network.components.MixedNoticeProcessor
import net.mamoe.mirai.internal.network.components.PipelineContext import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.notice.decoders.MsgType0x2DC 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.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus 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.MsgComm
@ -23,17 +22,13 @@ 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.network.protocol.packet.chat.NewContact
import net.mamoe.mirai.internal.utils._miraiContentToString import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.context
import net.mamoe.mirai.utils.debug import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.toUHexString import net.mamoe.mirai.utils.toUHexString
internal class UnconsumedNoticesAlerter( internal class UnconsumedNoticesAlerter(
private val logger: MiraiLogger, private val logger: MiraiLogger,
) : MixedNoticeProcessor() { ) : 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) { override suspend fun PipelineContext.processImpl(data: MsgType0x210) {
if (isConsumed) return if (isConsumed) return
when (data.uSubMsgType) { when (data.uSubMsgType) {
@ -42,7 +37,6 @@ internal class UnconsumedNoticesAlerter(
0xD4L, // bot 在其他客户端被踢或主动退出而同步情况 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 // 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 -> { 0xE2L -> {
@ -51,10 +45,11 @@ internal class UnconsumedNoticesAlerter(
// 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 // 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()) // vProtobuf.loadAs(Msgtype0x210.serializer())
} }
else -> {
}
logger.debug { "Unknown group 528 type 0x${data.uSubMsgType.toUHexString("")}, data: " + data.vProtobuf.toUHexString() } logger.debug { "Unknown group 528 type 0x${data.uSubMsgType.toUHexString("")}, data: " + data.vProtobuf.toUHexString() }
} }
}
}
override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) { override suspend fun PipelineContext.processImpl(data: MsgType0x2DC) {
if (isConsumed) return if (isConsumed) return
@ -125,11 +120,21 @@ internal class UnconsumedNoticesAlerter(
override suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) { override suspend fun PipelineContext.processImpl(data: Structmsg.StructMsg) {
if (isConsumed) return if (isConsumed) return
TODO("Not yet implemented") data.msg?.context {
throw contextualBugReportException(
"解析 NewContact.SystemMsgNewGroup, subType=$subType, groupMsgType=$groupMsgType",
forDebug = this._miraiContentToString(),
additional = "并尽量描述此时机器人是否正被邀请加入群, 或者是有有新群员加入此群",
)
}
} }
override suspend fun PipelineContext.processImpl(data: RequestPushStatus) { override suspend fun PipelineContext.processImpl(data: RequestPushStatus) {
if (isConsumed) return if (isConsumed) return
TODO("Not yet implemented") throw contextualBugReportException(
"decode SvcRequestPushStatus (PC Client status change)",
data._miraiContentToString(),
additional = "unknown status=${data.status}",
)
} }
} }

View File

@ -16,17 +16,34 @@ import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.contact.checkIsGroupImpl import net.mamoe.mirai.internal.contact.checkIsGroupImpl
import net.mamoe.mirai.internal.network.components.PipelineContext import net.mamoe.mirai.internal.network.components.PipelineContext
import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.components.syncOnlinePush
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo 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.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack.SvcReqPushMsg
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
import net.mamoe.mirai.internal.utils.io.serialization.loadAs 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.read
import net.mamoe.mirai.utils.toUHexString
/** /**
* Decodes [MsgInfo] and re-fire [MsgType0x210] or [MsgType0x2DC] * Decodes [SvcReqPushMsg] to [MsgInfo] then re-fire [MsgType0x210] or [MsgType0x2DC]
*/ */
internal class MsgInfoDecoder : SimpleNoticeProcessor<MsgInfo>(type()) { internal class MsgInfoDecoder(
override suspend fun PipelineContext.processImpl(data: MsgInfo) { private val logger: MiraiLogger,
markAsConsumed() ) : SimpleNoticeProcessor<SvcReqPushMsg>(type()) {
override suspend fun PipelineContext.processImpl(data: SvcReqPushMsg) {
// SvcReqPushMsg is fully handled here, no need to set consumed.
for (msgInfo in data.vMsgInfos) {
decodeMsgInfo(msgInfo)
}
}
private suspend fun PipelineContext.decodeMsgInfo(data: MsgInfo) {
if (!bot.syncController.syncOnlinePush(data)) return
when (data.shMsgType.toUShort().toInt()) { when (data.shMsgType.toUShort().toInt()) {
// 528 // 528
0x210 -> fire(data.vMsg.loadAs(MsgType0x210.serializer())) 0x210 -> fire(data.vMsg.loadAs(MsgType0x210.serializer()))
@ -43,7 +60,9 @@ internal class MsgInfoDecoder : SimpleNoticeProcessor<MsgInfo>(type()) {
fire(MsgType0x2DC(kind, group, this.readBytes())) fire(MsgType0x2DC(kind, group, this.readBytes()))
} }
} }
else -> markNotConsumed() else -> {
logger.debug { "Unknown MsgInfo kind ${data.shMsgType.toInt()}, data=${data.vMsg.toUHexString()}" }
}
} }
} }
} }
@ -52,4 +71,4 @@ internal class MsgType0x2DC(
val kind: Int, // inner kind, read from vMsg val kind: Int, // inner kind, read from vMsg
val group: GroupImpl, val group: GroupImpl,
val buf: ByteArray, val buf: ByteArray,
) ) : ProtocolStruct

View File

@ -13,7 +13,6 @@ import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline
import net.mamoe.mirai.internal.network.components.PacketCodec import net.mamoe.mirai.internal.network.components.PacketCodec
import net.mamoe.mirai.internal.network.protocol.packet.chat.* import net.mamoe.mirai.internal.network.protocol.packet.chat.*
import net.mamoe.mirai.internal.network.protocol.packet.chat.image.ImgStore import net.mamoe.mirai.internal.network.protocol.packet.chat.image.ImgStore
@ -28,9 +27,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.login.Heartbeat
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin
import net.mamoe.mirai.internal.network.protocol.packet.summarycard.SummaryCard import net.mamoe.mirai.internal.network.protocol.packet.summarycard.SummaryCard
import net.mamoe.mirai.internal.network.toPacket
import net.mamoe.mirai.utils.MiraiLoggerWithSwitch import net.mamoe.mirai.utils.MiraiLoggerWithSwitch
import net.mamoe.mirai.utils.TypeSafeMap
internal sealed class PacketFactory<TPacket : Packet?> { internal sealed class PacketFactory<TPacket : Packet?> {
/** /**
@ -39,17 +36,6 @@ internal sealed class PacketFactory<TPacket : Packet?> {
abstract val receivingCommandName: String abstract val receivingCommandName: String
open val canBeCached: Boolean get() = true open val canBeCached: Boolean get() = true
protected companion object {
@JvmStatic
suspend fun QQAndroidBot.processPacketThroughPipeline(
data: Any?,
attributes: TypeSafeMap = TypeSafeMap(),
): Packet {
return components.noticeProcessorPipeline.process(this, data, attributes).toPacket()
}
}
} }
/** /**

View File

@ -15,19 +15,23 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.event.events.NewFriendRequestEvent
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg import net.mamoe.mirai.internal.network.protocol.data.proto.Structmsg
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.internal.network.toPacket
import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
import kotlin.math.max import kotlin.math.max
internal class NewContact { internal class NewContact {
internal object SystemMsgNewFriend : internal object SystemMsgNewFriend :
OutgoingPacketFactory<Packet?>("ProfileService.Pb.ReqSystemMsgNew.Friend") { OutgoingPacketFactory<Packet>("ProfileService.Pb.ReqSystemMsgNew.Friend") {
operator fun invoke(client: QQAndroidClient) = buildOutgoingUniPacket(client) { operator fun invoke(client: QQAndroidClient) = buildOutgoingUniPacket(client) {
writeProtoBuf( writeProtoBuf(
@ -39,30 +43,24 @@ internal class NewContact {
frdMsgGetBusiCard = 1, frdMsgGetBusiCard = 1,
frdMsgNeedWaitingMsg = 1, frdMsgNeedWaitingMsg = 1,
frdMsgUint32NeedAllUnreadMsg = 1, frdMsgUint32NeedAllUnreadMsg = 1,
grpMsgMaskInviteAutoJoin = 1 grpMsgMaskInviteAutoJoin = 1,
), ),
friendMsgTypeFlag = 1, friendMsgTypeFlag = 1,
isGetFrdRibbon = false, isGetFrdRibbon = false,
isGetGrpRibbon = false, isGetGrpRibbon = false,
msgNum = 20, msgNum = 20,
version = 1000 version = 1000,
) ),
) )
} }
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet? { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet {
readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run { readProtoBuf(Structmsg.RspSystemMsgNew.serializer()).run {
return friendmsgs.filter { return friendmsgs.filter {
it.msgTime >= bot.client.syncingController.latestMsgNewFriendTime it.msgTime >= bot.syncController.latestMsgNewFriendTime
}.mapNotNull { struct -> }.mapNotNull { struct ->
if (!bot.client.syncingController.systemMsgNewFriendCacheList.addCache( if (!bot.syncController.syncNewFriend(struct.msgSeq, struct.msgTime)) { // duplicate
QQAndroidClient.MessageSvcSyncData.SystemMsgNewSyncId(
struct.msgSeq,
struct.msgTime
)
)
) { // duplicate
return@mapNotNull null return@mapNotNull null
} }
struct.msg?.run { struct.msg?.run {
@ -72,17 +70,11 @@ internal class NewContact {
msgAdditional, msgAdditional,
struct.reqUin, struct.reqUin,
groupCode, groupCode,
reqUinNick reqUinNick,
) )
} }
}.let { packets -> }.toPacket().also {
when { bot.syncController.run {
packets.isEmpty() -> null
packets.size == 1 -> packets[0]
else -> MultiPacket(packets)
}
}.also {
bot.client.syncingController.run {
latestMsgNewFriendTime = max(latestMsgNewFriendTime, friendmsgs.maxOfOrNull { it.msgTime } ?: 0) latestMsgNewFriendTime = max(latestMsgNewFriendTime, friendmsgs.maxOfOrNull { it.msgTime } ?: 0)
} }
} }
@ -96,7 +88,7 @@ internal class NewContact {
eventId: Long, eventId: Long,
fromId: Long, fromId: Long,
accept: Boolean, accept: Boolean,
blackList: Boolean = false blackList: Boolean = false,
) = ) =
buildOutgoingUniPacket(client) { buildOutgoingUniPacket(client) {
writeProtoBuf( writeProtoBuf(
@ -107,14 +99,14 @@ internal class NewContact {
addFrdSNInfo = Structmsg.AddFrdSNInfo(), addFrdSNInfo = Structmsg.AddFrdSNInfo(),
msg = "", msg = "",
remark = "", remark = "",
blacklist = !accept && blackList blacklist = !accept && blackList,
), ),
msgSeq = eventId, msgSeq = eventId,
reqUin = fromId, reqUin = fromId,
srcId = 6, srcId = 6,
subSrcId = 7, subSrcId = 7,
subType = 1 subType = 1,
) ),
) )
} }
@ -148,39 +140,29 @@ internal class NewContact {
grpMsgNeedAutoAdminWording = 1, grpMsgNeedAutoAdminWording = 1,
grpMsgNotAllowJoinGrpInviteNotFrd = 1, grpMsgNotAllowJoinGrpInviteNotFrd = 1,
grpMsgSupportInviteAutoJoin = 1, grpMsgSupportInviteAutoJoin = 1,
grpMsgWordingDown = 1 grpMsgWordingDown = 1,
), ),
friendMsgTypeFlag = 1, friendMsgTypeFlag = 1,
isGetFrdRibbon = false, isGetFrdRibbon = false,
isGetGrpRibbon = false, isGetGrpRibbon = false,
msgNum = 5, msgNum = 5,
version = 1000 version = 1000,
) ),
) )
} }
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet? { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Packet {
return readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run { return readBytes().loadAs(Structmsg.RspSystemMsgNew.serializer()).run {
groupmsgs.filter { groupmsgs.filter {
it.msgTime >= bot.client.syncingController.latestMsgNewGroupTime it.msgTime >= bot.syncController.latestMsgNewGroupTime
}.mapNotNull { struct -> }.mapNotNull { struct ->
if (!bot.client.syncingController.systemMsgNewGroupCacheList.addCache( if (!bot.syncController.syncNewGroup(struct.msgSeq, struct.msgTime)) { // duplicate
QQAndroidClient.MessageSvcSyncData.SystemMsgNewSyncId(
struct.msgSeq,
struct.msgTime
)
)
) { // duplicate
return@mapNotNull null return@mapNotNull null
} }
try { bot.processPacketThroughPipeline(struct)
bot.components.noticeProcessorPipeline.process(bot, struct).toPacket()
} catch (e: Throwable) {
ParseErrorPacket(e)
}
}.toPacket().also { }.toPacket().also {
bot.client.syncingController.run { bot.syncController.run {
latestMsgNewGroupTime = max(latestMsgNewGroupTime, groupmsgs.maxOfOrNull { it.msgTime } ?: 0) latestMsgNewGroupTime = max(latestMsgNewGroupTime, groupmsgs.maxOfOrNull { it.msgTime } ?: 0)
} }
} }
@ -197,7 +179,7 @@ internal class NewContact {
isInvited: Boolean, isInvited: Boolean,
accept: Boolean?, accept: Boolean?,
blackList: Boolean = false, blackList: Boolean = false,
message: String = "" message: String = "",
) = ) =
buildOutgoingUniPacket(client) { buildOutgoingUniPacket(client) {
writeProtoBuf( writeProtoBuf(
@ -212,7 +194,7 @@ internal class NewContact {
groupCode = groupId, groupCode = groupId,
msg = message, msg = message,
remark = "", remark = "",
blacklist = blackList blacklist = blackList,
), ),
groupMsgType = if (isInvited) 2 else 1, groupMsgType = if (isInvited) 2 else 1,
language = 1000, language = 1000,
@ -220,8 +202,8 @@ internal class NewContact {
reqUin = fromId, reqUin = fromId,
srcId = 3, srcId = 3,
subSrcId = if (isInvited) 10016 else 31, subSrcId = if (isInvited) 10016 else 31,
subType = 1 subType = 1,
) ),
) )
} }

View File

@ -22,13 +22,17 @@ import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.MultiPacket import net.mamoe.mirai.internal.network.MultiPacket
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.KEY_FROM_SYNC import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.KEY_FROM_SYNC
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.components.syncGetMessage
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm 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.data.proto.MsgSvc
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
import net.mamoe.mirai.utils.toLongUnsigned
import kotlin.random.Random import kotlin.random.Random
@ -57,7 +61,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
whisperSessionId = 0, whisperSessionId = 0,
syncFlag = syncFlag, syncFlag = syncFlag,
// serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY, // serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY,
syncCookie = syncCookie ?: client.syncingController.syncCookie syncCookie = syncCookie ?: client.bot.syncController.syncCookie
?: byteArrayOf(), //.also { client.c2cMessageSync.syncCookie = it }, ?: byteArrayOf(), //.also { client.c2cMessageSync.syncCookie = it },
// syncFlag = client.c2cMessageSync.syncFlag, // syncFlag = client.c2cMessageSync.syncFlag,
//msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf, //msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf,
@ -113,14 +117,14 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
} }
when (resp.msgRspType) { when (resp.msgRspType) {
0 -> { 0 -> {
bot.client.syncingController.syncCookie = resp.syncCookie bot.syncController.syncCookie = resp.syncCookie
bot.client.syncingController.pubAccountCookie = resp.pubAccountCookie bot.syncController.pubAccountCookie = resp.pubAccountCookie
} }
1 -> { 1 -> {
bot.client.syncingController.syncCookie = resp.syncCookie bot.syncController.syncCookie = resp.syncCookie
} }
2 -> { 2 -> {
bot.client.syncingController.pubAccountCookie = resp.pubAccountCookie bot.syncController.pubAccountCookie = resp.pubAccountCookie
} }
} }
@ -129,33 +133,20 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
// bot.logger.debug(resp.msgRspType._miraiContentToString()) // bot.logger.debug(resp.msgRspType._miraiContentToString())
// bot.logger.debug(resp.syncCookie._miraiContentToString()) // bot.logger.debug(resp.syncCookie._miraiContentToString())
bot.client.syncingController.msgCtrlBuf = resp.msgCtrlBuf bot.syncController.msgCtrlBuf = resp.msgCtrlBuf
if (resp.uinPairMsgs.isEmpty()) return EmptyResponse(bot) if (resp.uinPairMsgs.isEmpty()) return EmptyResponse(bot)
for (uinPairMsg in resp.uinPairMsgs) {
if (uinPairMsg.msg.isEmpty()) continue
for (msg in uinPairMsg.msg) {
if (msg.msgHead.msgTime <= uinPairMsg.lastReadTime.toLong() and 4294967295L) continue
}
}
val messages = resp.uinPairMsgs.asSequence() val messages = resp.uinPairMsgs.asSequence()
.filterNot { it.msg.isEmpty() } .filterNot { it.msg.isEmpty() }
.flatMap { pair -> .flatMap { pair ->
pair.msg.asSequence() pair.msg.asSequence()
.filter { msg: MsgComm.Msg -> msg.msgHead.msgTime > pair.lastReadTime.toLong() and 4294967295L } .filter { msg: MsgComm.Msg -> msg.msgHead.msgTime > pair.lastReadTime.toLongUnsigned() }
} }
.toList() .toList()
.also { MessageSvcPbDeleteMsg.delete(bot, it) } // 删除消息 .also { MessageSvcPbDeleteMsg.delete(bot, it) } // 删除消息
.filter { msg -> .filter { msg ->
bot.client.syncingController.pbGetMessageCacheList.addCache( bot.syncController.syncGetMessage(msg.msgHead)
QQAndroidClient.MessageSvcSyncData.PbGetMessageSyncId(
uid = msg.msgHead.msgUid,
sequence = msg.msgHead.msgSeq,
time = msg.msgHead.msgTime,
),
)
} }
.map { msg -> .map { msg ->
bot.processPacketThroughPipeline(msg, KEY_FROM_SYNC to false) bot.processPacketThroughPipeline(msg, KEY_FROM_SYNC to false)
@ -179,7 +170,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
MessageSvcPbGetMsg( MessageSvcPbGetMsg(
client, client,
MsgSvc.SyncFlag.CONTINUE, MsgSvc.SyncFlag.CONTINUE,
bot.client.syncingController.syncCookie, bot.syncController.syncCookie,
).sendAndExpect() ).sendAndExpect()
} }
return return
@ -190,7 +181,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
MessageSvcPbGetMsg( MessageSvcPbGetMsg(
client, client,
MsgSvc.SyncFlag.CONTINUE, MsgSvc.SyncFlag.CONTINUE,
bot.client.syncingController.syncCookie, bot.syncController.syncCookie,
).sendAndExpect() ).sendAndExpect()
} }
return return

View File

@ -23,7 +23,8 @@ import net.mamoe.mirai.internal.contact.uin
import net.mamoe.mirai.internal.message.* import net.mamoe.mirai.internal.message.*
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.QQAndroidClient.MessageSvcSyncData.PendingGroupMessageReceiptSyncId import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncCookie
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgCtrl import net.mamoe.mirai.internal.network.protocol.data.proto.MsgCtrl
@ -104,13 +105,13 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
msgBody: ImMsgBody.MsgBody, msgBody: ImMsgBody.MsgBody,
msgSeq: Int, msgSeq: Int,
msgRand: Int, msgRand: Int,
contentHead: MsgComm.ContentHead contentHead: MsgComm.ContentHead,
) -> MsgSvc.PbSendMsgReq, ) -> MsgSvc.PbSendMsgReq,
sequenceIds: AtomicReference<IntArray>, sequenceIds: AtomicReference<IntArray>,
sequenceIdsInitializer: (Int) -> IntArray, sequenceIdsInitializer: (Int) -> IntArray,
randIds: AtomicReference<IntArray>, randIds: AtomicReference<IntArray>,
doFragmented: Boolean = true, doFragmented: Boolean = true,
postInit: () -> Unit postInit: () -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
val fragmented = if (doFragmented) val fragmented = if (doFragmented)
message.fragmented() message.fragmented()
@ -126,7 +127,8 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
randIds.set(randIds0) randIds.set(randIds0)
postInit() postInit()
fragmented.forEachIndexed { pkgIndex, fMsg -> fragmented.forEachIndexed { pkgIndex, fMsg ->
response.add(buildOutgoingUniPacket(client) { response.add(
buildOutgoingUniPacket(client) {
writeProtoBuf( writeProtoBuf(
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq.serializer(),
pbSendMsgReq( pbSendMsgReq(
@ -136,11 +138,12 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
MsgComm.ContentHead( MsgComm.ContentHead(
pkgNum = pkgNum, pkgNum = pkgNum,
divSeq = div, divSeq = div,
pkgIndex = pkgIndex pkgIndex = pkgIndex,
),
),
) )
},
) )
)
})
} }
return response return response
} }
@ -162,7 +165,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
} else { } else {
0 0
} }
} },
) )
} }
@ -175,7 +178,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
target: Stranger, target: Stranger,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
source: (OnlineMessageSourceToStrangerImpl) -> Unit source: (OnlineMessageSourceToStrangerImpl) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
val sequenceIds = AtomicReference<IntArray>() val sequenceIds = AtomicReference<IntArray>()
@ -186,8 +189,8 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
fragmentTranslator = { fragmentTranslator = {
ImMsgBody.MsgBody( ImMsgBody.MsgBody(
richText = ImMsgBody.RichText( richText = ImMsgBody.RichText(
elems = it.toRichTextElems(messageTarget = target, withGeneralFlags = true) elems = it.toRichTextElems(messageTarget = target, withGeneralFlags = true),
) ),
) )
}, },
pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead -> pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead ->
@ -197,7 +200,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
msgBody = msgBody, msgBody = msgBody,
msgSeq = msgSeq, msgSeq = msgSeq,
msgRand = msgRand, msgRand = msgRand,
syncCookie = client.syncingController.syncCookie ?: byteArrayOf() syncCookie = client.syncCookie ?: byteArrayOf(),
// msgVia = 1 // msgVia = 1
) )
}, },
@ -214,11 +217,11 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
target = target, target = target,
time = currentTimeSeconds().toInt(), time = currentTimeSeconds().toInt(),
sequenceIds = sequenceIds.get(), sequenceIds = sequenceIds.get(),
originalMessage = message originalMessage = message,
) ),
) )
}, },
doFragmented = fragmented doFragmented = fragmented,
) )
} }
@ -231,7 +234,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
targetFriend: Friend, targetFriend: Friend,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
crossinline sourceCallback: (OnlineMessageSourceToFriendImpl) -> Unit crossinline sourceCallback: (OnlineMessageSourceToFriendImpl) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
contract { contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE) callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
@ -247,7 +250,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
richText = ImMsgBody.RichText( richText = ImMsgBody.RichText(
elems = subChain.toRichTextElems(messageTarget = targetFriend, withGeneralFlags = true), elems = subChain.toRichTextElems(messageTarget = targetFriend, withGeneralFlags = true),
ptt = subChain.findPtt(), ptt = subChain.findPtt(),
) ),
) )
}, },
pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead -> pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead ->
@ -257,7 +260,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
msgBody = msgBody, msgBody = msgBody,
msgSeq = msgSeq, msgSeq = msgSeq,
msgRand = msgRand, msgRand = msgRand,
syncCookie = client.syncingController.syncCookie ?: byteArrayOf() syncCookie = client.syncCookie ?: byteArrayOf(),
// msgVia = 1 // msgVia = 1
) )
}, },
@ -274,8 +277,8 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
target = targetFriend, target = targetFriend,
time = currentTimeSeconds().toInt(), time = currentTimeSeconds().toInt(),
sequenceIds = sequenceIds.get(), sequenceIds = sequenceIds.get(),
originalMessage = message originalMessage = message,
) ),
) )
}, },
doFragmented = fragmented, doFragmented = fragmented,
@ -307,7 +310,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
), ),
msgSeq = source.sequenceIds.single(), msgSeq = source.sequenceIds.single(),
msgRand = source.internalIds.single(), msgRand = source.internalIds.single(),
syncCookie = client.syncingController.syncCookie ?: byteArrayOf() syncCookie = client.syncCookie ?: byteArrayOf()
// msgVia = 1 // msgVia = 1
) )
) )
@ -322,23 +325,24 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
client: QQAndroidClient, client: QQAndroidClient,
targetMember: Member, targetMember: Member,
message: MessageChain, message: MessageChain,
source: OnlineMessageSourceToTempImpl source: OnlineMessageSourceToTempImpl,
) = buildOutgoingUniPacket(client) { ) = buildOutgoingUniPacket(client) {
writeProtoBuf( writeProtoBuf(
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq( MsgSvc.PbSendMsgReq.serializer(),
MsgSvc.PbSendMsgReq(
routingHead = MsgSvc.RoutingHead( routingHead = MsgSvc.RoutingHead(
grpTmp = MsgSvc.GrpTmp(targetMember.group.uin, targetMember.id) grpTmp = MsgSvc.GrpTmp(targetMember.group.uin, targetMember.id),
), ),
contentHead = MsgComm.ContentHead(pkgNum = 1), contentHead = MsgComm.ContentHead(pkgNum = 1),
msgBody = ImMsgBody.MsgBody( msgBody = ImMsgBody.MsgBody(
richText = ImMsgBody.RichText( richText = ImMsgBody.RichText(
elems = message.toRichTextElems(messageTarget = targetMember, withGeneralFlags = true) elems = message.toRichTextElems(messageTarget = targetMember, withGeneralFlags = true),
) ),
), ),
msgSeq = source.sequenceIds.single(), msgSeq = source.sequenceIds.single(),
msgRand = source.internalIds.single(), msgRand = source.internalIds.single(),
syncCookie = client.syncingController.syncCookie ?: byteArrayOf() syncCookie = client.syncCookie ?: byteArrayOf(),
) ),
) )
} }
@ -352,7 +356,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
targetGroup: Group, targetGroup: Group,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
crossinline sourceCallback: (OnlineMessageSourceToGroupImpl) -> Unit crossinline sourceCallback: (OnlineMessageSourceToGroupImpl) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
val sequenceIds = AtomicReference<IntArray>() val sequenceIds = AtomicReference<IntArray>()
val randIds = AtomicReference<IntArray>() val randIds = AtomicReference<IntArray>()
@ -363,9 +367,9 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
ImMsgBody.MsgBody( ImMsgBody.MsgBody(
richText = ImMsgBody.RichText( richText = ImMsgBody.RichText(
elems = subChain.toRichTextElems(messageTarget = targetGroup, withGeneralFlags = true), elems = subChain.toRichTextElems(messageTarget = targetGroup, withGeneralFlags = true),
ptt = subChain.findPtt() ptt = subChain.findPtt(),
) ),
) )
}, },
pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead -> pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead ->
@ -375,12 +379,12 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
msgBody = msgBody, msgBody = msgBody,
msgSeq = msgSeq, msgSeq = msgSeq,
msgRand = msgRand, msgRand = msgRand,
syncCookie = client.syncingController.syncCookie ?: byteArrayOf(), syncCookie = client.syncCookie ?: byteArrayOf(),
msgVia = 1, msgVia = 1,
msgCtrl = msgCtrl =
if (message[ForwardMessageInternal] != null) if (message[ForwardMessageInternal] != null)
MsgCtrl.MsgCtrl(msgFlag = 4) MsgCtrl.MsgCtrl(msgFlag = 4)
else null else null,
) )
}, },
sequenceIds = sequenceIds, sequenceIds = sequenceIds,
@ -389,13 +393,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
IntArray(size) { client.atomicNextMessageSequenceId() } IntArray(size) { client.atomicNextMessageSequenceId() }
}, },
postInit = { postInit = {
randIds.get().forEach { id -> randIds.get().forEach { id -> client.syncController.syncGroupMessageReceipt(id) }
client.syncingController.pendingGroupMessageReceiptCacheList.addCache(
PendingGroupMessageReceiptSyncId(
messageRandom = id,
)
)
}
sourceCallback( sourceCallback(
OnlineMessageSourceToGroupImpl( OnlineMessageSourceToGroupImpl(
targetGroup, targetGroup,
@ -403,12 +401,12 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
sender = client.bot, sender = client.bot,
target = targetGroup, target = targetGroup,
time = currentTimeSeconds().toInt(), time = currentTimeSeconds().toInt(),
originalMessage = message//, originalMessage = message, //,
// sourceMessage = message // sourceMessage = message
) ),
) )
}, },
doFragmented = fragmented doFragmented = fragmented,
) )
} }
@ -468,7 +466,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
else -> Response.Failed( else -> Response.Failed(
response.result, response.result,
response.errtype, response.errtype,
response.errmsg response.errmsg,
) )
} }
@ -481,7 +479,7 @@ internal inline fun MessageSvcPbSendMsg.createToTemp(
member: Member, member: Member,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
crossinline sourceCallback: (Deferred<OnlineMessageSourceToTempImpl>) -> Unit crossinline sourceCallback: (Deferred<OnlineMessageSourceToTempImpl>) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
contract { contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE) callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
@ -492,14 +490,14 @@ internal inline fun MessageSvcPbSendMsg.createToTemp(
target = member, target = member,
time = currentTimeSeconds().toInt(), time = currentTimeSeconds().toInt(),
sequenceIds = intArrayOf(client.atomicNextMessageSequenceId()), sequenceIds = intArrayOf(client.atomicNextMessageSequenceId()),
originalMessage = message originalMessage = message,
) )
sourceCallback(CompletableDeferred(source)) sourceCallback(CompletableDeferred(source))
return createToTempImpl( return createToTempImpl(
client, client,
member, member,
message, message,
source source,
).let { listOf(it) } ).let { listOf(it) }
} }
@ -508,7 +506,7 @@ internal inline fun MessageSvcPbSendMsg.createToStranger(
stranger: Stranger, stranger: Stranger,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
crossinline sourceCallback: (Deferred<OnlineMessageSourceToStrangerImpl>) -> Unit crossinline sourceCallback: (Deferred<OnlineMessageSourceToStrangerImpl>) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
contract { contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE) callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
@ -517,7 +515,7 @@ internal inline fun MessageSvcPbSendMsg.createToStranger(
client, client,
stranger, stranger,
message, message,
fragmented fragmented,
) { sourceCallback(CompletableDeferred(it)) } ) { sourceCallback(CompletableDeferred(it)) }
} }
@ -526,7 +524,7 @@ internal inline fun MessageSvcPbSendMsg.createToFriend(
qq: Friend, qq: Friend,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
crossinline sourceCallback: (Deferred<OnlineMessageSourceToFriendImpl>) -> Unit crossinline sourceCallback: (Deferred<OnlineMessageSourceToFriendImpl>) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
contract { contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE) callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
@ -535,7 +533,7 @@ internal inline fun MessageSvcPbSendMsg.createToFriend(
client, client,
qq, qq,
message, message,
fragmented fragmented,
) { sourceCallback(CompletableDeferred(it)) } ) { sourceCallback(CompletableDeferred(it)) }
} }
@ -545,7 +543,7 @@ internal inline fun MessageSvcPbSendMsg.createToGroup(
group: Group, group: Group,
message: MessageChain, message: MessageChain,
fragmented: Boolean, fragmented: Boolean,
crossinline sourceCallback: (Deferred<OnlineMessageSourceToGroupImpl>) -> Unit crossinline sourceCallback: (Deferred<OnlineMessageSourceToGroupImpl>) -> Unit,
): List<OutgoingPacket> { ): List<OutgoingPacket> {
contract { contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE) callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
@ -554,6 +552,6 @@ internal inline fun MessageSvcPbSendMsg.createToGroup(
client, client,
group, group,
message, message,
fragmented fragmented,
) { sourceCallback(CompletableDeferred(it)) } ) { sourceCallback(CompletableDeferred(it)) }
} }

View File

@ -13,6 +13,7 @@ import kotlinx.atomicfu.loop
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushNotify import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushNotify
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgSvc import net.mamoe.mirai.internal.network.protocol.data.proto.MsgSvc
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
@ -30,18 +31,17 @@ internal object MessageSvcPushNotify : IncomingPacketFactory<RequestPushNotify>(
} }
override suspend fun QQAndroidBot.handle(packet: RequestPushNotify, sequenceId: Int): OutgoingPacket { override suspend fun QQAndroidBot.handle(packet: RequestPushNotify, sequenceId: Int): OutgoingPacket {
syncController.firstNotify.loop { firstNotify ->
client.syncingController.firstNotify.loop { firstNotify ->
network.run { network.run {
return MessageSvcPbGetMsg( return MessageSvcPbGetMsg(
client, client,
MsgSvc.SyncFlag.START, MsgSvc.SyncFlag.START,
if (firstNotify) { if (firstNotify) {
if (!client.syncingController.firstNotify.compareAndSet(firstNotify, false)) { if (!syncController.firstNotify.compareAndSet(firstNotify, false)) {
return@loop return@loop
} }
null null
} else packet.vNotifyCookie } else packet.vNotifyCookie,
) )
} }
} }

View File

@ -12,6 +12,7 @@ package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.utils.io.serialization.readUniPacket import net.mamoe.mirai.internal.utils.io.serialization.readUniPacket

View File

@ -12,21 +12,19 @@ package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.components.PipelineContext.Companion.KEY_FROM_SYNC 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.data.proto.MsgOnlinePush
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.network.toPacket
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
internal object PbC2CMsgSync : IncomingPacketFactory<Packet>( internal object PbC2CMsgSync : IncomingPacketFactory<Packet>(
"OnlinePush.PbC2CMsgSync", "" "OnlinePush.PbC2CMsgSync", "",
) { ) {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet {
return bot.components.noticeProcessorPipeline.process( return bot.processPacketThroughPipeline(
bot = bot, readProtoBuf(MsgOnlinePush.PbPushMsg.serializer()).msg,
data = readProtoBuf(MsgOnlinePush.PbPushMsg.serializer()).msg, KEY_FROM_SYNC to true,
attributes = KEY_FROM_SYNC to true, )
).toPacket()
} }
} }

View File

@ -7,18 +7,15 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.components.SsoProcessor import net.mamoe.mirai.internal.network.components.SsoProcessor
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush 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.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.network.toPacket
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
/** /**
@ -26,11 +23,9 @@ import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
*/ */
internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory<Packet?>("OnlinePush.PbPushGroupMsg") { internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory<Packet?>("OnlinePush.PbPushGroupMsg") {
@OptIn(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00 // 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
if (!bot.components[SsoProcessor].firstLoginSucceed) return null if (!bot.components[SsoProcessor].firstLoginSucceed) return null
return bot.components.noticeProcessorPipeline.process(bot, readProtoBuf(MsgOnlinePush.PbPushMsg.serializer())) return bot.processPacketThroughPipeline(readProtoBuf(MsgOnlinePush.PbPushMsg.serializer()))
.toPacket()
} }
} }

View File

@ -12,8 +12,9 @@ package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.noticeProcessorPipeline import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.components.syncPushTrans
import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans import net.mamoe.mirai.internal.network.protocol.data.proto.OnlinePushTrans
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
@ -27,20 +28,8 @@ internal object OnlinePushPbPushTransMsg :
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
val content = this.readProtoBuf(OnlinePushTrans.PbMsgInfo.serializer()) val content = this.readProtoBuf(OnlinePushTrans.PbMsgInfo.serializer())
if (!bot.syncController.syncPushTrans(content)) return null
if (!bot.client.syncingController.pbPushTransMsgCacheList.addCache( return bot.processPacketThroughPipeline(content)
content.run {
QQAndroidClient.MessageSvcSyncData.PbPushTransMsgSyncId(msgUid, msgSeq, msgTime)
}
)
) {
return null
}
// bot.network.logger.debug { content._miraiContentToString() }
bot.components.noticeProcessorPipeline.process(bot, content)
return null
} }
override suspend fun QQAndroidBot.handle(packet: Packet?, sequenceId: Int): OutgoingPacket { override suspend fun QQAndroidBot.handle(packet: Packet?, sequenceId: Int): OutgoingPacket {

View File

@ -7,14 +7,12 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@file:OptIn(
JavaFriendlyAPI::class
)
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.io.core.* import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.readUInt
import kotlinx.io.core.readUShort
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
@ -26,14 +24,13 @@ import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.contact.GroupImpl import net.mamoe.mirai.internal.contact.GroupImpl
import net.mamoe.mirai.internal.contact.checkIsGroupImpl import net.mamoe.mirai.internal.contact.checkIsGroupImpl
import net.mamoe.mirai.internal.contact.checkIsMemberImpl import net.mamoe.mirai.internal.contact.checkIsMemberImpl
import net.mamoe.mirai.internal.network.MultiPacketImpl import net.mamoe.mirai.internal.network.MultiPacket
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.components.NoticeProcessorPipeline.Companion.processPacketThroughPipeline
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.protocol.data.jce.MsgInfo 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.MsgType0x210
import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack import net.mamoe.mirai.internal.network.protocol.data.jce.OnlinePushPack
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPacket
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x122 import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x122
import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27.SubMsgType0x27.* import net.mamoe.mirai.internal.network.protocol.data.proto.Submsgtype0x27.SubMsgType0x27.*
import net.mamoe.mirai.internal.network.protocol.data.proto.TroopTips0x857 import net.mamoe.mirai.internal.network.protocol.data.proto.TroopTips0x857
@ -42,112 +39,49 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.internal.network.protocol.packet.buildResponseUniPacket import net.mamoe.mirai.internal.network.protocol.packet.buildResponseUniPacket
import net.mamoe.mirai.internal.utils._miraiContentToString import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.ProtoBuf import net.mamoe.mirai.internal.utils.io.ProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.* import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.utils.* import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.readUniPacket
import net.mamoe.mirai.internal.utils.io.serialization.writeJceRequestPacket
import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.encodeToString
import net.mamoe.mirai.utils.mapToIntArray
//0C 01 B1 89 BE 09 5E 3D 72 A6 00 01 73 68 FC 06 00 00 00 3C //0C 01 B1 89 BE 09 5E 3D 72 A6 00 01 73 68 FC 06 00 00 00 3C
internal object OnlinePushReqPush : IncomingPacketFactory<OnlinePushReqPush.ReqPushDecoded>( internal object OnlinePushReqPush : IncomingPacketFactory<OnlinePushReqPush.ReqPushDecoded>(
"OnlinePush.ReqPush", "OnlinePush.ReqPush",
"OnlinePush.RespPush" "OnlinePush.RespPush",
) { ) {
// to reduce nesting depth
private suspend fun List<MsgInfo>.deco(
client: QQAndroidClient,
mapper: suspend ByteReadPacket.(msgInfo: MsgInfo) -> Sequence<Packet>
): List<Packet> {
return mapNotNull { msg ->
val successful = client.syncingController.onlinePushReqPushCacheList.addCache(
QQAndroidClient.MessageSvcSyncData.OnlinePushReqPushSyncId(
uid = msg.lMsgUid ?: 0, sequence = msg.shMsgSeq, time = msg.uMsgTime
)
)
if (!successful) return@mapNotNull null
msg.vMsg.read { mapper(msg) }
}.asSequence().flatten().toList()
}
@ExperimentalUnsignedTypes
@OptIn(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): ReqPushDecoded { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): ReqPushDecoded {
val reqPushMsg = readUniPacket(OnlinePushPack.SvcReqPushMsg.serializer(), "req") val reqPushMsg = readUniPacket(OnlinePushPack.SvcReqPushMsg.serializer(), "req")
//bot.network.logger.debug { reqPushMsg._miraiContentToString() } return ReqPushDecoded(reqPushMsg, bot.processPacketThroughPipeline(reqPushMsg))
val packets = reqPushMsg.vMsgInfos.deco(bot.client) { msgInfo ->
when (msgInfo.shMsgType.toInt()) {
732 -> {
val group = bot.getGroup(readUInt().toLong())
?: return@deco emptySequence() // group has not been initialized
group.checkIsGroupImpl()
val internalType = readByte().toInt()
discardExact(1)
Transformers732[internalType]
?.let { it(this@deco, group, bot) }
?: kotlin.run {
bot.network.logger.debug {
"unknown group 732 type $internalType, data: " + readBytes().toUHexString()
}
return@deco emptySequence()
}
} }
// 00 27 1A 0C 1C 2C 3C 4C 5D 00 0C 6D 00 0C 7D 00 0C 8D 00 0C 9C AC BC CC DD 00 0C EC FC 0F 0B 2A 0C 1C 2C 3C 4C 5C 6C 0B 3A 0C 1C 2C 3C 4C 5C 6C 7C 8D 00 0C 9D 00 0C AC BD 00 0C CD 00 0C DC ED 00 0C FC 0F FC 10 0B 4A 0C 1C 2C 3C 4C 5C 6C 7C 8C 96 00 0B 5A 0C 1C 2C 3C 4C 5C 6C 7C 8C 9D 00 0C 0B 6A 0C 1A 0C 1C 26 00 0B 2A 0C 0B 3A 0C 16 00 0B 4A 09 0C 0B 5A 09 0C 0B 0B 7A 0C 1C 2C 36 00 0B 8A 0C 1C 2C 36 00 0B 9A 09 0C 0B AD 00 00 1E 0A 1C 10 28 4A 18 0A 16 08 00 10 A2 FF 8C F0 03 1A 0C E6 BD 9C E6 B1 9F E7 BE A4 E5 8F 8B internal class ReqPushDecoded(val request: OnlinePushPack.SvcReqPushMsg, packet: Packet) :
528 -> { MultiPacket by MultiPacket(packet), Packet.NoLog {
val notifyMsgBody = readJceStruct(MsgType0x210.serializer()) override fun toString(): String = "OnlinePush.ReqPush.ReqPushDecoded"
Transformers528[notifyMsgBody.uSubMsgType]
?.let { processor -> processor(notifyMsgBody, bot, msgInfo) }
?: kotlin.run {
bot.network.logger.debug {
"unknown group 528 type 0x${notifyMsgBody.uSubMsgType.toUHexString("")}, data: " + notifyMsgBody.vProtobuf.toUHexString()
}
return@deco emptySequence()
}
}
else -> {
bot.network.logger.debug { "unknown sh type ${msgInfo.shMsgType.toInt()}" }
bot.network.logger.debug { "data=${readBytes().toUHexString()}" }
return@deco emptySequence()
}
}
}
return ReqPushDecoded(reqPushMsg, packets)
}
@Suppress("SpellCheckingInspection")
internal data class ReqPushDecoded(val request: OnlinePushPack.SvcReqPushMsg, val sequence: Collection<Packet>) :
MultiPacketImpl(sequence), Packet.NoLog {
override fun toString(): String {
return "OnlinePush.ReqPush.ReqPushDecoded"
}
} }
override suspend fun QQAndroidBot.handle(packet: ReqPushDecoded, sequenceId: Int): OutgoingPacket { override suspend fun QQAndroidBot.handle(packet: ReqPushDecoded, sequenceId: Int): OutgoingPacket {
return buildResponseUniPacket(client) { return buildResponseUniPacket(client) {
writeJceStruct( writeJceRequestPacket(
RequestPacket.serializer(),
RequestPacket(
servantName = "OnlinePush", servantName = "OnlinePush",
funcName = "SvcRespPushMsg", funcName = "SvcRespPushMsg",
requestId = sequenceId, name = "resp",
sBuffer = jceRequestSBuffer( serializer = OnlinePushPack.SvcRespPushMsg.serializer(),
"resp", body = OnlinePushPack.SvcRespPushMsg(
OnlinePushPack.SvcRespPushMsg.serializer(),
OnlinePushPack.SvcRespPushMsg(
packet.request.uin, packet.request.uin,
packet.request.vMsgInfos.map { msg -> packet.request.vMsgInfos.map { msg ->
OnlinePushPack.DelMsgInfo( OnlinePushPack.DelMsgInfo(
fromUin = msg.lFromUin, fromUin = msg.lFromUin,
shMsgSeq = msg.shMsgSeq, shMsgSeq = msg.shMsgSeq,
vMsgCookies = msg.vMsgCookies, vMsgCookies = msg.vMsgCookies,
uMsgTime = msg.uMsgTime // captured 0 uMsgTime = msg.uMsgTime, // captured 0
)
}
)
)
) )
},
),
) )
} }
} }
@ -171,7 +105,7 @@ private fun handleMuteMemberPacket(
group: GroupImpl, group: GroupImpl,
operator: NormalMember, operator: NormalMember,
target: Long, target: Long,
timeSeconds: Int timeSeconds: Int,
): Packet? { ): Packet? {
if (target == 0L) { if (target == 0L) {
val new = timeSeconds != 0 val new = timeSeconds != 0
@ -209,7 +143,7 @@ private fun handleMuteMemberPacket(
else MemberMuteEvent(member, timeSeconds, operator) else MemberMuteEvent(member, timeSeconds, operator)
} }
private object Transformers732 : Map<Int, Lambda732> by mapOf( internal object Transformers732 : Map<Int, Lambda732> by mapOf(
// mute // mute
0x0c to lambda732 { group: GroupImpl, bot: QQAndroidBot -> 0x0c to lambda732 { group: GroupImpl, bot: QQAndroidBot ->
val operatorUin = readUInt().toLong() val operatorUin = readUInt().toLong()
@ -274,8 +208,8 @@ private object Transformers732 : Map<Int, Lambda732> by mapOf(
target = if (target.id == bot.id) bot else target, target = if (target.id == bot.id) bot else target,
action = action, action = action,
suffix = suffix, suffix = suffix,
subject = group subject = group,
) ),
) )
} }
//龙王 //龙王
@ -294,7 +228,7 @@ private object Transformers732 : Map<Int, Lambda732> by mapOf(
sequenceOf( sequenceOf(
GroupTalkativeChangeEvent(group, now, it), GroupTalkativeChangeEvent(group, now, it),
MemberHonorChangeEvent.Lose(it, GroupHonorType.TALKATIVE), MemberHonorChangeEvent.Lose(it, GroupHonorType.TALKATIVE),
MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE) MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE),
) )
} ?: sequenceOf(MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE)) } ?: sequenceOf(MemberHonorChangeEvent.Achieve(now, GroupHonorType.TALKATIVE))
} }
@ -331,8 +265,8 @@ private object Transformers732 : Map<Int, Lambda732> by mapOf(
new, new,
!new, !new,
group, group,
false false,
) ),
) )
} }
else -> { else -> {
@ -439,18 +373,17 @@ private object Transformers732 : Map<Int, Lambda732> by mapOf(
firstPkg.time, firstPkg.time,
operator, operator,
group, group,
group[firstPkg.authorUin] ?: return@lambda732 emptySequence() group[firstPkg.authorUin] ?: return@lambda732 emptySequence(),
) ),
) )
} }
} },
) )
internal interface Lambda528 { internal interface Lambda528 {
suspend operator fun invoke(msg: MsgType0x210, bot: QQAndroidBot, msgInfo: MsgInfo): Sequence<Packet> suspend operator fun invoke(msg: MsgType0x210, bot: QQAndroidBot, msgInfo: MsgInfo): Sequence<Packet>
} }
@kotlin.internal.LowPriorityInOverloadResolution
internal inline fun lambda528(crossinline block: suspend MsgType0x210.(QQAndroidBot) -> Sequence<Packet>): Lambda528 { internal inline fun lambda528(crossinline block: suspend MsgType0x210.(QQAndroidBot) -> Sequence<Packet>): Lambda528 {
return object : Lambda528 { return object : Lambda528 {
override suspend fun invoke(msg: MsgType0x210, bot: QQAndroidBot, msgInfo: MsgInfo): Sequence<Packet> { override suspend fun invoke(msg: MsgType0x210, bot: QQAndroidBot, msgInfo: MsgInfo): Sequence<Packet> {
@ -472,7 +405,7 @@ internal inline fun lambda528(crossinline block: suspend MsgType0x210.(QQAndroid
@Serializable @Serializable
private class Wording( private class Wording(
@ProtoNumber(1) val itemID: Int = 0, @ProtoNumber(1) val itemID: Int = 0,
@ProtoNumber(2) val itemName: String = "" @ProtoNumber(2) val itemName: String = "",
) : ProtoBuf ) : ProtoBuf
@Serializable @Serializable
@ -487,7 +420,7 @@ private class Sub8AMsgInfo(
@ProtoNumber(8) val pkgIndex: Int, // 0 @ProtoNumber(8) val pkgIndex: Int, // 0
@ProtoNumber(9) val devSeq: Int, // 0 @ProtoNumber(9) val devSeq: Int, // 0
@ProtoNumber(12) val flag: Int, // 1 @ProtoNumber(12) val flag: Int, // 1
@ProtoNumber(13) val wording: Wording @ProtoNumber(13) val wording: Wording,
) : ProtoBuf ) : ProtoBuf
@Serializable @Serializable
@ -496,7 +429,7 @@ private class Sub8A(
@ProtoNumber(2) val appId: Int, // 1 @ProtoNumber(2) val appId: Int, // 1
@ProtoNumber(3) val instId: Int, // 1 @ProtoNumber(3) val instId: Int, // 1
@ProtoNumber(4) val longMessageFlag: Int, // 0 @ProtoNumber(4) val longMessageFlag: Int, // 0
@ProtoNumber(5) val reserved: ByteArray? = null // struct{ boolean(1), boolean(2) } @ProtoNumber(5) val reserved: ByteArray? = null, // struct{ boolean(1), boolean(2) }
) : ProtoBuf ) : ProtoBuf
@ -519,7 +452,7 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
messageInternalIds = intArrayOf(info.srcInternalId.toInt()), messageInternalIds = intArrayOf(info.srcInternalId.toInt()),
messageTime = info.time.toInt(), messageTime = info.time.toInt(),
operatorId = info.fromUin, operatorId = info.fromUin,
operator = bot.getFriend(info.fromUin) ?: return@mapNotNull null operator = bot.getFriend(info.fromUin) ?: return@mapNotNull null,
) )
} }
}, },
@ -567,7 +500,7 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
NudgeEvent(from = bot, target = subject, subject = subject, action, suffix) NudgeEvent(from = bot, target = subject, subject = subject, action, suffix)
} }
else -> NudgeEvent(from = subject, target = subject, subject = subject, action, suffix) else -> NudgeEvent(from = subject, target = subject, subject = subject, action, suffix)
} },
) )
} }
else -> { else -> {

View File

@ -22,14 +22,9 @@ import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
internal object OnlinePushSidExpired : IncomingPacketFactory<Packet?>("OnlinePush.SidTicketExpired") { internal object OnlinePushSidExpired : IncomingPacketFactory<Packet?>("OnlinePush.SidTicketExpired") {
override suspend fun QQAndroidBot.handle(packet: Packet?, sequenceId: Int): OutgoingPacket { override suspend fun QQAndroidBot.handle(packet: Packet?, sequenceId: Int): OutgoingPacket {
return buildResponseUniPacket(
client,
sequenceId = sequenceId,
key = client.wLoginSigInfo.d2Key
) {}.also {
WtLogin10(client, mainSigMap = 3554528).sendAndExpect(bot) WtLogin10(client, mainSigMap = 3554528).sendAndExpect(bot)
StatSvc.Register.online(client).sendAndExpect(bot) StatSvc.Register.online(client).sendAndExpect(bot)
} return buildResponseUniPacket(client, sequenceId = sequenceId)
} }
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {

View File

@ -1,15 +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/dev/LICENSE
*/
package net.mamoe.mirai.internal.utils.io
/**
* 仅有标示作用
*/
internal interface ProtoBuf

View File

@ -9,4 +9,6 @@
package net.mamoe.mirai.internal.utils.io package net.mamoe.mirai.internal.utils.io
internal interface JceStruct internal interface ProtocolStruct
internal interface ProtoBuf : ProtocolStruct
internal interface JceStruct : ProtocolStruct