mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-09 01:30:17 +08:00
Improved message parsing
This commit is contained in:
parent
c6373ec727
commit
522ac8b839
@ -1,174 +1,167 @@
|
||||
package net.mamoe.mirai.message;
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
/**
|
||||
* @author LamGC
|
||||
* @author Him188moe
|
||||
*/
|
||||
public enum FaceID {
|
||||
@Suppress("EnumEntryName", "unused", "SpellCheckingInspection")
|
||||
enum class FaceID constructor(val id: Int) {
|
||||
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 添加更多表情
|
||||
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);
|
||||
|
||||
;
|
||||
|
||||
private final int id;
|
||||
|
||||
FaceID(int id) {
|
||||
this.id = id;
|
||||
override fun toString(): String {
|
||||
return "$name($id)"
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
companion object {
|
||||
|
||||
public static FaceID ofId(int id) {
|
||||
for (FaceID value : FaceID.values()) {
|
||||
fun ofId(id: Int): FaceID {
|
||||
for (value in values()) {
|
||||
if (value.id == id) {
|
||||
return value;
|
||||
return value
|
||||
}
|
||||
}
|
||||
return FaceID.unknown;
|
||||
return unknown
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,11 @@ class Face(val id: FaceID) : Message() {
|
||||
override val type: MessageKey = Key
|
||||
|
||||
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 ->
|
||||
@ -48,7 +52,7 @@ class Face(val id: FaceID) : Message() {
|
||||
|
||||
override operator fun contains(sub: String): Boolean = false
|
||||
|
||||
internal object PacketHelper {
|
||||
object PacketHelper {
|
||||
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 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() {
|
||||
override val type: MessageKey = Key
|
||||
|
||||
override fun toStringImpl(): String {
|
||||
return imageId
|
||||
return "[$imageId]"
|
||||
}
|
||||
|
||||
override fun toObjectString(): String {
|
||||
return "Image[$imageId]"
|
||||
}
|
||||
|
||||
override fun toByteArray(): ByteArray = dataEncode { section ->
|
||||
@ -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
|
||||
|
||||
internal object PacketHelper {
|
||||
object PacketHelper {
|
||||
@JvmStatic
|
||||
fun ofByteArray0x06(data: ByteArray): Image = dataDecode(data) {
|
||||
it.skip(1)
|
||||
|
@ -2,7 +2,12 @@ package net.mamoe.mirai.message.defaults
|
||||
|
||||
import net.mamoe.mirai.message.Message
|
||||
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.toUHexString
|
||||
import java.io.DataInputStream
|
||||
import java.util.*
|
||||
import java.util.stream.Collectors
|
||||
import java.util.stream.Stream
|
||||
@ -95,4 +100,69 @@ class MessageChain : Message {
|
||||
operator fun component1(): Message = this.list[0]
|
||||
operator fun component2(): Message = this.list[1]
|
||||
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
|
||||
}
|
@ -38,7 +38,7 @@ class PlainText(private val text: String) : Message() {
|
||||
|
||||
override operator fun contains(sub: String): Boolean = this.toString().contains(sub)
|
||||
|
||||
internal object PacketHelper {
|
||||
object PacketHelper {
|
||||
@JvmStatic
|
||||
fun ofByteArray(data: ByteArray): PlainText = dataDecode(data) {
|
||||
it.skip(1)
|
||||
|
@ -39,6 +39,7 @@ object TIMProtocol {
|
||||
*/
|
||||
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 00 00 00 01 2E 01 00 00 69 35
|
||||
/**
|
||||
* 0825data1
|
||||
*/
|
||||
@ -105,6 +106,7 @@ object TIMProtocol {
|
||||
* length=15
|
||||
*/
|
||||
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()
|
||||
|
||||
|
@ -2,11 +2,8 @@
|
||||
|
||||
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.PlainText
|
||||
import net.mamoe.mirai.message.defaults.readMessageChain
|
||||
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
|
||||
import net.mamoe.mirai.utils.dataDecode
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
@ -49,7 +46,7 @@ abstract class ServerEventPacket(input: DataInputStream, val packetId: ByteArray
|
||||
|
||||
@PacketId("00 17")
|
||||
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,
|
||||
this.input.goto(108)
|
||||
this.input.readLVByteArray()
|
||||
input.skip(2)//2个0x00
|
||||
message = input.readSections()
|
||||
message = input.readMessageChain()
|
||||
|
||||
val map = input.readTLVMap(true)
|
||||
if (map.containsKey(18)) {
|
||||
@ -262,7 +259,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
|
||||
input.goto(93 + l1)
|
||||
input.readLVByteArray()//font
|
||||
input.skip(2)//2个0x00
|
||||
message = input.readSections()
|
||||
message = input.readMessageChain()
|
||||
|
||||
val map: Map<Int, ByteArray> = input.readTLVMap(true).withDefault { byteArrayOf() }
|
||||
println(map.getValue(18))
|
||||
@ -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
|
||||
|
@ -34,11 +34,22 @@ class ClientSendFriendMessagePacket(
|
||||
writeRandom(2)
|
||||
writeTime()
|
||||
writeHex("00 00" +
|
||||
"00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00")
|
||||
//01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 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()
|
||||
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
|
||||
writeZero(2)
|
||||
|
||||
@ -56,9 +67,5 @@ class ClientSendFriendMessagePacket(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun main() {
|
||||
|
||||
}
|
||||
@PacketId("00 CD")
|
||||
class ServerSendFriendMessageResponsePacket(input: DataInputStream) : ServerPacket(input)
|
@ -69,7 +69,6 @@ fun DataOutputStream.writeVarInt(signedInt: Int) {
|
||||
this.writeUVarInt(encodeZigZag32(signedInt))
|
||||
}
|
||||
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun DataOutputStream.writeUVarInt(uint: UInt) {
|
||||
return writeUVarInt(uint.toLong())
|
||||
|
Loading…
Reference in New Issue
Block a user