mzdluo123 hace 5 años
padre
commit
2ec431489e

+ 3 - 1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt

@@ -411,7 +411,9 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
         logger.info { "Syncing friend message history..." }
         withTimeoutOrNull(30000) {
             launch(CoroutineName("Syncing friend message history")) { syncFromEvent<MessageSvcPbGetMsg.GetMsgSuccess, Unit> { Unit } }
-            MessageSvcPbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendAndExpect<Packet>()
+            // 别问我为什么要发两个 我也不知道 反正它能用
+            MessageSvcPbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds, null,firstSync = true).sendAndExpect<Packet>()
+            MessageSvcPbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds, null,firstSync = true).sendAndExpect<Packet>()
         } ?: error("timeout syncing friend message history")
         logger.info { "Syncing friend message history: Success" }
     }

+ 5 - 0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt

@@ -11,6 +11,7 @@
 
 package net.mamoe.mirai.qqandroid.network
 
+import kotlinx.atomicfu.AtomicBoolean
 import kotlinx.atomicfu.AtomicInt
 import kotlinx.atomicfu.atomic
 import kotlinx.io.core.*
@@ -27,6 +28,7 @@ import net.mamoe.mirai.qqandroid.utils.*
 import net.mamoe.mirai.qqandroid.utils.cryptor.ECDH
 import net.mamoe.mirai.qqandroid.utils.cryptor.TEA
 import net.mamoe.mirai.utils.*
+import kotlin.jvm.Volatile
 import kotlin.random.Random
 
 internal val DeviceInfo.guid: ByteArray get() = generateGuid(androidId, macAddress)
