mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-08 17:20:11 +08:00
New PacketFactory structure
This commit is contained in:
parent
26c86129c6
commit
63a4d5f3b9
@ -104,7 +104,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
|
||||
override suspend fun init() {
|
||||
delay(5000)
|
||||
// delay(5000)
|
||||
|
||||
this@QQAndroidBotNetworkHandler.subscribeAlways<ForceOfflineEvent> {
|
||||
if (this@QQAndroidBotNetworkHandler.bot == this.bot) {
|
||||
@ -126,7 +126,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
20,
|
||||
0,
|
||||
0
|
||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>()
|
||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 1000)
|
||||
|
||||
totalFriendCount = data.totalFriendCount
|
||||
data.friendList.forEach {
|
||||
@ -150,7 +150,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
bot.logger.info("开始加载组信息")
|
||||
val troopData = FriendList.GetTroopListSimplify(
|
||||
bot.client
|
||||
).sendAndExpect<FriendList.GetTroopListSimplify.Response>()
|
||||
).sendAndExpect<FriendList.GetTroopListSimplify.Response>(timeoutMillis = 1000)
|
||||
println(troopData.contentToString())
|
||||
} catch (e: Exception) {
|
||||
bot.logger.info("加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表")
|
||||
@ -235,7 +235,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
bot.logger.info("Received packet: $packet")
|
||||
|
||||
packetFactory?.run {
|
||||
bot.handle(packet)
|
||||
when (this) {
|
||||
is OutgoingPacketFactory<P> -> bot.handle(packet)
|
||||
is IncomingPacketFactory<P> -> bot.handle(packet, sequenceId)?.sendWithoutExpect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,116 +0,0 @@
|
||||
# QQAndroid Protocol
|
||||
|
||||
## Overview
|
||||
|
||||
Note: `head` and `body` functions do nothing. They just work as
|
||||
notations
|
||||
|
||||
PseudoCode:
|
||||
```
|
||||
OutgoingPacket {
|
||||
int head.size + body.size + 4
|
||||
head {
|
||||
int 0x0A
|
||||
byte 0x02
|
||||
int extra data size + 4
|
||||
byte[] extra data // initially={}
|
||||
byte 0
|
||||
int uinAccount.length + 4
|
||||
byte[] uinAccount // =qqNumber.toString()
|
||||
}
|
||||
body { // encrypted by `ByteArray(16)` when login, after which by sessionKey
|
||||
SSOPacket {
|
||||
int head.size + 4
|
||||
head {
|
||||
int sequenceId
|
||||
int subAppId
|
||||
int subAppId
|
||||
hex "01 00 00 00 00 00 00 00 00 00 01 00" // unknown values
|
||||
int extraData.size + 4
|
||||
byte[] extraData // empty when login
|
||||
int commandName.length + 4
|
||||
byte[] commandName // e.g. wtlogin.login
|
||||
int 4 + 4
|
||||
int 0x02B05B8B
|
||||
int imei.length + 4
|
||||
byte[] imei
|
||||
int 0 + 4
|
||||
short ksid.length + 2
|
||||
byte[] ksid
|
||||
int 0 + 4
|
||||
}
|
||||
|
||||
int body.size + 4
|
||||
body {
|
||||
OicqRequestPacket {
|
||||
head {
|
||||
byte 2 // head flag
|
||||
short 27 + 2 + remaining.length
|
||||
ushort client.protocolVersion // const 8001
|
||||
ushort commandId // e.g. 0x0810
|
||||
ushort 0x0001
|
||||
uint client.uin
|
||||
byte 3 // const
|
||||
ubyte encryptMethod.value // [EncryptMethod]
|
||||
byte 0 // const
|
||||
int 2 // const
|
||||
int client.appClientVersion
|
||||
int 0 // const
|
||||
}
|
||||
|
||||
body {
|
||||
// only write one of the following two structures!!
|
||||
|
||||
// if encryption method is ECDH
|
||||
EncryptionMethodECDH {
|
||||
head {
|
||||
byte 1
|
||||
byte 1
|
||||
byte[] privateKey // random key
|
||||
short 258
|
||||
short [ECDH.publicKey].size // always 49
|
||||
byte[] [ECDH.publicKey]
|
||||
}
|
||||
|
||||
body {
|
||||
// real body
|
||||
}
|
||||
}
|
||||
|
||||
// if encryption method is SessionKey
|
||||
EncryptionMethodSessionKey {
|
||||
head {
|
||||
byte 1
|
||||
byte if (currentLoginState == 2) 3 else 2
|
||||
fully key
|
||||
short 258 // const
|
||||
short 0
|
||||
}
|
||||
|
||||
body {
|
||||
// real body
|
||||
}
|
||||
}
|
||||
}
|
||||
tail {
|
||||
byte 3 // tail flag
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Packet bodies
|
||||
|
||||
### LoginPacket - SubCommand 9
|
||||
**TO BE UPDATED**
|
||||
|
||||
PseudoCode:
|
||||
```
|
||||
short 9 // subCommand
|
||||
tlvList {
|
||||
|
||||
}
|
||||
```
|
@ -0,0 +1,2 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.packet
|
||||
|
@ -12,10 +12,6 @@ import net.mamoe.mirai.utils.io.writeHex
|
||||
import net.mamoe.mirai.utils.io.writeIntLVPacket
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
|
||||
/**
|
||||
* 待发送给服务器的数据包. 它代表着一个 [ByteReadPacket].
|
||||
* 只有最终的包才会被包装为 [OutgoingPacket].
|
||||
*/
|
||||
internal class OutgoingPacket constructor(
|
||||
name: String?,
|
||||
val commandName: String,
|
||||
@ -31,25 +27,11 @@ internal val KEY_16_ZEROS = ByteArray(16)
|
||||
internal val EMPTY_BYTE_ARRAY = ByteArray(0)
|
||||
|
||||
/**
|
||||
* 最外层的包. 结构适用于登录之后的过程.
|
||||
*
|
||||
* 在 QQ 中这个被以 JNI 实现:
|
||||
* com.tencent.qphone.base.util.CodecWarpper#encodeRequest(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int, int, java.lang.String, byte, byte, byte, byte[], byte[], boolean)
|
||||
*
|
||||
* **Packet structure**
|
||||
* int remaining.length + 4
|
||||
* int 0x0B
|
||||
* byte 0x01
|
||||
* int sequenceId
|
||||
* byte 0
|
||||
* int uinAccount.length + 4
|
||||
* byte[] uinAccount
|
||||
*
|
||||
* byte[] body encrypted by 16 zero
|
||||
*/
|
||||
@Deprecated("危险", level = DeprecationLevel.ERROR)
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun PacketFactory<*>.buildOutgoingPacket(
|
||||
internal inline fun OutgoingPacketFactory<*>.buildOutgoingPacket(
|
||||
client: QQAndroidClient,
|
||||
bodyType: Byte = 1, // 1: PB?
|
||||
name: String? = this.commandName,
|
||||
@ -76,11 +58,8 @@ internal inline fun PacketFactory<*>.buildOutgoingPacket(
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* buildOutgoingPacket 与 writeUniPacket 的 fast-path
|
||||
*/
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun PacketFactory<*>.buildOutgoingUniPacket(
|
||||
internal inline fun OutgoingPacketFactory<*>.buildOutgoingUniPacket(
|
||||
client: QQAndroidClient,
|
||||
bodyType: Byte = 1, // 1: PB?
|
||||
name: String? = this.commandName,
|
||||
@ -110,6 +89,37 @@ internal inline fun PacketFactory<*>.buildOutgoingUniPacket(
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun IncomingPacketFactory<*>.buildResponseUniPacket(
|
||||
client: QQAndroidClient,
|
||||
bodyType: Byte = 1, // 1: PB?
|
||||
name: String? = this.responseCommandName,
|
||||
commandName: String = this.responseCommandName,
|
||||
key: ByteArray = client.wLoginSigInfo.d2Key,
|
||||
extraData: ByteReadPacket = BRP_STUB,
|
||||
sequenceId: Int = client.nextSsoSequenceId(),
|
||||
body: BytePacketBuilder.(sequenceId: Int) -> Unit
|
||||
): OutgoingPacket {
|
||||
return OutgoingPacket(name, commandName, sequenceId, buildPacket {
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
writeInt(0x0B)
|
||||
writeByte(bodyType)
|
||||
writeInt(sequenceId)
|
||||
writeByte(0)
|
||||
client.uin.toString().let {
|
||||
writeInt(it.length + 4)
|
||||
writeStringUtf8(it)
|
||||
}
|
||||
encryptAndWrite(key) {
|
||||
writeUniPacket(commandName, client.outgoingPacketUnknownValue, extraData) {
|
||||
body(sequenceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun BytePacketBuilder.writeUniPacket(
|
||||
commandName: String,
|
||||
@ -140,25 +150,10 @@ internal inline fun BytePacketBuilder.writeUniPacket(
|
||||
|
||||
|
||||
/**
|
||||
* 最外层的包. 结构适用于登录.
|
||||
*
|
||||
* 在 QQ 中这个被以 JNI 实现:
|
||||
* com.tencent.qphone.base.util.CodecWarpper#encodeRequest(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int, int, java.lang.String, byte, byte, byte, byte[], byte[], boolean)
|
||||
*
|
||||
* **Packet structure**
|
||||
* int remaining.length + 4
|
||||
* int 0x0A
|
||||
* byte 0x02
|
||||
* int extra data size + 4
|
||||
* byte[] extra data
|
||||
* byte 0
|
||||
* int uinAccount.length + 4
|
||||
* byte[] uinAccount
|
||||
*
|
||||
* byte[] body encrypted by 16 zero
|
||||
*/
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
|
||||
internal inline fun OutgoingPacketFactory<*>.buildLoginOutgoingPacket(
|
||||
client: QQAndroidClient,
|
||||
bodyType: Byte,
|
||||
extraData: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
@ -193,30 +188,6 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
|
||||
|
||||
private inline val BRP_STUB get() = ByteReadPacket.Empty
|
||||
|
||||
/**
|
||||
* The second outermost packet for login
|
||||
*
|
||||
* int headRemaining.size+4
|
||||
* int sequenceId
|
||||
* int subAppId
|
||||
* int subAppId
|
||||
* hex "01 00 00 00 00 00 00 00 00 00 01 00" // unknown values
|
||||
* int extraData.size+4
|
||||
* byte[] extraData
|
||||
* int commandName.length+4
|
||||
* byte[] commandName
|
||||
* int 4+4
|
||||
* int 0x02B05B8B
|
||||
* int imei.length+4
|
||||
* byte[] imei
|
||||
* int 0+4
|
||||
* int ksid.length+4
|
||||
* byte[] ksid
|
||||
* int 0+4
|
||||
*
|
||||
* int bodyRemaining.size+4
|
||||
* byte[] body()
|
||||
*/
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun BytePacketBuilder.writeSsoPacket(
|
||||
client: QQAndroidClient,
|
||||
@ -266,26 +237,6 @@ internal inline fun BytePacketBuilder.writeSsoPacket(
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }, builder = body)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes a request packet
|
||||
* This is the innermost packet structure
|
||||
*
|
||||
* **Packet Structure**
|
||||
* byte 2 // head flag
|
||||
* short 27 + 2 + remaining.length
|
||||
* ushort client.protocolVersion // const 8001
|
||||
* ushort 0x0001
|
||||
* uint client.uin
|
||||
* byte 3 // const
|
||||
* ubyte encryptMethod.value // [EncryptMethod]
|
||||
* byte 0 // const
|
||||
* int 2 // const
|
||||
* int client.appClientVersion
|
||||
* int 0 // const
|
||||
* bodyBlock()
|
||||
* byte 3 // tail
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
|
||||
internal fun BytePacketBuilder.writeOicqRequestPacket(
|
||||
client: QQAndroidClient,
|
||||
@ -294,8 +245,6 @@ internal fun BytePacketBuilder.writeOicqRequestPacket(
|
||||
bodyBlock: BytePacketBuilder.() -> Unit
|
||||
) {
|
||||
val body = encryptMethod.makeBody(client, bodyBlock)
|
||||
// writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
// Head
|
||||
writeByte(0x02) // head
|
||||
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
|
||||
writeShort(client.protocolVersion)
|
||||
@ -309,72 +258,7 @@ internal fun BytePacketBuilder.writeOicqRequestPacket(
|
||||
writeInt(client.appClientVersion)
|
||||
writeInt(0) // constp_always_0
|
||||
|
||||
// Body
|
||||
writePacket(body)
|
||||
|
||||
// Tail
|
||||
writeByte(0x03) // tail
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
00 00 01 64
|
||||
00 00 00 0A
|
||||
02
|
||||
00 00 00 04
|
||||
00
|
||||
|
||||
00 00 00 0E
|
||||
31 39 39 34 37 30 31 30 32 31
|
||||
|
||||
// encrypted with 16zero
|
||||
F8 22 FC 39 2E 93 D7 73 A9 75 A2 D4 67 D2 C4 0D F1 02 1F A5 74 8F D8 0E 8E 86 AF 4F 4A A9 C7 74 56 71 B9 03 FC B3 DE A0 F3 14 B7 E9 54 3B 22 F0 24 10 BD 52 88 FC F3 58 66 6C B9 DB 4D 45 2C EF DE 2C C9 E1 1B 27 C7 E2 EF 38 6A 7E 8B 52 3A F4 93 40 E1 A9 ED 10 C3 A3 7E 64 17 02 8F 5C 01 92 72 C7 B8 E0 E1 A5 AF 0B 27 D0 05 C1 33 37 77 37 6D 96 0B B4 1F 41 98 42 35 2C 2A 00 E4 ED E8 C6 42 C4 F4 FD 13 39 D8 E8 19 50 E9 49 06 37 CA CF 42 C3 DD B5 DC B0 E9 87 83 6E 77 AE B6 5C F5 0D 6A 08 67 D0 61 B0 86 39 F7 2E AF E7 B7 C5 F4 42 40 A1 E1 A9 90 55 26 BD C6 03 73 73 BF A2 0A 3F E6 D3 8D B3 69 63 81 83 1E F1 72 5D FA FC 5E 65 B9 C1 FE 77 A8 50 80 F1 A5 DF E0 C4 96 1D 21 CD 5B 70 62 35 51 B5 37 1F 0B 4A 6D 97 92 D0 33 2B 56 11 CB 54 E5 6A A4 B9 97 04 B3 4B 27 A6 61 B7 77 5C C0 D1 6B 98 1C 7A 7B 57 28 3B 80 3B 81 88 69 D2 1C 91 B8 4A DE 0F FD A2 82 F8 3B F6 61 90 84 EF 4A 17 B6 30 1D 09 62 11 C7 BB 00 76 8E 0D 48 1B 11 F4 90 7A 13 0F 09 2B 4E 2F BE FD D9 57 07 18 29 4C 52 23 2E AE
|
||||
|
||||
//decrypted:
|
||||
00 00 00 C1
|
||||
00 01 4E 6A
|
||||
20 02 ED BD
|
||||
20 02 ED BD
|
||||
01 00 00 00 00 00 00 00 00 00 01 00
|
||||
00 00 00 4C
|
||||
B8 12 0D E1 DA 19 AF D3 EB 36 76 BD 42 08 F6 DC A5 35 69 C0 8F F2 75 28 B4 CE 09 C9 B7 86 E3 5A 14 D1 0D CA 5D D4 CB 16 77 8B 32 8D 81 3B 3F D9 52 13 77 03 D3 F7 0E CD 7B 21 95 D2 59 CE 0C 31 D6 F1 38 2A FA 82 AD 60
|
||||
00 00 00 14
|
||||
47 72 61 79 55 69 6E 50 72 6F 2E 43 68 65 63 6B // serviceCommand
|
||||
00 00 00 08
|
||||
02 B0 5B 8B
|
||||
00 00 00 13
|
||||
38 35 38 34 31 34 33 36 39 32 31 31 39 39 33
|
||||
00 00 00 04
|
||||
00 22
|
||||
7C 34 35 34 30 30 31 32 32 38 34 33 37 35 39 30 7C 41 38 2E 32 2E 30 2E 32 37 66 36 65 61 39 36 00 00 00 04
|
||||
|
||||
00 00 00 7A // UniPacket
|
||||
10
|
||||
03 2C
|
||||
3C 42 00 01 4E 69 56 22 4B 51 51 2E 43 6F 6E 66 69 67 53 65 72 76 69 63 65 2E 43 6F 6E 66 69 67 53 65 72 76 61 6E 74 4F 62 6A 66 09 43 6C 69 65 6E 74 52 65 71 7D 00 00 35 08 00 01 06 03 72 65 71 1D 00 00 29 0A 12 20 02 ED BD 26 0A 31 39 39 34 37 30 31 30 32 31 36 00 46 12 31 30 31 31 30 33 30 38 33 38 34 36 30 36 32 30 34 32 0B 8C 98 0C A8 0C
|
||||
|
||||
*/
|
||||
/*
|
||||
00 00 00 FC
|
||||
00 00 00 0B
|
||||
01 // packet type?
|
||||
00 01 50 DE
|
||||
00
|
||||
|
||||
00 00 00 0E
|
||||
31 39 39 34 37 30 31 30 32 31
|
||||
|
||||
4E 32 1B 0F 07 DC 39 FE 14 78 ED 32 60 C4 07 31 9D CD 1A E0 C4 F6 21 6B EA 52 A4 F4 C1 D2 AF FB 17 5A C4 15 BC 35 BC 45 58 B6 11 19 DA AF 12 91 B5 A0 5D E4 FD 5A 49 1A 55 71 45 89 6F 3A 09 E6 32 F4 96 4A BB B2 EE 35 B9 39 63 5B FF E3 F0 94 69 67 99 64 A2 03 23 D0 F7 74 81 D1 20 F8 20 E6 F3 5B E6 C2 A2 25 6F 90 C5 DA CB D2 08 9D 5D 83 47 F3 27 3F 41 19 E5 9A C0 F2 05 70 B2 C5 DC F9 F1 6D 2A E9 92 84 9C 8D 98 04 E8 A1 3B 40 F2 71 60 9F 2C D8 6A CD 6B F5 2B 12 68 C7 9C 6B 0E D2 F7 16 40 47 72 3D 6A AF 36 2E 43 0C 96 28 C7 A6 B1 04 3B 29 F6 8B A4 E0 47 1A 3D 51 32 C7 AF A5 7E FD F7 50 FC 81 3D 13 45 60 6B 8D F4 A6 9B E7 46 D4 1E 9B 2C 00 D0 24 2F 0E 44 29 43 A8 F6 25
|
||||
|
||||
*/
|
||||
/*
|
||||
00 00 01 04
|
||||
00 00 00 0B
|
||||
01
|
||||
00 01 50 CE
|
||||
00
|
||||
|
||||
00 00 00 0E 31 39 39 34 37 30 31 30 32 31 D2 D5 37 8A 3C 47 B1 84 E2 94 B2 AF BF 14 70 4D 73 17 BB 38 BE 82 73 DF A2 87 E0 0A 7A BA 8A 81 71 77 1D E1 71 7F B7 C1 66 1D 8C 3D 41 4F 51 09 6A B7 B7 7B 88 28 A6 5A AB 7E 40 25 9B C8 35 9C C6 E2 3A 5F 94 1D 70 0F D7 89 4D 41 6B 7A 29 A2 70 77 3D F8 1D 32 65 D7 D8 D1 6D 13 42 9C 0C 72 DB 48 95 4B 66 EF B9 E6 E4 C1 3B 2C 36 B0 D7 3F E2 85 C8 2A 8C 65 0F 0B 1C F1 A7 C7 E1 1F 0C 32 F5 08 14 AA 5A 43 CD 8E A8 82 14 24 97 63 F0 53 79 4E 33 8D 5F 1C F8 1C 89 3B 39 44 CC A7 63 5F FC BF 87 42 89 2D A5 F4 BC B2 69 49 54 DD AE E6 3F A2 A2 98 DC 3B D4 A2 27 10 F2 06 42 93 C5 30 4A D4 FA F5 BA A5 B2 4B 56 45 59 94 CA 4C 4B 17 55 C7 23 AF F0 8B E5 DC 3A 1B B6 A7 2E 10 BB 9A E7 70 54 BA F5 4B 70 91
|
||||
|
||||
*/
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -2,18 +2,18 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.ProtoBufWithNullableSupport
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.ProtoBufWithNullableSupport
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
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.buildLoginOutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352Packet
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.GetImgUrlReq
|
||||
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.buildLoginOutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
|
||||
|
||||
internal object ImageDownPacket : PacketFactory<ImageDownPacket.ImageDownPacketResponse>("LongConn.OffPicDown") {
|
||||
internal object ImageDownPacket : OutgoingPacketFactory<ImageDownPacket.ImageDownPacketResponse>("LongConn.OffPicDown") {
|
||||
|
||||
operator fun invoke(client: QQAndroidClient, req: GetImgUrlReq): OutgoingPacket {
|
||||
// TODO: 2020/1/24 测试: bodyType, subAppId
|
||||
|
@ -2,18 +2,18 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.ProtoBufWithNullableSupport
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.ProtoBufWithNullableSupport
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
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.buildLoginOutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352Packet
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.UploadImgReq
|
||||
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.buildLoginOutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
|
||||
|
||||
internal object ImageUpPacket : PacketFactory<ImageUpPacket.ImageUpPacketResponse>("LongConn.OffPicUp") {
|
||||
internal object ImageUpPacket : OutgoingPacketFactory<ImageUpPacket.ImageUpPacketResponse>("LongConn.OffPicUp") {
|
||||
|
||||
operator fun invoke(client: QQAndroidClient, req: UploadImgReq): OutgoingPacket {
|
||||
// TODO: 2020/1/24 测试: bodyType, subAppId
|
||||
|
@ -19,9 +19,7 @@ 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.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.PacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
import net.mamoe.mirai.qqandroid.utils.toMessageChain
|
||||
import net.mamoe.mirai.qqandroid.utils.toRichTextElems
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
@ -36,19 +34,18 @@ internal class MessageSvc {
|
||||
/**
|
||||
* 告知要刷新好友消息
|
||||
*/
|
||||
internal object PushNotify : PacketFactory<RequestPushNotify>("MessageSvc.PushNotify") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify {
|
||||
internal object PushNotify : IncomingPacketFactory<RequestPushNotify>("MessageSvc.PushNotify") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): RequestPushNotify {
|
||||
discardExact(8)
|
||||
|
||||
return decodeUniPacket(RequestPushNotify.serializer())
|
||||
}
|
||||
|
||||
override suspend fun QQAndroidBot.handle(packet: RequestPushNotify) {
|
||||
override suspend fun QQAndroidBot.handle(packet: RequestPushNotify, sequenceId: Int): OutgoingPacket? {
|
||||
network.run {
|
||||
PbGetMsg(client, MsgSvc.SyncFlag.START, packet.stMsgInfo?.uMsgTime ?: 0).sendAndExpect<MultiPacket<FriendMessage>>()
|
||||
return PbGetMsg(client, MsgSvc.SyncFlag.START, packet.stMsgInfo?.uMsgTime ?: 0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +53,7 @@ internal class MessageSvc {
|
||||
* 获取好友消息和消息记录
|
||||
*/
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal object PbGetMsg : PacketFactory<PbGetMsg.Response>("MessageSvc.PbGetMsg") {
|
||||
internal object PbGetMsg : OutgoingPacketFactory<PbGetMsg.Response>("MessageSvc.PbGetMsg") {
|
||||
val EXTRA_DATA =
|
||||
"08 00 12 33 6D 6F 64 65 6C 3A 78 69 67 6F 6D 69 20 36 3B 6F 73 3A 32 32 3B 76 65 72 73 69 6F 6E 3A 76 32 6D 61 6E 3A 78 69 61 6F 6D 69 73 79 73 3A 4C 4D 59 34 38 5A 18 E4 E1 A4 FF FE 2D 20 E9 E1 A4 FF FE 2D 28 A8 E1 A4 FF FE 2D 30 99 E1 A4 FF FE 2D".hexToBytes()
|
||||
|
||||
@ -81,7 +78,7 @@ internal class MessageSvc {
|
||||
syncFlag = syncFlag,
|
||||
// serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY,
|
||||
syncCookie = client.c2cMessageSync.syncCookie
|
||||
?: SyncCookie(time = Random.nextLong()).toByteArray(SyncCookie.serializer())//.also { client.c2cMessageSync.syncCookie = it },
|
||||
?: SyncCookie(time = msgTime + client.timeDifference).toByteArray(SyncCookie.serializer())//.also { client.c2cMessageSync.syncCookie = it },
|
||||
// syncFlag = client.c2cMessageSync.syncFlag,
|
||||
//msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf,
|
||||
//pubaccountCookie = client.c2cMessageSync.pubAccountCookie
|
||||
@ -160,7 +157,7 @@ internal class MessageSvc {
|
||||
/**
|
||||
* 被挤下线
|
||||
*/
|
||||
internal object PushForceOffline : PacketFactory<ForceOfflineEvent>("MessageSvc.PushForceOffline") {
|
||||
internal object PushForceOffline : OutgoingPacketFactory<ForceOfflineEvent>("MessageSvc.PushForceOffline") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): ForceOfflineEvent {
|
||||
discardExact(4)
|
||||
val struct = this.decodeUniPacket(RequestPushForceOffline.serializer())
|
||||
@ -168,7 +165,7 @@ internal class MessageSvc {
|
||||
}
|
||||
}
|
||||
|
||||
internal object PbSendMsg : PacketFactory<PbSendMsg.Response>("MessageSvc.PbSendMsg") {
|
||||
internal object PbSendMsg : OutgoingPacketFactory<PbSendMsg.Response>("MessageSvc.PbSendMsg") {
|
||||
sealed class Response : Packet {
|
||||
object SUCCESS : Response() {
|
||||
override fun toString(): String = "MessageSvc.PbSendMsg.Response.SUCCESS"
|
||||
@ -230,9 +227,9 @@ internal class MessageSvc {
|
||||
elems = message.toRichTextElems()
|
||||
)
|
||||
),
|
||||
msgSeq = client.atomicNextMessageSequenceId()
|
||||
// msgRand = 123
|
||||
//syncCookie = client.c2cMessageSync.syncCookie?.takeIf { it.isNotEmpty() } ?:
|
||||
msgSeq = client.atomicNextMessageSequenceId(),
|
||||
//msgRand = Random.nextInt() and 0x7FFF,
|
||||
syncCookie = client.c2cMessageSync.syncCookie?.takeIf { it.isNotEmpty() } ?: EMPTY_BYTE_ARRAY
|
||||
//SyncCookie(currentTimeSeconds, Random.nextLong().absoluteValue, Random.nextLong().absoluteValue).toByteArray(SyncCookie.serializer())
|
||||
// msgVia = 1
|
||||
)
|
||||
|
@ -11,7 +11,7 @@ import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.ProtoBufWithNullableSupport
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgOnlinePush
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.utils.toMessageChain
|
||||
|
||||
|
||||
@ -19,9 +19,9 @@ internal class OnlinePush {
|
||||
/**
|
||||
* 接受群消息
|
||||
*/
|
||||
internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
|
||||
internal object PbPushGroupMsg : IncomingPacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
|
||||
@UseExperimental(ExperimentalStdlibApi::class)
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): GroupMessage {
|
||||
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
|
||||
discardExact(4)
|
||||
val pbPushMsg = ProtoBufWithNullableSupport.load(MsgOnlinePush.PbPushMsg.serializer(), readBytes())
|
||||
@ -48,9 +48,5 @@ internal class OnlinePush {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun QQAndroidBot.handle(packet: GroupMessage) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.jce.*
|
||||
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.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.utils.io.discardExact
|
||||
|
||||
@ -22,7 +22,7 @@ import net.mamoe.mirai.utils.io.discardExact
|
||||
internal class FriendList {
|
||||
|
||||
internal object GetTroopMemberList :
|
||||
PacketFactory<GetTroopMemberList.Response>("friendlist.GetTroopMemberListReq") {
|
||||
OutgoingPacketFactory<GetTroopMemberList.Response>("friendlist.GetTroopMemberListReq") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GetTroopMemberList.Response {
|
||||
TODO()
|
||||
}
|
||||
@ -65,7 +65,7 @@ internal class FriendList {
|
||||
}
|
||||
|
||||
internal object GetTroopListSimplify :
|
||||
PacketFactory<GetTroopListSimplify.Response>("friendlist.GetTroopListReqV2") {
|
||||
OutgoingPacketFactory<GetTroopListSimplify.Response>("friendlist.GetTroopListReqV2") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GetTroopListSimplify.Response {
|
||||
val res = this.decodeUniPacket(GetTroopListRespV2.serializer())
|
||||
return Response(res.vecTroopList.orEmpty())
|
||||
@ -109,7 +109,8 @@ internal class FriendList {
|
||||
}
|
||||
}
|
||||
}
|
||||
internal object GetFriendGroupList : PacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
|
||||
|
||||
internal object GetFriendGroupList : OutgoingPacketFactory<GetFriendGroupList.Response>("friendlist.getFriendGroupList") {
|
||||
|
||||
class Response(
|
||||
val totalFriendCount: Short,
|
||||
|
@ -9,23 +9,25 @@ import net.mamoe.mirai.qqandroid.io.serialization.jceRequestSBuffer
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.writeJceStruct
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.PushResp
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
|
||||
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.IncomingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildResponseUniPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.PushReq as PushReqJceStruct
|
||||
|
||||
|
||||
internal class ConfigPushSvc {
|
||||
object PushReq : PacketFactory<PushReqJceStruct>("ConfigPushSvc.PushReq") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): PushReqJceStruct {
|
||||
object PushReq : IncomingPacketFactory<PushReqJceStruct>(
|
||||
receivingCommandName = "ConfigPushSvc.PushReq",
|
||||
responseCommandName = "ConfigPushSvc.PushResp"
|
||||
) {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): PushReqJceStruct {
|
||||
discardExact(4)
|
||||
val pushReq = decodeUniPacket(PushReqJceStruct.serializer())
|
||||
//println(pushReq.contentToString())
|
||||
return pushReq
|
||||
return decodeUniPacket(PushReqJceStruct.serializer())
|
||||
}
|
||||
|
||||
override suspend fun QQAndroidBot.handle(packet: PushReqJceStruct) {
|
||||
network.run {
|
||||
buildOutgoingUniPacket(
|
||||
override suspend fun QQAndroidBot.handle(packet: PushReqJceStruct, sequenceId: Int): OutgoingPacket? {
|
||||
return network.run {
|
||||
buildResponseUniPacket(
|
||||
client,
|
||||
sequenceId = client.configPushSvcPushReqSequenceId,
|
||||
commandName = "ConfigPushSvc.PushResp",
|
||||
@ -51,7 +53,7 @@ internal class ConfigPushSvc {
|
||||
charset = JceCharset.UTF8
|
||||
)
|
||||
// writePacket(this.build().debugPrintThis())
|
||||
}.sendWithoutExpect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,16 +11,19 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
import net.mamoe.mirai.qqandroid.utils.GuidSource
|
||||
import net.mamoe.mirai.qqandroid.utils.MacOrAndroidIdChangeFlag
|
||||
import net.mamoe.mirai.qqandroid.utils.guidFlag
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.MiraiDebugAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.cryptor.decryptBy
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
import net.mamoe.mirai.utils.io.discardExact
|
||||
import net.mamoe.mirai.utils.md5
|
||||
|
||||
/**
|
||||
* OicqRequest
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wtlogin.login") {
|
||||
internal object LoginPacket : OutgoingPacketFactory<LoginPacket.LoginPacketResponse>("wtlogin.login") {
|
||||
|
||||
/**
|
||||
* 提交验证码
|
||||
@ -686,7 +689,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
|
||||
*/
|
||||
private fun QQAndroidClient.analysisTlv130(t130: ByteArray) = t130.read {
|
||||
discardExact(2)
|
||||
timeDifference = readUInt().toLong() - currentTimeMillis
|
||||
timeDifference = readUInt().toLong() - currentTimeSeconds
|
||||
ipFromT149 = readBytes(4)
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.SvcReqRegister
|
||||
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.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
|
||||
@ -33,7 +33,7 @@ internal enum class RegPushReason {
|
||||
}
|
||||
|
||||
internal class StatSvc {
|
||||
internal object Register : PacketFactory<Register.Response>("StatSvc.register") {
|
||||
internal object Register : OutgoingPacketFactory<Register.Response>("StatSvc.register") {
|
||||
|
||||
internal object Response : Packet {
|
||||
override fun toString(): String = "Response(StatSvc.register)"
|
||||
|
@ -7,7 +7,7 @@ import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
|
||||
internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>("wtlogin.trans_emp") {
|
||||
internal object TransEmpPacket : OutgoingPacketFactory<TransEmpPacket.Response>("wtlogin.trans_emp") {
|
||||
|
||||
private const val appId = 16L
|
||||
private const val subAppId = 537062845L
|
||||
|
@ -4,10 +4,7 @@ package androidPacketTests
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.DECRYPTER_16_ZERO
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.withUse
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
import net.mamoe.mirai.utils.cryptor.ECDH
|
||||
import net.mamoe.mirai.utils.cryptor.adjustToPublicKey
|
||||
import net.mamoe.mirai.utils.cryptor.decryptBy
|
||||
@ -99,7 +96,7 @@ private fun processFullPacketWithoutLength(packet: ByteReadPacket) {
|
||||
try {
|
||||
bytes.toReadPacket().parseOicqResponse {
|
||||
debugIfFail {
|
||||
if (it.packetFactory.commandName == "wtlogin.login") {
|
||||
if ((it.packetFactory as? OutgoingPacketFactory<*>)?.commandName == "wtlogin.login") {
|
||||
DebugLogger.info("服务器发来了 wtlogin.login. 正在解析 key")
|
||||
try {
|
||||
val subCommand = readUShort().toInt()
|
||||
|
@ -5,59 +5,73 @@ import kotlin.jvm.JvmOverloads
|
||||
|
||||
|
||||
/**
|
||||
* 用于创建默认的日志记录器. 在一些需要使用日志的 Mirai 的组件, 如 [Bot], 都会通过这个函数构造日志记录器
|
||||
* 用于创建默认的日志记录器. 在一些需要使用日志的 Mirai 的组件, 如 [Bot], 都会通过这个函数构造日志记录器.
|
||||
* 可直接修改这个变量的值来重定向日志输出.
|
||||
*
|
||||
* **注意:** 请务必将所有的输出定向到日志记录系统, 否则在某些情况下 (如 web 控制台中) 将无法接收到输出
|
||||
*
|
||||
* **注意:** 请为日志做好分类, 即不同的模块使用不同的 [MiraiLogger].
|
||||
* 如, [Bot] 中使用 identity 为 "Bot(qqId)" 的 [MiraiLogger]
|
||||
* 而 [Bot] 的网络处理中使用 identity 为 "BotNetworkHandler" 的.
|
||||
*/
|
||||
var DefaultLogger: (identity: String?) -> MiraiLogger = { PlatformLogger(it) }
|
||||
|
||||
/**
|
||||
* 当前平台的默认的日志记录器.
|
||||
* 在 _JVM 控制台_ 端的实现为 [println]
|
||||
* 在 _Android_ 端的实现为 [android.util.Log]
|
||||
*
|
||||
* 不应该直接构造这个类的实例. 请使用 [DefaultLogger], 或使用默认的顶层日志记录 [MiraiLogger.Companion]
|
||||
*/
|
||||
expect open class PlatformLogger @JvmOverloads internal constructor(identity: String? = "Mirai") : MiraiLoggerPlatformBase
|
||||
|
||||
/**
|
||||
* 给这个 logger 添加一个开关, 用于控制是否记录 log
|
||||
*
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun MiraiLogger.withSwitch(default: Boolean = true): MiraiLoggerWithSwitch = MiraiLoggerWithSwitch(this, default)
|
||||
|
||||
/**
|
||||
* 日志记录器. 所有的输出均依赖于它.
|
||||
* 不同的对象可能拥有只属于自己的 logger. 通过 [identity] 来区分.
|
||||
* 不同的对象可拥有只属于自己的 logger. 通过 [identity] 来区分.
|
||||
*
|
||||
* 注意: 请不要直接实现这个接口, 请继承 [MiraiLoggerPlatformBase]
|
||||
* 注意: 如果你需要重新实现日志, 请不要直接实现这个接口, 请继承 [MiraiLoggerPlatformBase]
|
||||
*
|
||||
* @see MiraiLoggerPlatformBase 平台通用基础实现
|
||||
* 在定义 logger 变量时, 请一直使用 [MiraiLogger] 或者 [MiraiLoggerWithSwitch].
|
||||
*
|
||||
* @see SimpleLogger 简易 logger, 它将所有的日志记录操作都转移给 lambda `(String?, Throwable?) -> Unit`
|
||||
* @see PlatformLogger 各个平台下的默认日志记录实现.
|
||||
* @see SilentLogger 忽略任何日志记录操作的 logger 实例.
|
||||
*
|
||||
* @see MiraiLoggerPlatformBase 平台通用基础实现. 若
|
||||
*/
|
||||
interface MiraiLogger {
|
||||
/**
|
||||
* 顶层日志记录器.
|
||||
*
|
||||
* 顶层日志会导致混乱并难以定位问题. 请自行构造 logger 实例并使用.
|
||||
* 请参考使用 [DefaultLogger]
|
||||
*/
|
||||
@Deprecated(message = "顶层日志会导致混乱并难以定位问题. 请自行构造 logger 实例并使用.", level = DeprecationLevel.WARNING)
|
||||
companion object : MiraiLogger by DefaultLogger("Mirai")
|
||||
|
||||
/**
|
||||
* 日志的标记. 在 Mirai 中, identity 可为
|
||||
* - "Bot"
|
||||
* - "BotNetworkHandler"
|
||||
* 等.
|
||||
*
|
||||
* 它只用于帮助调试或统计. 十分建议清晰定义 identity
|
||||
*/
|
||||
val identity: String?
|
||||
|
||||
/**
|
||||
* 随从. 在 this 中调用所有方法后都应继续往 [follower] 传递调用.
|
||||
* [follower] 的存在可以让一次日志被多个日志记录器记录.
|
||||
*
|
||||
* 例:
|
||||
* ```kotlin
|
||||
* val bot = Bot( ... )
|
||||
* bot.follower = MyOwnLogger()
|
||||
* 一般不建议直接修改这个属性. 请通过 [plus] 来连接两个日志记录器.
|
||||
* 如: `val logger = bot.logger + MyOwnLogger()`
|
||||
* 这样, 当调用 `logger.info()` 时, bot.logger 会首先记录, MyOwnLogger 会随后记录.
|
||||
*
|
||||
* bot.info("Hi")
|
||||
* ```
|
||||
* 在这个例子中的 `MyOwnLogger` 将可以记录到 "Hi".
|
||||
* 当然, 多个 logger 也可以加在一起: `val logger = bot.logger + MyOwnLogger() + MyOwnLogger2()`
|
||||
*/
|
||||
var follower: MiraiLogger?
|
||||
|
||||
/**
|
||||
* 记录一个 `verbose` 级别的日志.
|
||||
* 无关紧要的, 经常大量输出的日志应使用它.
|
||||
*/
|
||||
fun verbose(any: Any?)
|
||||
|
||||
@ -65,7 +79,7 @@ interface MiraiLogger {
|
||||
fun verbose(message: String?, e: Throwable?)
|
||||
|
||||
/**
|
||||
* 记录一个 `debug` 级别的日志.
|
||||
* 记录一个 _调试_ 级别的日志.
|
||||
*/
|
||||
fun debug(any: Any?)
|
||||
|
||||
@ -74,7 +88,7 @@ interface MiraiLogger {
|
||||
|
||||
|
||||
/**
|
||||
* 记录一个 `info` 级别的日志.
|
||||
* 记录一个 _信息_ 级别的日志.
|
||||
*/
|
||||
fun info(any: Any?)
|
||||
|
||||
@ -83,7 +97,7 @@ interface MiraiLogger {
|
||||
|
||||
|
||||
/**
|
||||
* 记录一个 `warning` 级别的日志.
|
||||
* 记录一个 _警告_ 级别的日志.
|
||||
*/
|
||||
fun warning(any: Any?)
|
||||
|
||||
@ -92,7 +106,7 @@ interface MiraiLogger {
|
||||
|
||||
|
||||
/**
|
||||
* 记录一个 `error` 级别的日志.
|
||||
* 记录一个 _错误_ 级别的日志.
|
||||
*/
|
||||
fun error(e: Any?)
|
||||
|
||||
@ -109,10 +123,9 @@ interface MiraiLogger {
|
||||
* | base | <-- | follower | <-- | follower | <-- | follower |
|
||||
* +------+ +----------+ +----------+ +----------+
|
||||
*
|
||||
* @see follower
|
||||
* @return [follower]
|
||||
*/
|
||||
operator fun plus(follower: MiraiLogger): MiraiLogger
|
||||
operator fun <T : MiraiLogger> plus(follower: T): T
|
||||
|
||||
/**
|
||||
* 添加一个 [follower]
|
||||
@ -123,6 +136,15 @@ interface MiraiLogger {
|
||||
operator fun plusAssign(follower: MiraiLogger)
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前平台的默认的日志记录器.
|
||||
* 在 _JVM 控制台_ 端的实现为 [println]
|
||||
* 在 _Android_ 端的实现为 [android.util.Log]
|
||||
*
|
||||
* 不应该直接构造这个类的实例. 请使用 [DefaultLogger], 或使用默认的顶层日志记录 [MiraiLogger.Companion]
|
||||
*/
|
||||
expect open class PlatformLogger @JvmOverloads internal constructor(identity: String? = "Mirai") : MiraiLoggerPlatformBase
|
||||
|
||||
/**
|
||||
* 不做任何事情的 logger, keep silent.
|
||||
*/
|
||||
@ -167,7 +189,11 @@ class SimpleLogger(override val identity: String?, private val logger: (String?,
|
||||
class MiraiLoggerWithSwitch internal constructor(private val delegate: MiraiLogger, default: Boolean) : MiraiLoggerPlatformBase() {
|
||||
override val identity: String? get() = delegate.identity
|
||||
|
||||
private var switch: Boolean = default
|
||||
/**
|
||||
* true 为开启.
|
||||
*/
|
||||
@PublishedApi
|
||||
internal var switch: Boolean = default
|
||||
|
||||
fun enable() {
|
||||
switch = true
|
||||
@ -188,15 +214,53 @@ class MiraiLoggerWithSwitch internal constructor(private val delegate: MiraiLogg
|
||||
override fun error0(any: Any?) = if (switch) delegate.error(any) else Unit
|
||||
override fun error0(message: String?, e: Throwable?) = if (switch) delegate.error(message, e) else Unit
|
||||
|
||||
inline fun verbose(lazyMessage: () -> String) {
|
||||
if (switch) verbose(lazyMessage())
|
||||
}
|
||||
|
||||
inline fun verbose(lazyMessage: () -> String, e: Throwable?) {
|
||||
if (switch) verbose(lazyMessage(), e)
|
||||
}
|
||||
|
||||
inline fun debug(lazyMessage: () -> Any?) {
|
||||
if (switch) debug(lazyMessage())
|
||||
}
|
||||
|
||||
inline fun debug(lazyMessage: () -> String?, e: Throwable?) {
|
||||
if (switch) debug(lazyMessage(), e)
|
||||
}
|
||||
|
||||
inline fun info(lazyMessage: () -> Any?) {
|
||||
if (switch) info(lazyMessage())
|
||||
}
|
||||
|
||||
inline fun info(lazyMessage: () -> String?, e: Throwable?) {
|
||||
if (switch) info(lazyMessage(), e)
|
||||
}
|
||||
|
||||
inline fun warning(lazyMessage: () -> Any?) {
|
||||
if (switch) warning(lazyMessage())
|
||||
}
|
||||
|
||||
inline fun warning(lazyMessage: () -> String?, e: Throwable?) {
|
||||
if (switch) warning(lazyMessage(), e)
|
||||
}
|
||||
|
||||
inline fun error(lazyMessage: () -> Any?) {
|
||||
if (switch) error(lazyMessage())
|
||||
}
|
||||
|
||||
inline fun error(lazyMessage: () -> String?, e: Throwable?) {
|
||||
if (switch) error(lazyMessage(), e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台日志基类.
|
||||
* 实现了 [follower] 的调用传递.
|
||||
* 日志基类. 实现了 [follower] 的调用传递.
|
||||
* 若 Mirai 自带的日志系统无法满足需求, 请继承这个类并实现其抽象函数.
|
||||
*
|
||||
* 若要自行实现日志记录, 请优先考虑继承 [PlatformLogger].
|
||||
*
|
||||
* 它不应该被用作变量的类型定义. 只应被继承
|
||||
* 这个类不应该被用作变量的类型定义. 只应被作为继承对象.
|
||||
* 在定义 logger 变量时, 请一直使用 [MiraiLogger] 或者 [MiraiLoggerWithSwitch].
|
||||
*/
|
||||
abstract class MiraiLoggerPlatformBase : MiraiLogger {
|
||||
final override var follower: MiraiLogger? = null
|
||||
@ -262,7 +326,7 @@ abstract class MiraiLoggerPlatformBase : MiraiLogger {
|
||||
protected abstract fun error0(any: Any?)
|
||||
protected abstract fun error0(message: String?, e: Throwable?)
|
||||
|
||||
override fun plus(follower: MiraiLogger): MiraiLogger {
|
||||
override operator fun <T : MiraiLogger> plus(follower: T): T {
|
||||
this.follower = follower
|
||||
return follower
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user