Commit 424c9bb2 authored by jiahua.liu's avatar jiahua.liu

Friend List Complete

parent 722422d4
...@@ -23,6 +23,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket ...@@ -23,6 +23,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.utils.LockFreeLinkedList import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.getValue import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.unsafeWeakRef import net.mamoe.mirai.utils.unsafeWeakRef
...@@ -104,51 +105,57 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -104,51 +105,57 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
override suspend fun init() { override suspend fun init() {
delay(5000) delay(5000)
bot.logger.info("开始加载好友信息")
this@QQAndroidBotNetworkHandler.subscribeAlways<ForceOfflineEvent> { this@QQAndroidBotNetworkHandler.subscribeAlways<ForceOfflineEvent> {
if (this@QQAndroidBotNetworkHandler.bot == this.bot) { if (this@QQAndroidBotNetworkHandler.bot == this.bot) {
close() close()
} }
} }
/*
* 开始加载Contact表 try {
* */ bot.logger.info("开始加载组信息")
var currentFriendCount = 0 val troopData = FriendList.GetTroopListSimplify(
var totalFriendCount: Short bot.client
while (true) { ).sendAndExpect<FriendList.GetTroopListSimplify.Response>(10000)
val data = FriendList.GetFriendGroupList( println(troopData.contentToString())
bot.client, } catch (e: Exception) {
currentFriendCount, bot.logger.info("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表")
20, }
0, try {
0 bot.logger.info("开始加载好友信息")
).sendAndExpect<FriendList.GetFriendGroupList.Response>( var currentFriendCount = 0
timeoutMillis = 8000, var totalFriendCount: Short
retry = 5 while (true) {
) val data = FriendList.GetFriendGroupList(
totalFriendCount = data.totalFriendCount bot.client,
data.friendList.forEach { currentFriendCount,
// atomic add 20,
bot.qqs.delegate.addLast(QQImpl(bot, EmptyCoroutineContext, it.friendUin).also { 0,
currentFriendCount++ 0
}) ).sendAndExpect<FriendList.GetFriendGroupList.Response>(
} timeoutMillis = 8000,
bot.logger.verbose("正在加载好友信息 ${currentFriendCount}/${totalFriendCount}") retry = 5
if (currentFriendCount >= totalFriendCount) { )
break
totalFriendCount = data.totalFriendCount
data.friendList.forEach {
// atomic add
bot.qqs.delegate.addLast(QQImpl(bot, EmptyCoroutineContext, it.friendUin).also {
currentFriendCount++
})
}
bot.logger.verbose("正在加载好友信息 ${currentFriendCount}/${totalFriendCount}")
if (currentFriendCount >= totalFriendCount) {
break
}
delay(200)
} }
delay(200) bot.logger.info("好友信息加载完成, 共 ${currentFriendCount}个")
} catch (e: Exception) {
bot.logger.info("加载好友信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载好友列表")
} }
bot.logger.info("好友信息加载完成, 共 ${currentFriendCount}个")
//发送事件 //发送事件
/**
val data = FriendList.GetTroopList(
bot.client
).sendAndExpect<FriendList.GetTroopList.Response>(100000)
println(data.contentToString())
*/
} }
/** /**
......
...@@ -105,3 +105,15 @@ internal class stLevelRankPair( ...@@ -105,3 +105,15 @@ internal class stLevelRankPair(
@SerialId(0) val dwLevel: Long? = null, @SerialId(0) val dwLevel: Long? = null,
@SerialId(1) val rank: String? = "" @SerialId(1) val rank: String? = ""
) : JceStruct ) : JceStruct
@Serializable
internal class GetTroopMemberListReq(
@SerialId(0) val uin: Long,
@SerialId(1) val groupCode: Long,
@SerialId(2) val nextUin: Long,
@SerialId(3) val groupUin: Long,
@SerialId(4) val version: Long? = null,
@SerialId(5) val reqType: Long? = null,
@SerialId(6) val getListAppointTime: Long? = null,
@SerialId(7) val richCardNameVer: Byte? = null
) : JceStruct
\ No newline at end of file
...@@ -67,7 +67,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( ...@@ -67,7 +67,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
MessageSvc.PushForceOffline, MessageSvc.PushForceOffline,
MessageSvc.PbSendMsg, MessageSvc.PbSendMsg,
FriendList.GetFriendGroupList, FriendList.GetFriendGroupList,
FriendList.GetTroopList FriendList.GetTroopListSimplify
) { ) {
// SvcReqMSFLoginNotify 自己的其他设备上限 // SvcReqMSFLoginNotify 自己的其他设备上限
// MessageSvc.PushReaded 电脑阅读了别人的消息, 告知手机 // MessageSvc.PushReaded 电脑阅读了别人的消息, 告知手机
......
package net.mamoe.mirai.qqandroid.network.protocol.packet.list package net.mamoe.mirai.qqandroid.network.protocol.packet.list
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.contact.GroupId
import net.mamoe.mirai.contact.toInternalId
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket
...@@ -9,20 +11,18 @@ import net.mamoe.mirai.qqandroid.io.serialization.toByteArray ...@@ -9,20 +11,18 @@ import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.io.serialization.writeJceStruct import net.mamoe.mirai.qqandroid.io.serialization.writeJceStruct
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.* import net.mamoe.mirai.qqandroid.network.protocol.data.jce.*
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.FriendInfo
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GetFriendListReq import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GetFriendListReq
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GetFriendListResp import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GetFriendListResp
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GetTroopListReqV2Simplify import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GetTroopListReqV2Simplify
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.GroupInfo
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Vec0xd50 import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Vec0xd50
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Vec0xd6b
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY 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.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList.GetFriendGroupList.decode import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList.GetFriendGroupList.decode
import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.io.debugPrint
import net.mamoe.mirai.utils.io.discardExact import net.mamoe.mirai.utils.io.discardExact
import net.mamoe.mirai.utils.io.readRemainingBytes import net.mamoe.mirai.utils.io.readRemainingBytes
import net.mamoe.mirai.utils.io.toUHexString import net.mamoe.mirai.utils.io.toUHexString
...@@ -30,23 +30,38 @@ import net.mamoe.mirai.utils.io.toUHexString ...@@ -30,23 +30,38 @@ import net.mamoe.mirai.utils.io.toUHexString
internal class FriendList { internal class FriendList {
/** internal object GetTroopMemberList :
* Get Troop List不一定会得到服务器的回应 据推测与群数量有关 PacketFactory<GetTroopMemberList.Response>("friendlist.GetTroopMemberListReq") {
* 因此 应对timeout方法做出处理 override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GetTroopMemberList.Response {
* timeout时间应不小于 8s? TODO()
* }
*/
internal object GetTroopList :
PacketFactory<GetTroopList.Response>("friendlist.GetTroopListReqV2") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GetTroopList.Response {
debugPrint()
this.discardExact(4)
val res = this.decodeUniPacket(GetTroopListRespV2.serializer())
println(res.contentToString())
return Response(
)
operator fun invoke(
client: QQAndroidClient,
targetGroupId: Long,
nextUin: Long = 0
): OutgoingPacket {
return buildOutgoingUniPacket(client, bodyType = 1, key = client.wLoginSigInfo.d2Key) {
writeJceStruct(
RequestPacket.serializer(),
RequestPacket(
sFuncName = "GetTroopMemberListReq",
sServantName = "mqq.IMService.FriendListServiceServantObj",
iVersion = 3,
sBuffer = jceRequestSBuffer(
"GTML",
GetTroopMemberListReq.serializer(),
GetTroopMemberListReq(
uin = client.uin,
groupCode = GroupId(targetGroupId).toInternalId().value,
groupUin = targetGroupId,
nextUin = 0,
reqType = 0
)
)
)
)
}
} }
class Response( class Response(
...@@ -55,6 +70,22 @@ internal class FriendList { ...@@ -55,6 +70,22 @@ internal class FriendList {
override fun toString(): String = "FriendList.GetFriendGroupList.Response" override fun toString(): String = "FriendList.GetFriendGroupList.Response"
} }
}
internal object GetTroopListSimplify :
PacketFactory<GetTroopListSimplify.Response>("friendlist.GetTroopListReqV2") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GetTroopListSimplify.Response {
this.discardExact(4)
val res = this.decodeUniPacket(GetTroopListRespV2.serializer())
return Response(res.vecTroopList.orEmpty())
}
class Response(
val groups: List<stTroopNum>
) : Packet {
override fun toString(): String = "FriendList.GetFriendGroupList.Response"
}
operator fun invoke( operator fun invoke(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket { ): OutgoingPacket {
...@@ -67,18 +98,18 @@ internal class FriendList { ...@@ -67,18 +98,18 @@ internal class FriendList {
iVersion = 3, iVersion = 3,
cPacketType = 0x00, cPacketType = 0x00,
iMessageType = 0x00000, iMessageType = 0x00000,
iRequestId = 1921334513,
sBuffer = jceRequestSBuffer( sBuffer = jceRequestSBuffer(
"GetTroopListReqV2Simplify", "GetTroopListReqV2Simplify",
GetTroopListReqV2Simplify.serializer(), GetTroopListReqV2Simplify.serializer(),
GetTroopListReqV2Simplify( GetTroopListReqV2Simplify(
uin = client.uin, uin = client.uin,
getMSFMsgFlag = 0, // const getMSFMsgFlag = 0,
groupFlagExt = 1,// const groupFlagExt = 1,
shVersion = 7, // const shVersion = 7,
dwCompanyId = 0, dwCompanyId = 0,
versionNum = 1, // const versionNum = 1,
vecGroupInfo = listOf(), getLongGroupName = 1
getLongGroupName = 1// const
) )
) )
) )
...@@ -87,6 +118,7 @@ internal class FriendList { ...@@ -87,6 +118,7 @@ internal class FriendList {
} }
} }
internal object GetFriendGroupList : PacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") { internal object GetFriendGroupList : PacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
class Response( class Response(
val totalFriendCount: Short, val totalFriendCount: Short,
val friendList: List<FriendInfo> val friendList: List<FriendInfo>
...@@ -119,24 +151,25 @@ internal class FriendList { ...@@ -119,24 +151,25 @@ internal class FriendList {
iVersion = 3, iVersion = 3,
cPacketType = 0x003, cPacketType = 0x003,
iMessageType = 0x00000, iMessageType = 0x00000,
iRequestId = 1921334514,
sBuffer = jceRequestSBuffer( sBuffer = jceRequestSBuffer(
"FL", "FL",
GetFriendListReq.serializer(), GetFriendListReq.serializer(),
GetFriendListReq( GetFriendListReq(
reqtype = 3, reqtype = 3,
ifReflush = if (friendListStartIndex == 0) { ifReflush = if (friendListStartIndex <= 0) {
1
} else {
0 0
} else {
1
}, },
uin = client.uin, uin = client.uin,
startIndex = friendListStartIndex.toShort(), startIndex = friendListStartIndex.toShort(),
getfriendCount = friendListCount.toShort(), getfriendCount = friendListCount.toShort(),
groupid = 0, groupid = 0,
ifGetGroupInfo = if (friendListStartIndex == 0) { ifGetGroupInfo = if (groupListCount <= 0) {
1
} else {
0 0
} else {
1
}, },
groupstartIndex = groupListStartIndex.toByte(), groupstartIndex = groupListStartIndex.toByte(),
getgroupCount = groupListCount.toByte(), getgroupCount = groupListCount.toByte(),
...@@ -147,7 +180,7 @@ internal class FriendList { ...@@ -147,7 +180,7 @@ internal class FriendList {
eAppType = 0, eAppType = 0,
ifGetBothFlag = 0, ifGetBothFlag = 0,
ifGetDOVId = 0, ifGetDOVId = 0,
vec0xd6bReq = Vec0xd6b.ReqBody().toByteArray(Vec0xd6b.ReqBody.serializer()), vec0xd6bReq = EMPTY_BYTE_ARRAY,
vec0xd50Req = Vec0xd50.ReqBody( vec0xd50Req = Vec0xd50.ReqBody(
appid = 10002L, appid = 10002L,
reqKsingSwitch = 1, reqKsingSwitch = 1,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment