mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-09 19:50:27 +08:00
Name and permission analyzing is now available
This commit is contained in:
parent
7e90737c68
commit
d5587bb3d8
@ -5,12 +5,20 @@ import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.message.Message
|
||||
import net.mamoe.mirai.message.MessageChain
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.SenderPermission
|
||||
|
||||
|
||||
abstract class GroupEvent(bot: Bot, val group: Group) : BotEvent(bot)
|
||||
|
||||
|
||||
class GroupMessageEvent(bot: Bot, group: Group, val sender: QQ, val message: MessageChain) : GroupEvent(bot, group) {
|
||||
class GroupMessageEvent(
|
||||
bot: Bot,
|
||||
group: Group,
|
||||
val sender: QQ,
|
||||
val message: MessageChain,
|
||||
val senderPermission: SenderPermission,
|
||||
val senderName: String//若他有群名片就是群名片, 没有就是昵称
|
||||
) : GroupEvent(bot, group) {
|
||||
suspend inline fun reply(message: Message) = group.sendMessage(message)
|
||||
|
||||
suspend inline fun reply(message: String) = group.sendMessage(message)
|
||||
|
@ -29,30 +29,31 @@ internal fun IoBuffer.parseMessageImage0x06(): Image {
|
||||
//MiraiLogger.logDebug(this.toUHexString())
|
||||
val filenameLength = readShort()
|
||||
val suffix = readString(filenameLength).substringAfter(".")
|
||||
discardExact(this.readRemaining - 37 - 1 - filenameLength - 2 - 8 - 4)
|
||||
val imageId = readString(36)
|
||||
MiraiLogger.logDebug("imageId=$imageId")//todo ID似乎错了??
|
||||
discardExact(1)//0x41
|
||||
return Image("{$imageId}.$suffix")
|
||||
discardExact(8)//03 00 04 00 00 02 9C 04
|
||||
val length = readShort()//27
|
||||
discardExact(1)
|
||||
return Image("{${readString(length - 2/*去掉首尾各一个*/)}}.$suffix")
|
||||
}
|
||||
}
|
||||
|
||||
//00 1B filenameLength
|
||||
// 43 37 46 29 5F 34 32 34 4E 33 55 37 7B 4C 47 36 7D 4F 25 5A 51 58 51 2E 6A 70 67 get suffix
|
||||
// 03 00 04 00 00 02 9C 04
|
||||
// 00 25 2F 32 65 37 61 65 33 36 66 2D 61 39 31 63 2D 34 31 32 39 2D 62 61 34 32 2D 37 65 30 31 32 39 37 37 35 63 63 38 14
|
||||
// 00 04 03 00 00 00 18
|
||||
// 00 25 2F 32 65 37 61 65 33 36 66 2D 61 39 31 63 2D 34 31 32 39 2D 62 61 34 32 2D 37 65 30 31 32 39 37 37 35 63 63 38 19
|
||||
// 00 04 00 00 00 2E 1A 00 04 00 00 00 2E FF
|
||||
// 00 63 16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 20 36 36 38 65 35 43 36 38 45 36 42 44 32 46 35 38 34 31 42 30 39 37 39 45 37 46 32 35 34 33 38 38 31 33 43 33 2E 6A 70 67 66 2F 32 65 37 61 65 33 36 66 2D 61 39 31 63 2D 34 31 32 39 2D 62 61 34 32 2D 37 65 30 31 32 39 37 37 35 63 63 38 41
|
||||
|
||||
fun main() {
|
||||
println("f/".toByteArray().toUHexString())
|
||||
println("16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 20 36 36 38 65 35 43 36 38 45 36 42 44 32 46 35 38 34 31 42 30 39 37 39 45 37 46 32 35 34 33 38 38 31 33 43 33 2E 6A 70 67 66 2F 32 65 37 61 65 33 36 66 2D 61 39 31 63 2D 34 31 32 39 2D 62 61 34 32 2D 37 65 30 31 32 39 37 37 35 63 63 38 41"
|
||||
.hexToBytes().stringOf())
|
||||
}
|
||||
|
||||
internal fun IoBuffer.parseMessageImage0x03(): Image {
|
||||
discardExact(1)
|
||||
return Image(String(readLVByteArray()))
|
||||
/*
|
||||
println(String(readLVByteArray()))
|
||||
readTLVMap()
|
||||
return Image(String(readLVByteArray().cutTail(5).getRight(42)))
|
||||
/
|
||||
discardExact(data.size - 47)
|
||||
val imageId = String(readBytes(42))
|
||||
discardExact(1)//0x41
|
||||
discardExact(1)//0x42
|
||||
discardExact(1)//0x43
|
||||
discardExact(1)//0x41
|
||||
|
||||
return Image(imageId)*/
|
||||
}
|
||||
|
||||
internal fun ByteReadPacket.parseMessageChain(): MessageChain {
|
||||
@ -63,50 +64,56 @@ internal fun ByteReadPacket.readMessage(): Message? {
|
||||
val messageType = this.readByte().toInt()
|
||||
val sectionLength = this.readShort().toLong()//sectionLength: short
|
||||
val sectionData = this.readIoBuffer(sectionLength.toInt())//use buffer instead
|
||||
return when (messageType) {
|
||||
0x01 -> sectionData.parsePlainText()
|
||||
0x02 -> sectionData.parseMessageFace()
|
||||
0x03 -> sectionData.parseMessageImage0x03()
|
||||
0x06 -> sectionData.parseMessageImage0x06()
|
||||
|
||||
return try {
|
||||
when (messageType) {
|
||||
0x01 -> sectionData.parsePlainText()
|
||||
0x02 -> sectionData.parseMessageFace()
|
||||
0x03 -> sectionData.parseMessageImage0x03()
|
||||
0x06 -> sectionData.parseMessageImage0x06()
|
||||
|
||||
|
||||
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
|
||||
// 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
|
||||
return null
|
||||
sectionData.readBytes().debugPrint("sectionData")
|
||||
return PlainText("[UNKNOWN(${this.readBytes().toUHexString()})]")
|
||||
println()
|
||||
val value = readLVByteArray()
|
||||
//todo 未知压缩算法
|
||||
PlainText(String(value))
|
||||
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
|
||||
// 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
|
||||
return null
|
||||
sectionData.readBytes().debugPrint("sectionData")
|
||||
return PlainText("[UNKNOWN(${this.readBytes().toUHexString()})]")
|
||||
println()
|
||||
val value = readLVByteArray()
|
||||
//todo 未知压缩算法
|
||||
PlainText(String(value))
|
||||
|
||||
// PlainText(String(GZip.uncompress( value)))
|
||||
}
|
||||
|
||||
|
||||
0x14 -> {//长文本
|
||||
val value = readLVByteArray()
|
||||
println(value.size)
|
||||
println(value.toUHexString())
|
||||
//todo 未知压缩算法
|
||||
this.discardExact(7)//几个TLV
|
||||
return PlainText(String(value))
|
||||
}
|
||||
|
||||
0x0E -> {
|
||||
null
|
||||
}
|
||||
|
||||
else -> {
|
||||
println("未知的messageType=0x${messageType.toByte().toUHexString()}")
|
||||
println("后文=${this.readBytes().toUHexString()}")
|
||||
null
|
||||
// PlainText(String(GZip.uncompress( value)))
|
||||
}
|
||||
|
||||
|
||||
0x14 -> {//长文本
|
||||
|
||||
//是否要用 sectionData.read?
|
||||
val value = readLVByteArray()
|
||||
println(value.size)
|
||||
println(value.toUHexString())
|
||||
//todo 未知压缩算法
|
||||
this.discardExact(7)//几个TLV
|
||||
return PlainText(String(value))
|
||||
}
|
||||
|
||||
0x0E -> {
|
||||
null
|
||||
}
|
||||
|
||||
else -> {
|
||||
println("未知的messageType=0x${messageType.toByte().toUHexString()}")
|
||||
println("后文=${this.readBytes().toUHexString()}")
|
||||
null
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
sectionData.release(IoBuffer.Pool)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun ByteReadPacket.readMessageChain(): MessageChain {
|
||||
|
@ -10,7 +10,9 @@ import net.mamoe.mirai.getQQ
|
||||
import net.mamoe.mirai.message.MessageChain
|
||||
import net.mamoe.mirai.network.BotSession
|
||||
import net.mamoe.mirai.network.distributePacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.*
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.IgnoredServerEventPacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerFriendOnlineStatusChangedPacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.action.ClientSendFriendMessagePacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.action.ClientSendGroupMessagePacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.action.ServerSendFriendMessageResponsePacket
|
||||
@ -41,7 +43,14 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
|
||||
is ServerGroupMessageEventPacket -> {
|
||||
if (packet.qq.toLong() == bot.account.account) return
|
||||
|
||||
GroupMessageEvent(bot, bot.getGroupByNumber(packet.groupNumber), bot.getQQ(packet.qq), packet.message).broadcast()
|
||||
GroupMessageEvent(
|
||||
bot,
|
||||
group = bot.getGroupByNumber(packet.groupNumber),
|
||||
sender = bot.getQQ(packet.qq),
|
||||
message = packet.message,
|
||||
senderName = packet.senderName,
|
||||
senderPermission = packet.senderPermission
|
||||
).broadcast()
|
||||
}
|
||||
|
||||
is ServerSendFriendMessageResponsePacket,
|
||||
@ -49,8 +58,8 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
|
||||
//ignored
|
||||
}
|
||||
|
||||
is ServerFieldOnlineStatusChangedPacket.Encrypted -> distributePacket(packet.decrypt(sessionKey))
|
||||
is ServerFieldOnlineStatusChangedPacket -> {
|
||||
is ServerFriendOnlineStatusChangedPacket.Encrypted -> distributePacket(packet.decrypt(sessionKey))
|
||||
is ServerFriendOnlineStatusChangedPacket -> {
|
||||
MiraiLogger.logInfo("${packet.qq.toLong()} 登录状态改变为 ${packet.status}")
|
||||
//TODO
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import kotlin.properties.Delegates
|
||||
* 好友在线状态改变
|
||||
*/
|
||||
@PacketId(0x00_81u)
|
||||
class ServerFieldOnlineStatusChangedPacket(input: ByteReadPacket) : ServerPacket(input) {
|
||||
class ServerFriendOnlineStatusChangedPacket(input: ByteReadPacket) : ServerPacket(input) {
|
||||
var qq: UInt by Delegates.notNull()
|
||||
lateinit var status: OnlineStatus
|
||||
|
||||
@ -28,6 +28,6 @@ class ServerFieldOnlineStatusChangedPacket(input: ByteReadPacket) : ServerPacket
|
||||
|
||||
@PacketId(0x00_81u)
|
||||
class Encrypted(input: ByteReadPacket) : ServerPacket(input) {
|
||||
fun decrypt(sessionKey: ByteArray): ServerFieldOnlineStatusChangedPacket = ServerFieldOnlineStatusChangedPacket(this.decryptBy(sessionKey)).applySequence(sequenceId)
|
||||
fun decrypt(sessionKey: ByteArray): ServerFriendOnlineStatusChangedPacket = ServerFriendOnlineStatusChangedPacket(this.decryptBy(sessionKey)).applySequence(sequenceId)
|
||||
}
|
||||
}
|
@ -1,325 +0,0 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
package net.mamoe.mirai.network.protocol.tim.packet
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.message.MessageChain
|
||||
import net.mamoe.mirai.message.internal.readMessageChain
|
||||
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
* 事件的识别 ID. 在 [事件确认包][ServerEventPacket.ResponsePacket] 中被使用.
|
||||
*/
|
||||
data class EventPacketIdentity(
|
||||
val from: UInt,//对于好友消息, 这个是发送人
|
||||
val to: UInt,//对于好友消息, 这个是bot
|
||||
internal val uniqueId: IoBuffer//8
|
||||
) {
|
||||
override fun toString(): String = "(from=$from, to=$to)"
|
||||
}
|
||||
|
||||
fun BytePacketBuilder.writeEventPacketIdentity(identity: EventPacketIdentity) = with(identity) {
|
||||
writeUInt(from)
|
||||
writeUInt(to)
|
||||
writeFully(uniqueId)
|
||||
}
|
||||
|
||||
fun <S : ServerEventPacket> S.applyId(id: UShort): S {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet id: `00 CE` or `00 17`
|
||||
*
|
||||
* @author Him188moe
|
||||
*/
|
||||
abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: EventPacketIdentity) : ServerPacket(input) {
|
||||
override var id: UShort = 0u
|
||||
|
||||
class Raw(input: ByteReadPacket, override val id: UShort) : ServerPacket(input) {
|
||||
fun distribute(): ServerEventPacket = with(input) {
|
||||
val eventIdentity = EventPacketIdentity(
|
||||
from = readUInt(),
|
||||
to = readUInt(),
|
||||
uniqueId = readIoBuffer(8)
|
||||
)
|
||||
discardExact(2)
|
||||
val type = readBytes(2)
|
||||
//DebugLogger.logPurple("unknown2Byte+byte = ${unknown2Byte.toUHexString()} ${type.toUHexString()}")
|
||||
return when (type.toUHexString()) {
|
||||
"00 C4" -> {
|
||||
discardExact(13)
|
||||
if (readBoolean()) {
|
||||
ServerAndroidOfflineEventPacket(input, eventIdentity)
|
||||
} else {
|
||||
ServerAndroidOnlineEventPacket(input, eventIdentity)
|
||||
}
|
||||
}
|
||||
"00 2D" -> ServerGroupUploadFileEventPacket(input, eventIdentity)
|
||||
|
||||
"00 52" -> ServerGroupMessageEventPacket(input, eventIdentity)
|
||||
|
||||
"00 A6" -> ServerFriendMessageEventPacket(input.debugPrint("好友消息事件"), 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
|
||||
//00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 07 00 00 00
|
||||
"02 10" -> {
|
||||
discardExact(19)
|
||||
println(readUByte().toUInt())
|
||||
|
||||
//todo 错了. 可能是 00 79 才是.
|
||||
ServerFriendTypingCanceledPacket(input, eventIdentity)
|
||||
/*
|
||||
if (readUByte().toUInt() == 0x37u) ServerFriendTypingStartedPacket(input, eventIdentity)
|
||||
else /*0x22*/ ServerFriendTypingCanceledPacket(input, eventIdentity)*/
|
||||
}
|
||||
"00 79" -> IgnoredServerEventPacket(type, input, eventIdentity)
|
||||
|
||||
//"02 10", "00 12" -> ServerUnknownEventPacket(input, eventIdentity)
|
||||
|
||||
else -> {
|
||||
MiraiLogger.logDebug("UnknownEvent type = ${type.toUHexString()}")
|
||||
UnknownServerEventPacket(input, eventIdentity)
|
||||
}
|
||||
}.applyId(id).applySequence(sequenceId)
|
||||
}
|
||||
|
||||
class Encrypted(input: ByteReadPacket, override var id: UShort, override var sequenceId: UShort) : ServerPacket(input) {
|
||||
fun decrypt(sessionKey: ByteArray): Raw = Raw(this.decryptBy(sessionKey), id).applySequence(sequenceId)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ResponsePacket(
|
||||
val bot: Long,
|
||||
val sessionKey: ByteArray
|
||||
) : ClientPacket() {
|
||||
override val id: UShort get() = this@ServerEventPacket.id
|
||||
override val sequenceId: UShort get() = this@ServerEventPacket.sequenceId
|
||||
|
||||
override fun encode(builder: BytePacketBuilder) = with(builder) {
|
||||
this.writeQQ(bot)
|
||||
this.writeHex(TIMProtocol.fixVer2)
|
||||
this.encryptAndWrite(sessionKey) {
|
||||
writeEventPacketIdentity(eventIdentity)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略的事件.
|
||||
* 如 00 79: 总是与 01 12 一起发生, 但 00 79 却没多大意义
|
||||
*/
|
||||
class IgnoredServerEventPacket(val eventId: ByteArray/*2*/, input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
|
||||
|
||||
/**
|
||||
* Unknown event
|
||||
*/
|
||||
class UnknownServerEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
override fun decode() {
|
||||
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 客户端上线
|
||||
*/
|
||||
class ServerAndroidOnlineEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
|
||||
|
||||
/**
|
||||
* Android 客户端下线
|
||||
*/
|
||||
class ServerAndroidOfflineEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
|
||||
|
||||
|
||||
/**
|
||||
* 群文件上传
|
||||
*/
|
||||
class ServerGroupUploadFileEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
private lateinit var xmlMessage: String
|
||||
|
||||
override fun decode() {
|
||||
this.input.discardExact(60)
|
||||
val size = this.input.readShort().toInt()
|
||||
this.input.discardExact(3)
|
||||
xmlMessage = this.input.readString(size)
|
||||
}//todo test
|
||||
}
|
||||
|
||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||
class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
var groupNumber: UInt by Delegates.notNull()
|
||||
var qq: UInt by Delegates.notNull()
|
||||
lateinit var senderName: String
|
||||
lateinit var message: MessageChain
|
||||
|
||||
override fun decode() = with(input) {
|
||||
discardExact(31)
|
||||
groupNumber = readUInt()
|
||||
discardExact(1)
|
||||
qq = readUInt()
|
||||
|
||||
discardExact(48)
|
||||
readLVByteArray()
|
||||
discardExact(2)//2个0x00
|
||||
message = readMessageChain()
|
||||
|
||||
val map = readTLVMap(true)
|
||||
map.printTLVMap("父map")
|
||||
if (map.containsKey(18)) {
|
||||
senderName = map.getValue(18).read {
|
||||
val tlv = readTLVMap(true)
|
||||
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
|
||||
//群主的 子map= {5=00 00 00 03, 8=00 00 00 04, 1=48 69 6D 31 38 38 6D 6F 65, 3=04, 4=00 00 00 08}
|
||||
when {
|
||||
tlv.containsKey(0x01) -> String(tlv.getValue(0x01))
|
||||
tlv.containsKey(0x02) -> String(tlv.getValue(0x02))
|
||||
else -> "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//以前的消息: 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
|
||||
|
||||
fun main() {
|
||||
println("01 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 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 C0 03 00 D0 03 00 E8 03 00".hexToBytes().stringOf())
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
//来自自己发送给自己
|
||||
//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) {
|
||||
input.discardExact(2)
|
||||
val l1 = readShort()
|
||||
discardExact(1)//0x00
|
||||
isPrevious = readByte().toInt() == 0x08
|
||||
discardExact(l1.toInt() - 2)
|
||||
discardExact(69)
|
||||
readLVByteArray()//font
|
||||
discardExact(2)//2个0x00
|
||||
message = readMessageChain()
|
||||
|
||||
val map: Map<Int, ByteArray> = readTLVMap(true).withDefault { byteArrayOf() }
|
||||
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
|
||||
|
||||
/*
|
||||
val offset = unknownLength0 + fontLength//57
|
||||
event = MessageChain(PlainText(let {
|
||||
val length = input.readShortAt(101 + offset)//
|
||||
input.goto(103 + offset).readString(length.toInt())
|
||||
}))*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
牛逼 (10404
|
||||
3E 03 3F A2 8F 00 1A E5 00 0B 53 3B 64 6B 91 17 1F 40 00 A6 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 8F 00 1A E5 3B DF D8 CE 2B 2E 96 D0 12 CF 0D 44 CF C9 22 A0 00 0B 32 40 5D 73 AF A1 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 73 AF A1 1F EE 24 55 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 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
|
||||
|
||||
牛逼 (10404
|
||||
3E 03 3F A2 8F 00 1A E5 00 00 86 F3 09 18 83 47 1F 40 00 A6 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 8F 00 1A E5 3B DF D8 CE 2B 2E 96 D0 12 CF 0D 44 CF C9 22 A0 00 0B 32 41 5D 73 B3 21 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 73 B3 20 94 B0 82 BC 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 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
|
||||
|
||||
牛逼 (19947
|
||||
76 E4 B8 DD 8F 00 1A E5 00 0D A2 8A 0A 65 7C D0 1F 40 00 A6 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 76 E4 B8 DD 8F 00 1A E5 4E 35 88 98 FE 64 7C E9 33 F7 2F B1 32 5D 5F A9 00 0B 77 FC 5D 73 B4 38 02 5B 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 73 B4 38 A6 60 C7 9A 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 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 0E 00 07 01 00 04 00 00 00 00
|
||||
|
||||
牛逼 (jiahua
|
||||
B1 89 BE 09 8F 00 1A E5 00 0D EB CB 09 90 BA CF 1F 40 00 A6 00 00 00 20 00 05 00 02 00 01 00 06 00 04 00 01 05 0F 00 09 00 06 03 E9 20 02 E5 B3 00 0A 00 04 01 00 00 00 25 15 B1 89 BE 09 8F 00 1A E5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B 77 A3 5D 73 B4 7D 00 00 5D 73 B4 7D 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 73 B4 7D 0E A3 93 E3 00 00 00 00 09 00 86 00 00 09 48 65 6C 76 65 74 69 63 61 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 0E 01 00 04 00 00 00 00 0A 00 04 00 00 00 00 19 00 1C 01 00 19 AA 02 16 08 00 88 01 00 9A 01 0E 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00
|
||||
|
||||
牛逼 (jiahua
|
||||
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 02 00 01 00 06 00 04 00 01 05 0F 00 09 00 06 03 E9 20 02 E5 B3 00 0A 00 04 01 00 00 00 25 15 B1 89 BE 09 8F 00 1A E5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B 77 A5 5D 73 B6 33 00 00 5D 73 B6 33 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 73 B6 33 22 DE A7 56 00 00 00 00 09 00 86 00 00 09 48 65 6C 76 65 74 69 63 61 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 0E 01 00 04 00 00 00 00 0A 00 04 00 00 00 00 19 00 1C 01 00 19 AA 02 16 08 00 88 01 00 9A 01 0E 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00
|
||||
|
||||
牛逼[EMOJI表情1]牛逼 (10404
|
||||
3E 03 3F A2 8F 00 1A E5 00 0B 59 A3 64 6B 91 17 1F 40 00 A6 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 8F 00 1A E5 3B DF D8 CE 2B 2E 96 D0 12 CF 0D 44 CF C9 22 A0 00 0B 32 44 5D 73 BA D9 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 73 BA D9 12 C7 FC CD 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 02 00 14 01 00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D 01 00 09 01 00 06 E7 89 9B E9 80 BC 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
|
||||
|
||||
牛逼[EMOJI表情2]牛逼 (10404
|
||||
3E 03 3F A2 8F 00 1A E5 00 0D 4D 4A 09 18 83 47 1F 40 00 A6 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 8F 00 1A E5 3B DF D8 CE 2B 2E 96 D0 12 CF 0D 44 CF C9 22 A0 00 0B 32 45 5D 73 BF A0 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 73 BF A0 68 31 43 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 02 00 14 01 00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0 01 00 09 01 00 06 E7 89 9B E9 80 BC 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
|
||||
|
||||
牛逼[EMOJI表情1]牛逼 (10404
|
||||
3E 03 3F A2 8F 00 1A E5 00 02 3C 8E 64 6B 91 17 1F 40 00 A6 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 8F 00 1A E5 3B DF D8 CE 2B 2E 96 D0 12 CF 0D 44 CF C9 22 A0 00 0B 32 47 5D 73 C3 76 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 73 C3 75 41 3B 97 72 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 0F 01 00 0C E7 89 9B E9 80 BC E7 89 9B E9 80 BC 02 00 14 01 00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D 01 00 09 01 00 06 E7 89 9B E9 80 BC 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
|
||||
|
||||
[图片] (10404
|
||||
3E 03 3F A2 8F 00 1A E5 00 0E 02 CF 64 6B A0 0C 1F 40 00 A6 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 8F 00 1A E5 3B DF D8 CE 2B 2E 96 D0 12 CF 0D 44 CF C9 22 A0 00 0B 32 4B 5D 73 D1 1C 01 1D 00 00 00 00 01 00 00 00 0C 4D 53 47 00 00 00 00 00 5D 73 D1 1C F5 78 37 16 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 06 00 F0 02 00 1B 28 5A 53 41 58 40 57 4B 52 4A 5A 31 7E 33 59 4F 53 53 4C 4D 32 4B 49 2E 6A 70 67 03 00 04 00 00 06 E2 04 00 25 2F 65 64 33 39 30 66 38 34 2D 34 66 38 37 2D 34 36 64 63 2D 62 33 38 35 2D 34 35 35 36 62 35 31 30 61 61 35 33 14 00 04 03 00 00 00 18 00 25 2F 65 64 33 39 30 66 38 34 2D 34 66 38 37 2D 34 36 64 63 2D 62 33 38 35 2D 34 35 35 36 62 35 31 30 61 61 35 33 19 00 04 00 00 00 38 1A 00 04 00 00 00 34 FF 00 63 16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 31 37 36 32 65 42 39 45 32 37 32 31 43 39 36 44 37 39 41 38 32 31 36 45 30 41 44 34 30 42 35 39 35 39 31 38 36 2E 6A 70 67 66 2F 65 64 33 39 30 66 38 34 2D 34 66 38 37 2D 34 36 64 63 2D 62 33 38 35 2D 34 35 35 36 62 35 31 30 61 61 35 33 41 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
3E 03 3F A2 76 E4 B8 DD 00 09 7C 3F 64 5C 2A 60 1F 40 00 A6 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 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E4 5D 6B A8 F6 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A8 F6 08 7E 90 CE 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 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
|
||||
3E 03 3F A2 76 E4 B8 DD 00 03 5F 85 64 5C 2A A4 1F 40 00 A6 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 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E5 5D 6B A9 16 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A9 17 1B B3 4D D7 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 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
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
|
||||
backup
|
||||
|
||||
class ServerFriendMessageEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
var qq: Long = 0
|
||||
lateinit var event: String
|
||||
|
||||
|
||||
|
||||
override fun dataDecode() {
|
||||
//start at Sep1.0:27
|
||||
qq = input.readIntAt(0)
|
||||
val msgLength = input.readShortAt(22)
|
||||
val fontLength = input.readShortAt(93+msgLength)
|
||||
val offset = msgLength+fontLength
|
||||
event = if(input.readByteAt(97+offset).toUHexString() == "02"){
|
||||
"[face" + input.goto(103+offset).readByteAt(1).toInt().toString() + ".gif]"
|
||||
//.gif
|
||||
}else {
|
||||
val offset2 = input.readShortAt(101 + offset)
|
||||
input.goto(103 + offset).readString(offset2.toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
@ -0,0 +1,16 @@
|
||||
package net.mamoe.mirai.network.protocol.tim.packet.event
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.EventPacketIdentity
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerEventPacket
|
||||
|
||||
|
||||
/**
|
||||
* Android 客户端上线
|
||||
*/
|
||||
class ServerAndroidOnlineEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
|
||||
|
||||
/**
|
||||
* Android 客户端下线
|
||||
*/
|
||||
class ServerAndroidOfflineEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
|
@ -0,0 +1,32 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
||||
|
||||
package net.mamoe.mirai.network.protocol.tim.packet.event
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.EventPacketIdentity
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerEventPacket
|
||||
import net.mamoe.mirai.utils.readString
|
||||
|
||||
|
||||
/**
|
||||
* 群文件上传
|
||||
*/
|
||||
class ServerGroupUploadFileEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
private lateinit var xmlMessage: String
|
||||
|
||||
override fun decode() {
|
||||
this.input.discardExact(60)
|
||||
val size = this.input.readShort().toInt()
|
||||
this.input.discardExact(3)
|
||||
xmlMessage = this.input.readString(size)
|
||||
}//todo test
|
||||
}
|
||||
|
||||
class ServerGroupUnknownChangedEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
|
||||
override fun decode() = with(input) {
|
||||
//00 00 00 08 00 0A 00 04 01 00 00 00 22 96 29 7B 01 01 00 00 F3 55 00 00 00 05 00 00 00 E9 00 00 00 05
|
||||
//00 00 00 08 00 0A 00 04 01 00 00 00 22 96 29 7B 01 01 00 00 F3 56 00 00 00 05 00 00 00 EA 00 00 00 05
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
|
||||
|
||||
package net.mamoe.mirai.network.protocol.tim.packet.event
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readUInt
|
||||
import net.mamoe.mirai.message.MessageChain
|
||||
import net.mamoe.mirai.message.internal.readMessageChain
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.EventPacketIdentity
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerEventPacket
|
||||
import net.mamoe.mirai.utils.printTLVMap
|
||||
import net.mamoe.mirai.utils.read
|
||||
import net.mamoe.mirai.utils.readLVByteArray
|
||||
import net.mamoe.mirai.utils.readTLVMap
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
||||
enum class SenderPermission {
|
||||
OWNER,
|
||||
OPERATOR,
|
||||
MEMBER;
|
||||
}
|
||||
|
||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||
class ServerGroupMessageEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
var groupNumber: UInt by Delegates.notNull()
|
||||
var qq: UInt by Delegates.notNull()
|
||||
lateinit var senderName: String
|
||||
/**
|
||||
* 发送方权限.
|
||||
*/
|
||||
lateinit var senderPermission: SenderPermission
|
||||
lateinit var message: MessageChain
|
||||
|
||||
override fun decode() = with(input) {
|
||||
discardExact(31)
|
||||
groupNumber = readUInt()
|
||||
discardExact(1)
|
||||
qq = readUInt()
|
||||
|
||||
discardExact(48)
|
||||
readLVByteArray()
|
||||
discardExact(2)//2个0x00
|
||||
message = readMessageChain()
|
||||
|
||||
val map = readTLVMap(true).withDefault { byteArrayOf(0, 0, 0, 0) }
|
||||
//map.printTLVMap("父map")
|
||||
if (map.containsKey(18)) {
|
||||
senderName = map.getValue(18).read {
|
||||
val tlv = readTLVMap(true)
|
||||
//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
|
||||
//群主的 子map= {5=00 00 00 03, 8=00 00 00 04, 1=48 69 6D 31 38 38 6D 6F 65, 3=04, 4=00 00 00 08}
|
||||
//管理员 子map= {5=00 00 00 03, 8=00 00 00 04, 2=65 6F 6D 38 38 31 6D 69 48, 3=02, 4=00 00 00 10}
|
||||
//群成员 子map= {5=00 00 00 03, 8=00 00 00 04, 2=65 6F 6D 38 38 31 6D 69 48, 3=02}
|
||||
|
||||
senderPermission = when (val value0x03 = tlv.getValue(0x03)[0].toUInt()) {
|
||||
0x04u -> SenderPermission.OWNER
|
||||
0x03u -> {
|
||||
when (val value0x04 = tlv.getValue(0x04)[3].toUInt()) {
|
||||
0x08u -> SenderPermission.OPERATOR
|
||||
0x10u -> SenderPermission.MEMBER
|
||||
else -> error("Could not determine member permission, unknown tlv(key=0x04,value=$value0x04)")
|
||||
}
|
||||
}
|
||||
|
||||
else -> error("Could not determine member permission, unknown tlv(key=0x03,value=$value0x03)")
|
||||
}
|
||||
|
||||
when {
|
||||
tlv.containsKey(0x01) -> kotlinx.io.core.String(tlv.getValue(0x01))//这个人的qq昵称
|
||||
tlv.containsKey(0x02) -> kotlinx.io.core.String(tlv.getValue(0x02))//这个人的群名片
|
||||
else -> "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//以前的消息: 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, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
val qq: UInt get() = eventIdentity.from
|
||||
|
||||
/**
|
||||
* 是否是在这次登录之前的消息, 即消息记录
|
||||
*/
|
||||
var isPrevious: Boolean = false
|
||||
|
||||
lateinit var message: MessageChain
|
||||
|
||||
//来自自己发送给自己
|
||||
//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) {
|
||||
input.discardExact(2)
|
||||
val l1 = readShort()
|
||||
discardExact(1)//0x00
|
||||
isPrevious = readByte().toInt() == 0x08
|
||||
discardExact(l1.toInt() - 2)
|
||||
discardExact(69)
|
||||
readLVByteArray()//font
|
||||
discardExact(2)//2个0x00
|
||||
message = readMessageChain()
|
||||
|
||||
val map: Map<Int, ByteArray> = readTLVMap(true).withDefault { byteArrayOf() }
|
||||
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
|
||||
|
||||
/*
|
||||
val offset = unknownLength0 + fontLength//57
|
||||
event = MessageChain(PlainText(let {
|
||||
val length = input.readShortAt(101 + offset)//
|
||||
input.goto(103 + offset).readString(length.toInt())
|
||||
}))*/
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
package net.mamoe.mirai.network.protocol.tim.packet
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.event.*
|
||||
import net.mamoe.mirai.utils.*
|
||||
|
||||
/**
|
||||
* 事件的识别 ID. 在 [事件确认包][ServerEventPacket.ResponsePacket] 中被使用.
|
||||
*/
|
||||
data class EventPacketIdentity(
|
||||
val from: UInt,//对于好友消息, 这个是发送人
|
||||
val to: UInt,//对于好友消息, 这个是bot
|
||||
internal val uniqueId: IoBuffer//8
|
||||
) {
|
||||
override fun toString(): String = "(from=$from, to=$to)"
|
||||
}
|
||||
|
||||
fun BytePacketBuilder.writeEventPacketIdentity(identity: EventPacketIdentity) = with(identity) {
|
||||
writeUInt(from)
|
||||
writeUInt(to)
|
||||
writeFully(uniqueId)
|
||||
}
|
||||
|
||||
fun <S : ServerEventPacket> S.applyId(id: UShort): S {
|
||||
this.id = id
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet id: `00 CE` or `00 17`
|
||||
*
|
||||
* @author Him188moe
|
||||
*/
|
||||
abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: EventPacketIdentity) : ServerPacket(input) {
|
||||
override var id: UShort = 0u
|
||||
|
||||
class Raw(input: ByteReadPacket, override val id: UShort) : ServerPacket(input) {
|
||||
fun distribute(): ServerEventPacket = with(input) {
|
||||
val eventIdentity = EventPacketIdentity(
|
||||
from = readUInt(),
|
||||
to = readUInt(),
|
||||
uniqueId = readIoBuffer(8)
|
||||
)
|
||||
discardExact(2)
|
||||
val type = readUShort()
|
||||
//DebugLogger.logPurple("unknown2Byte+byte = ${unknown2Byte.toUHexString()} ${type.toUHexString()}")
|
||||
return when (type.toUInt()) {
|
||||
0x00C4u -> {
|
||||
discardExact(13)
|
||||
if (readBoolean()) {
|
||||
ServerAndroidOfflineEventPacket(input, eventIdentity)
|
||||
} else {
|
||||
ServerAndroidOnlineEventPacket(input, eventIdentity)
|
||||
}
|
||||
}
|
||||
0x002Du -> ServerGroupUploadFileEventPacket(input, eventIdentity)
|
||||
|
||||
0x0052u -> ServerGroupMessageEventPacket(input, eventIdentity)
|
||||
|
||||
0x00A6u -> ServerFriendMessageEventPacket(input.debugPrint("好友消息事件"), 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
|
||||
//00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 07 00 00 00
|
||||
0x0210u -> {
|
||||
discardExact(19)
|
||||
println("type事件" + readUByte().toUInt())
|
||||
|
||||
//todo 错了. 可能是 00 79 才是.
|
||||
ServerFriendTypingCanceledPacket(input, eventIdentity)
|
||||
/*
|
||||
if (readUByte().toUInt() == 0x37u) ServerFriendTypingStartedPacket(input, eventIdentity)
|
||||
else /*0x22*/ ServerFriendTypingCanceledPacket(input, eventIdentity)*/
|
||||
}
|
||||
0x0079u -> IgnoredServerEventPacket(type, input, eventIdentity)
|
||||
|
||||
//"02 10", "00 12" -> ServerUnknownEventPacket(input, eventIdentity)
|
||||
|
||||
else -> {
|
||||
MiraiLogger.logDebug("UnknownEvent type = ${type.toInt().toByteArray().toUHexString()}")
|
||||
UnknownServerEventPacket(input, eventIdentity)
|
||||
}
|
||||
}.applyId(id).applySequence(sequenceId)
|
||||
}
|
||||
|
||||
class Encrypted(input: ByteReadPacket, override var id: UShort, override var sequenceId: UShort) : ServerPacket(input) {
|
||||
fun decrypt(sessionKey: ByteArray): Raw = Raw(this.decryptBy(sessionKey), id).applySequence(sequenceId)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ResponsePacket(
|
||||
val bot: Long,
|
||||
val sessionKey: ByteArray
|
||||
) : ClientPacket() {
|
||||
override val id: UShort get() = this@ServerEventPacket.id
|
||||
override val sequenceId: UShort get() = this@ServerEventPacket.sequenceId
|
||||
|
||||
override fun encode(builder: BytePacketBuilder) = with(builder) {
|
||||
this.writeQQ(bot)
|
||||
this.writeHex(TIMProtocol.fixVer2)
|
||||
this.encryptAndWrite(sessionKey) {
|
||||
writeEventPacketIdentity(eventIdentity)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略的事件.
|
||||
* 如 00 79: 总是与 01 12 一起发生, 但 00 79 却没多大意义
|
||||
*/
|
||||
@Suppress("unused")
|
||||
class IgnoredServerEventPacket(val eventId: UShort, input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity)
|
||||
|
||||
/**
|
||||
* Unknown event
|
||||
*/
|
||||
class UnknownServerEventPacket(input: ByteReadPacket, eventIdentity: EventPacketIdentity) : ServerEventPacket(input, eventIdentity) {
|
||||
override fun decode() {
|
||||
MiraiLogger.logDebug("UnknownServerEventPacket data: " + this.input.readBytes().toUHexString())
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.mamoe.mirai.network.protocol.tim.packet.event
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.EventPacketIdentity
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.ServerEventPacket
|
||||
|
||||
|
||||
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)
|
@ -75,7 +75,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
|
||||
0x00_58_u -> ServerHeartbeatResponsePacket(this)
|
||||
0x00_BA_u -> ServerCaptchaPacket.Encrypted(this)
|
||||
0x00_CE_u, 0x00_17_u -> ServerEventPacket.Raw.Encrypted(this, id, sequenceId)
|
||||
0x00_81_u -> ServerFieldOnlineStatusChangedPacket.Encrypted(this)
|
||||
0x00_81_u -> ServerFriendOnlineStatusChangedPacket.Encrypted(this)
|
||||
0x00_CD_u -> ServerSendFriendMessageResponsePacket(this)
|
||||
0x00_02_u -> ServerSendGroupMessageResponsePacket(this)
|
||||
0x00_A7_u -> ServerCanAddFriendResponsePacket(this)
|
||||
|
@ -17,6 +17,7 @@ import net.mamoe.mirai.utils.BotAccount
|
||||
import net.mamoe.mirai.utils.Console
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
suspend fun main() {
|
||||
val bot = Bot(BotAccount(//填写你的账号
|
||||
account = 1994701021,
|
||||
|
Loading…
Reference in New Issue
Block a user