mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-03 11:32:28 +08:00
Fix StackOverflowError
This commit is contained in:
parent
f402451812
commit
39204730eb
@ -2,14 +2,12 @@ package net.mamoe.mirai.network
|
|||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.io.core.use
|
import kotlinx.io.core.use
|
||||||
import kotlinx.io.streams.inputStream
|
import kotlinx.io.streams.inputStream
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.message.Image
|
import net.mamoe.mirai.message.Image
|
||||||
import net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter
|
|
||||||
import net.mamoe.mirai.network.protocol.tim.packet.SessionKey
|
import net.mamoe.mirai.network.protocol.tim.packet.SessionKey
|
||||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@ -21,8 +19,9 @@ import java.io.InputStream
|
|||||||
*/
|
*/
|
||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
actual class BotSession internal actual constructor(
|
actual class BotSession internal actual constructor(
|
||||||
bot: Bot
|
bot: Bot,
|
||||||
) : BotSessionBase(bot) {
|
sessionKey: SessionKey
|
||||||
|
) : BotSessionBase(bot, sessionKey) {
|
||||||
|
|
||||||
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
|
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
|
||||||
suspend inline fun Image.downloadAsBitmap(): Bitmap = withContext(Dispatchers.IO) { downloadAsStream().use { BitmapFactory.decodeStream(it) } }
|
suspend inline fun Image.downloadAsBitmap(): Bitmap = withContext(Dispatchers.IO) { downloadAsStream().use { BitmapFactory.decodeStream(it) } }
|
||||||
|
@ -41,10 +41,11 @@ fun GroupId.toInternalId(): GroupInternalId {//求你别出错
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun GroupInternalId.toId(): GroupId {//求你别出错
|
fun GroupInternalId.toId(): GroupId = with(value) {
|
||||||
|
//求你别出错
|
||||||
var left: UInt = this.toString().let {
|
var left: UInt = this.toString().let {
|
||||||
if (it.length < 6) {
|
if (it.length < 6) {
|
||||||
return GroupId(this.value)
|
return GroupId(value)
|
||||||
}
|
}
|
||||||
it.substring(0 until it.length - 6).toUInt()
|
it.substring(0 until it.length - 6).toUInt()
|
||||||
}
|
}
|
||||||
@ -96,6 +97,6 @@ fun GroupInternalId.toId(): GroupId {//求你别出错
|
|||||||
left = left.toString().substring(0 until 3).toUInt()
|
left = left.toString().substring(0 until 3).toUInt()
|
||||||
((left - 349u).toString() + right.toString()).toUInt()
|
((left - 349u).toString() + right.toString()).toUInt()
|
||||||
}
|
}
|
||||||
else -> this.value
|
else -> value
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -6,8 +6,10 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.contact.data.Profile
|
import net.mamoe.mirai.contact.data.Profile
|
||||||
import net.mamoe.mirai.network.BotSession
|
import net.mamoe.mirai.network.BotSession
|
||||||
|
import net.mamoe.mirai.network.protocol.tim.packet.action.AvatarLink
|
||||||
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark
|
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark
|
||||||
import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
|
import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
|
||||||
|
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* QQ 对象.
|
* QQ 对象.
|
||||||
@ -22,6 +24,12 @@ import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
|
|||||||
* @author Him188moe
|
* @author Him188moe
|
||||||
*/
|
*/
|
||||||
interface QQ : Contact, CoroutineScope {
|
interface QQ : Contact, CoroutineScope {
|
||||||
|
/**
|
||||||
|
* 请求头像下载链接
|
||||||
|
*/
|
||||||
|
// @MiraiExperimentalAPI
|
||||||
|
//suspend fun queryAvatar(): AvatarLink
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询用户资料
|
* 查询用户资料
|
||||||
*/
|
*/
|
||||||
|
@ -31,7 +31,7 @@ import kotlin.coroutines.coroutineContext
|
|||||||
* 构造 [BotSession] 的捷径
|
* 构造 [BotSession] 的捷径
|
||||||
*/
|
*/
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||||
internal inline fun TIMBotNetworkHandler.BotSession(): BotSession = BotSession(bot)
|
internal inline fun TIMBotNetworkHandler.BotSession(sessionKey: SessionKey): BotSession = BotSession(bot, sessionKey)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录会话. 当登录完成后, 客户端会拿到 sessionKey.
|
* 登录会话. 当登录完成后, 客户端会拿到 sessionKey.
|
||||||
@ -43,7 +43,8 @@ internal inline fun TIMBotNetworkHandler.BotSession(): BotSession = BotSession(b
|
|||||||
*/
|
*/
|
||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
expect class BotSession internal constructor(
|
expect class BotSession internal constructor(
|
||||||
bot: Bot
|
bot: Bot,
|
||||||
|
sessionKey: SessionKey
|
||||||
) : BotSessionBase
|
) : BotSessionBase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,9 +53,9 @@ expect class BotSession internal constructor(
|
|||||||
@MiraiInternalAPI
|
@MiraiInternalAPI
|
||||||
// cannot be internal because of `public BotSession`
|
// cannot be internal because of `public BotSession`
|
||||||
abstract class BotSessionBase internal constructor(
|
abstract class BotSessionBase internal constructor(
|
||||||
val bot: Bot
|
val bot: Bot,
|
||||||
|
internal val sessionKey: SessionKey
|
||||||
) {
|
) {
|
||||||
internal val sessionKey: SessionKey get() = bot.sessionKey
|
|
||||||
val socket: DataPacketSocketAdapter get() = bot.network.socket
|
val socket: DataPacketSocketAdapter get() = bot.network.socket
|
||||||
val NetworkScope: CoroutineScope get() = bot.network
|
val NetworkScope: CoroutineScope get() = bot.network
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
|||||||
BotLoginSucceedEvent(bot).broadcast()
|
BotLoginSucceedEvent(bot).broadcast()
|
||||||
|
|
||||||
|
|
||||||
session = BotSession()
|
session = BotSession(sessionKey)
|
||||||
|
|
||||||
val configuration = currentBotConfiguration()
|
val configuration = currentBotConfiguration()
|
||||||
heartbeatJob = this@TIMBotNetworkHandler.launch {
|
heartbeatJob = this@TIMBotNetworkHandler.launch {
|
||||||
|
@ -79,6 +79,7 @@ internal enum class KnownPacketId(override inline val value: UShort, override in
|
|||||||
|
|
||||||
inline REQUEST_PROFILE_AVATAR(0x0031u, RequestProfileAvatarPacket),
|
inline REQUEST_PROFILE_AVATAR(0x0031u, RequestProfileAvatarPacket),
|
||||||
inline REQUEST_PROFILE_DETAILS(0x003Cu, RequestProfileDetailsPacket),
|
inline REQUEST_PROFILE_DETAILS(0x003Cu, RequestProfileDetailsPacket),
|
||||||
|
inline QUERY_NICKNAME(0x0126u, QueryNicknamePacket),
|
||||||
|
|
||||||
inline QUERY_PREVIOUS_NAME(0x01BCu, QueryPreviousNamePacket),
|
inline QUERY_PREVIOUS_NAME(0x01BCu, QueryPreviousNamePacket),
|
||||||
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package net.mamoe.mirai.network.protocol.tim.packet.action
|
||||||
|
|
||||||
|
|
||||||
|
// 0001
|
||||||
|
// 已确认 查好友列表的列表
|
||||||
|
|
||||||
|
// send
|
||||||
|
// 20 01 00 00 00 00 01 00 00
|
||||||
|
|
||||||
|
// receive
|
||||||
|
// 20 00 01 03 00 00 00 15 01 01 03
|
||||||
|
// 00 0C 01 02 [09] E4 BF A1 E7 94 A8 E5 8D A1
|
||||||
|
// 00 0F 02 03 [0C] E8 BD AF E4 BB B6 E6 B3 A8 E5 86 8C
|
||||||
|
// 00 09 03 04 [06] E6 BA 90 E7 A0 81
|
||||||
|
// 00 00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 0134
|
||||||
|
// 这里有好友也有群(为 internal id) 97208217
|
||||||
|
// 不太确定. 可能是查好友与群列表??
|
||||||
|
// send
|
||||||
|
// 00 00 01 5B 5D EB 58 AD 00 00 03 E8 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
|
||||||
|
// receive
|
||||||
|
// 00 00 19 00 00 01 5D 5D EB 5D C6 00 00 00 00 01 00 00 00 19 00 54 E5 06 01 00 00 00 00 00 01 00 00 00 64 B2 1D 01 00 00 00 00 00 01 00 00 00 66 7C C5 01 00 00 00 00 00 01 00 00 01 60 31 EC 01 00 00 00 00 00 01 00 00 01 B3 E6 AC 01 00 00 00 00 00 01 00 00 02 45 16 DF 01 00 00 00 00 00 01 00 00 03 37 67 20 01 00 00 00 00 00 01 00 00 05 B0 F4 6F 01 00 00 00 00 00 01 00 00 0C D9 1F 45 01 00 00 00 00 00 01 00 00 0F 0D 35 E1 01 00 00 00 00 00 01 00 00 10 18 86 83 01 00 00 00 00 00 01 00 00 11 A9 8B F7 01 00 00 00 00 00 01 00 00 31 05 12 1C 01 00 00 00 00 00 01 00 00 37 99 77 D7 01 00 00 00 00 00 01 00 00 37 C8 4D C7 04 00 00 00 00 00 00 37 E9 68 46 01 00 00 00 00 00 01 00 00 37 E9 94 CF 01 00 00 00 00 00 01 00 00 3E 03 3F A2 01 00 00 00 00 00 01 00 00 50 BA 4A 8F 01 00 00 00 00 00 01 00 00 55 7A D6 86 01 00 00 00 00 00 01 00 00 6C 78 B1 E0 01 00 00 00 00 00 01 00 00 78 59 79 87 01 00 00 00 00 00 01 00 00 79 9B 1B 59 04 00 00 00 00 00 00 A6 81 A4 9D 01 00 00 00 00 00 01 00 00 A6 A0 EE EF 01 00 00 00 00 00 01 00 00 00 00
|
||||||
|
|
||||||
|
|
@ -10,12 +10,133 @@ import net.mamoe.mirai.network.BotNetworkHandler
|
|||||||
import net.mamoe.mirai.network.protocol.tim.packet.*
|
import net.mamoe.mirai.network.protocol.tim.packet.*
|
||||||
import net.mamoe.mirai.utils.io.*
|
import net.mamoe.mirai.utils.io.*
|
||||||
|
|
||||||
|
inline class AvatarLink(val value: String) : Packet
|
||||||
|
|
||||||
|
inline class NicknameMap(val delegate: Map<UInt, String>) : Packet
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询昵称.
|
||||||
|
*/
|
||||||
|
@AnnotatedId(KnownPacketId.QUERY_NICKNAME)
|
||||||
|
internal object QueryNicknamePacket : SessionPacketFactory<NicknameMap>() {
|
||||||
|
/**
|
||||||
|
* 单个查询.
|
||||||
|
*/
|
||||||
|
@PacketVersion(date = "2019.12.7", timVersion = "2.3.2 (21173)")
|
||||||
|
operator fun invoke(
|
||||||
|
bot: UInt,
|
||||||
|
sessionKey: SessionKey,
|
||||||
|
qq: UInt
|
||||||
|
): OutgoingPacket = buildSessionPacket(bot, sessionKey) {
|
||||||
|
writeHex("03 00 00 00 00 00 00 00 00 00 00")
|
||||||
|
writeByte(1)
|
||||||
|
writeUInt(qq)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询.
|
||||||
|
* 注意!! 服务器不一定全都返回... 需要重复查没返回的
|
||||||
|
*/
|
||||||
|
@PacketVersion(date = "2019.12.7", timVersion = "2.3.2 (21173)")
|
||||||
|
operator fun invoke(
|
||||||
|
bot: UInt,
|
||||||
|
sessionKey: SessionKey,
|
||||||
|
qq: Array<UInt>
|
||||||
|
): OutgoingPacket = buildSessionPacket(bot, sessionKey) {
|
||||||
|
writeHex("03 00 00 00 00 00 00 00 00 00 00")
|
||||||
|
writeUByte(qq.size.toUByte())
|
||||||
|
qq.forEach {
|
||||||
|
writeUInt(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
批量查询昵称
|
||||||
|
|
||||||
|
发出包ID = UnknownPacketId(01 26)
|
||||||
|
sequence = 44 57
|
||||||
|
fixVer2=02 00 00 00 01 2E 01 00 00 69 35
|
||||||
|
解密body=03 00 00 00 00 00 00 00 00 00 00 [24]
|
||||||
|
(02 45 16 DF) (6C 78 B1 E0) (11 73 69 76) (36 79 19 E1) (49 28 A4 F4) (81 66 8B BC) (2D 6B 19 EC) (28 3D 91 25) (00 54 E5 06) (37 E9 94 CF) (55 7A D6 86)
|
||||||
|
(01 60 31 EC) (2F B1 5E EF) (05 B0 F4 6F) (0F 0D 35 E1) (00 66 7C C5) A6 81 A4 9D 31 05 12 1C A6 A0 EE EF 10 18 86 83 37 99 77 D7 50 BA 4A 8F 10 CE 72 4C 32 71 EE 30 79 63 C6 98 (3E C2 FA 6E) 02 27 13 93 01 2E E5 D7 37 E9 68 46 00 64 B2 1D 03 37 67 20 0A 9C 58 FB 05 94 75 87
|
||||||
|
(0B 9F C6 B6)
|
||||||
|
(18 BE 4B 0E)
|
||||||
|
|
||||||
|
接收包id=UnknownPacketId(01 26),
|
||||||
|
sequence=44 57
|
||||||
|
解析body=UnknownPacket(01 26)
|
||||||
|
body= 03 00 00 00 00 00 00 00 00 00 00 12 04 14 37
|
||||||
|
(02 45 16 DF) 00 36 FF 00
|
||||||
|
[0F] E6 94 BE E7 9D 9B E3 81 AE E5 A4 A9 E7 A9 BA
|
||||||
|
11 88 02 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 80 08 80 00 41
|
||||||
|
(6C 78 B1 E0) 00 2D 1C 01
|
||||||
|
[19] 61 2E E8 B4 A2 E7 A5 9E 7C 20 E6 8E A5 E5 90 84 E7 A7 8D E4 B8 9A E5 8A A1
|
||||||
|
11 C0 02 40 07 C7 08 1C 00 4D 59 53 00 00 4B 4C 00 4B 55 4C 00 00 00 00 00 00 04 00 00 E2 10 34
|
||||||
|
(11 73 69 76) 01 DD 19 00
|
||||||
|
[0C] E5 BC 80 E5 BF 83 E5 B0 B1 E5 A5 BD
|
||||||
|
11 08 82 46 07 CA 00 00 00 00 00 31 00 00 33 32 00 00 00 35 08 04 08 04 08 04 04 01 17 E3 10 32
|
||||||
|
(36 79 19 E1) 00 00 1F 00
|
||||||
|
[0A] 45 70 69 6D 65 74 68 65 75 73
|
||||||
|
00 08 02 00 07 C4 02 08 00 41 42 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 10 49
|
||||||
|
(49 28 A4 F4) 02 B5 17 01
|
||||||
|
[21] E9 A1 B9 E7 9B AE 6B 61 6B 61 6F 74 61 6C 6B EF BC 88 E6 9C 89 E4 BA 8B E6 8A 96 E6 88 91 EF BC 89
|
||||||
|
11 80 02 00 07 CC 06 0B 00 00 00 31 00 00 34 34 00 00 00 31 00 00 00 00 00 00 04 00 00 80 10 2E
|
||||||
|
(81 66 8B BC) 02 64 77 00
|
||||||
|
[06] E4 B8 87 E7 A0 81
|
||||||
|
00 80 02 00 07 6C 0A 03 00 00 00 31 00 00 33 31 00 00 00 35 00 00 00 00 00 00 04 00 00 00 00 37
|
||||||
|
(2D 6B 19 EC) 02 58 16 01
|
||||||
|
[0F] E5 93 A5 E5 8F AA E6 98 AF E4 BC A0 E9 80 81
|
||||||
|
11 00 02 00 07 CC 0C 0F 00 00 00 31 00 00 35 33 00 00 00 33 00 00 00 00 00 00 04 00 00 00 00 31
|
||||||
|
28 3D 91 25 02 D9 FF FF 09 E5 B0 8F E8 A1 A8 E5 BC 9F 11 C8 02 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 04 08 04 08 04 04 20 06 E2 00 3B 00 54 E5 06 02 5B 78 00 13 61 E5 85 A8 E6 96 B0 E5 9F 9F E5 90 8D E6 89 B9 E5 8F 91 00 08 82 46 07 6B 08 16 00 00 00 31 00 00 34 33 00 00 00 31 00 00 00 00 00 00 04 00 08 02 00 4C 37 E9 94 CF 00 00 00 FF 24 E6 B3 89 E5 B7 9E E5 B8 82 E6 86 A8 E9 BC A0 E7 BD 91 E7 BB 9C E7 A7 91 E6 8A 80 E6 9C 89 E9 99 90 E5 85 AC 01 00 00 00 00 00 00 00 00 00 00 31 00 00 33 35 00 00 00 35 00 00 00 00 00 00 04 00 00 40 02 30 55 7A D6 86 02 49 1B 01 08 E5 AE A2 E6 9C 8D 56 36 11 00 02 00 07 C8 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 12 00 4A 01 60 31 EC 02 58 FF 00 22 E5 BC 80 E5 BD A9 E7 BD 91 2D E5 B0 8F E8 B1 86 28 31 32 E5 88 B0 32 32 E7 82 B9 E5 9C A8 E7 BA BF 29 00 40 00 00 00 00 05 1E 00 00 00 31 00 00 35 31 00 00 00 31 08 04 04 09 0C 04 04 00 00 02 00 38 2F B1 5E EF 00 00 00 FF 10 E4 B8 8A E6 96 B9 65 E6 8E A8 E8 BD AF E4 BB B6 01 80 00 00 00 00 00 00 00 00 00 31 00 00 34 34 00 00 00 33 00 00 00 00 00 00 04 00 00 00 00 39 05 B0 F4 6F 00 78 23 01 11 E2 99 A1 20 E2 9C BF E2 80 BF E2 9C BF 20 52 4F 4E 11 88 82 42 07 C0 09 0C 00 00 00 31 00 00 33 35 00 00 00 35 00 00 00 00 00 00 04 00 00 80 00 2E 0F 0D 35 E1 00 00 23 00 06 E5 9C B0 E8 A1 A3 00 40 02 46 07 C0 02 08 00 00 00 31 00 00 34 35 00 00 00 33 00 00 00 00 00 00 04 10 00 02 00 31 00 66 7C C5 00 00 0A 00 09 E8 B5 9A E5 B0 8F E5 AE A2 00 C8 02 42 07 D8 0C 0C 00 00 00 31 00 00 34 31 00 00 00 31 00 00 00 00 00 00 04 24 02 00 00 3A
|
||||||
|
(A6 81 A4 9D) 02 25 29 00 12 E6 96 B0 E6 98 93 E9 80 9A E5 AE A2 E6 9C 8D E4 B8 89 11 80 02 01 07 BA 0A 10 00 00 00 31 00 00 33 35 00 00 00 35 00 00 00 00 00 00 04 00 00 00 00 3A 31 05 12 1C 01 86 1C 00 12 E5 BF A7 E4 BC A4 E8 BF 98 E6 98 AF E5 BF AB E4 B9 90 00 88 02 02 07 C7 04 13 00 00 00 31 00 00 33 35 00 00 00 35 00 00 00 00 00 00 04 00 08 20 00 00 04 5D EC AF 48
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
发出包ID = UnknownPacketId(01 26)
|
||||||
|
sequence = 44 58
|
||||||
|
fixVer2=02 00 00 00 01 2E 01 00 00 69 35
|
||||||
|
解密body=03 00 00 00 00 00 00 00 00 00 00 12 A6 A0 EE EF 10 18 86 83 37 99 77 D7 50 BA 4A 8F 10 CE 72 4C 32 71 EE 30 79 63 C6 98
|
||||||
|
(3E C2 FA 6E) 02 27 13 93 01 2E E5 D7 37 E9 68 46 (00 64 B2 1D) (03 37 67 20) 0A 9C 58 FB 05 94 75 87 (11 48 2B 1A) 0B 9F C6 B6 18 BE 4B 0E
|
||||||
|
|
||||||
|
接收包id=UnknownPacketId(01 26),
|
||||||
|
sequence=44 58
|
||||||
|
解析body=UnknownPacket(01 26)
|
||||||
|
body=03 00 00 00 00 00 00 00 00 00 00 00 03 8E 3C A6 A0 EE EF 02 07 6C 01 14 E8 8B B9 E6 9E 9C 49 44 E4 B8 93 E4 B8 9A E8 A7 A3 E9 94 81 11 00 02 01 07 77 01 01 00 00 00 31 00 00 31 31 00 00 00 31 00 00 00 00 00 00 04 00 00 02 00 31 10 18 86 83 00 C3 22 00 09 35 35 38 E7 94 B5 E8 AE AF 00 08 02 40 07 C1 0C 01 00 00 00 31 00 00 33 35 00 00 00 35 08 04 08 04 08 04 04 00 04 00 10 35 37 99 77 D7 02 5B 2A 00 0D E8 BF 9C E6 8B 93 E7 94 B5 E8 AE AF 33 00 C0 00 02 07 B9 09 0E 00 00 00 31 00 00 33 35 00 00 00 35 00 00 00 00 00 00 04 00 00 40 00 2E 50 BA 4A 8F 02 1C 09 00 06 E6 96 B9 E5 80 8D 11 40 02 00 07 DA 01 01 00 00 00 31 00 00 34 34 00 00 00 33 00 00 00 00 00 00 04 00 00 82 00 2C 10 CE 72 4C 00 00 23 00 04 4C 6F 73 74 11 08 02 00 07 C0 02 12 00 00 00 31 00 00 31 31 00 00 00 38 08 04 00 00 00 00 04 00 08 72 00 30 32 71 EE 30 00 93 21 00 08 69 57 65 62 53 68 6F 70 00 00 02 00 07 C2 01 01 00 00 00 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 12 00 2B 79 63 C6 98 02 A6 12 00 03 5E 4F 5E 11 80 02 00 07 D1 08 12 00 00 00 31 00 00 33 37 00 00 00 32 00 00 00 00 00 00 04 00 00 60 00 3D 3E C2 FA 6E 02 2B 1D 01 15 E9 A3 8E E9 93 83 E8 8D 89 E6 95 99 E8 82 B2 E6 9C 8D E5 8A A1 00 80 00 00 07 C6 06 10 00 00 00 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 2E 02 27 13 93 02 0D FF FF 06 E7 83 82 E8 8F 9C 00 08 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 04 A2 00 33 01 2E E5 D7 00 D8 22 00 0B 4F 28 E2 88 A9 5F E2 88 A9 29 4F 11 48 82 46 07 C1 08 1A 00 00 00 31 00 00 33 35 00 00 00 35 08 04 08 04 08 04 04 00 0C 80 08 30 37 E9 68 46 00 00 00 FF 08 33 35 E4 BA 92 E8 81 94 01 00 00 00 00 00 00 00 00 00 00 31 00 00 33 35 00 00 00 32 00 00 00 00 00 00 04 00 00 40 02 37 00 64 B2 1D 00 00 FF FF 0F E5 98 89 E4 BC A6 E8 99 8E E8 99 8E E8 99 8E 01 48 06 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 01 40 8C 00 34 03 37 67 20 00 93 24 00 0C E8 93 9D E6 98 9F E7 A7 91 E6 8A 80 00 08 02 46 07 BF 0A 1A 00 00 00 31 00 00 33 35 00 00 00 35 08 04 08 04 08 04 04 00 00 00 10 2C 0A 9C 58 FB 01 53 00 00 04 4B E3 80 81 00 48 02 02 07 E3 00 00 00 00 00 31 00 00 00 00 00 00 00 00 0C 04 08 04 04 09 04 FD 03 02 00 2E 05 94 75 87 02 25 1F 00 06 54 4E 54 50 52 4F 00 40 02 00 07 C4 01 01 00 00 00 31 00 00 34 33 00 00 00 31 00 00 00 00 00 00 04 00 00 02 00 2E 11 48 2B 1A 02 0A 0B 00 06 E6 9D 8E E9 98 B3 11 08 02 02 07 D8 03 1C 00 00 00 31 00 00 34 34 00 00 00 33 00 00 00 00 00 00 04 00 00 6C 00 30 0B 9F C6 B6 00 AE 14 00 08 F0 9F 91 BC F0 9F 91 BF 11 00 02 42 07 CF 01 18 00 00 00 00 00 00 00 00 00 00 00 00 08 04 08 04 04 07 04 00 04 A0 00 34
|
||||||
|
(18 BE 4B 0E) 00 00 36 00
|
||||||
|
[0C] E5 B3 B0 E5 9B 9E E8 B7 AF E8 BD AC
|
||||||
|
00 08 02 00 07 AD 02 03 00 00 00 31 00 00 31 35 00 00 32 32 00 00 00 00 00 00 04 00 00 00 00 00
|
||||||
|
|
||||||
|
04 5D EC AF 48
|
||||||
|
*/
|
||||||
|
|
||||||
|
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): NicknameMap {
|
||||||
|
//03 00 00 00 00 00 00 00 00 00 00 12 04 14 37
|
||||||
|
val type = readUByte().toInt()
|
||||||
|
if (type == 15) {
|
||||||
|
discardExact(14)
|
||||||
|
|
||||||
|
val map = linkedMapOf<UInt, String>()
|
||||||
|
while (remaining != 5L) { // 最后总是会剩余 04 5D EC AF 48
|
||||||
|
val qq = readUInt()
|
||||||
|
discardExact(4) // 4 个状态信息, 未知
|
||||||
|
val nickname = readString(readUByte().toInt())
|
||||||
|
discardExact(32) // 未知
|
||||||
|
map[qq] = nickname
|
||||||
|
}
|
||||||
|
return NicknameMap(map)
|
||||||
|
} else {
|
||||||
|
error("Unsupported type $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 用户资料的头像
|
// 用户资料的头像
|
||||||
/**
|
/**
|
||||||
* 请求获取头像
|
* 请求获取头像
|
||||||
*/
|
*/ // ? 这个包的数据跟下面那个包一样
|
||||||
@AnnotatedId(KnownPacketId.REQUEST_PROFILE_AVATAR)
|
@AnnotatedId(KnownPacketId.REQUEST_PROFILE_AVATAR)
|
||||||
internal object RequestProfileAvatarPacket : SessionPacketFactory<NoPacket>() {
|
internal object RequestProfileAvatarPacket : SessionPacketFactory<AvatarLink>() {
|
||||||
//00 01 00 17 D4 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 29 4E 22 4E 25 4E 26 4E 27 4E 29 4E 2A 4E 2B 4E 2D 4E 2E 4E 2F 4E 30 4E 31 4E 33 4E 35 4E 36 4E 37 4E 38 4E 3F 4E 40 4E 41 4E 42 4E 43 4E 45 4E 49 4E 4B 4E 4F 4E 54 4E 5B 52 0B 52 0F 5D C2 5D C8 65 97 69 9D 69 A9 9D A5 A4 91 A4 93 A4 94 A4 9C A4 B5
|
//00 01 00 17 D4 54 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 29 4E 22 4E 25 4E 26 4E 27 4E 29 4E 2A 4E 2B 4E 2D 4E 2E 4E 2F 4E 30 4E 31 4E 33 4E 35 4E 36 4E 37 4E 38 4E 3F 4E 40 4E 41 4E 42 4E 43 4E 45 4E 49 4E 4B 4E 4F 4E 54 4E 5B 52 0B 52 0F 5D C2 5D C8 65 97 69 9D 69 A9 9D A5 A4 91 A4 93 A4 94 A4 9C A4 B5
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
bot: UInt,
|
bot: UInt,
|
||||||
@ -27,9 +148,9 @@ internal object RequestProfileAvatarPacket : SessionPacketFactory<NoPacket>() {
|
|||||||
writeHex("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 29 4E 22 4E 25 4E 26 4E 27 4E 29 4E 2A 4E 2B 4E 2D 4E 2E 4E 2F 4E 30 4E 31 4E 33 4E 35 4E 36 4E 37 4E 38 4E 3F 4E 40 4E 41 4E 42 4E 43 4E 45 4E 49 4E 4B 4E 4F 4E 54 4E 5B 52 0B 52 0F 5D C2 5D C8 65 97 69 9D 69 A9 9D A5 A4 91 A4 93 A4 94 A4 9C A4 B5")
|
writeHex("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 29 4E 22 4E 25 4E 26 4E 27 4E 29 4E 2A 4E 2B 4E 2D 4E 2E 4E 2F 4E 30 4E 31 4E 33 4E 35 4E 36 4E 37 4E 38 4E 3F 4E 40 4E 41 4E 42 4E 43 4E 45 4E 49 4E 4B 4E 4F 4E 54 4E 5B 52 0B 52 0F 5D C2 5D C8 65 97 69 9D 69 A9 9D A5 A4 91 A4 93 A4 94 A4 9C A4 B5")
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): NoPacket {
|
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: UShort, handler: BotNetworkHandler<*>): AvatarLink {
|
||||||
println(" RequestProfileAvatarPacket body=${this.readBytes().toUHexString()}")
|
println(" RequestProfileAvatarPacket body=${this.readBytes().toUHexString()}")
|
||||||
return NoPacket
|
TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,26 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai
|
package net.mamoe.mirai
|
||||||
|
|
||||||
|
import kotlinx.io.core.buildPacket
|
||||||
|
import kotlinx.io.core.readBytes
|
||||||
|
import net.mamoe.mirai.contact.GroupInternalId
|
||||||
|
import net.mamoe.mirai.contact.toId
|
||||||
|
import net.mamoe.mirai.utils.io.toByteArray
|
||||||
|
import net.mamoe.mirai.utils.io.toUHexString
|
||||||
|
|
||||||
actual object MiraiEnvironment {
|
actual object MiraiEnvironment {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
actual val platform: Platform get() = Platform.JVM
|
actual val platform: Platform
|
||||||
|
get() = Platform.JVM
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun main() {
|
||||||
|
println(GroupInternalId(2793514141u).toId().value.toLong())
|
||||||
|
println(GroupInternalId(2040208217u).toId().value.toLong())
|
||||||
|
println(289942298u.toByteArray().toUHexString())
|
||||||
|
println(1040400290u.toByteArray().toUHexString())
|
||||||
|
println(buildPacket {
|
||||||
|
writeStringUtf8("信用卡")
|
||||||
|
}.readBytes().toUByteArray().toUHexString())
|
||||||
}
|
}
|
@ -1,13 +1,11 @@
|
|||||||
package net.mamoe.mirai.network
|
package net.mamoe.mirai.network
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.io.core.use
|
import kotlinx.io.core.use
|
||||||
import kotlinx.io.streams.inputStream
|
import kotlinx.io.streams.inputStream
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.message.Image
|
import net.mamoe.mirai.message.Image
|
||||||
import net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter
|
|
||||||
import net.mamoe.mirai.network.protocol.tim.packet.SessionKey
|
import net.mamoe.mirai.network.protocol.tim.packet.SessionKey
|
||||||
import net.mamoe.mirai.utils.ExternalImage
|
import net.mamoe.mirai.utils.ExternalImage
|
||||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
@ -24,8 +22,9 @@ import javax.imageio.ImageIO
|
|||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
actual class BotSession internal actual constructor(
|
actual class BotSession internal actual constructor(
|
||||||
bot: Bot
|
bot: Bot,
|
||||||
) : BotSessionBase(bot) {
|
sessionKey: SessionKey
|
||||||
|
) : BotSessionBase(bot, sessionKey) {
|
||||||
|
|
||||||
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
|
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
|
||||||
suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(IO) { downloadAsStream().use { ImageIO.read(it) } }
|
suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(IO) { downloadAsStream().use { ImageIO.read(it) } }
|
||||||
|
@ -134,27 +134,29 @@ suspend fun main() {
|
|||||||
println("Ready perfectly")
|
println("Ready perfectly")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun decryptRecordedPackets(filename: String) {
|
suspend fun decryptRecordedPackets(filename: String?) {
|
||||||
File(filename).toRecorder()
|
(if (filename == null) File(".").listFiles()?.maxBy { it.lastModified() }!!
|
||||||
.list.forEach {
|
else File(filename)).toRecorder().also {
|
||||||
|
println("total count = " + it.list.size)
|
||||||
|
println()
|
||||||
|
}.list.forEach {
|
||||||
if (it.isSend) {
|
if (it.isSend) {
|
||||||
try {
|
try {
|
||||||
dataSent(it.data)
|
dataSent(it.data)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
//e.printStackTrace()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
dataReceived(it.data)
|
dataReceived(it.data)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
// e.printStackTrace()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptRecordedPackets("GMTDate(seconds=3, minutes=46, hours=7, dayOfWeek=SATURDAY, dayOfMonth=7, dayOfYear=341, month=DECEMBER, year=2019, timestamp=1575704763731).record")
|
decryptRecordedPackets(null)
|
||||||
//startPacketListening()
|
//startPacketListening()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,13 +182,13 @@ internal object PacketDebugger {
|
|||||||
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
|
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
|
||||||
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
|
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
|
||||||
*/
|
*/
|
||||||
val sessionKey: SessionKey = SessionKey("98 4C 42 37 0F 87 BB A2 97 57 A1 77 A9 A9 74 37".hexToBytes())
|
val sessionKey: SessionKey = SessionKey("F3 4A 4E F4 79 C4 92 62 EF 0F D8 6E D3 AB E3 80".hexToBytes())
|
||||||
// TODO: 2019/12/7 无法访问 internal 是 kotlin bug, KT-34849
|
// TODO: 2019/12/7 无法访问 internal 是 kotlin bug, KT-34849
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* null 则不筛选
|
* null 则不筛选
|
||||||
*/
|
*/
|
||||||
val qq: UInt? = null
|
val qq: UInt? = 215555909u
|
||||||
/**
|
/**
|
||||||
* 打开后则记录每一个包到文件.
|
* 打开后则记录每一个包到文件.
|
||||||
*/
|
*/
|
||||||
@ -229,7 +231,7 @@ internal object PacketDebugger {
|
|||||||
}
|
}
|
||||||
.runCatching {
|
.runCatching {
|
||||||
decode(id, sequenceId, DebugNetworkHandler)
|
decode(id, sequenceId, DebugNetworkHandler)
|
||||||
}.getOrElse { it.printStackTrace(); null }
|
}.getOrElse { /*it.printStackTrace();*/ null }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +239,9 @@ internal object PacketDebugger {
|
|||||||
if (packet !is IgnoredEventPacket) {
|
if (packet !is IgnoredEventPacket) {
|
||||||
println("--------------")
|
println("--------------")
|
||||||
println("接收包id=$id, \nsequence=${sequenceId.toUHexString()}")
|
println("接收包id=$id, \nsequence=${sequenceId.toUHexString()}")
|
||||||
println(" 解密body=${decodedBody.toUHexString()}")
|
if (packet !is UnknownPacket) {
|
||||||
|
println(" 解密body=${decodedBody.toUHexString()}")
|
||||||
|
}
|
||||||
println(" 解析body=$packet")
|
println(" 解析body=$packet")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +394,7 @@ internal object DebugNetworkHandler : BotNetworkHandler<DataPacketSocketAdapter>
|
|||||||
|
|
||||||
}
|
}
|
||||||
override val bot: Bot = Bot(qq ?: 0u, "", coroutineContext)
|
override val bot: Bot = Bot(qq ?: 0u, "", coroutineContext)
|
||||||
override val session = BotSession(bot)
|
override val session = BotSession(bot, SessionKey(byteArrayOf()))
|
||||||
|
|
||||||
override suspend fun login(): LoginResult = LoginResult.SUCCESS
|
override suspend fun login(): LoginResult = LoginResult.SUCCESS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user