diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MsgSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MsgSvc.kt index 0f07c98a5..f357e0af6 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MsgSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MsgSvc.kt @@ -19,7 +19,7 @@ internal class MsgSvc : ProtoBuf { @ProtoNumber(1) @JvmField val result: Int = 0, @ProtoNumber(2) @JvmField val errmsg: String = "", @ProtoNumber(3) @JvmField val syncCookie: ByteArray? = EMPTY_BYTE_ARRAY, - @ProtoNumber(4) @JvmField val syncFlag: SyncFlag, + @ProtoNumber(4) @JvmField val syncFlag: SyncFlag = SyncFlag.CONTINUE, @ProtoNumber(5) @JvmField val uinPairMsgs: List<MsgComm.UinPairMsg>? = null, @ProtoNumber(6) @JvmField val bindUin: Long = 0L, @ProtoNumber(7) @JvmField val msgRspType: Int = 0, diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt index 41ace422f..6eed3e4c6 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt @@ -14,6 +14,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive import kotlinx.atomicfu.loop import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* +import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.discardExact @@ -43,6 +44,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.NewContact import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList +import net.mamoe.mirai.qqandroid.utils._miraiContentToString import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.qqandroid.utils.read @@ -56,6 +58,12 @@ import net.mamoe.mirai.utils.warning * 获取好友消息和消息记录 */ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Response>("MessageSvc.PbGetMsg") { + + + private val msgUidQueue = ArrayDeque<Long>() + private val msgUidSet = hashSetOf<Long>() + private val msgQueueMutex = Mutex() + @Suppress("SpellCheckingInspection") operator fun invoke( client: QQAndroidClient, @@ -114,8 +122,9 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re private fun MsgComm.Msg.getNewMemberInfo(): MemberInfo { return object : MemberInfo { - override val nameCard: String get() = msgHead.authNick.takeIf { it.isNotEmpty() } - ?: msgHead.fromNick + override val nameCard: String + get() = msgHead.authNick.takeIf { it.isNotEmpty() } + ?: msgHead.fromNick override val permission: MemberPermission get() = MemberPermission.MEMBER override val specialTitle: String get() = "" override val muteTimestamp: Int get() = 0 @@ -135,9 +144,23 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re .warning { "MessageSvcPushNotify: result != 0, result = ${resp.result}, errorMsg=${resp.errmsg}" } return EmptyResponse } + when (resp.msgRspType) { + 0 -> { + bot.client.c2cMessageSync.syncCookie = resp.syncCookie + bot.client.c2cMessageSync.pubAccountCookie = resp.pubAccountCookie + } + 1 -> { + bot.client.c2cMessageSync.syncCookie = resp.syncCookie + } + 2 -> { + bot.client.c2cMessageSync.pubAccountCookie = resp.pubAccountCookie + + } + } + +// bot.logger.debug(resp.msgRspType._miraiContentToString()) +// bot.logger.debug(resp.syncCookie._miraiContentToString()) - bot.client.c2cMessageSync.syncCookie = resp.syncCookie - bot.client.c2cMessageSync.pubAccountCookie = resp.pubAccountCookie bot.client.c2cMessageSync.msgCtrlBuf = resp.msgCtrlBuf if (resp.uinPairMsgs == null) { @@ -151,10 +174,21 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re .filter { msg: MsgComm.Msg -> msg.msgHead.msgTime > it.lastReadTime.toLong() and 4294967295L } }.also { MessageSvcPbDeleteMsg.delete(bot, it) // 删除消息 - // todo 实现一个锁来防止重复收到消息 } .mapNotNull<MsgComm.Msg, Packet> { msg -> + msgQueueMutex.lock() + val msgUid = msg.msgHead.msgUid + if (msgUidSet.size > 50) { + msgUidSet.remove(msgUidQueue.removeFirst()) + } + if (!msgUidSet.add(msgUid)) { + msgQueueMutex.unlock() + return@mapNotNull null + } + msgQueueMutex.unlock() + msgUidQueue.addLast(msgUid) + suspend fun createGroupForBot(groupUin: Long): Group? { val group = bot.getGroupByUinOrNull(groupUin) if (group != null) { @@ -294,18 +328,15 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re return@mapNotNull null } - if (friend.lastMessageSequence.compareAndSet( - friend.lastMessageSequence.value, - msg.msgHead.msgSeq - ) - ) { - return@mapNotNull FriendMessageEvent( - friend, - msg.toMessageChain(bot, groupIdOrZero = 0, onlineSource = true), - msg.msgHead.msgTime - ) + friend.lastMessageSequence.loop { + if (friend.lastMessageSequence.compareAndSet(it, msg.msgHead.msgSeq)) { + return@mapNotNull FriendMessageEvent( + friend, + msg.toMessageChain(bot, groupIdOrZero = 0, onlineSource = true), + msg.msgHead.msgTime + ) + } else return@mapNotNull null } - return@mapNotNull null } 208 -> { // friend ptt @@ -387,7 +418,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re MessageSvcPbGetMsg( client, MsgSvc.SyncFlag.CONTINUE, - packet.syncCookie + bot.client.c2cMessageSync.syncCookie ).sendAndExpect<Packet>() } return @@ -398,7 +429,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re MessageSvcPbGetMsg( client, MsgSvc.SyncFlag.CONTINUE, - packet.syncCookie + bot.client.c2cMessageSync.syncCookie ).sendAndExpect<Packet>() } return