@@ -204,6 +206,9 @@ internal open class QQAndroidClient(
     val protocolVersion: Short = 8001
 
     class C2cMessageSyncData {
+        val firstNotify: AtomicBoolean = atomic(true)
+
+        @Volatile
         var syncCookie: ByteArray? = null
         var pubAccountCookie = EMPTY_BYTE_ARRAY
         var msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY

+ 1 - 1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/PushNotifyPack.kt

@@ -33,7 +33,7 @@ internal class RequestPushNotify(
     @JceId(11) @JvmField val serverBuf: ByteArray?,
     @JceId(12) @JvmField val pingFlag: Long?,
     @JceId(13) @JvmField val svrip: Int?
-) : JceStruct, Packet, Packet.NoLog
+) : JceStruct, Packet
 
 @Serializable
 internal class MsgInfo(

+ 5 - 0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/SyncCookie.kt

@@ -16,6 +16,9 @@ import kotlin.jvm.JvmField
 import kotlin.math.absoluteValue
 import kotlin.random.Random
 
+
+// COMMENTED ON 2020/7/25
+
 @Serializable
 internal class SyncCookie(
     @ProtoId(1) @JvmField val time1: Long? = null, // 1580277992
@@ -31,6 +34,8 @@ internal class SyncCookie(
 
 private val const1_: Long = Random.nextLong().absoluteValue
 private val const2_: Long = Random.nextLong().absoluteValue
+
+
 /*
 
 @Serializable

+ 42 - 15
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PbGetMsg.kt

@@ -37,7 +37,6 @@ import net.mamoe.mirai.qqandroid.network.Packet
 import net.mamoe.mirai.qqandroid.network.QQAndroidClient
 import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
 import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
-import net.mamoe.mirai.qqandroid.network.protocol.data.proto.SyncCookie
 import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
 import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
 import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
@@ -45,7 +44,6 @@ 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.io.serialization.readProtoBuf
-import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
 import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
 import net.mamoe.mirai.qqandroid.utils.read
 import net.mamoe.mirai.qqandroid.utils.toInt
@@ -59,15 +57,21 @@ import net.mamoe.mirai.utils.warning
  * 获取好友消息和消息记录
  */
 internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Response>("MessageSvc.PbGetMsg") {
+    private var firstSyncPackets = 0  // 启动时候仅将所有好友信息设为已读的包
     @Suppress("SpellCheckingInspection")
     operator fun invoke(
         client: QQAndroidClient,
         syncFlag: MsgSvc.SyncFlag = MsgSvc.SyncFlag.START,
-        msgTime: Long //PbPushMsg.msg.msgHead.msgTime
+        msgTime: Long, //PbPushMsg.msg.msgHead.msgTime
+        syncCookie: ByteArray?,
+        firstSync: Boolean = false
     ): OutgoingPacket = buildOutgoingUniPacket(
         client
     ) {
         //println("syncCookie=${client.c2cMessageSync.syncCookie?.toUHexString()}")
+        if (firstSync) {
+            firstSyncPackets++
+        }
         writeProtoBuf(
             MsgSvc.PbGetMsgReq.serializer(),
             MsgSvc.PbGetMsgReq(
@@ -80,8 +84,8 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
                 whisperSessionId = 0,
                 syncFlag = syncFlag,
                 //  serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY,
-                syncCookie = client.c2cMessageSync.syncCookie
-                    ?: SyncCookie(time = msgTime).toByteArray(SyncCookie.serializer())//.also { client.c2cMessageSync.syncCookie = it },
+                syncCookie = syncCookie ?: client.c2cMessageSync.syncCookie
+                ?: byteArrayOf()//.also { client.c2cMessageSync.syncCookie = it },
                 // syncFlag = client.c2cMessageSync.syncFlag,
                 //msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf,
                 //pubaccountCookie = client.c2cMessageSync.pubAccountCookie
@@ -89,7 +93,10 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
         )
     }
 
-    open class GetMsgSuccess(delegate: List<Packet>) : Response(MsgSvc.SyncFlag.STOP, delegate), Event,
+    open class GetMsgSuccess(delegate: List<Packet>, syncCookie: ByteArray?) : Response(
+        MsgSvc.SyncFlag.STOP, delegate,
+        syncCookie
+    ), Event,
         Packet.NoLog {
         override fun toString(): String = "MessageSvcPbGetMsg.GetMsgSuccess(messages=<Iterable>))"
     }
@@ -97,7 +104,11 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
     /**
      * 不要直接 expect 这个 class. 它可能还没同步完成
      */
-    open class Response(internal val syncFlagFromServer: MsgSvc.SyncFlag, delegate: List<Packet>) :
+    open class Response(
+        internal val syncFlagFromServer: MsgSvc.SyncFlag,
+        delegate: List<Packet>,
+        val syncCookie: ByteArray?
+    ) :
         AbstractEvent(),
         MultiPacket<Packet>,
         Iterable<Packet> by (delegate) {
@@ -106,7 +117,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
             "MessageSvcPbGetMsg.Response(syncFlagFromServer=$syncFlagFromServer, messages=<Iterable>))"
     }
 
-    object EmptyResponse : GetMsgSuccess(emptyList())
+    object EmptyResponse : GetMsgSuccess(emptyList(), null)
 
     private fun MsgComm.Msg.getNewMemberInfo(): MemberInfo {
         return object : MemberInfo {
@@ -268,7 +279,9 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
                     */
 
                     166 -> {
-
+                        if (firstSyncPackets != 0) {
+                            return@mapNotNull null
+                        }
                         if (msg.msgHead.fromUin == bot.id) {
                             loop@ while (true) {
                                 val instance = bot.client.getFriendSeq()
@@ -361,27 +374,41 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
                     }
                 }
             }
-
         val list: List<Packet> = messages.toList()
         if (resp.syncFlag == MsgSvc.SyncFlag.STOP) {
-            return GetMsgSuccess(list)
+            return GetMsgSuccess(list, resp.syncCookie)
         }
-        return Response(resp.syncFlag, list)
+        return Response(resp.syncFlag, list, resp.syncCookie)
     }
 
     override suspend fun QQAndroidBot.handle(packet: Response) {
         when (packet.syncFlagFromServer) {
-            MsgSvc.SyncFlag.STOP -> return
+            MsgSvc.SyncFlag.STOP -> {
+                if (firstSyncPackets != 0) {
+                    firstSyncPackets--
+                }
+            }
+
             MsgSvc.SyncFlag.START -> {
                 network.run {
-                    MessageSvcPbGetMsg(client, MsgSvc.SyncFlag.CONTINUE, currentTimeSeconds).sendAndExpect<Packet>()
+                    MessageSvcPbGetMsg(
+                        client,
+                        MsgSvc.SyncFlag.CONTINUE,
+                        currentTimeSeconds,
+                        packet.syncCookie
+                    ).sendAndExpect<Packet>()
                 }
                 return
             }
 
             MsgSvc.SyncFlag.CONTINUE -> {
                 network.run {
-                    MessageSvcPbGetMsg(client, MsgSvc.SyncFlag.CONTINUE, currentTimeSeconds).sendAndExpect<Packet>()
+                    MessageSvcPbGetMsg(
+                        client,
+                        MsgSvc.SyncFlag.CONTINUE,
+                        currentTimeSeconds,
+                        packet.syncCookie
+                    ).sendAndExpect<Packet>()
                 }
                 return
             }

+ 6 - 5
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PbSendMsg.kt

@@ -25,14 +25,15 @@ import net.mamoe.mirai.qqandroid.message.MessageSourceToTempImpl
 import net.mamoe.mirai.qqandroid.message.toRichTextElems
 import net.mamoe.mirai.qqandroid.network.Packet
 import net.mamoe.mirai.qqandroid.network.QQAndroidClient
-import net.mamoe.mirai.qqandroid.network.protocol.data.proto.*
+import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
+import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
+import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgCtrl
+import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
 import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
 import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
 import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
 import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
-import net.mamoe.mirai.qqandroid.utils.hexToBytes
 import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
-import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
 import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
 import net.mamoe.mirai.utils.currentTimeSeconds
 import kotlin.contracts.InvocationKind
@@ -79,7 +80,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
                 ),
                 msgSeq = source.sequenceId,
                 msgRand = source.internalId,
-                syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer())
+                syncCookie = client.c2cMessageSync.syncCookie ?: byteArrayOf()
                 // msgVia = 1
             )
         )
@@ -109,7 +110,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
                 ),
                 msgSeq = source.sequenceId,
                 msgRand = source.internalId,
-                syncCookie = SyncCookie(time = source.time.toLong()).toByteArray(SyncCookie.serializer())
+                syncCookie = client.c2cMessageSync.syncCookie ?: byteArrayOf()
             )
         )
     }

+ 15 - 6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt

@@ -9,6 +9,7 @@
 
 package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
 
+import kotlinx.atomicfu.loop
 import kotlinx.io.core.ByteReadPacket
 import kotlinx.io.core.discardExact
 import net.mamoe.mirai.qqandroid.QQAndroidBot
@@ -31,12 +32,20 @@ internal object MessageSvcPushNotify : IncomingPacketFactory<RequestPushNotify>(
 
     override suspend fun QQAndroidBot.handle(packet: RequestPushNotify, sequenceId: Int): OutgoingPacket? {
 
-        network.run {
-            return MessageSvcPbGetMsg(
-                client,
-                MsgSvc.SyncFlag.START,
-                packet.stMsgInfo?.uMsgTime ?: currentTimeSeconds
-            )
+        client.c2cMessageSync.firstNotify.loop { firstNotify ->
+            network.run {
+                return MessageSvcPbGetMsg(
+                    client,
+                    MsgSvc.SyncFlag.START,
+                    packet.stMsgInfo?.uMsgTime ?: currentTimeSeconds,
+                    if (firstNotify) {
+                        if (!client.c2cMessageSync.firstNotify.compareAndSet(firstNotify, false)) {
+                            return@loop
+                        }
+                        null
+                    } else packet.vNotifyCookie
+                )
+            }
         }
     }
 }