mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-13 03:16:05 +08:00
QQA Debugging update
This commit is contained in:
parent
1de776f092
commit
9353a5af7b
@ -29,6 +29,22 @@ class JceInput(
|
||||
return JceHead(tag = tag, type = type)
|
||||
}
|
||||
|
||||
fun read(default: Byte, tag: Int): Byte = readByteOrNull(tag) ?: default
|
||||
fun read(default: Short, tag: Int): Short = readShortOrNull(tag) ?: default
|
||||
fun read(default: Int, tag: Int): Int = readIntOrNull(tag) ?: default
|
||||
fun read(default: Long, tag: Int): Long = readLongOrNull(tag) ?: default
|
||||
fun read(default: Float, tag: Int): Float = readFloatOrNull(tag) ?: default
|
||||
fun read(default: Double, tag: Int): Double = readDoubleOrNull(tag) ?: default
|
||||
fun read(default: Boolean, tag: Int): Boolean = readBooleanOrNull(tag) ?: default
|
||||
|
||||
fun read(default: ByteArray, tag: Int): ByteArray = readByteArrayOrNull(tag) ?: default
|
||||
fun read(default: ShortArray, tag: Int): ShortArray = readShortArrayOrNull(tag) ?: default
|
||||
fun read(default: IntArray, tag: Int): IntArray = readIntArrayOrNull(tag) ?: default
|
||||
fun read(default: LongArray, tag: Int): LongArray = readLongArrayOrNull(tag) ?: default
|
||||
fun read(default: FloatArray, tag: Int): FloatArray = readFloatArrayOrNull(tag) ?: default
|
||||
fun read(default: DoubleArray, tag: Int): DoubleArray = readDoubleArrayOrNull(tag) ?: default
|
||||
fun read(default: BooleanArray, tag: Int): BooleanArray = readBooleanArrayOrNull(tag) ?: default
|
||||
|
||||
fun readBoolean(tag: Int): Boolean = readBooleanOrNull(tag) ?: error("cannot find tag $tag")
|
||||
fun readByte(tag: Int): Byte = readByteOrNull(tag) ?: error("cannot find tag $tag")
|
||||
fun readShort(tag: Int): Short = readShortOrNull(tag) ?: error("cannot find tag $tag")
|
||||
@ -176,7 +192,7 @@ class JceInput(
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Map<K, V>, K, V> readMapOrNull(defaultKey: K, defaultValue: V, tag: Int): Map<K, V>? = skipToTagOrNull(tag) {
|
||||
fun <K, V> readMapOrNull(defaultKey: K, defaultValue: V, tag: Int): Map<K, V>? = skipToTagOrNull(tag) {
|
||||
check(it.type.toInt() == 8) { "type mismatch" }
|
||||
val size = readInt(0)
|
||||
val map = HashMap<K, V>(size)
|
||||
@ -186,6 +202,16 @@ class JceInput(
|
||||
return map
|
||||
}
|
||||
|
||||
inline fun <reified K, reified V> readMapOrNull(tag: Int): Map<K, V>? = skipToTagOrNull(tag) {
|
||||
check(it.type.toInt() == 8) { "type mismatch" }
|
||||
val size = readInt(0)
|
||||
val map = HashMap<K, V>(size)
|
||||
repeat(size) {
|
||||
map[readSimpleObject(0)] = readSimpleObject(0)
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
fun <T> readListOrNull(defaultElement: T, tag: Int): List<T>? = skipToTagOrNull(tag) { head ->
|
||||
check(head.type.toInt() == 9) { "type mismatch" }
|
||||
val size = readInt(0)
|
||||
|
@ -2,21 +2,31 @@ package net.mamoe.mirai.qqandroid.network.io
|
||||
|
||||
import kotlinx.io.charsets.Charset
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.utils.io.ByteArrayPool
|
||||
import net.mamoe.mirai.utils.io.readRemainingBytes
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
private val CharsetGBK = Charset.forName("GBK")
|
||||
@PublishedApi
|
||||
internal val CharsetGBK = Charset.forName("GBK")
|
||||
|
||||
fun buildJcePacket(stringCharset: Charset = CharsetGBK, block: JceOutput.() -> Unit): ByteReadPacket {
|
||||
inline fun buildJcePacket(stringCharset: Charset = CharsetGBK, block: JceOutput.() -> Unit): ByteReadPacket {
|
||||
return JceOutput(stringCharset).apply(block).build()
|
||||
}
|
||||
|
||||
fun BytePacketBuilder.writeJcePacket(stringCharset: Charset = CharsetGBK, block: JceOutput.() -> Unit) {
|
||||
inline fun BytePacketBuilder.writeJcePacket(stringCharset: Charset = CharsetGBK, block: JceOutput.() -> Unit) {
|
||||
return this.writePacket(buildJcePacket(stringCharset, block))
|
||||
}
|
||||
|
||||
fun jceStruct(tag: Int, struct: JceStruct): ByteArray{
|
||||
return buildJcePacket {
|
||||
writeJceStruct(struct, tag)
|
||||
}.readBytes()
|
||||
}
|
||||
|
||||
fun <K, V> jceMap(tag: Int, vararg entries: Pair<K, V>): ByteArray {
|
||||
return buildJcePacket {
|
||||
writeMap(mapOf(*entries), tag)
|
||||
}.readBytes()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* From: com.qq.taf.jce.JceOutputStream
|
||||
|
@ -6,21 +6,55 @@ import net.mamoe.mirai.qqandroid.network.io.JceStruct
|
||||
|
||||
private val EMPTY_MAP = mapOf<String, String>()
|
||||
|
||||
class RequestPacket(
|
||||
val sBuffer: ByteArray,
|
||||
val cPacketType: Byte = 0,
|
||||
val iMessageType: Int = 0,
|
||||
val iRequestId: Int = 0,
|
||||
val iTimeout: Int = 3000,
|
||||
val iVersion: Short = 3,
|
||||
val context: Map<String, String> = EMPTY_MAP,
|
||||
val sFuncName: String = "",
|
||||
val sServantName: String = "",
|
||||
val status: Map<String, String> = EMPTY_MAP
|
||||
) : JceStruct() {
|
||||
class RequestPacket() : JceStruct() {
|
||||
lateinit var sBuffer: ByteArray
|
||||
var cPacketType: Byte = 0
|
||||
var iMessageType: Int = 0
|
||||
var iRequestId: Int = 0
|
||||
var iTimeout: Int = 3000
|
||||
var iVersion: Short = 3
|
||||
var context: Map<String, String> = EMPTY_MAP
|
||||
var sFuncName: String = ""
|
||||
var sServantName: String = ""
|
||||
var status: Map<String, String> = EMPTY_MAP
|
||||
|
||||
constructor(
|
||||
sBuffer: ByteArray,
|
||||
cPacketType: Byte = 0,
|
||||
iMessageType: Int = 0,
|
||||
iRequestId: Int = 0,
|
||||
iTimeout: Int = 3000,
|
||||
iVersion: Short = 3,
|
||||
context: Map<String, String> = EMPTY_MAP,
|
||||
sFuncName: String = "",
|
||||
sServantName: String = "",
|
||||
status: Map<String, String> = EMPTY_MAP
|
||||
) : this() {
|
||||
this.sBuffer = sBuffer
|
||||
this.cPacketType = cPacketType
|
||||
this.iMessageType = iMessageType
|
||||
this.iRequestId = iRequestId
|
||||
this.iTimeout = iTimeout
|
||||
this.iVersion = iVersion
|
||||
this.context = context
|
||||
this.sFuncName = sFuncName
|
||||
this.sServantName = sServantName
|
||||
this.status = status
|
||||
}
|
||||
|
||||
companion object : Factory<RequestPacket> {
|
||||
override fun newInstanceFrom(input: JceInput): RequestPacket {
|
||||
TODO("not implemented")
|
||||
val iVersion = input.readShort(1)
|
||||
val cPacketType = input.readByte(2)
|
||||
val iMessageType = input.readInt(3)
|
||||
val iRequestId = input.readInt(4)
|
||||
val sServantName = input.readString(5)
|
||||
val sFuncName = input.readString(6)
|
||||
val sBuffer = input.readByteArray(7)
|
||||
val iTimeout = input.readInt(8)
|
||||
val context = input.readMap("", "", 9)
|
||||
val status = input.readMap("", "", 10)
|
||||
return RequestPacket(sBuffer, cPacketType, iMessageType, iRequestId, iTimeout, iVersion, context, sFuncName, sServantName, status)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ import net.mamoe.mirai.qqandroid.network.io.JceOutput
|
||||
import net.mamoe.mirai.qqandroid.network.io.buildJcePacket
|
||||
import net.mamoe.mirai.qqandroid.network.io.writeJcePacket
|
||||
|
||||
fun BytePacketBuilder.writeUniRequestPacket(requestPacket: RequestPacket) {
|
||||
inline fun BytePacketBuilder.writeUniRequestPacket(requestPacket: RequestPacket.() -> Unit) {
|
||||
writeJcePacket {
|
||||
requestPacket.writeTo(this)
|
||||
RequestPacket().apply(requestPacket).writeTo(this)
|
||||
}
|
||||
}
|
@ -81,6 +81,8 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
|
||||
}
|
||||
else -> error("Illegal flag2. Expected 0x02, got $flag2")
|
||||
}
|
||||
// 00 00 00 60 00 00 00 0B 02 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 CE 35 53 19 84 A8 1A B8 5B 48 E3 7C D0 A6 BA 58 6A EB CE 50 B9 A0 98 D5 B9 D0 1C 72 E2 86 24 FC 55 44 6C 6E E3 F9 15 6C EC 6C 6B 94 40 F7 B4 45 CF B4 D0 79 84 FE 30 EA 98 84 44 84 02 32 70 DD D7 07 07 72 DE 87 59 AC
|
||||
0x0B ->
|
||||
else -> error("Illegal flag1. Expected 0x0A or 0x0B, got $flag1")
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.io.buildJcePacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
|
||||
import net.mamoe.mirai.qqandroid.network.io.jceMap
|
||||
import net.mamoe.mirai.qqandroid.network.io.jceStruct
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
@ -38,73 +37,63 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
|
||||
operator fun invoke(
|
||||
client: QQAndroidClient,
|
||||
regPushReason: RegPushReason = RegPushReason.setOnlineStatus
|
||||
): OutgoingPacket = buildOutgingPacket(client, key = client.wLoginSigInfo.wtSessionTicketKey) {
|
||||
writeUniRequestPacket(
|
||||
RequestPacket(
|
||||
sServantName = "PushService",
|
||||
sFuncName = "SvcReqRegister",
|
||||
sBuffer = buildJcePacket {
|
||||
writeMap(
|
||||
mapOf(
|
||||
"SvcReqRegister" to buildJcePacket {
|
||||
writeJceStruct(
|
||||
SvcReqRegister(
|
||||
cConnType = 0,
|
||||
lBid = 1 or 2 or 4,
|
||||
lUin = client.uin,
|
||||
iStatus = client.onlineStatus.id,
|
||||
bKikPC = 0, // 是否把 PC 踢下线
|
||||
bKikWeak = 0,
|
||||
timeStamp = currentTimeSeconds, // millis or seconds??
|
||||
iLargeSeq = 0,
|
||||
bRegType =
|
||||
if (regPushReason == RegPushReason.appRegister ||
|
||||
regPushReason == RegPushReason.fillRegProxy ||
|
||||
regPushReason == RegPushReason.createDefaultRegInfo ||
|
||||
regPushReason == RegPushReason.setOnlineStatus
|
||||
) {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}.toByte(),
|
||||
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0,
|
||||
iOSVersion = client.device.version.sdk.toLong(),
|
||||
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0,
|
||||
vecGuid = client.device.guid,
|
||||
strDevName = client.device.model.encodeToString(),
|
||||
strDevType = client.device.model.encodeToString(),
|
||||
strOSVer = client.device.version.release.encodeToString(),
|
||||
): OutgoingPacket = buildOutgingPacket(client, key = client.wLoginSigInfo.d2Key) {
|
||||
writeUniRequestPacket {
|
||||
sServantName = "PushService"
|
||||
sFuncName = "SvcReqRegister"
|
||||
sBuffer = jceMap(
|
||||
0,
|
||||
"SvcReqRegister" to jceStruct(
|
||||
0,
|
||||
SvcReqRegister(
|
||||
cConnType = 0,
|
||||
lBid = 1 or 2 or 4,
|
||||
lUin = client.uin,
|
||||
iStatus = client.onlineStatus.id,
|
||||
bKikPC = 0, // 是否把 PC 踢下线
|
||||
bKikWeak = 0,
|
||||
timeStamp = currentTimeSeconds, // millis or seconds??
|
||||
iLargeSeq = 0,
|
||||
bRegType =
|
||||
(if (regPushReason == RegPushReason.appRegister ||
|
||||
regPushReason == RegPushReason.fillRegProxy ||
|
||||
regPushReason == RegPushReason.createDefaultRegInfo ||
|
||||
regPushReason == RegPushReason.setOnlineStatus
|
||||
) 0 else 1).toByte(),
|
||||
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0,
|
||||
iOSVersion = client.device.version.sdk.toLong(),
|
||||
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0,
|
||||
vecGuid = client.device.guid,
|
||||
strDevName = client.device.model.encodeToString(),
|
||||
strDevType = client.device.model.encodeToString(),
|
||||
strOSVer = client.device.version.release.encodeToString(),
|
||||
|
||||
// register 时还需要
|
||||
/*
|
||||
var44.uNewSSOIp = field_127445;
|
||||
var44.uOldSSOIp = field_127444;
|
||||
var44.strVendorName = ROMUtil.getRomName();
|
||||
var44.strVendorOSName = ROMUtil.getRomVersion(20);
|
||||
*/
|
||||
bytes_0x769_reqbody = ProtoBuf.dump(
|
||||
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
|
||||
rpt_config_list = listOf(
|
||||
Oidb0x769.ConfigSeq(
|
||||
type = 46,
|
||||
version = 4
|
||||
),
|
||||
Oidb0x769.ConfigSeq(
|
||||
type = 283,
|
||||
version = 0
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
bSetMute = 0
|
||||
), 0
|
||||
// register 时还需要
|
||||
/*
|
||||
var44.uNewSSOIp = field_127445;
|
||||
var44.uOldSSOIp = field_127444;
|
||||
var44.strVendorName = ROMUtil.getRomName();
|
||||
var44.strVendorOSName = ROMUtil.getRomVersion(20);
|
||||
*/
|
||||
bytes_0x769_reqbody = ProtoBuf.dump(
|
||||
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
|
||||
rpt_config_list = listOf(
|
||||
Oidb0x769.ConfigSeq(
|
||||
type = 46,
|
||||
version = 4
|
||||
),
|
||||
Oidb0x769.ConfigSeq(
|
||||
type = 283,
|
||||
version = 0
|
||||
)
|
||||
)
|
||||
}.readBytes()
|
||||
), 0
|
||||
)
|
||||
),
|
||||
bSetMute = 0
|
||||
)
|
||||
}.readBytes()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||
|
@ -27,7 +27,9 @@ actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo(
|
||||
override val imsiMd5: ByteArray
|
||||
get() = ubyteArrayOf(0xD4u, 0x1Du, 0x8Cu, 0xD9u, 0x8Fu, 0x00u, 0xB2u, 0x04u, 0xE9u, 0x80u, 0x09u, 0x98u, 0xECu, 0xF8u, 0x42u, 0x7Eu).toByteArray()
|
||||
override val imei: String get() = "858414369211993"
|
||||
override val ipAddress: ByteArray get() = localIpAddress().split(".").map { it.toByte() }.takeIf { it.size == 4 }?.toByteArray() ?: byteArrayOf()
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
override val ipAddress: ByteArray
|
||||
get() = localIpAddress().split(".").map { it.toUByte().toByte() }.takeIf { it.size == 4 }?.toByteArray() ?: byteArrayOf()
|
||||
override val androidId: ByteArray get() = "QSR1.190920.001".toByteArray()
|
||||
override val apn: ByteArray get() = "wifi".toByteArray()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user