Client to client message support

This commit is contained in:
Him188 2020-01-29 19:15:09 +08:00
parent 7dc23b5fbe
commit c0d6e906fa
4 changed files with 70 additions and 34 deletions

View File

@ -622,7 +622,7 @@ class ImMsgBody : ProtoBuf {
@Serializable @Serializable
class NotOnlineImage( class NotOnlineImage(
@SerialId(1) val filePath: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(1) val filePath: String = "",
@SerialId(2) val fileLen: Int = 0, @SerialId(2) val fileLen: Int = 0,
@SerialId(3) val downloadPath: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(3) val downloadPath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val oldVerSendFile: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(4) val oldVerSendFile: ByteArray = EMPTY_BYTE_ARRAY,
@ -631,7 +631,7 @@ class ImMsgBody : ProtoBuf {
@SerialId(7) val picMd5: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(7) val picMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val picHeight: Int = 0, @SerialId(8) val picHeight: Int = 0,
@SerialId(9) val picWidth: Int = 0, @SerialId(9) val picWidth: Int = 0,
@SerialId(10) val resId: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(10) val resId: String = "",
@SerialId(11) val flag: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(11) val flag: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val thumbUrl: String = "", @SerialId(12) val thumbUrl: String = "",
@SerialId(13) val original: Int = 0, @SerialId(13) val original: Int = 0,

View File

@ -145,7 +145,7 @@ class MsgComm : ProtoBuf {
@SerialId(1) val lastReadTime: Int = 0, @SerialId(1) val lastReadTime: Int = 0,
@SerialId(2) val peerUin: Long = 0L, @SerialId(2) val peerUin: Long = 0L,
@SerialId(3) val msgCompleted: Int = 0, @SerialId(3) val msgCompleted: Int = 0,
@SerialId(4) val msg: List<Msg>? = null, @SerialId(4) val msg: List<Msg>,
@SerialId(5) val unreadMsgNum: Int = 0, @SerialId(5) val unreadMsgNum: Int = 0,
@SerialId(8) val c2cType: Int = 0, @SerialId(8) val c2cType: Int = 0,
@SerialId(9) val serviceType: Int = 0, @SerialId(9) val serviceType: Int = 0,

View File

@ -2,15 +2,25 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import net.mamoe.mirai.data.MultiPacket
import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.readRemainingAsProtoBuf
import net.mamoe.mirai.qqandroid.io.serialization.loadAs import net.mamoe.mirai.qqandroid.io.serialization.loadAs
import net.mamoe.mirai.qqandroid.io.serialization.readRemainingAsJceStruct import net.mamoe.mirai.qqandroid.io.serialization.readRemainingAsJceStruct
import net.mamoe.mirai.qqandroid.io.writeProtoBuf
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.data.RequestDataVersion2 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.data.RequestDataVersion2
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.data.RequestPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.data.RequestPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.utils.toMessageChain
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.firstValue import net.mamoe.mirai.utils.firstValue
import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.toReadPacket import net.mamoe.mirai.utils.io.toReadPacket
class MessageSvc { class MessageSvc {
@ -18,15 +28,63 @@ class MessageSvc {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify {
discardExact(8) discardExact(8)
val requestPushNotify = readRemainingAsJceStruct(RequestPacket.serializer()).sBuffer return readRemainingAsJceStruct(RequestPacket.serializer()).sBuffer
.loadAs(RequestDataVersion2.serializer()).map.firstValue().firstValue() .loadAs(RequestDataVersion2.serializer()).map.firstValue().firstValue()
.toReadPacket().apply { discardExact(1) } .toReadPacket().apply { discardExact(1) }
.readRemainingAsJceStruct(RequestPushNotify.serializer()) .readRemainingAsJceStruct(RequestPushNotify.serializer())
}
println(requestPushNotify.contentToString()) override suspend fun QQAndroidBot.handle(packet: RequestPushNotify) {
network.run {
PbGetMsg(client, packet).sendAndExpect<MultiPacket<FriendMessage>>()
}
}
}
internal object PbGetMsg : PacketFactory<MultiPacket<FriendMessage>>("MessageSvc.PbGetMsg") {
operator fun invoke(
client: QQAndroidClient,
from: RequestPushNotify
): OutgoingPacket = buildOutgoingUniPacket(
client,
extraData = "08 00 12 33 6D 6F 64 65 6C 3A 78 69 61 6F 6D 69 20 36 3B 6F 73 3A 32 32 3B 76 65 72 73 69 6F 6E 3A 76 32 6D 61 6E 3A 78 69 61 6F 6D 69 73 79 73 3A 4C 4D 59 34 38 5A 18 E4 E1 A4 FF FE 2D 20 E9 E1 A4 FF FE 2D 28 A8 E1 A4 FF FE 2D 30 99 E1 A4 FF FE 2D".hexToBytes().toReadPacket()
) {
writeProtoBuf(
MsgSvc.PbGetMsgReq.serializer(),
MsgSvc.PbGetMsgReq(
msgReqType = from.ctype.toInt(),
contextFlag = 1,
rambleFlag = 0,
latestRambleNumber = 20,
otherRambleNumber = 3,
onlineSyncFlag = 1,
serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY
)
)
}
return requestPushNotify override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): MultiPacket<FriendMessage> {
// 00 00 01 0F 08 00 12 00 1A 34 08 FF C1 C4 F1 05 10 FF C1 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 8A CA 91 D1 0C 48 9B A5 BD 9B 0A 58 DE 9D 99 F8 08 60 1D 68 FF C1 C4 F1 05 70 00 20 02 2A 9D 01 08 F3 C1 C4 F1 05 10 A2 FF 8C F0 03 18 01 22 8A 01 0A 2A 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 A6 01 20 0B 28 AE F9 01 30 F4 C1 C4 F1 05 38 A7 E3 D8 D4 84 80 80 80 01 B8 01 CD B5 01 12 08 08 01 10 00 18 00 20 00 1A 52 0A 50 0A 27 08 00 10 F4 C1 C4 F1 05 18 A7 E3 D8 D4 04 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 08 0A 06 0A 04 4E 4D 53 4C 12 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 12 04 4A 02 08 00 30 01 2A 15 08 97 A2 C1 F1 05 10 95 A6 F5 E5 0C 18 01 30 01 40 01 48 81 01 2A 10 08 D3 F7 B5 F1 05 10 DD F1 92 B7 07 18 01 30 01 38 00 42 00 48 00
discardExact(4)
val resp = readRemainingAsProtoBuf(MsgSvc.PbGetMsgResp.serializer())
//println(resp.contentToString())
if (resp.uinPairMsgs == null) {
return MultiPacket(emptyList())
}
return MultiPacket(resp.uinPairMsgs.asSequence().flatMap { it.msg.asSequence() }.mapNotNull {
when (it.msgHead.msgType) {
166 -> {
FriendMessage(
bot,
false, // TODO: 2020/1/29 PREVIOUS??
bot.getQQ(it.msgHead.fromUin),
it.msgBody.richText.toMessageChain()
)
}
else -> null
}
}.toList())
} }
} }
} }

View File

@ -7,25 +7,12 @@ import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.message.GroupMessage import net.mamoe.mirai.message.GroupMessage
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.ImageId
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.toMessage
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.ImMsgBody import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush
import net.mamoe.mirai.qqandroid.utils.toMessageChain
internal class ImageIdQQA(
override val value: String,
originalLink: String
) : ImageId {
val link: ImageLink = ImageLinkQQA("http://gchat.qpic.cn$originalLink")
}
internal inline class ImageLinkQQA(override val original: String) : ImageLink
internal class OnlinePush { internal class OnlinePush {
internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") { internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
@ -34,17 +21,8 @@ internal class OnlinePush {
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 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 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 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 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00 // 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 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 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 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 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
discardExact(4) discardExact(4)
val pbPushMsg = ProtoBuf.load(MsgOnlinePush.PbPushMsg.serializer(), readBytes()) val pbPushMsg = ProtoBuf.load(MsgOnlinePush.PbPushMsg.serializer(), readBytes())
val message = MessageChain(initialCapacity = pbPushMsg.msg.msgBody.richText.elems.size)
var extraInfo: ImMsgBody.ExtraInfo? = null val extraInfo: ImMsgBody.ExtraInfo? = pbPushMsg.msg.msgBody.richText.elems.firstOrNull { it.extraInfo != null }?.extraInfo
pbPushMsg.msg.msgBody.richText.elems.forEach {
when {
it.customFace != null -> message.add(Image(ImageIdQQA(it.customFace.filePath, it.customFace.origUrl)))
it.text != null -> message.add(it.text.str.toMessage())
it.extraInfo != null -> extraInfo = it.extraInfo
}
}
val group = bot.getGroup(pbPushMsg.msg.msgHead.groupInfo!!.groupCode) val group = bot.getGroup(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
@ -54,7 +32,7 @@ internal class OnlinePush {
group = group, group = group,
senderName = pbPushMsg.msg.msgHead.groupInfo.groupCard, senderName = pbPushMsg.msg.msgHead.groupInfo.groupCard,
sender = group.getMember(pbPushMsg.msg.msgHead.fromUin), sender = group.getMember(pbPushMsg.msg.msgHead.fromUin),
message = message, message = pbPushMsg.msg.msgBody.richText.toMessageChain(),
permission = when { permission = when {
flags and 16 != 0 -> MemberPermission.ADMINISTRATOR flags and 16 != 0 -> MemberPermission.ADMINISTRATOR
flags and 8 != 0 -> MemberPermission.OWNER flags and 8 != 0 -> MemberPermission.OWNER