From daec69caaffa6e670325c53b676941eda35a8f9b Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Fri, 10 Jan 2020 22:50:50 +0800 Subject: [PATCH] Add weakRef bot to QQAClient --- .../net/mamoe/mirai/qqandroid/QQAndroidBot.kt | 2 +- .../qqandroid/network/QQAndroidClient.kt | 155 +++++++++++++++++- 2 files changed, 155 insertions(+), 2 deletions(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index f02238579..14f9d0236 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -25,7 +25,7 @@ internal abstract class QQAndroidBotBase constructor( account: BotAccount, configuration: BotConfiguration ) : BotImpl<QQAndroidBotNetworkHandler>(account, configuration) { - val client: QQAndroidClient = QQAndroidClient(context, account) + val client: QQAndroidClient = QQAndroidClient(context, account, bot = @Suppress("LeakingThis") this as QQAndroidBot) override val qqs: ContactList<QQ> get() = TODO("not implemented") diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt index cef4eee2b..521cf5b85 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt @@ -2,15 +2,19 @@ package net.mamoe.mirai.qqandroid.network import kotlinx.atomicfu.AtomicInt import kotlinx.atomicfu.atomic +import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.toByteArray import net.mamoe.mirai.BotAccount +import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.utils.Context import net.mamoe.mirai.qqandroid.utils.DeviceInfo import net.mamoe.mirai.qqandroid.utils.NetworkType import net.mamoe.mirai.qqandroid.utils.SystemDeviceInfo +import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.cryptor.ECDH import net.mamoe.mirai.utils.io.hexToBytes +import net.mamoe.mirai.utils.unsafeWeakRef /* APP ID: @@ -29,12 +33,17 @@ import net.mamoe.mirai.utils.io.hexToBytes @PublishedApi internal open class QQAndroidClient( val context: Context, + @MiraiInternalAPI("Be careful. Do not use the id in BotAccount. use client.uin instead") val account: BotAccount, val ecdh: ECDH = ECDH(), - val device: DeviceInfo = SystemDeviceInfo(context) + val device: DeviceInfo = SystemDeviceInfo(context), + bot: QQAndroidBot ) { + val bot: QQAndroidBot by bot.unsafeWeakRef() + val tgtgtKey: ByteArray = ByteArray(16) // generateTgtgtKey(device.guid) + val randomKey: ByteArray = ByteArray(16) // 加密使用 var miscBitMap: Int = 184024956 // 也可能是 150470524 ? var mainSigMap: Int = 16724722 @@ -65,5 +74,149 @@ internal open class QQAndroidClient( @Suppress("SpellCheckingInspection") @PublishedApi internal val apkId: ByteArray = "com.tencent.mobileqq".toByteArray() + + /* + * 以下登录使用 + */ + + + var t150: ByteArray? = null + var rollbackSig: ByteArray? = null + var ipFromT149: ByteArray? = null + /** + * 客户端与服务器时间差 + */ + var timeDifference: Long = 0 + /** + * 真实 QQ 号. 使用邮箱等登录时则需获取这个 uin 进行后续一些操作. + * + * **注意**: 总是使用这个属性, 而不要使用 [BotAccount.id]. 将来它可能会变为 [String] + */ + @UseExperimental(MiraiExperimentalAPI::class, MiraiInternalAPI::class) + var uin: Long = bot.account.id + var t530: ByteArray? = null + var t528: ByteArray? = null + /** + * t108 时更新 + */ + var ksid: String = "|454001228437590|A8.2.0.27f6ea96" + /** + * t186 + */ + var pwdFlag: Boolean = false + /** + * t537 + */ + var loginExtraData: LoginExtraData? = null + lateinit var wFastLoginInfo: WFastLoginInfo + lateinit var reserveUinInfo: ReserveUinInfo + var wLoginSigInfo: WLoginSigInfo? = null + var tlv113: ByteArray? = null + lateinit var qrPushSig: ByteArray + + lateinit var mainDisplayName: String } +class ReserveUinInfo( + val imgType: ByteArray, + val imgFormat: ByteArray, + val imgUrl: ByteArray +) + +class WFastLoginInfo( + val outA1: ByteReadPacket, + var adUrl: String = "", + var iconUrl: String = "", + var profileUrl: String = "", + var userJson: String = "" +) + +class WLoginSimpleInfo( + val uin: Long, // uin + val face: Int, // ubyte actually + val age: Int, // ubyte + val gender: Int, // ubyte + val nick: String, // ubyte lv string + val imgType: ByteArray, + val imgFormat: ByteArray, + val imgUrl: ByteArray, + val mainDisplayName: ByteArray +) + +class LoginExtraData( + val uin: Long, + val ip: ByteArray, + val time: Int, + val version: Int +) + +class WLoginSigInfo( + val uin: Long, + val encryptA1: ByteArray, // sigInfo[0] + val noPicSig: ByteArray, // sigInfo[1] + val G: ByteArray, // sigInfo[2] + val dpwd: ByteArray, + val randSeed: ByteArray, + + val simpleInfo: WLoginSimpleInfo, + + val appPri: Long, + val a2ExpiryTime: Long, + val loginBitmap: Long, + val tgt: ByteArray, + val a2CreationTime: Long, + val tgtKey: ByteArray, + val userStSig: UserStSig, + val userStKey: ByteArray, + val userStWebSig: UserStWebSig, + val userA5: UserA5, + val userA8: UserA8, + val lsKey: LSKey, + val sKey: SKey, + val userSig64: UserSig64, + val openId: ByteArray, + val openKey: OpenKey, + val vKey: VKey, + val accessToken: AccessToken, + val d2: D2, + val d2Key: ByteArray, + val sid: Sid, + val aqSig: AqSig, + val psKey: PSKey, + val superKey: ByteArray, + val payToken: ByteArray, + val pf: ByteArray, + val pfKey: ByteArray, + val da2: ByteArray, + // val pt4Token: ByteArray, + val wtSessionTicket: WtSessionTicket, + val wtSessionTicketKey: ByteArray, + val deviceToken: ByteArray +) + +class UserStSig(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class LSKey(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class UserStWebSig(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class UserA8(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class UserA5(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class SKey(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class UserSig64(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class OpenKey(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class VKey(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class AccessToken(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class D2(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class Sid(data: ByteArray, creationTime: Long, expireTime: Long) : KeyWithExpiry(data, creationTime, expireTime) +class AqSig(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class PSKey(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) +class WtSessionTicket(data: ByteArray, creationTime: Long) : KeyWithCreationTime(data, creationTime) + +open class KeyWithExpiry( + data: ByteArray, + creationTime: Long, + val expireTime: Long +) : KeyWithCreationTime(data, creationTime) + +open class KeyWithCreationTime( + val data: ByteArray, + val creationTime: Long +) \ No newline at end of file