mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-24 23:20:09 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
0c90b39c8d
@ -102,21 +102,26 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
override suspend fun init() {
|
override suspend fun init() {
|
||||||
//start updating friend/group list
|
//start updating friend/group list
|
||||||
bot.logger.info("Start updating friend/group list")
|
bot.logger.info("Start updating friend/group list")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
val data = FriendList.GetFriendGroupList(
|
val data = FriendList.GetFriendGroupList(
|
||||||
bot.client,
|
bot.client,
|
||||||
0,
|
0,
|
||||||
1,
|
20,
|
||||||
0,
|
0,
|
||||||
2
|
0
|
||||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>()
|
).sendAndExpect<FriendList.GetFriendGroupList.Response>()
|
||||||
*/
|
|
||||||
delay(2000)
|
|
||||||
|
println(data.contentToString())
|
||||||
|
*/
|
||||||
|
|
||||||
val data = FriendList.GetTroopList(
|
val data = FriendList.GetTroopList(
|
||||||
bot.client
|
bot.client
|
||||||
).sendAndExpect<FriendList.GetTroopList.Response>()
|
).sendAndExpect<FriendList.GetTroopList.Response>(100000)
|
||||||
println(data.contentToString())
|
println(data.contentToString())
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package net.mamoe.mirai.qqandroid.network.http
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.client.response.HttpResponse
|
||||||
|
import io.ktor.http.ContentType
|
||||||
|
import io.ktor.http.URLProtocol
|
||||||
|
import io.ktor.http.setCookie
|
||||||
|
import io.ktor.http.userAgent
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.io.readRemaining
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||||
|
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||||
|
import net.mamoe.mirai.utils.cryptor.contentToString
|
||||||
|
import net.mamoe.mirai.utils.currentTimeMillis
|
||||||
|
import net.mamoe.mirai.utils.io.readRemainingBytes
|
||||||
|
import net.mamoe.mirai.utils.io.toUHexString
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 好像不需要了
|
||||||
|
*/
|
||||||
|
object HttpRequest {
|
||||||
|
private lateinit var cookie: String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal suspend fun HttpClient.getPTLoginCookies(
|
||||||
|
client: QQAndroidClient
|
||||||
|
): String {
|
||||||
|
//$"https://ssl.ptlogin2.qq.com/jump?pt_clientver=5593&pt_src=1&keyindex=9&ptlang=2052&clientuin={QQ}&clientkey={Util.ToHex(TXProtocol.BufServiceTicketHttp, "", "{0}")}&u1=https:%2F%2Fuser.qzone.qq.com%2F417085811%3FADUIN=417085811%26ADSESSION={Util.GetTimeMillis(DateTime.Now)}%26ADTAG=CLIENT.QQ.5593_MyTip.0%26ADPUBNO=26841&source=namecardhoverstar"
|
||||||
|
// "https://ssl.ptlogin2.qq.com/jump?pt_clientver=5509&pt_src=1&keyindex=9&clientuin={0}&clientkey={1}&u1=http%3A%2F%2Fqun.qq.com%2Fmember.html%23gid%3D168209441",
|
||||||
|
val res = post<HttpResponse> {
|
||||||
|
println(client.wLoginSigInfo.userStWebSig.data.toUHexString().replace(" ", "").toLowerCase())
|
||||||
|
url {
|
||||||
|
protocol = URLProtocol.HTTPS
|
||||||
|
host = "ssl.ptlogin2.qq.com"
|
||||||
|
path(
|
||||||
|
"/jump?pt_clientver=5509&pt_src=1&keyindex=9&clientuin=${client.uin}&clientkey=${client.wLoginSigInfo.userStWebSig.data.toUHexString().replace(
|
||||||
|
" ",
|
||||||
|
""
|
||||||
|
)}&u1=http%3A%2F%2Fqun.qq.com%2Fmember.html%23gid%3D168209441&FADUIN=417085811&ADSESSION=${currentTimeMillis}&source=namecardhoverstar"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
headers {
|
||||||
|
userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println(res.status)
|
||||||
|
println(res.setCookie())
|
||||||
|
println(res.content.readRemaining().readRemainingBytes().toUHexString())
|
||||||
|
return "done";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal suspend fun HttpClient.getGroupList(
|
||||||
|
client: QQAndroidClient
|
||||||
|
): String {
|
||||||
|
// "https://ssl.ptlogin2.qq.com/jump?pt_clientver=5509&pt_src=1&keyindex=9&clientuin={0}&clientkey={1}&u1=http%3A%2F%2Fqun.qq.com%2Fmember.html%23gid%3D168209441",
|
||||||
|
val res = get<HttpResponse> {
|
||||||
|
url {
|
||||||
|
protocol = URLProtocol.HTTPS
|
||||||
|
host = "ssl.ptlogin2.qq.com"
|
||||||
|
path("jump")
|
||||||
|
parameters["pt_clientver"] = "5509"
|
||||||
|
parameters["pt_src"] = "1"
|
||||||
|
parameters["keyindex"] = "9"
|
||||||
|
parameters["u1"] = "http%3A%2F%2Fqun.qq.com%2Fmember.html%23gid%3D168209441"
|
||||||
|
parameters["clientuin"] = client.uin.toString()
|
||||||
|
parameters["clientkey"] = client.wLoginSigInfo.userStWebSig.data.toUHexString()
|
||||||
|
}
|
||||||
|
headers {
|
||||||
|
userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println(res.status)
|
||||||
|
println(res.setCookie())
|
||||||
|
return "done";
|
||||||
|
}
|
@ -24,3 +24,84 @@ internal class stTroopNumSimplify(
|
|||||||
@SerialId(2) val dwGroupFlagExt: Long? = null,
|
@SerialId(2) val dwGroupFlagExt: Long? = null,
|
||||||
@SerialId(3) val dwGroupRankSeq: Long? = null
|
@SerialId(3) val dwGroupRankSeq: Long? = null
|
||||||
) : JceStruct
|
) : JceStruct
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal class GetTroopListRespV2(
|
||||||
|
@SerialId(0) val uin: Long,
|
||||||
|
@SerialId(1) val troopcount: Short,
|
||||||
|
@SerialId(2) val result: Int,
|
||||||
|
@SerialId(3) val errorCode: Short? = null,
|
||||||
|
@SerialId(4) val vecCookies: ByteArray? = null,
|
||||||
|
@SerialId(5) val vecTroopList: List<stTroopNum>? = null,
|
||||||
|
@SerialId(6) val vecTroopListDel: List<stTroopNum>? = null,
|
||||||
|
@SerialId(7) val vecTroopRank: List<stGroupRankInfo>? = null,
|
||||||
|
@SerialId(8) val vecFavGroup: List<stFavoriteGroup>? = null,
|
||||||
|
@SerialId(9) val vecTroopListExt: List<stTroopNum>? = null
|
||||||
|
) : JceStruct
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal class stTroopNum(
|
||||||
|
@SerialId(0) val groupUin: Long,
|
||||||
|
@SerialId(1) val groupCode: Long,
|
||||||
|
@SerialId(2) val flag: Byte? = null,
|
||||||
|
@SerialId(3) val dwGroupInfoSeq: Long? = null,
|
||||||
|
@SerialId(4) val groupName: String? = "",
|
||||||
|
@SerialId(5) val groupMemo: String? = "",
|
||||||
|
@SerialId(6) val dwGroupFlagExt: Long? = null,
|
||||||
|
@SerialId(7) val dwGroupRankSeq: Long? = null,
|
||||||
|
@SerialId(8) val dwCertificationType: Long? = null,
|
||||||
|
@SerialId(9) val dwShutupTimestamp: Long? = null,
|
||||||
|
@SerialId(10) val dwMyShutupTimestamp: Long? = null,
|
||||||
|
@SerialId(11) val dwCmdUinUinFlag: Long? = null,
|
||||||
|
@SerialId(12) val dwAdditionalFlag: Long? = null,
|
||||||
|
@SerialId(13) val dwGroupTypeFlag: Long? = null,
|
||||||
|
@SerialId(14) val dwGroupSecType: Long? = null,
|
||||||
|
@SerialId(15) val dwGroupSecTypeInfo: Long? = null,
|
||||||
|
@SerialId(16) val dwGroupClassExt: Long? = null,
|
||||||
|
@SerialId(17) val dwAppPrivilegeFlag: Long? = null,
|
||||||
|
@SerialId(18) val dwSubscriptionUin: Long? = null,
|
||||||
|
@SerialId(19) val dwMemberNum: Long? = null,
|
||||||
|
@SerialId(20) val dwMemberNumSeq: Long? = null,
|
||||||
|
@SerialId(21) val dwMemberCardSeq: Long? = null,
|
||||||
|
@SerialId(22) val dwGroupFlagExt3: Long? = null,
|
||||||
|
@SerialId(23) val dwGroupOwnerUin: Long? = null,
|
||||||
|
@SerialId(24) val isConfGroup: Byte? = null,
|
||||||
|
@SerialId(25) val isModifyConfGroupFace: Byte? = null,
|
||||||
|
@SerialId(26) val isModifyConfGroupName: Byte? = null,
|
||||||
|
@SerialId(27) val dwCmduinJoinTime: Long? = null,
|
||||||
|
@SerialId(28) val ulCompanyId: Long? = null,
|
||||||
|
@SerialId(29) val dwMaxGroupMemberNum: Long? = null,
|
||||||
|
@SerialId(30) val dwCmdUinGroupMask: Long? = null,
|
||||||
|
@SerialId(31) val udwHLGuildAppid: Long? = null,
|
||||||
|
@SerialId(32) val udwHLGuildSubType: Long? = null,
|
||||||
|
@SerialId(33) val udwCmdUinRingtoneID: Long? = null,
|
||||||
|
@SerialId(34) val udwCmdUinFlagEx2: Long? = null
|
||||||
|
) : JceStruct
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal class stGroupRankInfo(
|
||||||
|
@SerialId(0) val dwGroupCode: Long,
|
||||||
|
@SerialId(1) val groupRankSysFlag: Byte? = null,
|
||||||
|
@SerialId(2) val groupRankUserFlag: Byte? = null,
|
||||||
|
@SerialId(3) val vecRankMap: List<stLevelRankPair>? = null,
|
||||||
|
@SerialId(4) val dwGroupRankSeq: Long? = null,
|
||||||
|
@SerialId(5) val ownerName: String? = "",
|
||||||
|
@SerialId(6) val adminName: String? = "",
|
||||||
|
@SerialId(7) val dwOfficeMode: Long? = null
|
||||||
|
) : JceStruct
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal class stFavoriteGroup(
|
||||||
|
@SerialId(0) val dwGroupCode: Long,
|
||||||
|
@SerialId(1) val dwTimestamp: Long? = null,
|
||||||
|
@SerialId(2) val dwSnsFlag: Long? = 1L,
|
||||||
|
@SerialId(3) val dwOpenTimestamp: Long? = null
|
||||||
|
) : JceStruct
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal class stLevelRankPair(
|
||||||
|
@SerialId(0) val dwLevel: Long? = null,
|
||||||
|
@SerialId(1) val rank: String? = ""
|
||||||
|
) : JceStruct
|
||||||
|
@ -8,16 +8,20 @@ import net.mamoe.mirai.qqandroid.io.serialization.jceRequestSBuffer
|
|||||||
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
|
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.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.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.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
|
||||||
@ -25,14 +29,28 @@ import net.mamoe.mirai.utils.io.toUHexString
|
|||||||
|
|
||||||
internal class FriendList {
|
internal class FriendList {
|
||||||
|
|
||||||
internal object GetTroopList : PacketFactory<GetTroopList.Response>("friendlist.GetTroopListReqV2") {
|
/**
|
||||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
* Get Troop List不一定会得到服务器的回应 据推测与群数量有关
|
||||||
println("获取到了GetTroopList的回信")
|
* 因此 应对timeout方法做出处理
|
||||||
println(this.readRemainingBytes().toUHexString())
|
* timeout时间应不小于 8s?
|
||||||
return Response()
|
*
|
||||||
|
*/
|
||||||
|
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(
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Response : Packet {
|
class Response(
|
||||||
|
|
||||||
|
) : Packet {
|
||||||
override fun toString(): String = "FriendList.GetFriendGroupList.Response"
|
override fun toString(): String = "FriendList.GetFriendGroupList.Response"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +66,6 @@ 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(),
|
||||||
@ -68,18 +85,21 @@ internal class FriendList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object GetFriendGroupList : PacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
|
internal object GetFriendGroupList : PacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
|
||||||
|
class Response(
|
||||||
class Response : Packet {
|
val totalFriendCount: Short,
|
||||||
|
val friendList: List<FriendInfo>
|
||||||
|
) : Packet {
|
||||||
override fun toString(): String = "FriendList.GetFriendGroupList.Response"
|
override fun toString(): String = "FriendList.GetFriendGroupList.Response"
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||||
this.discardExact(4)
|
this.discardExact(4)
|
||||||
val res = this.decodeUniPacket(GetFriendListResp.serializer())
|
val res = this.decodeUniPacket(GetFriendListResp.serializer())
|
||||||
println(res.contentToString())
|
return Response(
|
||||||
return Response()
|
res.totoalFriendCount,
|
||||||
|
res.vecFriendInfo.orEmpty()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
|
@ -276,6 +276,9 @@ fun ByteReadPacket.decodeUni() {
|
|||||||
//return
|
//return
|
||||||
readBytes(readInt() - 4).debugPrint("head").toReadPacket().apply {
|
readBytes(readInt() - 4).debugPrint("head").toReadPacket().apply {
|
||||||
val commandName = readString(readInt() - 4).also { PacketLogger.warning("commandName=$it") }
|
val commandName = readString(readInt() - 4).also { PacketLogger.warning("commandName=$it") }
|
||||||
|
if(commandName.contains("GetTroopList")){
|
||||||
|
println("!\n".repeat(100))
|
||||||
|
}
|
||||||
println(commandName)
|
println(commandName)
|
||||||
println(" unknown4Bytes=" + readBytes(readInt() - 4).toUHexString())
|
println(" unknown4Bytes=" + readBytes(readInt() - 4).toUHexString())
|
||||||
// 00 00 00 1A 43 6F 6E 66 69 67 50 75 73 68 53 76 63 2E 50 75 73 68 52 65 73 70
|
// 00 00 00 1A 43 6F 6E 66 69 67 50 75 73 68 53 76 63 2E 50 75 73 68 52 65 73 70
|
||||||
|
@ -219,6 +219,9 @@ private fun parseSsoFrame(flag3: Int, input: ByteReadPacket): KnownPacketFactori
|
|||||||
|
|
||||||
commandName = readString(readInt() - 4)
|
commandName = readString(readInt() - 4)
|
||||||
DebugLogger.warning("commandName=$commandName")
|
DebugLogger.warning("commandName=$commandName")
|
||||||
|
if(commandName.contains("GetTroopList")){
|
||||||
|
println("!\n".repeat(100))
|
||||||
|
}
|
||||||
val unknown = readBytes(readInt() - 4)
|
val unknown = readBytes(readInt() - 4)
|
||||||
//if (unknown.toInt() != 0x02B05B8B) DebugLogger.debug("got new unknown: ${unknown.toUHexString()}")
|
//if (unknown.toInt() != 0x02B05B8B) DebugLogger.debug("got new unknown: ${unknown.toUHexString()}")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user