Commit d1c56633 authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

parents c9d40341 d845413b
package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.message.data.ImageId
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.utils.*
import kotlin.coroutines.CoroutineContext
internal abstract class ContactImpl : Contact
internal class QQImpl(bot: Bot, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), QQ {
override val bot: Bot by bot.unsafeWeakRef()
override suspend fun sendMessage(message: MessageChain) {
TODO("not implemented")
}
override suspend fun uploadImage(image: ExternalImage): ImageId {
TODO("not implemented")
}
override suspend fun queryProfile(): Profile {
TODO("not implemented")
}
override suspend fun queryPreviousNameList(): PreviousNameList {
TODO("not implemented")
}
override suspend fun queryRemark(): FriendNameRemark {
TODO("not implemented")
}
}
internal class MemberImpl(bot: Bot, group: Group, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), Member {
override val group: Group by group.unsafeWeakRef()
override val permission: MemberPermission
get() = TODO("not implemented")
override val bot: Bot by bot.unsafeWeakRef()
override suspend fun mute(durationSeconds: Int): Boolean {
TODO("not implemented")
}
override suspend fun unmute() {
TODO("not implemented")
}
override suspend fun queryProfile(): Profile {
TODO("not implemented")
}
override suspend fun queryPreviousNameList(): PreviousNameList {
TODO("not implemented")
}
override suspend fun queryRemark(): FriendNameRemark {
TODO("not implemented")
}
override suspend fun sendMessage(message: MessageChain) {
TODO("not implemented")
}
override suspend fun uploadImage(image: ExternalImage): ImageId {
TODO("not implemented")
}
}
@UseExperimental(MiraiInternalAPI::class)
internal class GroupImpl(bot: Bot, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), Group {
override val internalId: GroupInternalId = GroupId(id).toInternalId()
override val owner: Member
get() = TODO("not implemented")
override val name: String
get() = TODO("not implemented")
override val announcement: String
get() = TODO("not implemented")
override val members: ContactList<Member> = ContactList(LockFreeLinkedList())
override fun getMember(id: Long): Member = members.delegate.filteringGetOrAdd({ it.id == id }, { MemberImpl(bot, this, coroutineContext, id) })
override suspend fun updateGroupInfo(): GroupInfo {
TODO("not implemented")
}
override suspend fun quit(): Boolean {
TODO("not implemented")
}
override val bot: Bot by bot.unsafeWeakRef()
override suspend fun sendMessage(message: MessageChain) {
TODO("not implemented")
}
override suspend fun uploadImage(image: ExternalImage): ImageId {
TODO("not implemented")
}
}
\ No newline at end of file
...@@ -8,8 +8,10 @@ import net.mamoe.mirai.data.ImageLink ...@@ -8,8 +8,10 @@ import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.ImageIdQQA
import net.mamoe.mirai.qqandroid.utils.Context import net.mamoe.mirai.qqandroid.utils.Context
import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
...@@ -27,34 +29,35 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -27,34 +29,35 @@ internal abstract class QQAndroidBotBase constructor(
) : BotImpl<QQAndroidBotNetworkHandler>(account, configuration) { ) : BotImpl<QQAndroidBotNetworkHandler>(account, configuration) {
val client: QQAndroidClient = QQAndroidClient(context, account, bot = @Suppress("LeakingThis") this as QQAndroidBot) val client: QQAndroidClient = QQAndroidClient(context, account, bot = @Suppress("LeakingThis") this as QQAndroidBot)
override val qqs: ContactList<QQ> override val qqs: ContactList<QQ> = ContactList(LockFreeLinkedList())
get() = TODO("not implemented")
override fun getQQ(id: Long): QQ { override fun getQQ(id: Long): QQ {
TODO("not implemented") return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this, coroutineContext, id) })
} }
override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler { override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler {
return QQAndroidBotNetworkHandler(this as QQAndroidBot) return QQAndroidBotNetworkHandler(this as QQAndroidBot)
} }
override val groups: ContactList<Group> override val groups: ContactList<Group> = ContactList(LockFreeLinkedList())
get() = TODO("not implemented")
override suspend fun getGroup(id: GroupId): Group { override suspend fun getGroup(id: GroupId): Group {
TODO("not implemented") return groups.delegate.filteringGetOrAdd({ it.id == id.value }, { GroupImpl(this, coroutineContext, id.value) })
} }
override suspend fun getGroup(internalId: GroupInternalId): Group { override suspend fun getGroup(internalId: GroupInternalId): Group {
TODO("not implemented") internalId.toId().value.let { id ->
return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this, coroutineContext, id) })
}
} }
override suspend fun getGroup(id: Long): Group { override suspend fun getGroup(id: Long): Group {
TODO("not implemented") return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this, coroutineContext, id) })
} }
override suspend fun Image.getLink(): ImageLink { override suspend fun Image.getLink(): ImageLink {
TODO("not implemented") require(this.id is ImageIdQQA) { "image.id must be ImageIdQQA" }
return (this.id as ImageIdQQA).link
} }
override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult { override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult {
......
...@@ -4,6 +4,9 @@ import kotlinx.coroutines.* ...@@ -4,6 +4,9 @@ import kotlinx.coroutines.*
import kotlinx.io.core.* import kotlinx.io.core.*
import kotlinx.io.pool.ObjectPool import kotlinx.io.pool.ObjectPool
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.BroadcastControllable
import net.mamoe.mirai.event.Cancellable
import net.mamoe.mirai.event.Subscribable
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
...@@ -12,7 +15,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories ...@@ -12,7 +15,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket.LoginPacketResponse.* import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket.LoginPacketResponse.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
...@@ -48,7 +51,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -48,7 +51,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
} }
println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}") println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
SvcReqRegisterPacket(bot.client).sendAndExpect<SvcReqRegisterPacket.Response>() StatSvc.Register(bot.client).sendAndExpect<StatSvc.Register.Response>()
} }
/** /**
...@@ -113,11 +116,26 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -113,11 +116,26 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
if (PacketReceivedEvent(packet).broadcast().cancelled) { if (PacketReceivedEvent(packet).broadcast().cancelled) {
return@parseIncomingPacket return@parseIncomingPacket
} }
// pass to listeners (attached by sendAndExpect).
packetListeners.forEach { listener -> packetListeners.forEach { listener ->
if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) { if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) {
listener.complete(packet) listener.complete(packet)
} }
} }
// broadcast
if (packet is Subscribable) {
if (packet is BroadcastControllable) {
if (packet.shouldBroadcast) packet.broadcast()
} else {
packet.broadcast()
}
if (packet is Cancellable && packet.cancelled) return@parseIncomingPacket
}
bot.logger.info(packet)
} }
} finally { } finally {
println() println()
......
...@@ -6,6 +6,7 @@ import net.mamoe.mirai.data.Packet ...@@ -6,6 +6,7 @@ import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.io.JceInput import net.mamoe.mirai.qqandroid.network.io.JceInput
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.DefaultLogger
...@@ -49,7 +50,8 @@ internal val PacketLogger: MiraiLogger = DefaultLogger("Packet") ...@@ -49,7 +50,8 @@ internal val PacketLogger: MiraiLogger = DefaultLogger("Packet")
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
LoginPacket, LoginPacket,
SvcReqRegisterPacket SvcReqRegisterPacket,
OnlinePush.PbPushGroupMsg
) { ) {
fun findPacketFactory(commandName: String): PacketFactory<*>? = this.firstOrNull { it.commandName == commandName } fun findPacketFactory(commandName: String): PacketFactory<*>? = this.firstOrNull { it.commandName == commandName }
...@@ -117,7 +119,14 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( ...@@ -117,7 +119,14 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
} }
when (flag2) { when (flag2) {
1 -> it.data.parseUniResponse(bot, it.packetFactory, it.sequenceId, consumer) 1 ->//it.data.parseUniResponse(bot, it.packetFactory, it.sequenceId, consumer)
{
consumer(
it.packetFactory.run { decode(bot, it.data) },
it.packetFactory.commandName,
it.sequenceId
)
}
2 -> it.data.parseOicqResponse(bot, it.packetFactory, it.sequenceId, consumer) 2 -> it.data.parseOicqResponse(bot, it.packetFactory, it.sequenceId, consumer)
else -> error("unknown flag2: $flag2. Body to be parsed for inner packet=${it.data.readBytes().toUHexString()}") else -> error("unknown flag2: $flag2. Body to be parsed for inner packet=${it.data.readBytes().toUHexString()}")
} }
......
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data
import kotlinx.serialization.SerialId import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
......
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data
import kotlinx.serialization.SerialId import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
......
@file:Suppress("ArrayInDataClass")
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
class MessageCommon {
/**
* 1 -> varint
* 2 -> delimi
* 3 -> varint
* 4 -> varint
* 5 -> varint
* 6 -> varint
* 7 -> delimi
* 8 -> delimi
* 9 -> delimi
* 10 -> delimi
* 11 -> delimi
*/
@Serializable
data class PluginInfo(
@SerialId(1) val resId: Int = 0,
@SerialId(2) val packageName: String = "",
@SerialId(3) val newVer: Int = 0,
@SerialId(4) val resType: Int = 0,
@SerialId(5) val lanType: Int = 0,
@SerialId(6) val priority: Int = 0,
@SerialId(7) val resName: String = "",
@SerialId(8) val resDesc: String = "",
@SerialId(9) val resUrlBig: String = "",
@SerialId(10) val resUrlSmall: String = "",
@SerialId(11) val resConf: String = ""
)
@Serializable
data class AppShareInfo(
@ProtoType(ProtoNumberType.FIXED) @SerialId(1) val id: Int = 0,
@SerialId(2) val cookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val resource: PluginInfo = PluginInfo()
)
@Serializable
data class ContentHead(
@SerialId(1) val pkgNum: Int = 0,
@SerialId(2) val pkgIndex: Int = 0,
@SerialId(3) val divSeq: Int = 0,
@SerialId(4) val autoReply: Int = 0
)
@Serializable
data class Msg(
val s: String
)
}
\ No newline at end of file
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@Serializable
class ImCommon {
@Serializable
class GroupInfo(
@SerialId(1) val groupId: Long = 0L,
@SerialId(2) val groupType: Int /* enum */ = 1
)
@Serializable
class Signature(
@SerialId(1) val keyType: Int = 0,
@SerialId(2) val sessionAppId: Int = 0,
@SerialId(3) val sessionKey: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class Token(
@SerialId(1) val buf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val c2cType: Int = 0,
@SerialId(3) val serviceType: Int = 0
)
@Serializable
class User(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val appId: Int = 0,
@SerialId(3) val instanceId: Int = 0,
@SerialId(4) val appType: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(5) val clientIp: Int = 0,
@SerialId(6) val version: Int = 0,
@SerialId(7) val phoneNumber: String = "",
@SerialId(8) val platformId: Int = 0,
@SerialId(9) val language: Int = 0,
@SerialId(10) val equipKey: ByteArray = EMPTY_BYTE_ARRAY
)
}
@Serializable
class ImImagent {
@Serializable
class ImAgentHead(
@SerialId(1) val command: Int /* enum */ = 1,
@SerialId(2) val seq: Int = 0,
@SerialId(3) val result: Int = 0,
@SerialId(4) val err: String = "",
@SerialId(5) val echoBuf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val reqUser: ImCommon.User? = null,
@SerialId(7) val reqInfo: Requestinfo? = null,
@SerialId(8) val signature: Signature? = null,
@SerialId(9) val subCmd: Int = 0,
@SerialId(10) val serverIp: Int = 0
)
@Serializable
class ImAgentPackage(
@SerialId(1) val head: ImAgentHead? = null,
@SerialId(11) val msgSendReq: ImMsg.MsgSendReq? = null,
@SerialId(12) val msgSendResp: ImMsg.MsgSendResp? = null
)
@Serializable
class Requestinfo(
@ProtoType(ProtoNumberType.FIXED) @SerialId(1) val reqIp: Int = 0,
@SerialId(2) val reqPort: Int = 0,
@SerialId(3) val reqFlag: Int = 0
)
@Serializable
class Signature(
@SerialId(1) val keyType: Int = 0,
@SerialId(2) val sessionAppId: Int = 0,
@SerialId(3) val sessionKey: ByteArray = EMPTY_BYTE_ARRAY
)
}
@Serializable
class ImMsg {
@Serializable
class C2C(
@SerialId(1) val sender: ImCommon.User? = null,
@SerialId(2) val receiver: ImCommon.User? = null,
@SerialId(3) val c2cRelation: C2CRelation? = null
)
@Serializable
class C2CRelation(
@SerialId(1) val c2cType: Int /* enum */ = 0,
@SerialId(2) val groupInfo: ImCommon.GroupInfo? = null,
@SerialId(3) val token: ImCommon.Token? = null
)
@Serializable
class ContentHead(
@SerialId(1) val pkgNum: Int = 1,
@SerialId(2) val pkgIndex: Int = 0,
@SerialId(3) val seq: Int = 0,
@SerialId(4) val dateTime: Int = 0,
@SerialId(5) val msgType: Int = 0,
@SerialId(6) val divSeq: Int = 0,
@SerialId(7) val msgdbUin: Long = 0L,
@SerialId(8) val msgdbSeq: Int = 0,
@SerialId(9) val wordMsgSeq: Int = 0,
@SerialId(10) val msgRand: Int = 0
)
@Serializable
class Group(
@SerialId(1) val sender: ImCommon.User? = null,
@SerialId(2) val receiver: ImCommon.User? = null,
@SerialId(3) val groupInfo: ImCommon.GroupInfo? = null
)
@Serializable
class Msg(
@SerialId(1) val head: MsgHead? = null,
@SerialId(2) val body: ImMsgBody.MsgBody? = null
)
@Serializable
class MsgHead(
@SerialId(1) val routingHead: RoutingHead? = null,
@SerialId(2) val contentHead: ContentHead? = null,
@SerialId(3) val gbkTmpMsgBody: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class MsgSendReq(
@SerialId(1) val msg: Msg? = null,
@SerialId(2) val buMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val msgTailId: Int = 0,
@SerialId(4) val connMsgFlag: Int = 0,
@SerialId(5) val cookie: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class MsgSendResp
@Serializable
class RoutingHead(
@SerialId(1) val c2c: C2C? = null,
@SerialId(2) val group: Group? = null
)
}
@Serializable
class ImMsgBody {
@Serializable
class AnonymousGroupMsg(
@SerialId(1) val flags: Int = 0,
@SerialId(2) val anonId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val anonNick: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val headPortrait: Int = 0,
@SerialId(5) val expireTime: Int = 0,
@SerialId(6) val bubbleId: Int = 0,
@SerialId(7) val rankColor: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class ApolloActMsg(
@SerialId(1) val actionId: Int = 0,
@SerialId(2) val actionName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val actionText: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val flag: Int = 0,
@SerialId(5) val peerUin: Int = 0,
@SerialId(6) val senderTs: Int = 0,
@SerialId(7) val peerTs: Int = 0,
@SerialId(8) val int32SenderStatus: Int = 0,
@SerialId(9) val int32PeerStatus: Int = 0,
@SerialId(10) val diytextId: Int = 0,
@SerialId(11) val diytextContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val inputText: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class ArkAppElem(
@SerialId(1) val appName: String = "",
@SerialId(2) val minVersion: String = "",
@SerialId(3) val xmlTemplate: String = "",
@SerialId(4) val data: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class Attr(
@ProtoType(ProtoNumberType.SIGNED) @SerialId(1) val codePage: Int = -1,
@SerialId(2) val time: Int = 1,
@SerialId(3) val random: Int = 0,
@SerialId(4) val color: Int = 0,
@SerialId(5) val size: Int = 10,
@SerialId(6) val effect: Int = 7,
@SerialId(7) val charSet: Int = 78,
@SerialId(8) val pitchAndFamily: Int = 90,
@SerialId(9) val fontName: String = "Times New Roman",
@SerialId(10) val reserveData: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class BitAppMsg(
@SerialId(1) val buf: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class BlessingMessage(
@SerialId(1) val msgType: Int = 0,
@SerialId(2) val exFlag: Int = 0
)
@Serializable
class CommonElem(
@SerialId(1) val serviceType: Int = 0,
@SerialId(2) val pbElem: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val businessType: Int = 0
)
@Serializable
class ConferenceTipsInfo(
@SerialId(1) val sessionType: Int = 0,
@SerialId(2) val sessionUin: Long = 0L,
@SerialId(3) val text: String = ""
)
@Serializable
class CrmElem(
@SerialId(1) val crmBuf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val msgResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val qidianFlag: Int = 0,
@SerialId(4) val pushFlag: Int = 0,
@SerialId(5) val countFlag: Int = 0
)
@Serializable
class CustomElem(
@SerialId(1) val desc: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val data: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val enumType: Int /* enum */ = 1,
@SerialId(4) val ext: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val sound: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class CustomFace(
@SerialId(1) val guid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val filePath: String = "",
@SerialId(3) val shortcut: String = "",
@SerialId(4) val buffer: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val flag: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val oldData: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val fileId: Int = 0,
@SerialId(8) val serverIp: Int = 0,
@SerialId(9) val serverPort: Int = 0,
@SerialId(10) val fileType: Int = 0,
@SerialId(11) val signature: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val useful: Int = 0,
@SerialId(13) val md5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val thumbUrl: String = "",
@SerialId(15) val bigUrl: String = "",
@SerialId(16) val origUrl: String = "",
@SerialId(17) val bizType: Int = 0,
@SerialId(18) val repeatIndex: Int = 0,
@SerialId(19) val repeatImage: Int = 0,
@SerialId(20) val imageType: Int = 0,
@SerialId(21) val index: Int = 0,
@SerialId(22) val width: Int = 0,
@SerialId(23) val height: Int = 0,
@SerialId(24) val source: Int = 0,
@SerialId(25) val size: Int = 0,
@SerialId(26) val origin: Int = 0,
@SerialId(27) val thumbWidth: Int = 0,
@SerialId(28) val thumbHeight: Int = 0,
@SerialId(29) val showLen: Int = 0,
@SerialId(30) val downloadLen: Int = 0,
@SerialId(31) val _400Url: String = "",
@SerialId(32) val _400Width: Int = 0,
@SerialId(33) val _400Height: Int = 0,
@SerialId(34) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class DeliverGiftMsg(
@SerialId(1) val grayTipContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val animationPackageId: Int = 0,
@SerialId(3) val animationPackageUrlA: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val animationPackageUrlI: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val remindBrief: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val giftId: Int = 0,
@SerialId(7) val giftCount: Int = 0,
@SerialId(8) val animationBrief: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val senderUin: Long = 0L,
@SerialId(10) val receiverUin: Long = 0L,
@SerialId(11) val stmessageTitle: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val stmessageSubtitle: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val stmessageMessage: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val stmessageGiftpicid: Int = 0,
@SerialId(15) val stmessageComefrom: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(16) val stmessageExflag: Int = 0,
@SerialId(17) val toAllGiftId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(18) val comefromLink: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(20) val receiverName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(21) val receiverPic: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(22) val stmessageGifturl: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class EIMInfo(
@SerialId(1) val rootId: Long = 0L,
@SerialId(2) val flag: Int = 0
)
@Serializable
class Elem(
@SerialId(1) val text: ImMsgBody.Text? = null,
@SerialId(2) val face: ImMsgBody.Face? = null,
@SerialId(3) val onlineImage: ImMsgBody.OnlineImage? = null,
@SerialId(4) val notOnlineImage: ImMsgBody.NotOnlineImage? = null,
@SerialId(5) val transElemInfo: ImMsgBody.TransElem? = null,
@SerialId(6) val marketFace: ImMsgBody.MarketFace? = null,
@SerialId(7) val elemFlags: ImMsgBody.ElemFlags? = null,
@SerialId(8) val customFace: ImMsgBody.CustomFace? = null,
@SerialId(9) val elemFlags2: ImMsgBody.ElemFlags2? = null,
@SerialId(10) val funFace: ImMsgBody.FunFace? = null,
@SerialId(11) val secretFile: ImMsgBody.SecretFileMsg? = null,
@SerialId(12) val richMsg: ImMsgBody.RichMsg? = null,
@SerialId(13) val groupFile: ImMsgBody.GroupFile? = null,
@SerialId(14) val pubGroup: ImMsgBody.PubGroup? = null,
@SerialId(15) val marketTrans: ImMsgBody.MarketTrans? = null,
@SerialId(16) val extraInfo: ImMsgBody.ExtraInfo? = null,
@SerialId(17) val shakeWindow: ImMsgBody.ShakeWindow? = null,
@SerialId(18) val pubAccount: ImMsgBody.PubAccount? = null,
@SerialId(19) val videoFile: ImMsgBody.VideoFile? = null,
@SerialId(20) val tipsInfo: ImMsgBody.TipsInfo? = null,
@SerialId(21) val anonGroupMsg: ImMsgBody.AnonymousGroupMsg? = null,
@SerialId(22) val qqLiveOld: ImMsgBody.QQLiveOld? = null,
@SerialId(23) val lifeOnline: ImMsgBody.LifeOnlineAccount? = null,
@SerialId(24) val qqwalletMsg: ImMsgBody.QQWalletMsg? = null,
@SerialId(25) val crmElem: ImMsgBody.CrmElem? = null,
@SerialId(26) val conferenceTipsInfo: ImMsgBody.ConferenceTipsInfo? = null,
@SerialId(27) val redbagInfo: ImMsgBody.RedBagInfo? = null,
@SerialId(28) val lowVersionTips: ImMsgBody.LowVersionTips? = null,
@SerialId(29) val bankcodeCtrlInfo: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(30) val nearByMsg: ImMsgBody.NearByMessageType? = null,
@SerialId(31) val customElem: ImMsgBody.CustomElem? = null,
@SerialId(32) val locationInfo: ImMsgBody.LocationInfo? = null,
@SerialId(33) val pubAccInfo: ImMsgBody.PubAccInfo? = null,
@SerialId(34) val smallEmoji: ImMsgBody.SmallEmoji? = null,
@SerialId(35) val fsjMsgElem: ImMsgBody.FSJMessageElem? = null,
@SerialId(36) val arkApp: ImMsgBody.ArkAppElem? = null,
@SerialId(37) val generalFlags: ImMsgBody.GeneralFlags? = null,
@SerialId(38) val hcFlashPic: ImMsgBody.CustomFace? = null,
@SerialId(39) val deliverGiftMsg: ImMsgBody.DeliverGiftMsg? = null,
@SerialId(40) val bitappMsg: ImMsgBody.BitAppMsg? = null,
@SerialId(41) val openQqData: ImMsgBody.OpenQQData? = null,
@SerialId(42) val apolloMsg: ImMsgBody.ApolloActMsg? = null,
@SerialId(43) val groupPubAccInfo: ImMsgBody.GroupPubAccountInfo? = null,
@SerialId(44) val blessMsg: ImMsgBody.BlessingMessage? = null,
@SerialId(45) val srcMsg: ImMsgBody.SourceMsg? = null,
@SerialId(46) val lolaMsg: ImMsgBody.LolaMsg? = null,
@SerialId(47) val groupBusinessMsg: ImMsgBody.GroupBusinessMsg? = null,
@SerialId(48) val msgWorkflowNotify: ImMsgBody.WorkflowNotifyMsg? = null,
@SerialId(49) val patElem: ImMsgBody.PatsElem? = null,
@SerialId(50) val groupPostElem: ImMsgBody.GroupPostElem? = null,
@SerialId(51) val lightApp: ImMsgBody.LightAppElem? = null,
@SerialId(52) val eimInfo: ImMsgBody.EIMInfo? = null,
@SerialId(53) val commonElem: ImMsgBody.CommonElem? = null
)
@Serializable
class ElemFlags(
@SerialId(1) val flags1: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val businessData: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class ElemFlags2(
@SerialId(1) val colorTextId: Int = 0,
@SerialId(2) val msgId: Long = 0L,
@SerialId(3) val whisperSessionId: Int = 0,
@SerialId(4) val pttChangeBit: Int = 0,
@SerialId(5) val vipStatus: Int = 0,
@SerialId(6) val compatibleId: Int = 0,
@SerialId(7) val insts: List<ImMsgBody.ElemFlags2.Inst>? = null,
@SerialId(8) val msgRptCnt: Int = 0,
@SerialId(9) val srcInst: ImMsgBody.ElemFlags2.Inst? = null,
@SerialId(10) val longtitude: Int = 0,
@SerialId(11) val latitude: Int = 0,
@SerialId(12) val customFont: Int = 0,
@SerialId(13) val pcSupportDef: ImMsgBody.PcSupportDef? = null,
@SerialId(14) val crmFlags: Int = 0
) {
@Serializable
class Inst(
@SerialId(1) val appId: Int = 0,
@SerialId(2) val instId: Int = 0
)
}
@Serializable
class ExtraInfo(
@SerialId(1) val nick: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val groupCard: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val level: Int = 0,
@SerialId(4) val flags: Int = 0,
@SerialId(5) val groupMask: Int = 0,
@SerialId(6) val msgTailId: Int = 0,
@SerialId(7) val senderTitle: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val apnsTips: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val uin: Long = 0L,
@SerialId(10) val msgStateFlag: Int = 0,
@SerialId(11) val apnsSoundType: Int = 0,
@SerialId(12) val newGroupFlag: Int = 0
)
@Serializable
class Face(
@SerialId(1) val index: Int = 0,
@SerialId(2) val old: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val buf: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class FSJMessageElem(
@SerialId(1) val msgType: Int = 0
)
@Serializable
class FunFace(
@SerialId(1) val msgTurntable: ImMsgBody.FunFace.Turntable? = null,
@SerialId(2) val msgBomb: ImMsgBody.FunFace.Bomb? = null
) {
@Serializable
class Bomb(
@SerialId(1) val boolBurst: Boolean = false
)
@Serializable
class Turntable(
@SerialId(1) val uint64UinList: List<Long>? = null,
@SerialId(2) val hitUin: Long = 0L,
@SerialId(3) val hitUinNick: String = ""
)
}
@Serializable
class GeneralFlags(
@SerialId(1) val bubbleDiyTextId: Int = 0,
@SerialId(2) val groupFlagNew: Int = 0,
@SerialId(3) val uin: Long = 0L,
@SerialId(4) val rpId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val prpFold: Int = 0,
@SerialId(6) val longTextFlag: Int = 0,
@SerialId(7) val longTextResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val groupType: Int = 0,
@SerialId(9) val toUinFlag: Int = 0,
@SerialId(10) val glamourLevel: Int = 0,
@SerialId(11) val memberLevel: Int = 0,
@SerialId(12) val groupRankSeq: Long = 0L,
@SerialId(13) val olympicTorch: Int = 0,
@SerialId(14) val babyqGuideMsgCookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(15) val uin32ExpertFlag: Int = 0,
@SerialId(16) val bubbleSubId: Int = 0,
@SerialId(17) val pendantId: Long = 0L,
@SerialId(18) val rpIndex: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class GroupBusinessMsg(
@SerialId(1) val flags: Int = 0,
@SerialId(2) val headUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val headClkUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val nick: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val nickColor: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val rank: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val rankColor: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val rankBgcolor: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class GroupFile(
@SerialId(1) val filename: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fileSize: Long = 0L,
@SerialId(3) val fileId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val batchId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val mark: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val sequence: Long = 0L,
@SerialId(8) val batchItemId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val feedMsgTime: Int = 0,
@SerialId(10) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class GroupPostElem(
@SerialId(1) val transType: Int = 0,
@SerialId(2) val transMsg: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class GroupPubAccountInfo(
@SerialId(1) val pubAccount: Long = 0L
)
@Serializable
class LifeOnlineAccount(
@SerialId(1) val uniqueId: Long = 0L,
@SerialId(2) val op: Int = 0,
@SerialId(3) val showTime: Int = 0,
@SerialId(4) val report: Int = 0,
@SerialId(5) val ack: Int = 0,
@SerialId(6) val bitmap: Long = 0L,
@SerialId(7) val gdtImpData: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val gdtCliData: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val viewId: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class LightAppElem(
@SerialId(1) val data: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val msgResid: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class LocationInfo(
@SerialId(1) val longitude: Double = 0.0,
@SerialId(2) val latitude: Double = 0.0,
@SerialId(3) val desc: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class LolaMsg(
@SerialId(1) val msgResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val encodeContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val longMsgUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val downloadKey: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class LowVersionTips(
@SerialId(1) val businessId: Int = 0,
@SerialId(2) val sessionType: Int = 0,
@SerialId(3) val sessionUin: Long = 0L,
@SerialId(4) val senderUin: Long = 0L,
@SerialId(5) val text: String = ""
)
@Serializable
class MarketFace(
@SerialId(1) val faceName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val itemType: Int = 0,
@SerialId(3) val faceInfo: Int = 0,
@SerialId(4) val faceId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val tabId: Int = 0,
@SerialId(6) val subType: Int = 0,
@SerialId(7) val key: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val param: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val mediaType: Int = 0,
@SerialId(10) val imageWidth: Int = 0,
@SerialId(11) val imageHeight: Int = 0,
@SerialId(12) val mobileparam: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class MarketTrans(
@SerialId(1) val int32Flag: Int = 0,
@SerialId(2) val xml: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val msgResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val ability: Int = 0,
@SerialId(5) val minAbility: Int = 0
)
@Serializable
class MsgBody(
@SerialId(1) val richText: ImMsgBody.RichText? = null,
@SerialId(2) val msgContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val msgEncryptContent: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class MsgBodySubtype4(
@SerialId(1) val msgNotOnlineFile: ImMsgBody.NotOnlineFile? = null,
@SerialId(2) val msgTime: Int = 0
)
@Serializable
class NearByMessageType(
@SerialId(1) val type: Int = 0,
@SerialId(2) val identifyType: Int = 0
)
@Serializable
class NotOnlineFile(
@SerialId(1) val fileType: Int = 0,
@SerialId(2) val sig: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val fileUuid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val fileSize: Long = 0L,
@SerialId(7) val note: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val reserved: Int = 0,
@SerialId(9) val subcmd: Int = 0,
@SerialId(10) val microCloud: Int = 0,
@SerialId(11) val bytesFileUrls: List<ByteArray>? = null,
@SerialId(12) val downloadFlag: Int = 0,
@SerialId(50) val dangerEvel: Int = 0,
@SerialId(51) val lifeTime: Int = 0,
@SerialId(52) val uploadTime: Int = 0,
@SerialId(53) val absFileType: Int = 0,
@SerialId(54) val clientType: Int = 0,
@SerialId(55) val expireTime: Int = 0,
@SerialId(56) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class NotOnlineImage(
@SerialId(1) val filePath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fileLen: Int = 0,
@SerialId(3) val downloadPath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val oldVerSendFile: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val imgType: Int = 0,
@SerialId(6) val previewsImage: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val picMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val picHeight: Int = 0,
@SerialId(9) val picWidth: Int = 0,
@SerialId(10) val resId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val flag: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val thumbUrl: String = "",
@SerialId(13) val original: Int = 0,
@SerialId(14) val bigUrl: String = "",
@SerialId(15) val origUrl: String = "",
@SerialId(16) val bizType: Int = 0,
@SerialId(17) val result: Int = 0,
@SerialId(18) val index: Int = 0,
@SerialId(19) val opFaceBuf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(20) val oldPicMd5: Boolean = false,
@SerialId(21) val thumbWidth: Int = 0,
@SerialId(22) val thumbHeight: Int = 0,
@SerialId(23) val fileId: Int = 0,
@SerialId(24) val showLen: Int = 0,
@SerialId(25) val downloadLen: Int = 0,
@SerialId(26) val _400Url: String = "",
@SerialId(27) val _400Width: Int = 0,
@SerialId(28) val _400Height: Int = 0,
@SerialId(29) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class OnlineImage(
@SerialId(1) val guid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val filePath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val oldVerSendFile: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class OpenQQData(
@SerialId(1) val carQqData: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class PatsElem(
@SerialId(1) val patType: Int = 0,
@SerialId(2) val patCount: Int = 0
)
@Serializable
class PcSupportDef(
@SerialId(1) val pcPtlBegin: Int = 0,
@SerialId(2) val pcPtlEnd: Int = 0,
@SerialId(3) val macPtlBegin: Int = 0,
@SerialId(4) val macPtlEnd: Int = 0,
@SerialId(5) val ptlsSupport: List<Int>? = null,
@SerialId(6) val ptlsNotSupport: List<Int>? = null
)
@Serializable
class Ptt(
@SerialId(1) val fileType: Int = 0,
@SerialId(2) val srcUin: Long = 0L,
@SerialId(3) val fileUuid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val fileSize: Int = 0,
@SerialId(7) val reserve: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val fileId: Int = 0,
@SerialId(9) val serverIp: Int = 0,
@SerialId(10) val serverPort: Int = 0,
@SerialId(11) val boolValid: Boolean = false,
@SerialId(12) val signature: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val shortcut: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(15) val magicPttIndex: Int = 0,
@SerialId(16) val voiceSwitch: Int = 0,
@SerialId(17) val pttUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(18) val groupFileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val time: Int = 0,
@SerialId(20) val downPara: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(29) val format: Int = 0,
@SerialId(30) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(31) val bytesPttUrls: List<ByteArray>? = null,
@SerialId(32) val downloadFlag: Int = 0
)
@Serializable
class PubAccInfo(
@SerialId(1) val isInterNum: Int = 0,
@SerialId(2) val ingMsgTemplateId: String = "",
@SerialId(3) val ingLongMsgUrl: String = "",
@SerialId(4) val downloadKey: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class PubAccount(
@SerialId(1) val buf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val pubAccountUin: Long = 0L
)
@Serializable
class PubGroup(
@SerialId(1) val nickname: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val gender: Int = 0,
@SerialId(3) val age: Int = 0,
@SerialId(4) val distance: Int = 0
)
@Serializable
class QQLiveOld(
@SerialId(1) val subCmd: Int = 0,
@SerialId(2) val showText: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val param: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val introduce: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class QQWalletAioBody(
@SerialId(1) val senduin: Long = 0L,
@SerialId(2) val sender: ImMsgBody.QQWalletAioElem? = null,
@SerialId(3) val receiver: ImMsgBody.QQWalletAioElem? = null,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(4) val sint32Channelid: Int = 0,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(5) val sint32Templateid: Int = 0,
@SerialId(6) val resend: Int = 0,
@SerialId(7) val msgPriority: Int = 0,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(8) val sint32Redtype: Int = 0,
@SerialId(9) val billno: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val authkey: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(11) val sint32Sessiontype: Int = 0,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(12) val sint32Msgtype: Int = 0,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(13) val sint32Envelopeid: Int = 0,
@SerialId(14) val name: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(15) val sint32Conftype: Int = 0,
@ProtoType(ProtoNumberType.SIGNED) @SerialId(16) val sint32MsgFrom: Int = 0,
@SerialId(17) val pcBody: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(18) val ingIndex: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val redchannel: Int = 0,
@SerialId(20) val grapUin: List<Long>? = null,
@SerialId(21) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class QQWalletAioElem(
@SerialId(1) val background: Int = 0,
@SerialId(2) val icon: Int = 0,
@SerialId(3) val title: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val subtitle: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val content: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val linkurl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val blackstripe: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val notice: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val titleColor: Int = 0,
@SerialId(10) val subtitleColor: Int = 0,
@SerialId(11) val actionsPriority: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val jumpUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(13) val nativeIos: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val nativeAndroid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(15) val iconurl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(16) val contentColor: Int = 0,
@SerialId(17) val contentBgcolor: Int = 0,
@SerialId(18) val aioImageLeft: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val aioImageRight: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(20) val cftImage: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(21) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class QQWalletMsg(
@SerialId(1) val aioBody: ImMsgBody.QQWalletAioBody? = null
)
@Serializable
class RedBagInfo(
@SerialId(1) val redbagType: Int = 0
)
@Serializable
class RichMsg(
@SerialId(1) val template1: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val serviceId: Int = 0,
@SerialId(3) val msgResid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val rand: Int = 0,
@SerialId(5) val seq: Int = 0,
@SerialId(6) val flags: Int = 0
)
@Serializable
class RichText(
@SerialId(1) val attr: ImMsgBody.Attr? = null,
@SerialId(2) val elems: List<ImMsgBody.Elem>? = null,
@SerialId(3) val notOnlineFile: ImMsgBody.NotOnlineFile? = null,
@SerialId(4) val ptt: ImMsgBody.Ptt? = null,
@SerialId(5) val tmpPtt: ImMsgBody.TmpPtt? = null,
@SerialId(6) val trans211TmpMsg: ImMsgBody.Trans211TmpMsg? = null
)
@Serializable
class SecretFileMsg(
@SerialId(1) val fileKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fromUin: Long = 0L,
@SerialId(3) val toUin: Long = 0L,
@SerialId(4) val status: Int = 0,
@SerialId(5) val ttl: Int = 0,
@SerialId(6) val type: Int = 0,
@SerialId(7) val encryptPreheadLength: Int = 0,
@SerialId(8) val encryptType: Int = 0,
@SerialId(9) val encryptKey: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val readTimes: Int = 0,
@SerialId(11) val leftTime: Int = 0,
@SerialId(12) val notOnlineImage: ImMsgBody.NotOnlineImage? = null,
@SerialId(13) val elemFlags2: ImMsgBody.ElemFlags2? = null,
@SerialId(14) val opertype: Int = 0,
@SerialId(15) val fromphonenum: String = ""
)
@Serializable
class ShakeWindow(
@SerialId(1) val type: Int = 0,
@SerialId(2) val reserve: Int = 0,
@SerialId(3) val uin: Long = 0L
)
@Serializable
class SmallEmoji(
@SerialId(1) val packIdSum: Int = 0,
@SerialId(2) val imageType: Int = 0
)
@Serializable
class SourceMsg(
@SerialId(1) val origSeqs: List<Int>? = null,
@SerialId(2) val senderUin: Long = 0L,
@SerialId(3) val time: Int = 0,
@SerialId(4) val flag: Int = 0,
@SerialId(5) val elems: List<ImMsgBody.Elem>? = null,
@SerialId(6) val type: Int = 0,
@SerialId(7) val richMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(9) val srcMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val toUin: Long = 0L,
@SerialId(11) val troopName: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class Text(
@SerialId(1) val str: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val link: String = "",
@SerialId(3) val attr6Buf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val attr7Buf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val buf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(12) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class TipsInfo(
@SerialId(1) val text: String = ""
)
@Serializable
class TmpPtt(
@SerialId(1) val fileType: Int = 0,
@SerialId(2) val fileUuid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val fileName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val fileSize: Int = 0,
@SerialId(6) val pttTimes: Int = 0,
@SerialId(7) val userType: Int = 0,
@SerialId(8) val ptttransFlag: Int = 0,
@SerialId(9) val busiType: Int = 0,
@SerialId(10) val msgId: Long = 0L,
@SerialId(30) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(31) val pttEncodeData: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class Trans211TmpMsg(
@SerialId(1) val msgBody: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val c2cCmd: Int = 0
)
@Serializable
class TransElem(
@SerialId(1) val elemType: Int = 0,
@SerialId(2) val elemValue: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class VideoFile(
@SerialId(1) val fileUuid: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val fileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val fileName: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val fileFormat: Int = 0,
@SerialId(5) val fileTime: Int = 0,
@SerialId(6) val fileSize: Int = 0,
@SerialId(7) val thumbWidth: Int = 0,
@SerialId(8) val thumbHeight: Int = 0,
@SerialId(9) val thumbFileMd5: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(10) val source: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(11) val thumbFileSize: Int = 0,
@SerialId(12) val busiType: Int = 0,
@SerialId(13) val fromChatType: Int = 0,
@SerialId(14) val toChatType: Int = 0,
@SerialId(15) val boolSupportProgressive: Boolean = false,
@SerialId(16) val fileWidth: Int = 0,
@SerialId(17) val fileHeight: Int = 0,
@SerialId(18) val subBusiType: Int = 0,
@SerialId(19) val videoAttr: Int = 0,
@SerialId(20) val bytesThumbFileUrls: List<ByteArray>? = null,
@SerialId(21) val bytesVideoFileUrls: List<ByteArray>? = null,
@SerialId(22) val thumbDownloadFlag: Int = 0,
@SerialId(23) val videoDownloadFlag: Int = 0,
@SerialId(24) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class WorkflowNotifyMsg(
@SerialId(1) val extMsg: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val createUin: Long = 0L
)
}
@Serializable
class ImMsgHead {
@Serializable
class C2CHead(
@SerialId(1) val toUin: Long = 0L,
@SerialId(2) val fromUin: Long = 0L,
@SerialId(3) val ccType: Int = 0,
@SerialId(4) val ccCmd: Int = 0,
@SerialId(5) val authPicSig: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val authSig: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val authBuf: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(8) val serverTime: Int = 0,
@SerialId(9) val clientTime: Int = 0,
@SerialId(10) val rand: Int = 0,
@SerialId(11) val ingPhoneNumber: String = ""
)
@Serializable
class CSHead(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val command: Int = 0,
@SerialId(3) val seq: Int = 0,
@SerialId(4) val version: Int = 0,
@SerialId(5) val retryTimes: Int = 0,
@SerialId(6) val clientType: Int = 0,
@SerialId(7) val pubno: Int = 0,
@SerialId(8) val localid: Int = 0,
@SerialId(9) val timezone: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(10) val clientIp: Int = 0,
@SerialId(11) val clientPort: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(12) val connIp: Int = 0,
@SerialId(13) val connPort: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(14) val interfaceIp: Int = 0,
@SerialId(15) val interfacePort: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(16) val actualIp: Int = 0,
@SerialId(17) val flag: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(18) val timestamp: Int = 0,
@SerialId(19) val subcmd: Int = 0,
@SerialId(20) val result: Int = 0,
@SerialId(21) val appId: Int = 0,
@SerialId(22) val instanceId: Int = 0,
@SerialId(23) val sessionId: Long = 0L,
@SerialId(24) val idcId: Int = 0
)
@Serializable
class DeltaHead(
@SerialId(1) val totalLen: Long = 0L,
@SerialId(2) val offset: Long = 0L,
@SerialId(3) val ackOffset: Long = 0L,
@SerialId(4) val cookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val ackCookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val result: Int = 0,
@SerialId(7) val flags: Int = 0
)
@Serializable
class Head(
@SerialId(1) val headType: Int = 0,
@SerialId(2) val msgCsHead: CSHead? = null,
@SerialId(3) val msgS2cHead: S2CHead? = null,
@SerialId(4) val msgHttpconnHead: HttpConnHead? = null,
@SerialId(5) val paintFlag: Int = 0,
@SerialId(6) val msgLoginSig: LoginSig? = null,
@SerialId(7) val msgDeltaHead: DeltaHead? = null,
@SerialId(8) val msgC2cHead: C2CHead? = null,
@SerialId(9) val msgSconnHead: SConnHead? = null,
@SerialId(10) val msgInstCtrl: InstCtrl? = null
)
@Serializable
class HttpConnHead(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val command: Int = 0,
@SerialId(3) val subCommand: Int = 0,
@SerialId(4) val seq: Int = 0,
@SerialId(5) val version: Int = 0,
@SerialId(6) val retryTimes: Int = 0,
@SerialId(7) val clientType: Int = 0,
@SerialId(8) val pubNo: Int = 0,
@SerialId(9) val localId: Int = 0,
@SerialId(10) val timeZone: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(11) val clientIp: Int = 0,
@SerialId(12) val clientPort: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(13) val qzhttpIp: Int = 0,
@SerialId(14) val qzhttpPort: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(15) val sppIp: Int = 0,
@SerialId(16) val sppPort: Int = 0,
@SerialId(17) val flag: Int = 0,
@SerialId(18) val key: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(19) val compressType: Int = 0,
@SerialId(20) val originSize: Int = 0,
@SerialId(21) val errorCode: Int = 0,
@SerialId(22) val msgRedirect: RedirectMsg? = null,
@SerialId(23) val commandId: Int = 0,
@SerialId(24) val serviceCmdid: Int = 0,
@SerialId(25) val msgOidbhead: TransOidbHead? = null
)
@Serializable
class InstCtrl(
@SerialId(1) val msgSendToInst: List<InstInfo>? = null,
@SerialId(2) val msgExcludeInst: List<InstInfo>? = null,
@SerialId(3) val msgFromInst: InstInfo? = null
)
@Serializable
class InstInfo(
@SerialId(1) val apppid: Int = 0,
@SerialId(2) val instid: Int = 0,
@SerialId(3) val platform: Int = 0,
@SerialId(10) val enumDeviceType: Int /* enum */ = 0
)
@Serializable
class LoginSig(
@SerialId(1) val type: Int = 0,
@SerialId(2) val sig: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class RedirectMsg(
@ProtoType(ProtoNumberType.FIXED) @SerialId(1) val lastRedirectIp: Int = 0,
@SerialId(2) val lastRedirectPort: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(3) val redirectIp: Int = 0,
@SerialId(4) val redirectPort: Int = 0,
@SerialId(5) val redirectCount: Int = 0
)
@Serializable
class S2CHead(
@SerialId(1) val subMsgtype: Int = 0,
@SerialId(2) val msgType: Int = 0,
@SerialId(3) val fromUin: Long = 0L,
@SerialId(4) val msgId: Int = 0,
@ProtoType(ProtoNumberType.FIXED) @SerialId(5) val relayIp: Int = 0,
@SerialId(6) val relayPort: Int = 0,
@SerialId(7) val toUin: Long = 0L
)
@Serializable
class SConnHead
@Serializable
class TransOidbHead(
@SerialId(1) val command: Int = 0,
@SerialId(2) val serviceType: Int = 0,
@SerialId(3) val result: Int = 0,
@SerialId(4) val errorMsg: String = ""
)
}
@Serializable
class ImReceipt {
@Serializable
class MsgInfo(
@SerialId(1) val fromUin: Long = 0L,
@SerialId(2) val toUin: Long = 0L,
@SerialId(3) val msgSeq: Int = 0,
@SerialId(4) val msgRandom: Int = 0
)
@Serializable
class ReceiptInfo(
@SerialId(1) val readTime: Long = 0L
)
@Serializable
class ReceiptReq(
@SerialId(1) val command: Int /* enum */ = 1,
@SerialId(2) val msgInfo: MsgInfo? = null
)
@Serializable
class ReceiptResp(
@SerialId(1) val command: Int /* enum */ = 1,
@SerialId(2) val receiptInfo: ReceiptInfo? = null
)
}
@Serializable
class ObjMsg {
@Serializable
class MsgContentInfo(
@SerialId(1) val contentInfoId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val msgFile: MsgFile? = null
) {
@Serializable
class MsgFile(
@SerialId(1) val busId: Int = 0,
@SerialId(2) val filePath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val fileSize: Long = 0L,
@SerialId(4) val fileName: String = "",
@SerialId(5) val int64DeadTime: Long = 0L,
@SerialId(6) val fileSha1: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val ext: ByteArray = EMPTY_BYTE_ARRAY
)
}
@Serializable
class MsgPic(
@SerialId(1) val smallPicUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(2) val originalPicUrl: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val localPicId: Int = 0
)
@Serializable
class ObjMsg(
@SerialId(1) val msgType: Int = 0,
@SerialId(2) val title: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val bytesAbstact: List<ByteArray>? = null,
@SerialId(5) val titleExt: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val msgPic: List<MsgPic>? = null,
@SerialId(7) val msgContentInfo: List<MsgContentInfo>? = null,
@SerialId(8) val reportIdShow: Int = 0
)
}
\ No newline at end of file
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
/**
* msf.msgcomm.msg_comm
*/
@Serializable
class MsgComm {
@Serializable
class AppShareInfo(
@SerialId(1) val appshareId: Int = 0,
@SerialId(2) val appshareCookie: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(3) val appshareResource: PluginInfo? = null
)
@Serializable
class C2CTmpMsgHead(
@SerialId(1) val c2cType: Int = 0,
@SerialId(2) val serviceType: Int = 0,
@SerialId(3) val groupUin: Long = 0L,
@SerialId(4) val groupCode: Long = 0L,
@SerialId(5) val sig: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val sigType: Int = 0,
@SerialId(7) val fromPhone: String = "",
@SerialId(8) val toPhone: String = "",
@SerialId(9) val lockDisplay: Int = 0,
@SerialId(10) val directionFlag: Int = 0,
@SerialId(11) val reserved: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class ContentHead(
@SerialId(1) val pkgNum: Int = 0,
@SerialId(2) val pkgIndex: Int = 0,
@SerialId(3) val divSeq: Int = 0,
@SerialId(4) val autoReply: Int = 0
)
@Serializable
class DiscussInfo(
@SerialId(1) val discussUin: Long = 0L,
@SerialId(2) val discussType: Int = 0,
@SerialId(3) val discussInfoSeq: Long = 0L,
@SerialId(4) val discussRemark: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val discussName: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class ExtGroupKeyInfo(
@SerialId(1) val curMaxSeq: Int = 0,
@SerialId(2) val curTime: Long = 0L
)
@Serializable
class GroupInfo(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val groupType: Int = 0,
@SerialId(3) val groupInfoSeq: Long = 0L,
@SerialId(4) val groupCard: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val groupRank: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(6) val groupLevel: Int = 0,
@SerialId(7) val groupCardType: Int = 0,
@SerialId(8) val groupName: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class Msg(
@SerialId(1) val msgHead: MsgHead? = null,
@SerialId(2) val contentHead: ContentHead? = null,
@SerialId(3) val msgBody: ImMsgBody.MsgBody? = null,
@SerialId(4) val appshareInfo: AppShareInfo? = null
)
@Serializable
class MsgHead(
@SerialId(1) val fromUin: Long = 0L,
@SerialId(2) val toUin: Long = 0L,
@SerialId(3) val msgType: Int = 0,
@SerialId(4) val c2cCmd: Int = 0,
@SerialId(5) val msgSeq: Int = 0,
@SerialId(6) val msgTime: Int = 0,
@SerialId(7) val msgUid: Long = 0L,
@SerialId(8) val c2cTmpMsgHead: C2CTmpMsgHead? = null,
@SerialId(9) val groupInfo: GroupInfo? = null,
@SerialId(10) val fromAppid: Int = 0,
@SerialId(11) val fromInstid: Int = 0,
@SerialId(12) val userActive: Int = 0,
@SerialId(13) val discussInfo: DiscussInfo? = null,
@SerialId(14) val fromNick: String = "",
@SerialId(15) val authUin: Long = 0L,
@SerialId(16) val authNick: String = "",
@SerialId(17) val msgFlag: Int = 0,
@SerialId(18) val authRemark: String = "",
@SerialId(19) val groupName: String = "",
@SerialId(20) val mutiltransHead: MutilTransHead? = null,
@SerialId(21) val msgInstCtrl: ImMsgHead.InstCtrl? = null,
@SerialId(22) val publicAccountGroupSendFlag: Int = 0,
@SerialId(23) val wseqInC2cMsghead: Int = 0,
@SerialId(24) val cpid: Long = 0L,
@SerialId(25) val extGroupKeyInfo: ExtGroupKeyInfo? = null,
@SerialId(26) val multiCompatibleText: String = "",
@SerialId(27) val authSex: Int = 0,
@SerialId(28) val isSrcMsg: Boolean = false
)
@Serializable
class MsgType0x210(
@SerialId(1) val subMsgType: Int = 0,
@SerialId(2) val msgContent: ByteArray = EMPTY_BYTE_ARRAY
)
@Serializable
class MutilTransHead(
@SerialId(1) val status: Int = 0,
@SerialId(2) val msgId: Int = 0
)
@Serializable
class PluginInfo(
@SerialId(1) val resId: Int = 0,
@SerialId(2) val pkgName: String = "",
@SerialId(3) val newVer: Int = 0,
@SerialId(4) val resType: Int = 0,
@SerialId(5) val lanType: Int = 0,
@SerialId(6) val priority: Int = 0,
@SerialId(7) val resName: String = "",
@SerialId(8) val resDesc: String = "",
@SerialId(9) val resUrlBig: String = "",
@SerialId(10) val resUrlSmall: String = "",
@SerialId(11) val resConf: String = ""
)
@Serializable
class Uin2Nick(
@SerialId(1) val uin: Long = 0L,
@SerialId(2) val nick: String = ""
)
@Serializable
class UinPairMsg(
@SerialId(1) val lastReadTime: Int = 0,
@SerialId(2) val peerUin: Long = 0L,
@SerialId(3) val msgCompleted: Int = 0,
@SerialId(4) val msg: List<Msg>? = null,
@SerialId(5) val unreadMsgNum: Int = 0,
@SerialId(8) val c2cType: Int = 0,
@SerialId(9) val serviceType: Int = 0,
@SerialId(10) val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
)
}
\ No newline at end of file
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@Serializable
class MsgOnlinePush {
@Serializable
data class PbPushMsg(
@SerialId(1) val msg: MsgComm.Msg? = null,
@SerialId(2) val svrip: Int = 0,
@SerialId(3) val pushToken: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val pingFlag: Int = 0,
@SerialId(9) val generalFlag: Int = 0
)
}
\ No newline at end of file
...@@ -9,6 +9,8 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient ...@@ -9,6 +9,8 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket 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.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.Cmd0x352Packet
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.GetImgUrlReq
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
internal object ImageDownPacket : PacketFactory<ImageDownPacket.ImageDownPacketResponse>("LongConn.OffPicDown") { internal object ImageDownPacket : PacketFactory<ImageDownPacket.ImageDownPacketResponse>("LongConn.OffPicDown") {
......
...@@ -10,6 +10,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.* ...@@ -10,6 +10,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket 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.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.Cmd0x352Packet
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.UploadImgReq
internal object ImageUpPacket : PacketFactory<ImageUpPacket.ImageUpPacketResponse>("LongConn.OffPicUp") { internal object ImageUpPacket : PacketFactory<ImageUpPacket.ImageUpPacketResponse>("LongConn.OffPicUp") {
......
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive 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.readBytes
import kotlinx.serialization.protobuf.ProtoBuf
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.MsgOnlinePush
import net.mamoe.mirai.utils.io.encodeToString
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") {
@UseExperimental(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage {
TODO() // 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)
val pbPushMsg = ProtoBuf.load(MsgOnlinePush.PbPushMsg.serializer(), readBytes())
val message = MessageChain(initialCapacity = pbPushMsg.msg!!.msgBody!!.richText!!.elems!!.size)
var extraInfo: ImMsgBody.ExtraInfo? = null
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.encodeToString().toMessage())
it.extraInfo != null -> extraInfo = it.extraInfo
}
}
val group = bot.getGroup(pbPushMsg.msg.msgHead!!.groupInfo!!.groupCode)
val flags = extraInfo?.flags ?: 0
return GroupMessage(
bot = bot,
group = group,
senderName = pbPushMsg.msg.msgHead.groupInfo!!.groupCard.encodeToString(),
sender = group.getMember(pbPushMsg.msg.msgHead.fromUin),
message = message,
permission = when {
flags and 16 != 0 -> MemberPermission.ADMINISTRATOR
flags and 8 != 0 -> MemberPermission.OWNER
flags and 0 != 0 -> MemberPermission.MEMBER
else -> {
bot.logger.warning("判断群员权限失败")
MemberPermission.MEMBER
}
}
)
} }
} }
} }
\ No newline at end of file
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import kotlinx.io.core.ByteReadPacket
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.io.jceMap
import net.mamoe.mirai.qqandroid.network.io.jceStruct
import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
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.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.io.debugPrint
import net.mamoe.mirai.utils.io.encodeToString
import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.localIpAddress
@Suppress("EnumEntryName")
enum class RegPushReason {
appRegister,
createDefaultRegInfo,
fillRegProxy,
msfBoot,
msfByNetChange,
msfHeartTimeTooLong,
serverPush,
setOnlineStatus,
unknown
}
class StatSvc {
internal object Register : PacketFactory<Register.Response>("StatSvc.register") {
internal object Response : Packet {
override fun toString(): String = "Response(StatSvc.register)"
}
private const val subAppId = 537062845L
operator fun invoke(
client: QQAndroidClient,
regPushReason: RegPushReason = RegPushReason.appRegister
): OutgoingPacket = buildLoginOutgoingPacket(
client,
bodyType = 1,
extraData = client.wLoginSigInfo.d2.data,
key = client.wLoginSigInfo.d2Key
) { sequenceId ->
writeSsoPacket(
client, subAppId = subAppId, commandName = commandName,
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
) {
writeUniRequestPacket {
sServantName = "PushService"
sFuncName = "SvcReqRegister"
sBuffer = jceMap(
0,
"SvcReqRegister" to jceStruct(
0,
SvcReqRegister().apply {
cConnType = 0
lBid = 1 or 2 or 4
lUin = client.uin
iStatus = client.onlineStatus.id
bKikPC = 0 // 是否把 PC 踢下线
bKikWeak = 0
timeStamp = 0
// timeStamp = currentTimeSeconds // millis or seconds??
iLargeSeq = 1551 // ?
bOpenPush = 1
iLocaleID = 2052
bRegType =
(if (regPushReason == RegPushReason.appRegister ||
regPushReason == RegPushReason.fillRegProxy ||
regPushReason == RegPushReason.createDefaultRegInfo ||
regPushReason == RegPushReason.setOnlineStatus
) 0 else 1).toByte()
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0
iOSVersion = client.device.version.sdk.toLong()
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0
vecGuid = client.device.guid
strDevName = client.device.model.encodeToString()
strDevType = client.device.model.encodeToString()
strOSVer = client.device.version.release.encodeToString()
uOldSSOIp = 0
uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
acc or ((s.toLong() shl (index * 16)))
}
strVendorName = "MIUI"
strVendorOSName = "?ONEPLUS A5000_23_17"
// register 时还需要
/*
var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/
bytes_0x769_reqbody = ProtoBuf.dump(
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
rpt_config_list = listOf(
Oidb0x769.ConfigSeq(
type = 46,
version = 0
),
Oidb0x769.ConfigSeq(
type = 283,
version = 0
)
)
)
)
bSetMute = 0
}
)
)
}
this.writePacket(this.build().debugPrint("sso body"))
}
}
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
return Response
}
}
}
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import kotlinx.io.core.ByteReadPacket
import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.io.jceMap
import net.mamoe.mirai.qqandroid.network.io.jceStruct
import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
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.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.io.debugPrint
import net.mamoe.mirai.utils.io.encodeToString
import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.localIpAddress
@Suppress("EnumEntryName")
enum class RegPushReason {
appRegister,
createDefaultRegInfo,
fillRegProxy,
msfBoot,
msfByNetChange,
msfHeartTimeTooLong,
serverPush,
setOnlineStatus,
unknown
}
internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Response>("StatSvc.register") {
internal object Response : Packet
private const val subAppId = 537062845L
operator fun invoke(
client: QQAndroidClient,
regPushReason: RegPushReason = RegPushReason.appRegister
): OutgoingPacket = buildLoginOutgoingPacket(
client,
bodyType = 1,
extraData = client.wLoginSigInfo.d2.data,
key = client.wLoginSigInfo.d2Key
) { sequenceId ->
writeSsoPacket(
client, subAppId = subAppId, commandName = commandName,
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
) {
writeUniRequestPacket {
sServantName = "PushService"
sFuncName = "SvcReqRegister"
sBuffer = jceMap(
0,
"SvcReqRegister" to jceStruct(
0,
SvcReqRegister().apply {
cConnType = 0
lBid = 1 or 2 or 4
lUin = client.uin
iStatus = client.onlineStatus.id
bKikPC = 0 // 是否把 PC 踢下线
bKikWeak = 0
timeStamp = 0
// timeStamp = currentTimeSeconds // millis or seconds??
iLargeSeq = 1551 // ?
bOpenPush = 1
iLocaleID = 2052
bRegType =
(if (regPushReason == RegPushReason.appRegister ||
regPushReason == RegPushReason.fillRegProxy ||
regPushReason == RegPushReason.createDefaultRegInfo ||
regPushReason == RegPushReason.setOnlineStatus
) 0 else 1).toByte()
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0
iOSVersion = client.device.version.sdk.toLong()
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0
vecGuid = client.device.guid
strDevName = client.device.model.encodeToString()
strDevType = client.device.model.encodeToString()
strOSVer = client.device.version.release.encodeToString()
uOldSSOIp = 0
uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
acc or ((s.toLong() shl (index * 16)))
}
strVendorName = "MIUI"
strVendorOSName = "?ONEPLUS A5000_23_17"
// register 时还需要
/*
var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/
bytes_0x769_reqbody = ProtoBuf.dump(
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
rpt_config_list = listOf(
Oidb0x769.ConfigSeq(
type = 46,
version = 0
),
Oidb0x769.ConfigSeq(
type = 283,
version = 0
)
)
)
)
bSetMute = 0
}
)
)
}
this.writePacket(this.build().debugPrint("sso body"))
}
}
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
return Response
}
}
\ No newline at end of file
...@@ -5,6 +5,8 @@ package test ...@@ -5,6 +5,8 @@ package test
import net.mamoe.mirai.utils.cryptor.protoFieldNumber import net.mamoe.mirai.utils.cryptor.protoFieldNumber
import net.mamoe.mirai.utils.cryptor.protoType import net.mamoe.mirai.utils.cryptor.protoType
intArrayOf(8, 18, 26, 34, 80).forEach { intArrayOf(
8, 16, 24, 32, 40, 48, 56, 64, 74, 82
).forEach {
println(protoFieldNumber(it.toUInt()).toString() + " -> " + protoType(it.toUInt())) println(protoFieldNumber(it.toUInt()).toString() + " -> " + protoType(it.toUInt()))
} }
\ No newline at end of file
...@@ -4,7 +4,7 @@ import java.lang.reflect.Field ...@@ -4,7 +4,7 @@ import java.lang.reflect.Field
import kotlin.reflect.full.allSuperclasses import kotlin.reflect.full.allSuperclasses
actual fun Any.contentToStringReflectively(prefix: String): String { actual fun Any.contentToStringReflectively(prefix: String, filter: ((name: String, value: Any?) -> Boolean)?): String {
val newPrefix = prefix val newPrefix = prefix
return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" + return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" +
this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") } this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") }
...@@ -14,6 +14,11 @@ actual fun Any.contentToStringReflectively(prefix: String): String { ...@@ -14,6 +14,11 @@ actual fun Any.contentToStringReflectively(prefix: String): String {
prefix = newPrefix prefix = newPrefix
) { ) {
it.isAccessible = true it.isAccessible = true
if (filter != null) {
kotlin.runCatching {
if (!filter(it.name, it.get(this))) return@joinToStringPrefixed ""
}
}
it.name + "=" + kotlin.runCatching { it.name + "=" + kotlin.runCatching {
val value = it.get(this) val value = it.get(this)
if (value == this) "<this>" if (value == this) "<this>"
......
...@@ -14,6 +14,5 @@ interface ImageLink { ...@@ -14,6 +14,5 @@ interface ImageLink {
suspend fun downloadAsByteArray(): ByteArray = download().readBytes() suspend fun downloadAsByteArray(): ByteArray = download().readBytes()
@UseExperimental(KtorExperimentalAPI::class)
suspend fun download(): ByteReadPacket = Http.get(original) suspend fun download(): ByteReadPacket = Http.get(original)
} }
\ No newline at end of file
...@@ -242,7 +242,7 @@ object NullMessageChain : MessageChain { ...@@ -242,7 +242,7 @@ object NullMessageChain : MessageChain {
override fun contains(sub: String): Boolean = error("accessing NullMessageChain") override fun contains(sub: String): Boolean = error("accessing NullMessageChain")
override fun contains(element: Message): Boolean = error("accessing NullMessageChain") override fun contains(element: Message): Boolean = error("accessing NullMessageChain")
override fun followedBy(tail: Message): MessageChain = error("accessing NullMessageChain") override fun followedBy(tail: Message): MessageChain = tail.toChain()
override val size: Int get() = error("accessing NullMessageChain") override val size: Int get() = error("accessing NullMessageChain")
override fun containsAll(elements: Collection<Message>): Boolean = error("accessing NullMessageChain") override fun containsAll(elements: Collection<Message>): Boolean = error("accessing NullMessageChain")
......
...@@ -222,7 +222,7 @@ fun Any?.contentToString(prefix: String = ""): String = when (this) { ...@@ -222,7 +222,7 @@ fun Any?.contentToString(prefix: String = ""): String = when (this) {
} }
} }
expect fun Any.contentToStringReflectively(prefix: String = ""): String expect fun Any.contentToStringReflectively(prefix: String = "", filter: ((String, Any?) -> Boolean)? = null): String
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun ByteReadPacket.readProtoMap(length: Long = this.remaining): ProtoMap { fun ByteReadPacket.readProtoMap(length: Long = this.remaining): ProtoMap {
......
...@@ -6,19 +6,28 @@ import kotlin.reflect.full.allSuperclasses ...@@ -6,19 +6,28 @@ import kotlin.reflect.full.allSuperclasses
val FIELD_TRY_SET_ACCESSIBLE = Field::class.java.declaredMethods.firstOrNull { it.name == "trySetAccessible" } val FIELD_TRY_SET_ACCESSIBLE = Field::class.java.declaredMethods.firstOrNull { it.name == "trySetAccessible" }
actual fun Any.contentToStringReflectively(prefix: String): String { actual fun Any.contentToStringReflectively(prefix: String, filter: ((name: String, value: Any?) -> Boolean)?): String {
val newPrefix = prefix + ProtoMap.indent val newPrefix = prefix + ProtoMap.indent
return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" + return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" +
this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") } this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") }
.distinctBy { it.name } .distinctBy { it.name }
.filterNot { it.name.contains("$") || it.name == "Companion" || it.isSynthetic || it.name == "serialVersionUID" } .filterNot { it.name.contains("$") || it.name == "Companion" || it.isSynthetic || it.name == "serialVersionUID" }
.filterNot { it.isEnumConstant } .filterNot { it.isEnumConstant }
.map {
FIELD_TRY_SET_ACCESSIBLE?.invoke(it, true) ?: kotlin.run { it.isAccessible = true }
val value = it.get(this)
if (filter != null) {
kotlin.runCatching {
if (!filter(it.name, value)) return@map it.name to FIELD_TRY_SET_ACCESSIBLE
}
}
it.name to value
}
.filterNot { it.second === FIELD_TRY_SET_ACCESSIBLE }
.joinToStringPrefixed( .joinToStringPrefixed(
prefix = newPrefix prefix = newPrefix
) { ) { (name, value) ->
FIELD_TRY_SET_ACCESSIBLE?.invoke(it, true) ?: kotlin.run { it.isAccessible = true } "$name=" + kotlin.runCatching {
it.name + "=" + kotlin.runCatching {
val value = it.get(this)
if (value == this) "<this>" if (value == this) "<this>"
else value.contentToString(newPrefix) else value.contentToString(newPrefix)
}.getOrElse { "<!>" } }.getOrElse { "<!>" }
......
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