Commit 522ac8b8 authored by Him188's avatar Him188

Improved message parsing

parent c6373ec7
package net.mamoe.mirai.message; package net.mamoe.mirai.message
/** /**
* @author LamGC * @author LamGC
* @author Him188moe * @author Him188moe
*/ */
public enum FaceID { @Suppress("EnumEntryName", "unused", "SpellCheckingInspection")
enum class FaceID constructor(val id: Int) {
unknown(0xff), unknown(0xff),
Face_jingya(0),
Face_piezui(1),
Face_se(2),
Face_fadai(3),
Face_deyi(4),
Face_liulei(5),
Face_haixiu(6),
Face_bizui(7),
Face_shui(8),
Face_daku(9),
Face_ganga(10),
Face_fanu(11),
Face_tiaopi(12),
Face_ciya(13),
Face_weixiao(14),
Face_nanguo(15),
Face_ku(16),
Face_zhuakuang(18),
Face_tu(19),
Face_touxiao(20),
Face_keai(21),
Face_baiyan(22),
Face_aoman(23),
Face_ji_e(24),
Face_kun(25),
Face_jingkong(26),
Face_liuhan(27),
Face_hanxiao(28),
Face_dabing(29),
Face_fendou(30),
Face_zhouma(31),
Face_yiwen(32),
Face_yun(34),
Face_zhemo(35),
Face_shuai(36),
Face_kulou(37),
Face_qiaoda(38),
Face_zaijian(39),
Face_fadou(41),
Face_aiqing(42),
Face_tiaotiao(43),
Face_zhutou(46),
Face_yongbao(49),
Face_dan_gao(53),
Face_shandian(54),
Face_zhadan(55),
Face_dao(56),
Face_zuqiu(57),
Face_bianbian(59),
Face_kafei(60),
Face_fan(61),
Face_meigui(63),
Face_diaoxie(64),
Face_aixin(66),
Face_xinsui(67),
Face_liwu(69),
Face_taiyang(74),
Face_yueliang(75),
Face_qiang(76),
Face_ruo(77),
Face_woshou(78),
Face_shengli(79),
Face_feiwen(85),
Face_naohuo(86),
Face_xigua(89),
Face_lenghan(96),
Face_cahan(97),
Face_koubi(98),
Face_guzhang(99),
Face_qiudale(100),
Face_huaixiao(101),
Face_zuohengheng(102),
Face_youhengheng(103),
Face_haqian(104),
Face_bishi(105),
Face_weiqu(106),
Face_kuaikule(107),
Face_yinxian(108),
Face_qinqin(109),
Face_xia(110),
Face_kelian(111),
Face_caidao(112),
Face_pijiu(113),
Face_lanqiu(114),
Face_pingpang(115),
Face_shiai(116),
Face_piaochong(117),
Face_baoquan(118),
Face_gouyin(119),
Face_quantou(120),
Face_chajin(121),
Face_aini(122),
Face_bu(123),
Face_hao(124),
Face_zhuanquan(125),
Face_ketou(126),
Face_huitou(127),
Face_tiaosheng(128),
Face_huishou(129),
Face_jidong(130),
Face_jiewu(131),
Face_xianwen(132),
Face_zuotaiji(133),
Face_youtaiji(134),
Face_shuangxi(136),
Face_bianpao(137),
Face_denglong(138),
Face_facai(139),
Face_K_ge(140),
Face_gouwu(141),
Face_youjian(142),
Face_shuai_qi(143),
Face_hecai(144),
Face_qidao(145),
Face_baojin(146),
Face_bangbangtang(147),
Face_he_nai(148),
Face_xiamian(149),
Face_xiangjiao(150),
Face_feiji(151),
Face_kaiche(152),
Face_gaotiezuochetou(153),
Face_chexiang(154),
Face_gaotieyouchetou(155),
Face_duoyun(156),
Face_xiayu(157),
Face_chaopiao(158),
Face_xiongmao(159),
Face_dengpao(160),
Face_fengche(161),
Face_naozhong(162),
Face_dasan(163),
Face_caiqiu(164),
Face_zuanjie(165),
Face_shafa(166),
Face_zhijin(167),
Face_yao(168),
Face_shouqiang(169),
Face_qingwa(170),
// TODO: 2019/9/1 添加更多表情 // TODO: 2019/9/1 添加更多表情
jingya(0),
piezui(1),
se(2),
fadai(3),
deyi(4),
liulei(5),
haixiu(6),
bizui(7),
shui(8),
daku(9),
ganga(10),
fanu(11),
tiaopi(12),
ciya(13),
weixiao(14),
nanguo(15),
ku(16),
zhuakuang(18),
tu(19),
touxiao(20),
keai(21),
baiyan(22),
aoman(23),
ji_e(24),
kun(25),
jingkong(26),
liuhan(27),
hanxiao(28),
dabing(29),
fendou(30),
zhouma(31),
yiwen(32),
yun(34),
zhemo(35),
shuai(36),
kulou(37),
qiaoda(38),
zaijian(39),
fadou(41),
aiqing(42),
tiaotiao(43),
zhutou(46),
yongbao(49),
dan_gao(53),
shandian(54),
zhadan(55),
dao(56),
zuqiu(57),
bianbian(59),
kafei(60),
fan(61),
meigui(63),
diaoxie(64),
aixin(66),
xinsui(67),
liwu(69),
taiyang(74),
yueliang(75),
qiang(76),
ruo(77),
woshou(78),
shengli(79),
feiwen(85),
naohuo(86),
xigua(89),
lenghan(96),
cahan(97),
koubi(98),
guzhang(99),
qiudale(100),
huaixiao(101),
zuohengheng(102),
youhengheng(103),
haqian(104),
bishi(105),
weiqu(106),
kuaikule(107),
yinxian(108),
qinqin(109),
xia(110),
kelian(111),
caidao(112),
pijiu(113),
lanqiu(114),
pingpang(115),
shiai(116),
piaochong(117),
baoquan(118),
gouyin(119),
quantou(120),
chajin(121),
aini(122),
bu(123),
hao(124),
zhuanquan(125),
ketou(126),
huitou(127),
tiaosheng(128),
huishou(129),
jidong(130),
jiewu(131),
xianwen(132),
zuotaiji(133),
youtaiji(134),
shuangxi(136),
bianpao(137),
denglong(138),
facai(139),
K_ge(140),
gouwu(141),
youjian(142),
shuai_qi(143),
hecai(144),
qidao(145),
baojin(146),
bangbangtang(147),
he_nai(148),
xiamian(149),
xiangjiao(150),
feiji(151),
kaiche(152),
gaotiezuochetou(153),
chexiang(154),
gaotieyouchetou(155),
duoyun(156),
xiayu(157),
chaopiao(158),
xiongmao(159),
dengpao(160),
fengche(161),
naozhong(162),
dasan(163),
caiqiu(164),
zuanjie(165),
shafa(166),
zhijin(167),
yao(168),
shouqiang(169),
qingwa(170);
; override fun toString(): String {
return "$name($id)"
private final int id;
FaceID(int id) {
this.id = id;
} }
public int getId() { companion object {
return id;
}
public static FaceID ofId(int id) { fun ofId(id: Int): FaceID {
for (FaceID value : FaceID.values()) { for (value in values()) {
if (value.id == id) { if (value.id == id) {
return value; return value
} }
} }
return FaceID.unknown; return unknown
}
} }
} }
...@@ -20,7 +20,11 @@ class Face(val id: FaceID) : Message() { ...@@ -20,7 +20,11 @@ class Face(val id: FaceID) : Message() {
override val type: MessageKey = Key override val type: MessageKey = Key
override fun toStringImpl(): String { override fun toStringImpl(): String {
return String.format("[face%d]", id.id) return "[face${id.id}]"
}
override fun toObjectString(): String {
return "Face[$id]"
} }
override fun toByteArray(): ByteArray = dataEncode { section -> override fun toByteArray(): ByteArray = dataEncode { section ->
...@@ -48,7 +52,7 @@ class Face(val id: FaceID) : Message() { ...@@ -48,7 +52,7 @@ class Face(val id: FaceID) : Message() {
override operator fun contains(sub: String): Boolean = false override operator fun contains(sub: String): Boolean = false
internal object PacketHelper { object PacketHelper {
fun ofByteArray(data: ByteArray): Face = dataDecode(data) { fun ofByteArray(data: ByteArray): Face = dataDecode(data) {
//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
......
...@@ -22,7 +22,11 @@ open class Image(val imageId: String) : Message() { ...@@ -22,7 +22,11 @@ open class Image(val imageId: String) : Message() {
override val type: MessageKey = Key override val type: MessageKey = Key
override fun toStringImpl(): String { override fun toStringImpl(): String {
return imageId return "[$imageId]"
}
override fun toObjectString(): String {
return "Image[$imageId]"
} }
override fun toByteArray(): ByteArray = dataEncode { section -> override fun toByteArray(): ByteArray = dataEncode { section ->
...@@ -55,7 +59,7 @@ open class Image(val imageId: String) : Message() { ...@@ -55,7 +59,7 @@ open class Image(val imageId: String) : Message() {
override operator fun contains(sub: String): Boolean = false //No string can be contained in a image override operator fun contains(sub: String): Boolean = false //No string can be contained in a image
internal object PacketHelper { object PacketHelper {
@JvmStatic @JvmStatic
fun ofByteArray0x06(data: ByteArray): Image = dataDecode(data) { fun ofByteArray0x06(data: ByteArray): Image = dataDecode(data) {
it.skip(1) it.skip(1)
......
...@@ -2,7 +2,12 @@ package net.mamoe.mirai.message.defaults ...@@ -2,7 +2,12 @@ package net.mamoe.mirai.message.defaults
import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.MessageKey import net.mamoe.mirai.message.MessageKey
import net.mamoe.mirai.network.protocol.tim.packet.readLVByteArray
import net.mamoe.mirai.network.protocol.tim.packet.readNBytes
import net.mamoe.mirai.utils.dataDecode
import net.mamoe.mirai.utils.dataEncode import net.mamoe.mirai.utils.dataEncode
import net.mamoe.mirai.utils.toUHexString
import java.io.DataInputStream
import java.util.* import java.util.*
import java.util.stream.Collectors import java.util.stream.Collectors
import java.util.stream.Stream import java.util.stream.Stream
...@@ -95,4 +100,69 @@ class MessageChain : Message { ...@@ -95,4 +100,69 @@ class MessageChain : Message {
operator fun component1(): Message = this.list[0] operator fun component1(): Message = this.list[0]
operator fun component2(): Message = this.list[1] operator fun component2(): Message = this.list[1]
operator fun component3(): Message = this.list[2] operator fun component3(): Message = this.list[2]
object PacketHelper {
@JvmStatic
fun ofByteArray(byteArray: ByteArray): MessageChain = dataDecode(byteArray) {
it.readMessageChain()
}
}
}
fun DataInputStream.readMessage(): Message? {
val messageType = this.readByte().toInt()
val sectionLength = this.readShort().toLong()//sectionLength: short
val sectionData = this.readNBytes(sectionLength)
return when (messageType) {
0x01 -> PlainText.PacketHelper.ofByteArray(sectionData)
0x02 -> Face.PacketHelper.ofByteArray(sectionData)
0x03 -> Image.PacketHelper.ofByteArray0x03(sectionData)
0x06 -> Image.PacketHelper.ofByteArray0x06(sectionData)
0x19 -> {//长文本
val value = readLVByteArray()
//todo 未知压缩算法
PlainText(String(value))
// PlainText(String(GZip.uncompress( value)))
}
0x14 -> {//长文本
val value = readLVByteArray()
println(value.size)
println(value.toUHexString())
//todo 未知压缩算法
this.skip(7)//几个TLV
return PlainText(String(value))
}
0x0E -> {
//null
null
}
else -> {
println("未知的messageType=0x${messageType.toByte().toUHexString()}")
println("后文=${this.readAllBytes().toUHexString()}")
null
}
}
}
fun DataInputStream.readMessageChain(): MessageChain {
val chain = MessageChain()
var got: Message? = null
do {
if (got != null) {
chain.concat(got)
}
if (this.available() == 0) {
return chain
}
got = this.readMessage()
} while (got != null)
return chain
} }
\ No newline at end of file
...@@ -38,7 +38,7 @@ class PlainText(private val text: String) : Message() { ...@@ -38,7 +38,7 @@ class PlainText(private val text: String) : Message() {
override operator fun contains(sub: String): Boolean = this.toString().contains(sub) override operator fun contains(sub: String): Boolean = this.toString().contains(sub)
internal object PacketHelper { object PacketHelper {
@JvmStatic @JvmStatic
fun ofByteArray(data: ByteArray): PlainText = dataDecode(data) { fun ofByteArray(data: ByteArray): PlainText = dataDecode(data) {
it.skip(1) it.skip(1)
......
...@@ -39,6 +39,7 @@ object TIMProtocol { ...@@ -39,6 +39,7 @@ object TIMProtocol {
*/ */
const val fixVer2 = "02 00 00 00 01 01 01 00 00 68 20" const val fixVer2 = "02 00 00 00 01 01 01 00 00 68 20"
// 02 38 03 00 CD 48 68 3E 03 3F A2 02 00 00 00 // 02 38 03 00 CD 48 68 3E 03 3F A2 02 00 00 00
// 02 00 00 00 01 2E 01 00 00 69 35
/** /**
* 0825data1 * 0825data1
*/ */
...@@ -105,6 +106,7 @@ object TIMProtocol { ...@@ -105,6 +106,7 @@ object TIMProtocol {
* length=15 * length=15
*/ */
const val messageConst1 = "00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91" const val messageConst1 = "00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91"
// TIM最新 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91
private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf() private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf()
......
...@@ -2,11 +2,8 @@ ...@@ -2,11 +2,8 @@
package net.mamoe.mirai.network.protocol.tim.packet package net.mamoe.mirai.network.protocol.tim.packet
import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.defaults.Face
import net.mamoe.mirai.message.defaults.Image
import net.mamoe.mirai.message.defaults.MessageChain import net.mamoe.mirai.message.defaults.MessageChain
import net.mamoe.mirai.message.defaults.PlainText import net.mamoe.mirai.message.defaults.readMessageChain
import net.mamoe.mirai.network.protocol.tim.TIMProtocol import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.dataDecode import net.mamoe.mirai.utils.dataDecode
import net.mamoe.mirai.utils.hexToBytes import net.mamoe.mirai.utils.hexToBytes
...@@ -49,7 +46,7 @@ abstract class ServerEventPacket(input: DataInputStream, val packetId: ByteArray ...@@ -49,7 +46,7 @@ abstract class ServerEventPacket(input: DataInputStream, val packetId: ByteArray
@PacketId("00 17") @PacketId("00 17")
class Encrypted(input: DataInputStream, private val packetId: ByteArray) : ServerPacket(input) { class Encrypted(input: DataInputStream, private val packetId: ByteArray) : ServerPacket(input) {
fun decrypt(sessionKey: ByteArray): Raw = Raw(decryptBy(sessionKey), packetId).setId(this.idHex) fun decrypt(sessionKey: ByteArray): Raw = Raw(this.decryptBy(sessionKey), packetId).setId(this.idHex)
} }
} }
...@@ -135,7 +132,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, ...@@ -135,7 +132,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
this.input.goto(108) this.input.goto(108)
this.input.readLVByteArray() this.input.readLVByteArray()
input.skip(2)//2个0x00 input.skip(2)//2个0x00
message = input.readSections() message = input.readMessageChain()
val map = input.readTLVMap(true) val map = input.readTLVMap(true)
if (map.containsKey(18)) { if (map.containsKey(18)) {
...@@ -262,7 +259,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray ...@@ -262,7 +259,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
input.goto(93 + l1) input.goto(93 + l1)
input.readLVByteArray()//font input.readLVByteArray()//font
input.skip(2)//2个0x00 input.skip(2)//2个0x00
message = input.readSections() message = input.readMessageChain()
val map: Map<Int, ByteArray> = input.readTLVMap(true).withDefault { byteArrayOf() } val map: Map<Int, ByteArray> = input.readTLVMap(true).withDefault { byteArrayOf() }
println(map.getValue(18)) println(map.getValue(18))
...@@ -278,64 +275,6 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray ...@@ -278,64 +275,6 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
} }
} }
private fun DataInputStream.readSection(): Message? {
val messageType = this.readByte().toInt()
val sectionLength = this.readShort().toLong()//sectionLength: short
val sectionData = this.readNBytes(sectionLength)
return when (messageType) {
0x01 -> PlainText.PacketHelper.ofByteArray(sectionData)
0x02 -> Face.PacketHelper.ofByteArray(sectionData)
0x03 -> Image.PacketHelper.ofByteArray0x03(sectionData)
0x06 -> Image.PacketHelper.ofByteArray0x06(sectionData)
0x19 -> {//长文本
val value = readLVByteArray()
//todo 未知压缩算法
PlainText(String(value))
// PlainText(String(GZip.uncompress( value)))
}
0x14 -> {//长文本
val value = readLVByteArray()
println(value.size)
println(value.toUHexString())
//todo 未知压缩算法
this.skip(7)//几个TLV
return PlainText(String(value))
}
0x0E -> {
//null
null
}
else -> {
println("未知的messageType=0x${messageType.toByte().toUHexString()}")
println("后文=${this.readAllBytes().toUHexString()}")
null
}
}
}
private fun DataInputStream.readSections(): MessageChain {
val chain = MessageChain()
var got: Message? = null
do {
if (got != null) {
chain.concat(got)
}
if (this.available() == 0) {
return chain
}
got = this.readSection()
} while (got != null)
return chain
}
/* /*
牛逼 (10404 牛逼 (10404
......
...@@ -34,11 +34,22 @@ class ClientSendFriendMessagePacket( ...@@ -34,11 +34,22 @@ class ClientSendFriendMessagePacket(
writeRandom(2) writeRandom(2)
writeTime() writeTime()
writeHex("00 00" + writeHex("00 00" +
"00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00") "00 00 00 00")
//01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00
//消息过多要分包发送
//如果只有一个
writeByte(0x01)
writeByte(0)//第几个包
writeByte(0)
//如果大于一个,
//writeByte(0x02)//数量
//writeByte(0)//第几个包
//writeByte(0x91)//why?
writeHex("00 01 4D 53 47 00 00 00 00 00")
writeTime() writeTime()
writeRandom(4) writeRandom(4)
writeHex("00 00 00 00 09 00 86") writeHex("00 00 00 00 09 00 86")//TIM最新 0C 00 86
writeHex(TIMProtocol.messageConst1)//... 85 E9 BB 91 writeHex(TIMProtocol.messageConst1)//... 85 E9 BB 91
writeZero(2) writeZero(2)
...@@ -56,9 +67,5 @@ class ClientSendFriendMessagePacket( ...@@ -56,9 +67,5 @@ class ClientSendFriendMessagePacket(
} }
} }
fun main() {
}
@PacketId("00 CD") @PacketId("00 CD")
class ServerSendFriendMessageResponsePacket(input: DataInputStream) : ServerPacket(input) class ServerSendFriendMessageResponsePacket(input: DataInputStream) : ServerPacket(input)
\ No newline at end of file
...@@ -69,7 +69,6 @@ fun DataOutputStream.writeVarInt(signedInt: Int) { ...@@ -69,7 +69,6 @@ fun DataOutputStream.writeVarInt(signedInt: Int) {
this.writeUVarInt(encodeZigZag32(signedInt)) this.writeUVarInt(encodeZigZag32(signedInt))
} }
@Throws(IOException::class) @Throws(IOException::class)
fun DataOutputStream.writeUVarInt(uint: UInt) { fun DataOutputStream.writeUVarInt(uint: UInt) {
return writeUVarInt(uint.toLong()) return writeUVarInt(uint.toLong())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment