Use PacketHandler.Key

This commit is contained in:
Him188 2019-10-13 22:21:26 +08:00
parent d89f8acc43
commit ad43a92be4
16 changed files with 215 additions and 132 deletions

View File

@ -7,8 +7,10 @@ import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import net.mamoe.mirai.utils.BotAccount import net.mamoe.mirai.utils.BotAccount
import net.mamoe.mirai.utils.ContactList import net.mamoe.mirai.utils.ContactList
import net.mamoe.mirai.utils.LoginConfiguration
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
/** /**
@ -44,7 +46,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
val contacts = ContactSystem() val contacts = ContactSystem()
val network: BotNetworkHandler<*> = TIMBotNetworkHandler(this) var network: BotNetworkHandler<*> = TIMBotNetworkHandler(this)
init { init {
instances.add(this) instances.add(this)
@ -54,6 +56,17 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
override fun toString(): String = "Bot{id=$id,qq=${account.qqNumber}}" override fun toString(): String = "Bot{id=$id,qq=${account.qqNumber}}"
/**
* [关闭][BotNetworkHandler.close]网络处理器, 取消所有运行在 [BotNetworkHandler.NetworkScope] 下的协程.
* 然后重新启动并尝试登录
*/
suspend fun reinitializeNetworkHandler(configuration: LoginConfiguration): LoginResult {
logger.logPurple("Reinitializing BotNetworkHandler")
network.close()
network = TIMBotNetworkHandler(this)
return network.login(configuration)
}
/** /**
* Bot 联系人管理. * Bot 联系人管理.
* *

View File

@ -3,6 +3,7 @@ package net.mamoe.mirai.contact
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Group.Companion.groupNumberToId import net.mamoe.mirai.contact.Group.Companion.groupNumberToId
import net.mamoe.mirai.message.MessageChain import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler
import net.mamoe.mirai.utils.ContactList import net.mamoe.mirai.utils.ContactList
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
@ -28,7 +29,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number) {
get() = throw UnsupportedOperationException("Not yet supported") get() = throw UnsupportedOperationException("Not yet supported")
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
bot.network.event.sendGroupMessage(this, message) bot.network[EventPacketHandler].sendGroupMessage(this, message)
} }
override suspend fun sendXMLMessage(message: String) { override suspend fun sendXMLMessage(message: String) {

View File

@ -4,6 +4,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.message.At import net.mamoe.mirai.message.At
import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.MessageChain import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler
/** /**
* QQ 账号. * QQ 账号.
@ -19,7 +20,7 @@ import net.mamoe.mirai.message.MessageChain
*/ */
class QQ(bot: Bot, number: Long) : Contact(bot, number) { class QQ(bot: Bot, number: Long) : Contact(bot, number) {
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
bot.network.event.sendFriendMessage(this, message) bot.network[EventPacketHandler].sendFriendMessage(this, message)
} }
override suspend fun sendXMLMessage(message: String) { override suspend fun sendXMLMessage(message: String) {

View File

@ -6,7 +6,7 @@ import kotlinx.io.core.*
import net.mamoe.mirai.message.* import net.mamoe.mirai.message.*
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
internal fun ByteArray.parseMessageFace(): Face = read { internal fun IoBuffer.parseMessageFace(): Face {
//00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0 //00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0
//00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D //00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D
discardExact(1) discardExact(1)
@ -14,30 +14,30 @@ internal fun ByteArray.parseMessageFace(): Face = read {
val id1 = FaceID.ofId(readLVNumber().toInt().toUByte())//可能这个是id, 也可能下面那个 val id1 = FaceID.ofId(readLVNumber().toInt().toUByte())//可能这个是id, 也可能下面那个
discardExact(readByte().toLong()) discardExact(readByte().toLong())
readLVNumber()//某id? readLVNumber()//某id?
return@read Face(id1) return Face(id1)
} }
internal fun ByteArray.parsePlainText(): PlainText = read { internal fun IoBuffer.parsePlainText(): PlainText {
discardExact(1) discardExact(1)
PlainText(readLVString()) return PlainText(readLVString())
} }
internal fun ByteArray.parseMessageImage0x06(): Image = read { internal fun IoBuffer.parseMessageImage0x06(): Image {
discardExact(1) discardExact(1)
MiraiLogger.logDebug("好友的图片") this.debugPrint("好友的图片")
MiraiLogger.logDebug(this@parseMessageImage0x06.toUHexString()) //MiraiLogger.logDebug(this.toUHexString())
val filenameLength = readShort() val filenameLength = readShort()
val suffix = readString(filenameLength).substringAfter(".") val suffix = readString(filenameLength).substringAfter(".")
discardExact(this@parseMessageImage0x06.size - 37 - 1 - filenameLength - 2) discardExact(this@parseMessageImage0x06.readRemaining - 37 - 1 - filenameLength - 2)
val imageId = readString(36) val imageId = readString(36)
MiraiLogger.logDebug(imageId) MiraiLogger.logDebug(imageId)
discardExact(1)//0x41 discardExact(1)//0x41
return@read Image("{$imageId}.$suffix") return Image("{$imageId}.$suffix")
} }
internal fun ByteArray.parseMessageImage0x03(): Image = read { internal fun IoBuffer.parseMessageImage0x03(): Image {
discardExact(1) discardExact(1)
return@read Image(String(readLVByteArray())) return Image(String(readLVByteArray()))
/* /*
println(String(readLVByteArray())) println(String(readLVByteArray()))
readTLVMap() readTLVMap()
@ -53,14 +53,14 @@ internal fun ByteArray.parseMessageImage0x03(): Image = read {
return Image(imageId)*/ return Image(imageId)*/
} }
internal fun ByteArray.parseMessageChain(): MessageChain = read { internal fun ByteReadPacket.parseMessageChain(): MessageChain {
readMessageChain() return readMessageChain()
} }
internal fun ByteReadPacket.readMessage(): Message? { internal fun ByteReadPacket.readMessage(): Message? {
val messageType = this.readByte().toInt() val messageType = this.readByte().toInt()
val sectionLength = this.readShort().toLong()//sectionLength: short val sectionLength = this.readShort().toLong()//sectionLength: short
val sectionData = this.readBytes(sectionLength.toInt())//use buffer instead val sectionData = this.readIoBuffer(sectionLength.toInt())//use buffer instead
return when (messageType) { return when (messageType) {
0x01 -> sectionData.parsePlainText() 0x01 -> sectionData.parsePlainText()
0x02 -> sectionData.parseMessageFace() 0x02 -> sectionData.parseMessageFace()
@ -68,7 +68,12 @@ internal fun ByteReadPacket.readMessage(): Message? {
0x06 -> sectionData.parseMessageImage0x06() 0x06 -> sectionData.parseMessageImage0x06()
0x19 -> {//长文本 0x19 -> {//未知, 可能是长文本?
//bot手机自己跟自己发消息会出这个
//sectionData: 01 00 1C AA 02 19 08 00 88 01 00 9A 01 11 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00
sectionData.readBytes().debugPrint("sectionData")
return PlainText("[UNKNOWN(${this.readBytes().toUHexString()})]")
println()
val value = readLVByteArray() val value = readLVByteArray()
//todo 未知压缩算法 //todo 未知压缩算法
PlainText(String(value)) PlainText(String(value))
@ -87,7 +92,6 @@ internal fun ByteReadPacket.readMessage(): Message? {
} }
0x0E -> { 0x0E -> {
//null
null null
} }
@ -102,16 +106,11 @@ internal fun ByteReadPacket.readMessage(): Message? {
fun ByteReadPacket.readMessageChain(): MessageChain { fun ByteReadPacket.readMessageChain(): MessageChain {
val chain = MessageChain() val chain = MessageChain()
var got: Message? = null
do { do {
if (got != null) {
chain.concat(got)
}
if (this.remaining == 0L) { if (this.remaining == 0L) {
return chain return chain
} }
got = this.readMessage() } while (this.readMessage().takeIf { it != null }?.let { chain.concat(it) } != null)
} while (got != null)
return chain return chain
} }

View File

@ -45,22 +45,14 @@ interface BotNetworkHandler<Socket : DataPacketSocket> : Closeable {
var socket: Socket var socket: Socket
/** /**
* 事件处理. 如发送好友消息, 接受群消息并触发事件 * 得到 [PacketHandler].
* `get(EventPacketHandler)` 返回 [EventPacketHandler]
* `get(ActionPacketHandler)` 返回 [ActionPacketHandler]
*/ */
val event: EventPacketHandler operator fun <T : PacketHandler> get(key: PacketHandler.Key<T>): T
/** /**
* 动作处理. 如发送好友请求, 处理别人发来的好友请求等 * 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回登录结果
*/
val action: ActionPacketHandler
/**
* [PacketHandler] 列表
*/
val packetHandlers: PacketHandlerList
/**
* 尝试登录. 将会依次尝试登录到可用的服务器. 在任一服务器登录完成后返回登录结果
*/ */
suspend fun login(configuration: LoginConfiguration): LoginResult suspend fun login(configuration: LoginConfiguration): LoginResult

View File

@ -24,24 +24,19 @@ import net.mamoe.mirai.utils.*
* *
* @see BotNetworkHandler * @see BotNetworkHandler
*/ */
internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocket> { internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocket>, PacketHandlerList() {
override val NetworkScope: CoroutineScope = CoroutineScope(Dispatchers.Default) override val NetworkScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
override lateinit var socket: BotSocket override lateinit var socket: BotSocket
override lateinit var event: EventPacketHandler
override lateinit var action: ActionPacketHandler
override val packetHandlers: PacketHandlerList = PacketHandlerList()
internal val temporaryPacketHandlers = mutableListOf<TemporaryPacketHandler<*>>() internal val temporaryPacketHandlers = mutableListOf<TemporaryPacketHandler<*>>()
private var heartbeatJob: Job? = null private var heartbeatJob: Job? = null
override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*>) { override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*>) {
temporaryPacketHandlers.add(temporaryPacketHandler) temporaryPacketHandlers.add(temporaryPacketHandler)
temporaryPacketHandler.send(action.session) temporaryPacketHandler.send(this[ActionPacketHandler].session)
} }
override suspend fun login(configuration: LoginConfiguration): LoginResult { override suspend fun login(configuration: LoginConfiguration): LoginResult {
@ -68,13 +63,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
//private | internal //private | internal
private fun onLoggedIn(sessionKey: ByteArray) { private fun onLoggedIn(sessionKey: ByteArray) {
require(packetHandlers.size == 0) { "Already logged in" } require(size == 0) { "Already logged in" }
val session = LoginSession(bot, sessionKey, socket, NetworkScope) val session = LoginSession(bot, sessionKey, socket, NetworkScope)
event = EventPacketHandler(session)
action = ActionPacketHandler(session)
packetHandlers.add(event.asNode()) add(EventPacketHandler(session).asNode(EventPacketHandler))
packetHandlers.add(action.asNode()) add(ActionPacketHandler(session).asNode(ActionPacketHandler))
} }
private lateinit var sessionKey: ByteArray private lateinit var sessionKey: ByteArray
@ -89,7 +82,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
this.loginResult.cancel(CancellationException("socket closed")) this.loginResult.cancel(CancellationException("socket closed"))
} }
this.packetHandlers.forEach { this.forEach {
it.instance.close() it.instance.close()
} }
@ -177,21 +170,14 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
packet.use { packet.use {
//coz removeIf is not inline //coz removeIf is not inline
with(temporaryPacketHandlers.iterator()) { temporaryPacketHandlers.removeIfInlined {
while (hasNext()) { it.onPacketReceived(this@TIMBotNetworkHandler[ActionPacketHandler].session, packet)
if (next().onPacketReceived(action.session, packet)) { }
remove()
}
}
};
//For logDebug val name = packet::class.simpleName
{ if (name != null && !name.endsWith("Encrypted") && !name.endsWith("Raw")) {
val name = packet::class.simpleName bot.cyan("Packet received: $packet")
if (name != null && !name.endsWith("Encrypted") && !name.endsWith("Raw")) { }
bot.cyan("Packet received: $packet")
}
}()
if (packet is ServerEventPacket) { if (packet is ServerEventPacket) {
//no need to sync acknowledgement packets //no need to sync acknowledgement packets
@ -205,7 +191,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
} }
loginHandler.onPacketReceived(packet) loginHandler.onPacketReceived(packet)
packetHandlers.forEach { this@TIMBotNetworkHandler.forEach {
it.instance.onPacketReceived(packet) it.instance.onPacketReceived(packet)
} }
} }
@ -223,7 +209,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
try { try {
build.readAvailable(buffer) build.readAvailable(buffer)
channel.send(buffer)//JVM: withContext(IO) channel.send(buffer)//JVM: withContext(IO)
} catch (e: Exception) { } catch (e: SendPacketInternalException) {
bot.logger.logError("Caught SendPacketInternalException: ${e.cause?.message}")
bot.reinitializeNetworkHandler(configuration)
return@withContext
} catch (e: Throwable) {
e.log() e.log()
return@withContext return@withContext
} finally { } finally {
@ -379,7 +369,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
//登录成功后会收到大量上次的消息, 忽略掉 todo 优化 //登录成功后会收到大量上次的消息, 忽略掉 todo 优化
NetworkScope.launch { NetworkScope.launch {
delay(3000) delay(3000)
event.ignoreMessage = false this@TIMBotNetworkHandler[EventPacketHandler].ignoreMessage = false
} }
onLoggedIn(sessionKey) onLoggedIn(sessionKey)

View File

@ -23,6 +23,8 @@ import net.mamoe.mirai.utils.hexToBytes
* @author Him188moe * @author Him188moe
*/ */
class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
companion object Key : PacketHandler.Key<ActionPacketHandler>
private val addFriendSessions = mutableListOf<AddFriendSession>() private val addFriendSessions = mutableListOf<AddFriendSession>()
private val uploadImageSessions = mutableListOf<UploadImageSession>() private val uploadImageSessions = mutableListOf<UploadImageSession>()

View File

@ -24,6 +24,9 @@ import net.mamoe.mirai.utils.MiraiLogger
*/ */
@Suppress("EXPERIMENTAL_API_USAGE") @Suppress("EXPERIMENTAL_API_USAGE")
class EventPacketHandler(session: LoginSession) : PacketHandler(session) { class EventPacketHandler(session: LoginSession) : PacketHandler(session) {
companion object Key : PacketHandler.Key<EventPacketHandler>
internal var ignoreMessage: Boolean = true internal var ignoreMessage: Boolean = true
override suspend fun onPacketReceived(packet: ServerPacket): Unit = with(session) { override suspend fun onPacketReceived(packet: ServerPacket): Unit = with(session) {
@ -57,6 +60,16 @@ class EventPacketHandler(session: LoginSession) : PacketHandler(session) {
//TODO //TODO
} }
is ServerFriendTypingStartedPacket -> {
MiraiLogger.logInfo("${packet.qq.toLong()} 正在输入")
//TODO
}
is ServerFriendTypingCanceledPacket -> {
MiraiLogger.logInfo("${packet.qq.toLong()} 取消了输入")
//TODO
}
else -> { else -> {
//ignored //ignored
} }

View File

@ -12,6 +12,8 @@ abstract class PacketHandler(
) { ) {
abstract suspend fun onPacketReceived(packet: ServerPacket) abstract suspend fun onPacketReceived(packet: ServerPacket)
interface Key<T : PacketHandler>
open fun close() { open fun close() {
} }
@ -19,15 +21,18 @@ abstract class PacketHandler(
class PacketHandlerNode<T : PacketHandler>( class PacketHandlerNode<T : PacketHandler>(
val clazz: KClass<T>, val clazz: KClass<T>,
val instance: T val instance: T,
val key: PacketHandler.Key<T>
) )
fun <T : PacketHandler> T.asNode(): PacketHandlerNode<T> { fun <T : PacketHandler> T.asNode(key: PacketHandler.Key<T>): PacketHandlerNode<T> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return PacketHandlerNode(this::class as KClass<T>, this) return PacketHandlerNode(this::class as KClass<T>, this, key)
} }
class PacketHandlerList : MutableList<PacketHandlerNode<*>> by mutableListOf() { open class PacketHandlerList : MutableList<PacketHandlerNode<*>> by mutableListOf() {
@Suppress("UNCHECKED_CAST")
operator fun <T : PacketHandler> get(key: PacketHandler.Key<T>): T = this.first { it.key === key }.instance as T
operator fun <T : PacketHandler> get(clazz: KClass<T>): T { operator fun <T : PacketHandler> get(clazz: KClass<T>): T {
this.forEach { this.forEach {

View File

@ -14,7 +14,7 @@ data class EventPacketIdentity(
val to: UInt,//对于好友消息, 这个是bot val to: UInt,//对于好友消息, 这个是bot
internal val uniqueId: IoBuffer//8 internal val uniqueId: IoBuffer//8
) { ) {
override fun toString(): String = "EPI(from=$from, to=$to)" override fun toString(): String = "(from=$from, to=$to)"
} }
fun BytePacketBuilder.writeEventPacketIdentity(identity: EventPacketIdentity) = with(identity) { fun BytePacketBuilder.writeEventPacketIdentity(identity: EventPacketIdentity) = with(identity) {
@ -28,11 +28,8 @@ fun BytePacketBuilder.writeEventPacketIdentity(identity: EventPacketIdentity) =
* *
* @author Him188moe * @author Him188moe
*/ */
abstract class ServerEventPacket(input: ByteReadPacket, packetId: ByteArray, val eventIdentity: EventPacketIdentity) : ServerPacket(input) { abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: EventPacketIdentity) : ServerPacket(input) {
override val idByteArray: ByteArray = packetId class Raw(input: ByteReadPacket) : ServerPacket(input) {
override var idHex: String = packetId.toUHexString()
class Raw(input: ByteReadPacket, private val packetId: ByteArray) : ServerPacket(input) {
fun distribute(): ServerEventPacket = with(input) { fun distribute(): ServerEventPacket = with(input) {
val eventIdentity = EventPacketIdentity( val eventIdentity = EventPacketIdentity(
@ -46,25 +43,36 @@ abstract class ServerEventPacket(input: ByteReadPacket, packetId: ByteArray, val
"00 C4" -> { "00 C4" -> {
discardExact(13) discardExact(13)
if (readBoolean()) { if (readBoolean()) {
ServerAndroidOnlineEventPacket(input, packetId, eventIdentity) ServerAndroidOfflineEventPacket(input, eventIdentity)
} else { } else {
ServerAndroidOfflineEventPacket(input, packetId, eventIdentity) ServerAndroidOnlineEventPacket(input, eventIdentity)
} }
} }
"00 2D" -> ServerGroupUploadFileEventPacket(input, packetId, eventIdentity) "00 2D" -> ServerGroupUploadFileEventPacket(input, eventIdentity)
"00 52" -> ServerGroupMessageEventPacket(input, packetId, eventIdentity) "00 52" -> ServerGroupMessageEventPacket(input, eventIdentity)
"00 A6" -> ServerFriendMessageEventPacket(input, packetId, eventIdentity) "00 A6" -> ServerFriendMessageEventPacket(input.debugPrint("好友消息事件"), eventIdentity)
//"02 10", "00 12" -> ServerUnknownEventPacket(input, packetId, eventIdentity)
else -> UnknownServerEventPacket(input, packetId, eventIdentity) //00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 16 00 00 00 37 08 02 1A 12 08 95 02 10 90 04 40 98 E1 8C ED 05 48 AF 96 C3 A4 03 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 1A 29 08 00 10 05 18 98 E1 8C ED 05 20 01 28 FF FF FF FF 0F 32 15 E5 AF B9 E6 96 B9 E6 AD A3 E5 9C A8 E8 BE 93 E5 85 A5 2E 2E 2E
"02 10" -> {
discardExact(19)
if (readUByte().toUInt() == 0x37u) ServerFriendTypingStartedPacket(input, eventIdentity)
else /*0x22*/ ServerFriendTypingCanceledPacket(input, eventIdentity)
}
//"02 10", "00 12" -> ServerUnknownEventPacket(input, eventIdentity)
else -> {
MiraiLogger.logDebug("UnknownEvent type = ${type.toUHexString()}")
UnknownServerEventPacket(input, eventIdentity)
}
}.setId(idHex) }.setId(idHex)
} }
class Encrypted(input: ByteReadPacket, private val packetId: ByteArray) : ServerPacket(input) { class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
fun decrypt(sessionKey: ByteArray): Raw = Raw(this.decryptBy(sessionKey), packetId).setId(this.idHex) fun decrypt(sessionKey: ByteArray): Raw = Raw(this.decryptBy(sessionKey)).setId(this.idHex)
} }
} }
@ -90,26 +98,45 @@ abstract class ServerEventPacket(input: ByteReadPacket, packetId: ByteArray, val
/** /**
* Unknown event * Unknown event
*/ */
class UnknownServerEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) { class UnknownServerEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
override fun decode() { override fun decode() {
println("UnknownServerEventPacket data: " + this.input.readBytes().toUHexString()) MiraiLogger.logDebug("UnknownServerEventPacket data: " + this.input.readBytes().toUHexString())
} }
} }
sealed class ServerFriendTypingPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
val qq get() = eventIdentity.from
}
/**
* 对方正在输入
*/
class ServerFriendTypingStartedPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerFriendTypingPacket(input, eventIdentity)
/**
* 对方取消了输入
*/
class ServerFriendTypingCanceledPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerFriendTypingPacket(input, eventIdentity)
/** /**
* Android 客户端上线 * Android 客户端上线
*/ */
class ServerAndroidOnlineEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) class ServerAndroidOnlineEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
/** /**
* Android 客户端下线 * Android 客户端下线
*/ */
class ServerAndroidOfflineEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) class ServerAndroidOfflineEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
/** /**
* 群文件上传 * 群文件上传
*/ */
class ServerGroupUploadFileEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) { class ServerGroupUploadFileEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
private lateinit var xmlMessage: String private lateinit var xmlMessage: String
override fun decode() { override fun decode() {
@ -121,7 +148,7 @@ class ServerGroupUploadFileEventPacket(input: ByteReadPacket, packetId: ByteArra
} }
@Suppress("EXPERIMENTAL_API_USAGE") @Suppress("EXPERIMENTAL_API_USAGE")
class ServerGroupMessageEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) { class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
var groupNumber: UInt by Delegates.notNull() var groupNumber: UInt by Delegates.notNull()
var qq: UInt by Delegates.notNull() var qq: UInt by Delegates.notNull()
lateinit var senderName: String lateinit var senderName: String
@ -140,10 +167,11 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, packetId: ByteArray,
val map = readTLVMap(true) val map = readTLVMap(true)
map.printTLVMap("父map") map.printTLVMap("父map")
if (map.containsKey(0x18)) { if (map.containsKey(18)) {
senderName = map.getValue(0x18).read { senderName = map.getValue(18).read {
val tlv = readTLVMap(true) val tlv = readTLVMap(true)
tlv.printTLVMap("子map") tlv.printTLVMap("子map")
//群主的18: 05 00 04 00 00 00 03 08 00 04 00 00 00 04 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08
when { when {
tlv.containsKey(0x01) -> String(tlv.getValue(0x01)) tlv.containsKey(0x01) -> String(tlv.getValue(0x01))
@ -155,28 +183,48 @@ class ServerGroupMessageEventPacket(input: ByteReadPacket, packetId: ByteArray,
} }
} }
//牛逼[图片]牛逼[图片] 22 96 29 7B B4 DF 94 AA 00 08 74 A4 09 18 8D CC 1F 40 00 52 00 00 00 1B 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00 01 01 22 96 29 7B 01 3E 03 3F A2 00 03 7F 64 5D 7B AC BD 00 00 F3 36 02 03 00 02 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 7B AC BD 12 73 DB A2 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 CB 02 00 2A 7B 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 04 00 04 B4 52 77 F1 05 00 04 BC EB 03 B7 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 00 41 16 00 04 00 00 00 34 18 00 04 00 00 03 73 FF 00 5C 15 36 20 39 32 6B 41 31 43 62 34 35 32 37 37 66 31 62 63 65 62 30 33 62 37 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 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 41 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 77 02 00 2A 7B 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 04 00 04 B4 52 77 F1 05 00 04 BC EB 03 B7 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 00 41 16 00 04 00 00 00 34 18 00 04 00 00 03 73 FF 00 08 15 37 20 20 38 41 41 41 0E 00 0E 01 00 04 00 00 00 09 07 00 04 00 00 00 01 19 00 35 01 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 08 09 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 05 00 04 00 00 00 01 08 00 04 00 00 00 01 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 //
//牛逼[图片]牛逼 22 96 29 7B B4 DF 94 AA 00 0B C1 0A 09 18 89 93 1F 40 00 52 00 00 00 1B 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00 01 01 22 96 29 7B 01 3E 03 3F A2 00 03 7E F5 5D 7B 97 E7 00 00 F3 32 01 8D 00 02 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 7B 97 E6 FA BE 7F DC 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 CF 02 00 2A 7B 39 44 32 44 45 39 31 41 2D 33 39 38 39 2D 39 35 35 43 2D 44 35 42 34 2D 37 46 41 32 37 38 39 37 38 36 30 39 7D 2E 6A 70 67 04 00 04 97 15 7F 03 05 00 04 79 5C B1 A3 06 00 04 00 00 00 50 07 00 01 41 08 00 00 09 00 01 01 0B 00 00 14 00 04 03 00 00 00 15 00 04 00 00 00 3C 16 00 04 00 00 00 40 18 00 04 00 00 03 CC FF 00 60 15 36 20 39 36 6B 45 31 41 39 37 31 35 37 66 30 33 37 39 35 63 62 31 61 33 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 39 44 32 44 45 39 31 41 2D 33 39 38 39 2D 39 35 35 43 2D 44 35 42 34 2D 37 46 41 32 37 38 39 37 38 36 30 39 7D 2E 6A 70 67 31 32 31 32 41 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 0E 01 00 04 00 00 00 09 07 00 04 00 00 00 01 19 00 35 01 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 08 09 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 05 00 04 00 00 00 01 08 00 04 00 00 00 01 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 //以前的消息: 00 00 00 25 00 08 00 02 00 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD 58 2C 60 86 35 3A 30 B3 C7 63 4A 80 E7 CD 5B 64 00 0B 78 16 5D A3 0A FD 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A3 0A FD AB 77 16 02 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 04 01 00 01 36 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00
//刚刚的消息: 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD 11 F4 B2 F2 1A E7 1F C4 F1 3F 23 FB 74 80 42 64 00 0B 78 1A 5D A3 26 C1 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A3 26 C1 AA 34 08 42 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00
class ServerFriendMessageEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) { fun main() {
val group: UInt get() = eventIdentity.from println("08 02 1A 12 08 95 02 10 90 04 40 D6 DE 8C ED 05 48 CF B5 90 D6 02 08 DD F1 92 B7 07 10 DD F1 92 B7 07 1A 14 08 00 10 05 18 D6 DE 8C ED 05 20 02 28 FF FF FF FF 0F 32 00".hexToBytes().stringOf())
val qq: UInt get() = eventIdentity.to }
fun main2() {
val data = "00 00 00 20 00 05 00 02 00 06 00 06 00 04 00 01 01 07 00 09 00 06 03 E9 20 02 EB 94 00 0A 00 04 01 00 00 00 0C 17 76 E4 B8 DD 76 E4 B8 DD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B A6 D2 5D A3 2A 3F 00 00 5D A3 2A 3F 01 00 00 00 00 4D 53 47 00 00 00 00 00 5D A3 2A 3F 0C 8A 59 3D 00 00 00 00 0A 00 86 02 00 06 E5 AE 8B E4 BD 93 00 00 01 00 06 01 00 03 31 32 33 19 00 1F 01 00 1C AA 02 19 08 00 88 01 00 9A 01 11 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 0E 00 0E 01 00 04 00 00 00 00 0A 00 04 00 00 00 00".hexToBytes()
val packet = ServerFriendMessageEventPacket(data.toReadPacket(), EventPacketIdentity(0u, 0u, IoBuffer.Empty))
packet.decode()
println(packet)
}
class ServerFriendMessageEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
val qq: UInt get() = eventIdentity.from
/**
* 是否是在这次登录之前的消息, 即消息记录
*/
var isPrevious: Boolean = false
lateinit var message: MessageChain lateinit var message: MessageChain
//00 00 00 25 00 08 00 02 00 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD E7 86 74 F2 64 55 AD 9A EB 2F B9 DF F1 7F 8C 28 00 0B 78 14 5D A2 F5 CB 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A2 F5 CA 9D 26 CB 5E 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 //来自自己发送给自己
//00 00 00 20 00 05 00 02 00 06 00 06 00 04 00 01 01 07 00 09 00 06 03 E9 20 02 EB 94 00 0A 00 04 01 00 00 00 0C 17 76 E4 B8 DD 76 E4 B8 DD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B A6 D2 5D A3 2A 3F 00 00 5D A3 2A 3F 01 00 00 00 00 4D 53 47 00 00 00 00 00 5D A3 2A 3F 0C 8A 59 3D 00 00 00 00 0A 00 86 02 00 06 E5 AE 8B E4 BD 93 00 00 01 00 06 01 00 03 31 32 33 19 00 1F 01 00 1C AA 02 19 08 00 88 01 00 9A 01 11 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 0E 00 0E 01 00 04 00 00 00 00 0A 00 04 00 00 00 00
override fun decode() = with(input) { override fun decode() = with(input) {
input.discardExact(2) input.discardExact(2)
val l1 = readShort() val l1 = readShort()
discardExact(l1.toInt()) discardExact(1)//0x00
isPrevious = readByte().toInt() == 0x08
discardExact(l1.toInt() - 2)
discardExact(69) discardExact(69)
readLVByteArray()//font readLVByteArray()//font
discardExact(2)//2个0x00 discardExact(2)//2个0x00
message = readMessageChain() message = readMessageChain()
val map: Map<Int, ByteArray> = readTLVMap(true).withDefault { byteArrayOf() } val map: Map<Int, ByteArray> = readTLVMap(true).withDefault { byteArrayOf() }
println("map.getValue(18)=" + map.getValue(18)) map.printTLVMap("readTLVMap")
//println("map.getValue(18)=" + map.getValue(18).toUHexString())
//19 00 38 01 00 35 AA 02 32 50 03 60 00 68 00 9A 01 29 08 09 20 BF 02 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 05 00 04 00 00 00 01 08 00 04 00 00 00 01 //19 00 38 01 00 35 AA 02 32 50 03 60 00 68 00 9A 01 29 08 09 20 BF 02 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 05 00 04 00 00 00 01 08 00 04 00 00 00 01
@ -232,7 +280,7 @@ B1 89 BE 09 8F 00 1A E5 00 0B 03 A2 09 90 BB 7A 1F 40 00 A6 00 00 00 20 00 05 00
backup backup
class ServerFriendMessageEventPacket(input: ByteReadPacket, packetId: ByteArray, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, packetId, eventIdentity) { class ServerFriendMessageEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
var qq: Long = 0 var qq: Long = 0
lateinit var event: String lateinit var event: String

View File

@ -18,12 +18,12 @@ class ClientSendFriendMessagePacket(
private val message: MessageChain private val message: MessageChain
) : ClientPacket() { ) : ClientPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) { override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeRandom(2) writeRandom(2)
this.writeQQ(botQQ) writeQQ(botQQ)
this.writeHex(TIMProtocol.fixVer2) writeHex(TIMProtocol.fixVer2)
this.encryptAndWrite(sessionKey) { encryptAndWrite(sessionKey) {
writeQQ(botQQ) writeQQ(botQQ)
writeQQ(targetQQ) writeQQ(targetQQ)
writeHex("00 00 00 08 00 01 00 04 00 00 00 00") writeHex("00 00 00 08 00 01 00 04 00 00 00 00")

View File

@ -86,7 +86,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {//TODO 优化
"00 BA" -> ServerCaptchaPacket.Encrypted(this, idHex) "00 BA" -> ServerCaptchaPacket.Encrypted(this, idHex)
"00 CE", "00 17" -> ServerEventPacket.Raw.Encrypted(this, idHex.hexToBytes()) "00 CE", "00 17" -> ServerEventPacket.Raw.Encrypted(this)
"00 81" -> ServerFieldOnlineStatusChangedPacket.Encrypted(this) "00 81" -> ServerFieldOnlineStatusChangedPacket.Encrypted(this)
@ -102,7 +102,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {//TODO 优化
}.setId(idHex) }.setId(idHex)
} }
fun ByteReadPacket.readIP(): String = buildString(4 + 3) { fun Input.readIP(): String = buildString(4 + 3) {
repeat(4) { repeat(4) {
val byte = readUByte() val byte = readUByte()
this.append(byte.toString()) this.append(byte.toString())
@ -110,11 +110,11 @@ fun ByteReadPacket.readIP(): String = buildString(4 + 3) {
} }
} }
fun ByteReadPacket.readLVString(): String = String(this.readLVByteArray()) fun Input.readLVString(): String = String(this.readLVByteArray())
fun ByteReadPacket.readLVByteArray(): ByteArray = this.readBytes(this.readShort().toInt()) fun Input.readLVByteArray(): ByteArray = this.readBytes(this.readShort().toInt())
fun ByteReadPacket.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray> { fun Input.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray> {
val map = mutableMapOf<Int, ByteArray>() val map = mutableMapOf<Int, ByteArray>()
var type: UByte var type: UByte
@ -144,11 +144,11 @@ fun ByteReadPacket.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray
fun Map<Int, ByteArray>.printTLVMap(name: String) = debugPrintln("TLVMap $name= " + this.mapValues { (_, value) -> value.toUHexString() }) fun Map<Int, ByteArray>.printTLVMap(name: String) = debugPrintln("TLVMap $name= " + this.mapValues { (_, value) -> value.toUHexString() })
fun ByteReadPacket.readString(length: Number): String = String(this.readBytes(length.toInt())) fun Input.readString(length: Number): String = String(this.readBytes(length.toInt()))
private const val TRUE_BYTE_VALUE: Byte = 1 private const val TRUE_BYTE_VALUE: Byte = 1
fun ByteReadPacket.readBoolean(): Boolean = this.readByte() == TRUE_BYTE_VALUE fun Input.readBoolean(): Boolean = this.readByte() == TRUE_BYTE_VALUE
fun ByteReadPacket.readLVNumber(): Number { fun Input.readLVNumber(): Number {
return when (this.readShort().toInt()) { return when (this.readShort().toInt()) {
1 -> this.readByte() 1 -> this.readByte()
2 -> this.readShort() 2 -> this.readShort()
@ -161,7 +161,7 @@ fun ByteReadPacket.readLVNumber(): Number {
//添加@JvmSynthetic 导致 idea 无法检查这个文件的错误 //添加@JvmSynthetic 导致 idea 无法检查这个文件的错误
//@JvmSynthetic //@JvmSynthetic
@Deprecated("Low efficiency", ReplaceWith("")) @Deprecated("Low efficiency", ReplaceWith(""))
fun ByteReadPacket.gotoWhere(matcher: UByteArray): ByteReadPacket { fun <I : Input> I.gotoWhere(matcher: UByteArray): I {
return this.gotoWhere(matcher.toByteArray()) return this.gotoWhere(matcher.toByteArray())
} }
@ -169,7 +169,7 @@ fun ByteReadPacket.gotoWhere(matcher: UByteArray): ByteReadPacket {
* 去往下一个含这些连续字节的位置 * 去往下一个含这些连续字节的位置
*/ */
@Deprecated("Low efficiency", ReplaceWith("")) @Deprecated("Low efficiency", ReplaceWith(""))
fun ByteReadPacket.gotoWhere(matcher: ByteArray): ByteReadPacket { fun <I : Input> I.gotoWhere(matcher: ByteArray): I {
require(matcher.isNotEmpty()) require(matcher.isNotEmpty())
loop@ loop@

View File

@ -1,5 +1,6 @@
package net.mamoe.mirai.utils package net.mamoe.mirai.utils
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input import kotlinx.io.core.Input
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
@ -9,20 +10,26 @@ internal object DebugLogger : MiraiLogger by PlatformLogger("Packet Debug")
internal fun debugPrintln(any: Any?) = DebugLogger.logPurple(any) internal fun debugPrintln(any: Any?) = DebugLogger.logPurple(any)
@Deprecated("Debugging Warning", ReplaceWith(""))
internal fun ByteArray.debugPrint(name: String): ByteArray { internal fun ByteArray.debugPrint(name: String): ByteArray {
DebugLogger.logPurple(name + "=" + this.toUHexString()) DebugLogger.logPurple(name + "=" + this.toUHexString())
return this return this
} }
@Deprecated("Debugging Warning", ReplaceWith("")) @Deprecated("Low Efficiency", ReplaceWith(""))
internal fun IoBuffer.debugPrint(name: String): IoBuffer { internal fun IoBuffer.debugPrint(name: String): IoBuffer {
val readBytes = this.readBytes() val readBytes = this.readBytes()
DebugLogger.logPurple(name + "=" + readBytes.toUHexString()) DebugLogger.logPurple(name + "=" + readBytes.toUHexString())
return readBytes.toIoBuffer() return readBytes.toIoBuffer()
} }
@Deprecated("Debugging Warning", ReplaceWith("")) @Deprecated("Low Efficiency", ReplaceWith("discardExact(n)"))
internal fun Input.debugDiscardExact(n: Number, name: String = "") { internal fun Input.debugDiscardExact(n: Number, name: String = "") {
DebugLogger.logPurple("Discarded($n) $name=" + this.readBytes(n.toInt()).toUHexString()) DebugLogger.logPurple("Discarded($n) $name=" + this.readBytes(n.toInt()).toUHexString())
} }
@Deprecated("Low Efficiency", ReplaceWith(""))
internal fun ByteReadPacket.debugPrint(name: String = ""): ByteReadPacket {
val bytes = this.readBytes()
DebugLogger.logPurple("ByteReadPacket $name=" + bytes.toUHexString())
return bytes.toReadPacket()
}

View File

@ -11,4 +11,6 @@ expect class MiraiDatagramChannel(serverHost: String, serverPort: Short) : Close
val isOpen: Boolean val isOpen: Boolean
} }
expect class ClosedChannelException : IOException expect class ClosedChannelException : IOException
expect class SendPacketInternalException(cause: Throwable?) : Exception

View File

@ -14,7 +14,15 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP
private val channel: DatagramChannel = DatagramChannel.open().connect(serverAddress) private val channel: DatagramChannel = DatagramChannel.open().connect(serverAddress)
actual suspend fun read(buffer: IoBuffer) = withContext(Dispatchers.IO) { (channel as ReadableByteChannel).read(buffer) } actual suspend fun read(buffer: IoBuffer) = withContext(Dispatchers.IO) { (channel as ReadableByteChannel).read(buffer) }
actual suspend fun send(buffer: IoBuffer) = withContext(Dispatchers.IO) { buffer.readDirect { channel.send(it, serverAddress) } } actual suspend fun send(buffer: IoBuffer) = withContext(Dispatchers.IO) {
buffer.readDirect {
try {
channel.send(it, serverAddress)
} catch (e: Exception) {
throw SendPacketInternalException(e)
}
}
}
override fun close() { override fun close() {
channel.close() channel.close()
@ -23,4 +31,6 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP
actual val isOpen: Boolean get() = channel.isOpen actual val isOpen: Boolean get() = channel.isOpen
} }
actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException
actual class SendPacketInternalException actual constructor(cause: Throwable?) : Exception(cause)

View File

@ -20,14 +20,10 @@ import kotlin.math.max
object HexComparator { object HexComparator {
private val RED = "\u001b[31m" private val RED = "\u001b[31m"
private val GREEN = "\u001b[33m" private val GREEN = "\u001b[33m"
private val UNKNOWN = "\u001b[30m" private val UNKNOWN = "\u001b[30m"
private val BLUE = "\u001b[34m" private val BLUE = "\u001b[34m"
private val clipboardString: String? private val clipboardString: String?
get() { get() {
val trans = Toolkit.getDefaultToolkit().systemClipboard.getContents(null) val trans = Toolkit.getDefaultToolkit().systemClipboard.getContents(null)
@ -44,7 +40,6 @@ object HexComparator {
} }
class ConstMatcher constructor(hex: String) { class ConstMatcher constructor(hex: String) {
private val matches = LinkedList<Match>() private val matches = LinkedList<Match>()
object TestConsts { object TestConsts {
@ -59,6 +54,7 @@ object HexComparator {
val _Him188moe_ = "Him188moe".toByteArray().toUHexString() val _Him188moe_ = "Him188moe".toByteArray().toUHexString()
val 发图片 = "发图片".toByteArray().toUHexString() val 发图片 = "发图片".toByteArray().toUHexString()
val = "".toByteArray().toUHexString() val = "".toByteArray().toUHexString()
val 你好 = "你好".toByteArray().toUHexString()
val SINGLE_PLAIN_MESSAGE_HEAD = "00 00 01 00 09 01" val SINGLE_PLAIN_MESSAGE_HEAD = "00 00 01 00 09 01"
@ -69,7 +65,8 @@ object HexComparator {
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
object PacketIds { object PacketIds {
val heartbeat = "00 58" val heartbeat = "00 58"
val friendmsg = "00 CD" val friendmsgsend = "00 CD"
val friendmsgevent = "00 CE"
} }
init { init {
@ -104,7 +101,6 @@ object HexComparator {
} }
} }
private fun match(hex: String, field: Field): List<IntRange> { private fun match(hex: String, field: Field): List<IntRange> {
val constValue: String val constValue: String
try { try {
@ -293,6 +289,10 @@ object HexComparator {
} }
fun main() { fun main() {
// println(HexComparator.colorize("00 00 00 25 00 08 00 02 00 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD E7 86 74 F2 64 55 AD 9A EB 2F B9 DF F1 7F 8C 28 00 0B 78 14 5D A2 F5 CB 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A2 F5 CA 9D 26 CB 5E 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00"))
val scanner = Scanner(System.`in`) val scanner = Scanner(System.`in`)
while (true) { while (true) {
println("Hex1: ") println("Hex1: ")