send_forward_msg(support at face...)

This commit is contained in:
Simplxs 2024-02-24 02:10:41 +08:00
parent 46ed966c18
commit d22f3ad1cb
No known key found for this signature in database
GPG Key ID: E23537FF14DD6507
62 changed files with 1494 additions and 780 deletions

View File

@ -7,10 +7,6 @@ import kotlin.reflect.KClass
interface Protobuf<T: Protobuf<T>> interface Protobuf<T: Protobuf<T>>
inline fun <reified T: Protobuf<T>> KClass<T>.decode(data: ByteArray): T {
return ProtoBuf.decodeFromByteArray(data)
}
inline fun <reified T: Protobuf<T>> ByteArray.decodeProtobuf(to: KClass<T>? = null): T { inline fun <reified T: Protobuf<T>> ByteArray.decodeProtobuf(to: KClass<T>? = null): T {
return ProtoBuf.decodeFromByteArray(this) return ProtoBuf.decodeFromByteArray(this)
} }

View File

@ -0,0 +1,26 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class AppShareInfo(
@ProtoNumber(1) var appshareId: UInt? = null,
@ProtoNumber(2) var appshareCookie: ByteArray? = null,
@ProtoNumber(3) var appshareResource: PluginInfo? = null,
)
@Serializable
data class PluginInfo(
@ProtoNumber(1) var resId: UInt = 0u,
@ProtoNumber(2) var pkgName: String = "",
@ProtoNumber(3) var newVer: UInt = 0u,
@ProtoNumber(4) var resType: UInt = 0u,
@ProtoNumber(5) var lanType: UInt = 0u,
@ProtoNumber(6) var priority: UInt = 0u,
@ProtoNumber(7) var resName: String = "",
@ProtoNumber(8) var resDesc: String = "",
@ProtoNumber(9) var resUrlBig: String = "",
@ProtoNumber(10) var resUrlSmall: String = "",
@ProtoNumber(11) var resConf: String = "",
)

View File

@ -4,12 +4,12 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
@Serializable @Serializable
data class MessageContent( data class ContentHead(
@ProtoNumber(1) val msgType: Int = Int.MIN_VALUE, @ProtoNumber(1) val msgType: Int = Int.MIN_VALUE,
@ProtoNumber(2) val msgSubType: Int? = null, @ProtoNumber(2) val msgSubType: Int? = null,
@ProtoNumber(3) val u1: Int? = null, @ProtoNumber(3) val divSeq: Int? = null,
@ProtoNumber(4) val msgViaRandom: Long = Long.MIN_VALUE, @ProtoNumber(4) val msgViaRandom: Long = Long.MIN_VALUE,
@ProtoNumber(5) val msgSeq_: Long? = null, @ProtoNumber(5) val sequence: Long? = null,
@ProtoNumber(6) val msgTime: Long? = null, @ProtoNumber(6) val msgTime: Long? = null,
@ProtoNumber(7) val u2: Int? = null, @ProtoNumber(7) val u2: Int? = null,
@ProtoNumber(8) val u6: Int? = null, @ProtoNumber(8) val u6: Int? = null,
@ -27,5 +27,5 @@ data class ForwardHead(
@ProtoNumber(2) val u2: Int? = null, @ProtoNumber(2) val u2: Int? = null,
@ProtoNumber(3) val u3: Int? = null, @ProtoNumber(3) val u3: Int? = null,
@ProtoNumber(4) val ub641: String? = null, @ProtoNumber(4) val ub641: String? = null,
@ProtoNumber(5) val Avatar: String? = null @ProtoNumber(5) val avatar: String? = null
) )

View File

@ -0,0 +1,64 @@
package protobuf.message
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import protobuf.message.element.*
@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class Elem(
@ProtoNumber(1) val text: TextMsg? = null,
@ProtoNumber(2) val face: FaceMsg? = null,
// @ProtoNumber(3) val onlineImage: OnlineImage? = null,
@ProtoNumber(4) val notOnlineImage: NotOnlineImage? = null,
// @ProtoNumber(5) var transElemInfo: TransElem? = null,
@ProtoNumber(6) val marketFace: MarketFace? = null,
// @ProtoNumber(7) var elemFlags: ElemFlags? = null,
@ProtoNumber(8) val customFace: CustomFace? = null,
@ProtoNumber(9) var elemFlags2: ElemFlags2? = null,
// @ProtoNumber(10) var funFace: FunFace? = null,
// @ProtoNumber(11) var secretFile: SecretFileMsg? = null,
// @ProtoNumber(12) var richMsg: RichMsg? = null,
// @ProtoNumber(13) var groupFile: GroupFile? = null,
// @ProtoNumber(14) var pubGroup: PubGroup? = null,
// @ProtoNumber(15) var marketTrans: MarketTrans? = null,
// @ProtoNumber(16) var extraInfo: ExtraInfo? = null,
// @ProtoNumber(17) var shakeWindow: ShakeWindow? = null,
// @ProtoNumber(18) var pubAccount: PubAccount? = null,
// @ProtoNumber(19) var videoFile: VideoFile? = null,
// @ProtoNumber(20) var tipsInfo: TipsInfo? = null,
// @ProtoNumber(21) var anonGroupMsg: AnonymousGroupMsg? = null,
// @ProtoNumber(22) var qqLiveOld: QQLiveOld? = null,
// @ProtoNumber(23) var lifeOnline: LifeOnlineAccount? = null,
// @ProtoNumber(24) var qqwalletMsg: QQWalletMsg? = null,
// @ProtoNumber(25) var crmElem: CrmElem? = null,
// @ProtoNumber(26) var conferenceTipsInfo: ConferenceTipsInfo? = null,
// @ProtoNumber(27) var redbagInfo: RedBagInfo? = null,
// @ProtoNumber(28) var lowVersionTips: LowVersionTips? = null,
// @ProtoNumber(29) var bankcodeCtrlInfo: ByteArray? = null,
// @ProtoNumber(30) var nearByMsg: NearByMessageType? = null,
// @ProtoNumber(31) var customElem: CustomElem? = null,
// @ProtoNumber(32) var locationInfo: LocationInfo? = null,
// @ProtoNumber(33) var pubAccInfo: PubAccInfo? = null,
// @ProtoNumber(34) var smallEmoji: SmallEmoji? = null,
// @ProtoNumber(35) var fsjMsgElem: FSJMessageElem? = null,
// @ProtoNumber(36) var arkApp: ArkAppElem? = null,
@ProtoNumber(37) val generalFlags: GeneralFlags? = null,
// @ProtoNumber(38) var hcFlashPic: CustomFace? = null,
// @ProtoNumber(39) var deliverGiftMsg: DeliverGiftMsg? = null,
// @ProtoNumber(40) var bitapp_msg: BitAppMsg? = null,
// @ProtoNumber(41) var openQqData: OpenQQData? = null,
// @ProtoNumber(42) var apolloMsg: ApolloActMsg? = null,
// @ProtoNumber(43) var groupPubAccInfo: GroupPubAccountInfo? = null,
// @ProtoNumber(44) var blessMsg: BlessingMessage? = null,
@ProtoNumber(45) var srcMsg: SourceMsg? = null,
// @ProtoNumber(46) var lolaMsg: LolaMsg? = null,
// @ProtoNumber(47) var groupBusinessMsg: GroupBusinessMsg? = null,
// @ProtoNumber(48) var msgWorkflowNotify: WorkflowNotifyMsg? = null,
// @ProtoNumber(49) var patElem: PatsElem? = null,
// @ProtoNumber(50) var groupPostElem: GroupPostElem? = null,
@ProtoNumber(51) val lightApp: LightAppElem? = null,
// @ProtoNumber(52) var eimInfo: EIMInfo? = null,
@ProtoNumber(53) val commonElem: CommonElem? = null,
)

View File

@ -1,17 +0,0 @@
@file:OptIn(ExperimentalSerializationApi::class)
package protobuf.message
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class RichMessage(
@ProtoNumber(1) val font: Font? = null,
@ProtoNumber(2) val elements: List<MessageElement>? = null
)
@Serializable
data class Font(
@ProtoNumber(9) val fontName: String? = null
)

View File

@ -1,11 +0,0 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class MessageBody(
@ProtoNumber(1) val rich: RichMessage? = null,
@ProtoNumber(2) val rawBuffer: ByteArray? = null,
@ProtoNumber(3) val MsgEncryptContent: ByteArray? = null
)

View File

@ -1,13 +0,0 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import protobuf.message.element.*
@Serializable
data class MessageElement(
@ProtoNumber(1) val text: TextElement? = null,
@ProtoNumber(2) val face: FaceElement? = null,
@ProtoNumber(51) val json: JsonElement? = null,
@ProtoNumber(53) val comm: CommonElement? = null,
)

View File

@ -0,0 +1,11 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class MsgBody(
@ProtoNumber(1) val richText: RichText? = null,
@ProtoNumber(2) val msgContent: ByteArray? = null,
@ProtoNumber(3) val msgEncryptContent: ByteArray? = null
)

View File

@ -0,0 +1,9 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class MsgControl(
@ProtoNumber(1) val msgFlag: Int? = null,
)

View File

@ -0,0 +1,28 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class NotOnlineFile(
@ProtoNumber(1) var fileType: UInt? = null,
@ProtoNumber(2) var sig: ByteArray? = null,
@ProtoNumber(3) var fileUuid: ByteArray? = null,
@ProtoNumber(4) var fileMd5: ByteArray? = null,
@ProtoNumber(5) var fileName: ByteArray? = null,
@ProtoNumber(6) var fileSize: ULong? = null,
@ProtoNumber(7) var note: ByteArray? = null,
@ProtoNumber(8) var reserved: UInt? = null,
@ProtoNumber(9) var subcmd: UInt? = null,
@ProtoNumber(10) var microCloud: UInt? = null,
@ProtoNumber(11) var rptFileUrls: List<String>? = null,
@ProtoNumber(12) var downloadFlag: UInt? = null,
@ProtoNumber(50) var dangerEvel: UInt? = null,
@ProtoNumber(51) var lifeTime: UInt? = null,
@ProtoNumber(52) var uploadTime: UInt? = null,
@ProtoNumber(53) var absFileType: UInt? = null,
@ProtoNumber(54) var clientType: UInt? = null,
@ProtoNumber(55) var expireTime: UInt? = null,
@ProtoNumber(56) var pbReserve: ByteArray? = null,
@ProtoNumber(57) var fileidcrcMedia: String? = null,
)

View File

@ -1,11 +0,0 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class NtMessage(
@ProtoNumber(1) val msgHead: MessageHead? = null,
@ProtoNumber(2) val contentHead: MessageContent? = null,
@ProtoNumber(3) val body: MessageBody? = null,
)

View File

@ -0,0 +1,23 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class PbSendMsgReq(
@ProtoNumber(1) val routingHead: RoutingHead? = null,
@ProtoNumber(2) val contentHead: ContentHead? = null,
@ProtoNumber(3) val msgBody: MsgBody? = null,
@ProtoNumber(4) val msgSeq: UInt? = null,
@ProtoNumber(5) val msgRand: UInt? = null,
@ProtoNumber(6) val syncCookie: ByteArray? = null,
@ProtoNumber(7) val appShare: AppShareInfo? = null,
@ProtoNumber(8) val msgVia: UInt? = null,
@ProtoNumber(9) val dataStatist: UInt? = null,
// @ProtoNumber(10) val multiMsgAssist: MultiMsgAssist? = null,
// @ProtoNumber(11) val inputNotifyInfo: InputNotifyInfo? = null,
@ProtoNumber(12) val ctrl: MsgControl? = null,
// @ProtoNumber(13) val receiptReq: ReceiptReq? = null,
@ProtoNumber(14) val multiSendSeq: UInt? = null
) : Protobuf<PbSendMsgReq>

View File

@ -0,0 +1,32 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class Ptt(
@ProtoNumber(1) var fileType: UInt?=null,
@ProtoNumber(2) var srcUin: ULong?=null,
@ProtoNumber(3) var fileUuid: ByteArray?=null,
@ProtoNumber(4) var fileMd5: ByteArray?=null,
@ProtoNumber(5) var fileName: ByteArray?=null,
@ProtoNumber(6) var fileSize: UInt?=null,
@ProtoNumber(7) var reserve: ByteArray?=null,
@ProtoNumber(8) var fileId: UInt?=null,
@ProtoNumber(9) var serverIp: UInt?=null,
@ProtoNumber(10) var serverPort: UInt?=null,
@ProtoNumber(11) var boolValid: Boolean = false,
@ProtoNumber(12) var signature: ByteArray?=null,
@ProtoNumber(13) var shortcut: ByteArray?=null,
@ProtoNumber(14) var fileKey: ByteArray?=null,
@ProtoNumber(15) var magicPttIndex: UInt?=null,
@ProtoNumber(16) var voiceSwitch: UInt?=null,
@ProtoNumber(17) var pttUrl: ByteArray?=null,
@ProtoNumber(18) var groupFileKey: ByteArray?=null,
@ProtoNumber(19) var time: UInt?=null,
@ProtoNumber(20) var downPara: ByteArray?=null,
@ProtoNumber(29) var format: UInt?=null,
@ProtoNumber(30) var pbReserve: ByteArray?=null,
@ProtoNumber(31) var rptPttUrls: List<String>? = null,
@ProtoNumber(32) var downloadFlag: UInt?=null,
)

View File

@ -0,0 +1,11 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class PushMsgBody(
@ProtoNumber(1) val msgHead: ResponseHead? = null,
@ProtoNumber(2) val contentHead: ContentHead? = null,
@ProtoNumber(3) val body: MsgBody? = null,
)

View File

@ -6,25 +6,25 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
@Serializable @Serializable
data class MessageHead( data class ResponseHead(
@ProtoNumber(1) val peer: Long = Long.MIN_VALUE, @ProtoNumber(1) val peer: Long = Long.MIN_VALUE,
@ProtoNumber(2) val peerUid: String? = null, @ProtoNumber(2) val peerUid: String? = null,
@ProtoNumber(3) val flag: Int = Int.MIN_VALUE, @ProtoNumber(3) val flag: Int = Int.MIN_VALUE,
@ProtoNumber(4) val appId: Int = Int.MIN_VALUE, @ProtoNumber(4) val appId: Int = Int.MIN_VALUE,
@ProtoNumber(5) val receiver: Long? = null, @ProtoNumber(5) val receiver: Long? = null,
@ProtoNumber(6) val receiverUid: String? = null, @ProtoNumber(6) val receiverUid: String? = null,
@ProtoNumber(7) val forward: MessageForward? = null, @ProtoNumber(7) val forward: ResponseForward? = null,
@ProtoNumber(8) val groupInfo: GroupInfo? = null, @ProtoNumber(8) val responseGrp: ResponseGrp? = null,
) )
@Serializable @Serializable
data class MessageForward( data class ResponseForward(
@ProtoNumber(6) val friendName: String? = null, @ProtoNumber(6) val friendName: String? = null,
@ProtoNumber(11) val u1: Int? = null, @ProtoNumber(11) val u1: Int? = null,
) )
@Serializable @Serializable
data class GroupInfo( data class ResponseGrp(
@ProtoNumber(1) val groupCode: ULong = ULong.MIN_VALUE, @ProtoNumber(1) val groupCode: ULong = ULong.MIN_VALUE,
@ProtoNumber(4) val memberCard: String? = null, @ProtoNumber(4) val memberCard: String? = null,
@ProtoNumber(5) val u1: Int? = null, @ProtoNumber(5) val u1: Int? = null,

View File

@ -0,0 +1,31 @@
@file:OptIn(ExperimentalSerializationApi::class)
package protobuf.message
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class RichText(
@ProtoNumber(1) val attr: Attr? = null,
@ProtoNumber(2) val elements: List<Elem>? = null,
@ProtoNumber(3) val not_online_file: NotOnlineFile? = null,
@ProtoNumber(4) val ptt: Ptt? = null,
@ProtoNumber(5) val tmp_ptt: TmpPtt? = null,
@ProtoNumber(6) val trans_211_tmp_msg: Trans211TmpMsg? = null,
)
@Serializable
data class Attr(
@ProtoNumber(1) val codePage: Int? = null,
@ProtoNumber(2) val time: UInt? = null,
@ProtoNumber(3) val random: UInt? = null,
@ProtoNumber(4) val color: UInt? = null,
@ProtoNumber(5) val size: UInt? = null,
@ProtoNumber(6) val effect: UInt? = null,
@ProtoNumber(7) val charSet: UInt? = null,
@ProtoNumber(8) val pitchAndFamily: UInt? = null,
@ProtoNumber(9) val fontName: String? = null,
@ProtoNumber(10) val reserve_data: ByteArray? = null,
)

View File

@ -0,0 +1,14 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import protobuf.message.routing.*
@Serializable
data class RoutingHead(
@ProtoNumber(1) val c2c: C2C? = null,
@ProtoNumber(2) val grp: Grp? = null,
@ProtoNumber(3) val grpTmp: GrpTmp? = null,
@ProtoNumber(6) val wpaTmp: WPATmp? = null,
@ProtoNumber(15) val trans0X211: Trans0X211? = null
)

View File

@ -0,0 +1,20 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class TmpPtt(
@ProtoNumber(1) var fileType: UInt? = null,
@ProtoNumber(2) var fileUuid: ByteArray? = null,
@ProtoNumber(3) var fileMd5: ByteArray? = null,
@ProtoNumber(4) var fileName: ByteArray? = null,
@ProtoNumber(5) var fileSize: UInt? = null,
@ProtoNumber(6) var pttTimes: UInt? = null,
@ProtoNumber(7) var userType: UInt? = null,
@ProtoNumber(8) var ptttransFlag: UInt? = null,
@ProtoNumber(9) var busiType: UInt? = null,
@ProtoNumber(10) var msgId: ULong? = null,
@ProtoNumber(30) var pbReserve: ByteArray? = null,
@ProtoNumber(31) var pttEncodeData: ByteArray? = null,
)

View File

@ -0,0 +1,10 @@
package protobuf.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class Trans211TmpMsg(
@ProtoNumber(1) var msgBody: ByteArray? = null,
@ProtoNumber(2) var c2cCmd: UInt? = null,
)

View File

@ -0,0 +1,11 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class CommonElem(
@ProtoNumber(1) val serviceType: Int? = null,
@ProtoNumber(2) val elem: ByteArray? = null,
@ProtoNumber(3) val businessType: Int? = null,
)

View File

@ -1,11 +0,0 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class CommonElement(
@ProtoNumber(1) val type: Int? = null,
@ProtoNumber(2) val data: ByteArray? = null,
@ProtoNumber(3) val u1: Int? = null,
)

View File

@ -0,0 +1,49 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class CustomFace(
@ProtoNumber(1) var guid: ByteArray? = null,
@ProtoNumber(2) var filePath: String? = null,
@ProtoNumber(3) var shortcut: String? = null,
@ProtoNumber(4) var buffer: ByteArray? = null,
@ProtoNumber(5) var flag: ByteArray? = null,
@ProtoNumber(6) var oldData: ByteArray? = null,
@ProtoNumber(7) var fileId: UInt? = null,
@ProtoNumber(8) var serverIp: UInt? = null,
@ProtoNumber(9) var serverPort: UInt? = null,
@ProtoNumber(10) var fileType: UInt? = null, // 66
@ProtoNumber(11) var signature: ByteArray? = null,
@ProtoNumber(12) var useful: UInt? = null,
@ProtoNumber(13) var md5: ByteArray? = null,
@ProtoNumber(14) var thumbUrl: String? = null,
@ProtoNumber(15) var bigUrl: String? = null,
@ProtoNumber(16) var origUrl: String? = null,
@ProtoNumber(17) var bizType: UInt? = null,
@ProtoNumber(18) var repeatIndex: UInt? = null,
@ProtoNumber(19) var repeatImage: UInt? = null,
@ProtoNumber(20) var imageType: UInt? = null,
@ProtoNumber(21) var index: UInt? = null,
@ProtoNumber(22) var width: UInt? = null,
@ProtoNumber(23) var height: UInt? = null,
@ProtoNumber(24) var source: UInt? = null,
@ProtoNumber(25) var size: UInt? = null,
@ProtoNumber(26) var origin: UInt? = null,
@ProtoNumber(27) var thumbWidth: UInt? = null,
@ProtoNumber(28) var thumbHeight: UInt? = null,
@ProtoNumber(29) var showLen: UInt? = null,
@ProtoNumber(30) var downloadLen: UInt? = null,
@ProtoNumber(31) var url400: String? = null,
@ProtoNumber(32) var width400: UInt? = null,
@ProtoNumber(33) var height400: UInt? = null,
@ProtoNumber(34) var pbReserve: PbReserve? = null,
){
companion object{
@Serializable
data class PbReserve(
@ProtoNumber(1) var field1: Int? = null
)
}
}

View File

@ -0,0 +1,38 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class ElemFlags2(
@ProtoNumber(1) var color_text_id: UInt? = null,
@ProtoNumber(2) var msg_id: ULong? = null,
@ProtoNumber(3) var whisper_session_id: UInt? = null,
@ProtoNumber(4) var ptt_change_bit: UInt? = null,
@ProtoNumber(5) var vip_status: UInt? = null,
@ProtoNumber(6) var compatible_id: UInt? = null,
@ProtoNumber(7) var rpt_insts: List<Inst>? = null,
@ProtoNumber(8) var msg_rpt_cnt: UInt? = null,
@ProtoNumber(9) var src_inst: Inst? = null,
@ProtoNumber(10) var longtitude: UInt? = null,
@ProtoNumber(11) var latitude: UInt? = null,
@ProtoNumber(12) var custom_font: UInt? = null,
@ProtoNumber(13) var pc_support_def: PcSupportDef? = null,
@ProtoNumber(14) var crm_flags: UInt? = null,
)
@Serializable
data class Inst(
@ProtoNumber(1) var app_id: UInt? = null,
@ProtoNumber(2) var inst_id: UInt? = null,
)
@Serializable
data class PcSupportDef(
@ProtoNumber(1) var pc_ptl_begin: UInt? = null,
@ProtoNumber(2) var pc_ptl_end: UInt? = null,
@ProtoNumber(3) var mac_ptl_begin: UInt? = null,
@ProtoNumber(4) var mac_ptl_end: UInt? = null,
@ProtoNumber(5) var rpt_ptls_support: List<Int>? = null,
@ProtoNumber(6) var rpt_ptls_not_support: List<Int>? = null,
)

View File

@ -4,6 +4,9 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
@Serializable @Serializable
data class FaceElement( data class FaceMsg(
@ProtoNumber(1) val id: Int? = null, @ProtoNumber(1) val id: Int? = null,
@ProtoNumber(2) var old: ByteArray? = null,
@ProtoNumber(11) var buf: ByteArray? = null,
) )

View File

@ -0,0 +1,28 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class GeneralFlags(
@ProtoNumber(1) val bubbleDiyTextId: UInt? = null,
@ProtoNumber(2) val groupFlagNew: UInt? = null,
@ProtoNumber(3) val uin: ULong? = null,
@ProtoNumber(4) val rpId: ByteArray? = null,
@ProtoNumber(5) val prpFold: UInt? = null,
@ProtoNumber(6) val longTextFlag: UInt? = null,
@ProtoNumber(7) val longTextResid: ByteArray? = null,
@ProtoNumber(8) val groupType: UInt? = null,
@ProtoNumber(9) val toUinFlag: UInt? = null,
@ProtoNumber(10) val glamourLevel: UInt? = null,
@ProtoNumber(11) val memberLevel: UInt? = null,
@ProtoNumber(12) val groupRankSeq: ULong? = null,
@ProtoNumber(13) val olympicTorch: UInt? = null,
@ProtoNumber(14) val babyqGuideMsgCookie: ByteArray? = null,
@ProtoNumber(15) val expertFlag: UInt? = null,
@ProtoNumber(16) val bubbleSubId: UInt? = null,
@ProtoNumber(17) val pendantId: ULong? = null,
@ProtoNumber(18) val rpIndex: ByteArray? = null,
@ProtoNumber(19) val reserve: ByteArray? = null,
)

View File

@ -4,6 +4,6 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
@Serializable @Serializable
data class JsonElement( data class LightAppElem(
@ProtoNumber(1) val data: ByteArray? = null, @ProtoNumber(1) val data: ByteArray? = null,
) )

View File

@ -0,0 +1,21 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class MarketFace(
@ProtoNumber(1) var faceName: String? = null,
@ProtoNumber(2) var itemType: Int? = null,
@ProtoNumber(3) var faceInfo: Int? = null,
@ProtoNumber(4) var faceId: String? = null,
@ProtoNumber(5) var tabId: Int? = null,
@ProtoNumber(6) var subType: Int? = null,
@ProtoNumber(7) var key: ByteArray? = null,
@ProtoNumber(8) var param: ByteArray? = null,
@ProtoNumber(9) var mediaType: Int? = null,
@ProtoNumber(10) var imageWidth: Int? = null,
@ProtoNumber(11) var imageHeight: Int? = null,
@ProtoNumber(12) var mobileparam: ByteArray? = null,
@ProtoNumber(13) var pbReserve: ByteArray? = null,
)

View File

@ -0,0 +1,46 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class NotOnlineImage(
@ProtoNumber(1) val filePath: ByteArray? = null,
@ProtoNumber(2) val fileLen: UInt? = null,
@ProtoNumber(3) val downloadPath: ByteArray? = null,
@ProtoNumber(4) val oldVerSendFile: ByteArray? = null,
@ProtoNumber(5) val imgType: UInt? = null,
@ProtoNumber(6) val previewsImage: ByteArray? = null,
@ProtoNumber(7) val picMd5: ByteArray? = null,
@ProtoNumber(8) val picHeight: UInt? = null,
@ProtoNumber(9) val picWidth: UInt? = null,
@ProtoNumber(10) val resId: ByteArray? = null,
@ProtoNumber(11) val flag: ByteArray? = null,
@ProtoNumber(12) val thumbUrl: String? = null,
@ProtoNumber(13) val original: UInt? = null,
@ProtoNumber(14) val bigUrl: String? = null,
@ProtoNumber(15) val origUrl: String? = null,
@ProtoNumber(16) val bizType: UInt? = null,
@ProtoNumber(17) val result: UInt? = null,
@ProtoNumber(18) val index: UInt? = null,
@ProtoNumber(19) val opFaceBuf: ByteArray? = null,
@ProtoNumber(20) val oldPicMd5: Boolean = false,
@ProtoNumber(21) val thumbWidth: UInt? = null,
@ProtoNumber(22) val thumbHeight: UInt? = null,
@ProtoNumber(23) val fileId: UInt? = null,
@ProtoNumber(24) val showLen: UInt? = null,
@ProtoNumber(25) val downloadLen: UInt? = null,
@ProtoNumber(26) val url400: String? = null,
@ProtoNumber(27) val width400: UInt? = null,
@ProtoNumber(28) val height400: UInt? = null,
@ProtoNumber(29) val pbReserve: PbReserve? = null,
) {
companion object {
@Serializable
data class PbReserve(
@ProtoNumber(1) var field1: Int? = null,
@ProtoNumber(8) var field8: String? = null,
@ProtoNumber(30) var url: String? = null
)
}
}

View File

@ -0,0 +1,30 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import protobuf.message.Elem
@Serializable
data class SourceMsg(
@ProtoNumber(1) var origSeqs: List<Int>? = null,
@ProtoNumber(2) var senderUin: ULong? = null,
@ProtoNumber(3) var time: ULong? = null,
@ProtoNumber(4) var flag: UInt? = null,
@ProtoNumber(5) var elems: List<Elem>? = null,
@ProtoNumber(6) var type: UInt? = null,
@ProtoNumber(7) var richMsg: ByteArray? = null,
@ProtoNumber(8) var pbReserve: PbReserve? = null,
@ProtoNumber(9) var srcMsg: ByteArray? = null,
@ProtoNumber(10) var toUin: ULong? = null,
@ProtoNumber(11) var troopName: String? = null,
) {
companion object {
@Serializable
data class PbReserve(
@ProtoNumber(3) var field3: ULong? = null,
@ProtoNumber(6) var senderUid: String? = null,
@ProtoNumber(7) var receiverUid: String? = null,
@ProtoNumber(8) var field8: Int? = null,
)
}
}

View File

@ -1,40 +0,0 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class TextElement(
@ProtoNumber(1) val text: String? = null,
@ProtoNumber(2) val link: String? = null,
@ProtoNumber(3) val attr6Buf: ByteArray? = null,
@ProtoNumber(4) val attr7Buf: ByteArray? = null,
@ProtoNumber(11) val buf: ByteArray? = null,
@ProtoNumber(12) val pbReserve: TextResvAttr? = null,
) {
companion object {
@Serializable
data class TextResvAttr(
@ProtoNumber(1) val wording: ByteArray? = null,
@ProtoNumber(2) val textAnalysisResult: Int? = null,
@ProtoNumber(3) val atType: Int? = null,
@ProtoNumber(4) val atMemberUin: Long? = null,
@ProtoNumber(5) val atMemberTinyid: Long? = null,
@ProtoNumber(6) val atChannelInfo: ExtChannelInfo? = null,
@ProtoNumber(7) val atRoleInfo: ExtRoleInfo? = null,
)
@Serializable
data class ExtChannelInfo(
@ProtoNumber(1) val guildId: Long? = null,
@ProtoNumber(2) val channelId: Long? = null,
)
@Serializable
data class ExtRoleInfo(
@ProtoNumber(1) val id: Long? = null,
@ProtoNumber(2) val info: ByteArray? = null,
@ProtoNumber(3) val flag: Int? = null,
)
}
}

View File

@ -0,0 +1,14 @@
package protobuf.message.element
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class TextMsg(
@ProtoNumber(1) val str: String? = null,
@ProtoNumber(2) val link: String? = null,
@ProtoNumber(3) val attr6Buf: ByteArray? = null,
@ProtoNumber(4) val attr7Buf: ByteArray? = null,
@ProtoNumber(11) val buf: ByteArray? = null,
@ProtoNumber(12) val pbReserve: ByteArray? = null,
)

View File

@ -0,0 +1,53 @@
package protobuf.message.element.commelem
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class ButtonExtra(
@ProtoNumber(1) val field1: Object1? = null,
) : Protobuf<ButtonExtra>
@Serializable
data class Object1(
@ProtoNumber(1) val rows: List<Row>? = null,
@ProtoNumber(2) val appid: Int? = null,
)
@Serializable
data class Row(
@ProtoNumber(1) val buttons: List<Button>? = null,
)
@Serializable
data class Button(
@ProtoNumber(1) val id: Int? = null,
@ProtoNumber(2) val renderData: RenderData? = null,
@ProtoNumber(3) val action: Action? = null,
)
@Serializable
data class RenderData(
@ProtoNumber(1) val label: String? = null,
@ProtoNumber(2) val visitedLabel: String? = null,
@ProtoNumber(3) val style: Int? = null,
)
@Serializable
data class Action(
@ProtoNumber(1) val type: Int? = null,
@ProtoNumber(2) val permission: Permission? = null,
@ProtoNumber(4) val unsupportTips: String? = null,
@ProtoNumber(5) val data: String? = null,
@ProtoNumber(6) val reply: Boolean? = null,
@ProtoNumber(7) val enter: Boolean? = null,
)
@Serializable
data class Permission(
@ProtoNumber(1) val type: Int? = null,
@ProtoNumber(2) val specifyRoleIds: List<String>? = null,
@ProtoNumber(3) val specifyUserIds: List<String>? = null,
)

View File

@ -0,0 +1,10 @@
package protobuf.message.element.commelem
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class MarkdownExtra(
@ProtoNumber(1) val content: String? = null,
) : Protobuf<MarkdownExtra>

View File

@ -0,0 +1,12 @@
package protobuf.message.element.commelem
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class PokeExtra(
@ProtoNumber(1) val type: Int? = null,
@ProtoNumber(7) val field7: Int? = null,
@ProtoNumber(8) val field8: Int? = null
) : Protobuf<PokeExtra>

View File

@ -0,0 +1,17 @@
package protobuf.message.element.commelem
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class QFaceExtra(
@ProtoNumber(1) val packId: String? = null,
@ProtoNumber(2) val stickerId: String? = null,
@ProtoNumber(3) val faceId: Int? = null,
@ProtoNumber(4) val field4: Int? = null,
@ProtoNumber(5) val field5: Int? = null,
@ProtoNumber(6) val field6: String? = null,
@ProtoNumber(7) val faceText: String? = null,
@ProtoNumber(9) val field9: Int? = null
) : Protobuf<QFaceExtra>

View File

@ -6,16 +6,7 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf import moe.fuqiuluo.symbols.Protobuf
import protobuf.message.MessageBody import protobuf.message.PushMsgBody
import protobuf.message.MessageContent
import protobuf.message.MessageHead
@Serializable
data class PushMsgBody(
@ProtoNumber(1) val head: MessageHead? = null,
@ProtoNumber(2) val content: MessageContent? = null,
@ProtoNumber(3) val body: MessageBody? = null
)
@Serializable @Serializable
data class LongMsgContent( data class LongMsgContent(

View File

@ -0,0 +1,14 @@
package protobuf.message.routing
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class C2C(
@ProtoNumber(1) val uin: UInt? = null,
@ProtoNumber(2) val uid: String? = null,
@ProtoNumber(3) val field3: UInt? = null,
@ProtoNumber(4) val sig: UInt? = null,
@ProtoNumber(5) val receiverUin: UInt? = null,
@ProtoNumber(6) val receiverUid: String? = null
)

View File

@ -0,0 +1,9 @@
package protobuf.message.routing
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class Grp (
@ProtoNumber(1) var groupCode: UInt? = null,
)

View File

@ -0,0 +1,10 @@
package protobuf.message.routing
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class GrpTmp (
@ProtoNumber(1) var groupCode: UInt? = null,
@ProtoNumber(2) var ToUin: UInt? = null,
)

View File

@ -0,0 +1,11 @@
package protobuf.message.routing
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class Trans0X211(
@ProtoNumber(1) val toUin: ULong? = null,
@ProtoNumber(2) val ccCmd: UInt? = null,
@ProtoNumber(8) val uid: String? = null
)

View File

@ -0,0 +1,10 @@
package protobuf.message.routing
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class WPATmp (
@ProtoNumber(1) val toUin: Int? = null,
@ProtoNumber(2) val sig: ByteArray? = null,
)

View File

@ -1,104 +0,0 @@
package protobuf.msg
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class MsgBody(
@ProtoNumber(1) var richText: RichText,
//@ProtoNumber(2) var msgContent: ByteArray = EMPTY_BYTE_ARRAY,
//@/ProtoNumber(3) var msgEncryptContent: ByteArray = EMPTY_BYTE_ARRAY,
)
@Serializable
data class RichText(
//@ProtoNumber(1) var attr: Attr? = null,
@ProtoNumber(2) var elems: ArrayList<Elem>? = null,
//@ProtoNumber(3) var not_online_file: NotOnlineFile? = null,
//@ProtoNumber(4) var ptt: Ptt? = null,
//@ProtoNumber(5) var tmp_ptt: TmpPtt? = null,
//@ProtoNumber(6) var trans_211_tmp_msg: Trans211TmpMsg? = null,
)
@Serializable
data class Elem(
/*@ProtoNumber(1) var text: TextMsg? = null,
@ProtoNumber(2) var face: FaceMsg? = null,
@ProtoNumber(3) var online_image: OnlineImage? = null,
@ProtoNumber(4) var not_online_image: NotOnlineImage? = null,
@ProtoNumber(5) var trans_elem_info: TransElem? = null,
@ProtoNumber(6) var market_face: MarketFace? = null,
@ProtoNumber(7) var elem_flags: ElemFlags? = null,
@ProtoNumber(8) var customFace: CustomFace? = null,
@ProtoNumber(9) var elem_flags2: ElemFlags2? = null,
@ProtoNumber(10) var fun_face: FunFace? = null,
@ProtoNumber(11) var secret_file: SecretFileMsg? = null,
@ProtoNumber(12) var rich_msg: RichMsg? = null,
@ProtoNumber(13) var group_file: GroupFile? = null,
@ProtoNumber(14) var pub_group: PubGroup? = null,
@ProtoNumber(15) var market_trans: MarketTrans? = null,
@ProtoNumber(16) var extra_info: ExtraInfo? = null,
@ProtoNumber(17) var shake_window: ShakeWindow? = null,
@ProtoNumber(18) var pub_account: PubAccount? = null,
@ProtoNumber(19) var video_file: VideoFile? = null,
@ProtoNumber(20) var tips_info: TipsInfo? = null,
@ProtoNumber(21) var anon_group_msg: AnonymousGroupMsg? = null,
@ProtoNumber(22) var qq_live_old: QQLiveOld? = null,
@ProtoNumber(23) var life_online: LifeOnlineAccount? = null,
@ProtoNumber(24) var qqwallet_msg: QQWalletMsg? = null,
@ProtoNumber(25) var crm_elem: CrmElem? = null,
@ProtoNumber(26) var conference_tips_info: ConferenceTipsInfo? = null,
@ProtoNumber(27) var redbag_info: RedBagInfo? = null,
@ProtoNumber(28) var low_version_tips: LowVersionTips? = null,
@ProtoNumber(29) var bankcode_ctrl_info: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(30) var near_by_msg: NearByMessageType? = null,
@ProtoNumber(31) var custom_elem: CustomElem? = null,
@ProtoNumber(32) var location_info: LocationInfo? = null,
@ProtoNumber(33) var pub_acc_info: PubAccInfo? = null,
@ProtoNumber(34) var small_emoji: SmallEmoji? = null,
@ProtoNumber(35) var fsj_msg_elem: FSJMessageElem? = null,
@ProtoNumber(36) var ark_app: ArkAppElem? = null,
*/
@ProtoNumber(37) var generalFlags: GeneralFlags? = null,
/*
@ProtoNumber(38) var hc_flash_pic: CustomFace? = null,
@ProtoNumber(39) var deliver_gift_msg: DeliverGiftMsg? = null,
@ProtoNumber(40) var bitapp_msg: BitAppMsg? = null,
@ProtoNumber(41) var open_qq_data: OpenQQData? = null,
@ProtoNumber(42) var apollo_msg: ApolloActMsg? = null,
@ProtoNumber(43) var group_pub_acc_info: GroupPubAccountInfo? = null,
@ProtoNumber(44) var bless_msg: BlessingMessage? = null,
@ProtoNumber(45) var src_msg: SourceMsg? = null,
@ProtoNumber(46) var lola_msg: LolaMsg? = null,
@ProtoNumber(47) var group_business_msg: GroupBusinessMsg? = null,
@ProtoNumber(48) var msg_workflow_notify: WorkflowNotifyMsg? = null,
@ProtoNumber(49) var pat_elem: PatsElem? = null,
@ProtoNumber(50) var group_post_elem: GroupPostElem? = null,
@ProtoNumber(51) var light_app: LightAppElem? = null,
@ProtoNumber(52) var eim_info: EIMInfo? = null,
@ProtoNumber(53) var commonElem: CommonElem? = null,*/
)
@Serializable
data class GeneralFlags(
@ProtoNumber(1) var uint32_bubble_diy_text_id: UInt = 0u,
@ProtoNumber(2) var uint32_group_flag_new: UInt = 0u,
@ProtoNumber(3) var uint64_uin: ULong = 0u,
@ProtoNumber(4) var bytes_rp_id: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(5) var uint32_prp_fold: UInt = 0u,
@ProtoNumber(6) var long_text_flag: UInt = 0u,
@ProtoNumber(7) var long_text_resid: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(8) var uint32_group_type: UInt = 0u,
@ProtoNumber(9) var uint32_to_uin_flag: UInt = 0u,
@ProtoNumber(10) var uint32_glamour_level: UInt = 0u,
@ProtoNumber(11) var uint32_member_level: UInt = 0u,
@ProtoNumber(12) var uint64_group_rank_seq: ULong = 0u,
@ProtoNumber(13) var uint32_olympic_torch: UInt = 0u,
@ProtoNumber(14) var babyq_guide_msg_cookie: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(15) var uin32_expert_flag: UInt = 0u,
@ProtoNumber(16) var uint32_bubble_sub_id: UInt = 0u,
@ProtoNumber(17) var pendantId: ULong = 0u,
@ProtoNumber(18) var bytes_rp_index: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(19) var reserve: ByteArray = EMPTY_BYTE_ARRAY,
)

View File

@ -1,67 +0,0 @@
package protobuf.msg
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
class PbSendMsgReq(
@ProtoNumber(1) var routingHead: RoutingHead,
@ProtoNumber(2) var contentHead: ContentHead,
@ProtoNumber(3) var msgBody: MsgBody,
@ProtoNumber(4) var msgSeq: ULong = 0u,
@ProtoNumber(5) var msgRand: UInt = 0u,
//@ProtoNumber(6) var sync_cookie: ByteArray = EMPTY_BYTE_ARRAY,
//@ProtoNumber(7) var app_share: AppShareInfo? = null,
@ProtoNumber(8) var msgVia: UInt = 0u,
//@ProtoNumber(9) var data_statist: UInt = 0u,
//@ProtoNumber(10) var multi_msg_assist: MultiMsgAssist? = null,
//@ProtoNumber(11) var input_notify_info: PbInputNotifyInfo? = null,
//@ProtoNumber(12) var msgCtrl: MsgCtrl? = null,
//@ProtoNumber(13) var receipt_req: ReceiptReq? = null,
//@ProtoNumber(14) var multi_send_seq: UInt = 0u,
): Protobuf<PbSendMsgReq>
@Serializable
data class ContentHead(
@ProtoNumber(1) var pkg_num: UInt = 0u,
@ProtoNumber(2) var pkg_index: UInt = 0u,
@ProtoNumber(3) var div_seq: UInt = 0u,
@ProtoNumber(4) var auto_reply: UInt = 0u,
)
@Serializable
class RoutingHead(
@ProtoNumber(1) var c2c: C2C? = null,
@ProtoNumber(2) var grp: Grp? = null,
// @ProtoNumber(3) var grp_tmp: GrpTmp? = null,
//@ProtoNumber(4) var dis: Dis? = null,
// @ProtoNumber(5) var dis_tmp: DisTmp? = null,
// @ProtoNumber(6) var wpa_tmp: WPATmp? = null,
// @ProtoNumber(7) var secret_file: SecretFileHead? = null,
// @ProtoNumber(8) var public_plat: PublicPlat? = null,
/*@ProtoNumber(9) var trans_msg: TransMsg? = null,
@ProtoNumber(10) var address_list: AddressListTmp? = null,
@ProtoNumber(11) var rich_status_tmp: RichStatusTmp? = null,
@ProtoNumber(12) var trans_cmd: TransCmd? = null,
@ProtoNumber(13) var accost_tmp: AccostTmp? = null,
@ProtoNumber(14) var pub_group_tmp: PubGroupTmp? = null,
@ProtoNumber(15) var trans_0x211: Trans0x211? = null,
@ProtoNumber(16) var business_wpa_tmp: BusinessWPATmp? = null,
@ProtoNumber(17) var auth_tmp: AuthTmp? = null,
@ProtoNumber(18) var bsns_tmp: BsnsTmp? = null,
@ProtoNumber(19) var qq_querybusiness_tmp: QQQueryBusinessTmp? = null,
@ProtoNumber(20) var nearby_dating_tmp: NearByDatingTmp? = null,
@ProtoNumber(21) var nearby_assistant_tmp: NearByAssistantTmp? = null,
@ProtoNumber(22) var comm_tmp: CommTmp? = null,*/
)
@Serializable
class C2C(
@ProtoNumber(1) var to_uin: ULong = 0u,
)
@Serializable
class Grp(
@ProtoNumber(1) var groupCode: ULong = 0u,
)

View File

@ -3,11 +3,11 @@ package protobuf.push
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf import moe.fuqiuluo.symbols.Protobuf
import protobuf.message.NtMessage import protobuf.message.PushMsgBody
@Serializable @Serializable
data class MessagePush( data class MessagePush(
@ProtoNumber(1) val msgBody: NtMessage? = null, @ProtoNumber(1) val msgBody: PushMsgBody? = null,
@ProtoNumber(4) val clientInfo: MessagePushClientInfo? = null, @ProtoNumber(4) val clientInfo: MessagePushClientInfo? = null,
): Protobuf<MessagePush> ): Protobuf<MessagePush>

View File

@ -9,7 +9,6 @@ import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
import moe.fuqiuluo.shamrock.tools.slice import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.tools.toHexString import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.DeflateTools import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.oidb.cmd0x6d7.CreateFolderReq import protobuf.oidb.cmd0x6d7.CreateFolderReq
import protobuf.oidb.cmd0x6d7.DeleteFolderReq import protobuf.oidb.cmd0x6d7.DeleteFolderReq

View File

@ -22,7 +22,6 @@ import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
import moe.fuqiuluo.shamrock.tools.slice import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.utils.PlatformUtils import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.auto.toByteArray import protobuf.auto.toByteArray
import protobuf.guild.GetGuildFeedsReq import protobuf.guild.GetGuildFeedsReq

View File

@ -1,5 +1,3 @@
@file:OptIn(DelicateCoroutinesApi::class)
package moe.fuqiuluo.qqinterface.servlet package moe.fuqiuluo.qqinterface.servlet
import com.tencent.mobileqq.qroute.QRoute import com.tencent.mobileqq.qroute.QRoute
@ -7,14 +5,13 @@ import com.tencent.mobileqq.troop.api.ITroopMemberNameService
import com.tencent.qqnt.kernel.api.IKernelService import com.tencent.qqnt.kernel.api.IKernelService
import com.tencent.qqnt.kernel.nativeinterface.* import com.tencent.qqnt.kernel.nativeinterface.*
import com.tencent.qqnt.msg.api.IMsgService import com.tencent.qqnt.msg.api.IMsgService
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import moe.fuqiuluo.qqinterface.servlet.msg.messageelement.toSegments
import moe.fuqiuluo.qqinterface.servlet.msg.toListMap import moe.fuqiuluo.qqinterface.servlet.msg.toListMap
import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
import moe.fuqiuluo.shamrock.helper.ContactHelper import moe.fuqiuluo.shamrock.helper.ContactHelper
import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
@ -26,9 +23,9 @@ import moe.fuqiuluo.shamrock.tools.*
import moe.fuqiuluo.shamrock.utils.DeflateTools import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import moe.fuqiuluo.shamrock.xposed.helper.msgService import moe.fuqiuluo.shamrock.xposed.helper.msgService
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.auto.toByteArray import protobuf.auto.toByteArray
import protobuf.message.PushMsgBody
import protobuf.message.longmsg.* import protobuf.message.longmsg.*
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
@ -295,27 +292,27 @@ internal object MsgSvc : BaseSvc() {
if (it.command == "MultiMsg") { if (it.command == "MultiMsg") {
return Result.success(it.data?.body?.map { msg -> return Result.success(it.data?.body?.map { msg ->
val chatType = val chatType =
if (msg.content!!.msgType == 82) MsgConstant.KCHATTYPEGROUP else MsgConstant.KCHATTYPEC2C if (msg.contentHead!!.msgType == 82) MsgConstant.KCHATTYPEGROUP else MsgConstant.KCHATTYPEC2C
MessageDetail( MessageDetail(
time = msg.content?.msgTime?.toInt() ?: 0, time = msg.contentHead?.msgTime?.toInt() ?: 0,
msgType = MessageHelper.obtainDetailTypeByMsgType(chatType), msgType = MessageHelper.obtainDetailTypeByMsgType(chatType),
msgId = 0, // MessageHelper.generateMsgIdHash(chatType, msg.content!!.msgViaRandom), msgViaRandom 为空 msgId = 0, // MessageHelper.generateMsgIdHash(chatType, msg.content!!.msgViaRandom), msgViaRandom 为空
realId = msg.content!!.msgSeq?.toInt() ?: 0, realId = msg.contentHead!!.msgSeq?.toInt() ?: 0,
sender = MessageSender( sender = MessageSender(
msg.head?.peer ?: 0, msg.msgHead?.peer ?: 0,
msg.head?.groupInfo?.memberCard?.ifEmpty { msg.head?.forward?.friendName } msg.msgHead?.responseGrp?.memberCard?.ifEmpty { msg.msgHead?.forward?.friendName }
?: msg.head?.forward?.friendName ?: "", ?: msg.msgHead?.forward?.friendName ?: "",
"unknown", "unknown",
0, 0,
msg.head?.peerUid ?: "", msg.msgHead?.peerUid ?: "",
msg.head?.peerUid ?: "" msg.msgHead?.peerUid ?: ""
), ),
message = msg.body?.rich?.elements?.toSegments(chatType, msg.head?.peer.toString(), "0") message = msg.body?.richText?.elements?.toSegments(chatType, msg.msgHead?.peer.toString(), "0")
?.toListMap() ?: emptyList(), ?.toListMap() ?: emptyList(),
peerId = msg.head?.peer ?: 0, peerId = msg.msgHead?.peer ?: 0,
groupId = if (chatType == MsgConstant.KCHATTYPEGROUP) msg.head?.groupInfo?.groupCode?.toLong() groupId = if (chatType == MsgConstant.KCHATTYPEGROUP) msg.msgHead?.responseGrp?.groupCode?.toLong()
?: 0 else 0, ?: 0 else 0,
targetId = if (chatType != MsgConstant.KCHATTYPEGROUP) msg.head?.peer ?: 0 else 0 targetId = if (chatType != MsgConstant.KCHATTYPEGROUP) msg.msgHead?.peer ?: 0 else 0
) )
} }
?: return Result.failure(Exception("Msg is empty"))) ?: return Result.failure(Exception("Msg is empty")))

View File

@ -9,19 +9,18 @@ import io.ktor.utils.io.core.writeFully
import io.ktor.utils.io.core.writeInt import io.ktor.utils.io.core.writeInt
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.encodeToByteArray
import moe.fuqiuluo.shamrock.remote.action.handlers.GetHistoryMsg import moe.fuqiuluo.shamrock.remote.action.handlers.GetHistoryMsg
import moe.fuqiuluo.shamrock.remote.service.listener.AioListener import moe.fuqiuluo.shamrock.remote.service.listener.AioListener
import moe.fuqiuluo.shamrock.tools.broadcast import moe.fuqiuluo.shamrock.tools.broadcast
import moe.fuqiuluo.shamrock.utils.DeflateTools import moe.fuqiuluo.shamrock.utils.DeflateTools
import protobuf.message.element.JsonElement import protobuf.message.element.LightAppElem
import protobuf.message.NtMessage import protobuf.message.PushMsgBody
import protobuf.message.MessageContent import protobuf.message.ContentHead
import protobuf.message.MessageElement import protobuf.message.Elem
import protobuf.message.RichMessage import protobuf.message.RichText
import protobuf.message.MessageHead import protobuf.message.ResponseHead
import protobuf.message.MessageBody import protobuf.message.MsgBody
import protobuf.push.MessagePush import protobuf.push.MessagePush
import mqq.app.MobileQQ import mqq.app.MobileQQ
import protobuf.auto.toByteArray import protobuf.auto.toByteArray
@ -34,14 +33,14 @@ internal object PacketSvc: BaseSvc() {
suspend fun fakeSelfRecvJsonMsg(msgService: IKernelMsgService, content: String): Long { suspend fun fakeSelfRecvJsonMsg(msgService: IKernelMsgService, content: String): Long {
return fakeReceiveSelfMsg(msgService) { return fakeReceiveSelfMsg(msgService) {
listOf( listOf(
MessageElement( Elem(
json = JsonElement((byteArrayOf(1) + DeflateTools.compress(content.toByteArray()))) lightApp = LightAppElem((byteArrayOf(1) + DeflateTools.compress(content.toByteArray())))
) )
) )
} }
} }
private suspend fun fakeReceiveSelfMsg(msgService: IKernelMsgService, builder: () -> List<MessageElement>): Long { private suspend fun fakeReceiveSelfMsg(msgService: IKernelMsgService, builder: () -> List<Elem>): Long {
val latestMsg = withTimeoutOrNull(3000) { val latestMsg = withTimeoutOrNull(3000) {
suspendCancellableCoroutine { suspendCancellableCoroutine {
msgService.getMsgs(Contact(MsgConstant.KCHATTYPEC2C, app.currentUid, ""), 0L, 1, true) { code, why, msgs -> msgService.getMsgs(Contact(MsgConstant.KCHATTYPEC2C, app.currentUid, ""), 0L, 1, true) { code, why, msgs ->
@ -52,27 +51,27 @@ internal object PacketSvc: BaseSvc() {
val msgSeq = (latestMsg?.msgSeq ?: 0) + 1 val msgSeq = (latestMsg?.msgSeq ?: 0) + 1
val msgPush = MessagePush( val msgPush = MessagePush(
msgBody = NtMessage( msgBody = PushMsgBody(
msgHead = MessageHead( msgHead = ResponseHead(
peer = app.longAccountUin, peer = app.longAccountUin,
peerUid = app.currentUid, peerUid = app.currentUid,
flag = 1001, flag = 1001,
receiver = app.longAccountUin, receiver = app.longAccountUin,
receiverUid = app.currentUid receiverUid = app.currentUid
), ),
contentHead = MessageContent( contentHead = ContentHead(
msgType = 166, msgType = 166,
msgSubType = 11, msgSubType = 11,
msgSeq = msgSeq, msgSeq = msgSeq,
msgViaRandom = msgSeq, msgViaRandom = msgSeq,
msgTime = System.currentTimeMillis() / 1000, msgTime = System.currentTimeMillis() / 1000,
u2 = 1, u2 = 1,
msgSeq_ = msgSeq, sequence = msgSeq,
msgRandom = msgService.getMsgUniqueId(System.currentTimeMillis()), msgRandom = msgService.getMsgUniqueId(System.currentTimeMillis()),
u4 = msgSeq - 2, u4 = msgSeq - 2,
u5 = msgSeq u5 = msgSeq
), ),
body = MessageBody(RichMessage( body = MsgBody(RichText(
elements = builder() elements = builder()
)) ))
) )

View File

@ -0,0 +1,79 @@
package moe.fuqiuluo.qqinterface.servlet.msg
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import moe.fuqiuluo.qqinterface.servlet.msg.converter.MessageElementConverter
import moe.fuqiuluo.qqinterface.servlet.msg.converter.MsgElementConverter
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.MessageHelper
import protobuf.message.Elem
@JvmName("elemListToSegments")
internal suspend fun List<Elem>.toSegments(
chatType: Int,
peerId: String,
subPeer: String
): List<MessageSegment> {
val messageData = arrayListOf<MessageSegment>()
this.forEach { msg ->
kotlin.runCatching {
val elementType = if (msg.text != null) {
1
} else if (msg.face != null) {
2
} else if (msg.lightApp != null) {
51
} else if (msg.commonElem != null) {
53
} else
throw UnsupportedOperationException("不支持的消息element类型$msg")
val converter = MessageElementConverter[elementType]
converter?.invoke(chatType, peerId, subPeer, msg)
?: throw UnsupportedOperationException("不支持的消息element类型$elementType")
}.onSuccess {
messageData.add(it)
}.onFailure {
if (it is UnknownError) {
// 不处理的消息类型抛出unknown error
} else {
LogCenter.log("消息element转换错误$it", Level.WARN)
}
}
}
return messageData
}
@JvmName("msgElementListToSegments")
internal suspend fun List<MsgElement>.toSegments(chatType: Int, peerId: String, subPeer: String): List<MessageSegment> {
val messageData = arrayListOf<MessageSegment>()
this.forEach { msg ->
kotlin.runCatching {
val converter = MsgElementConverter[msg.elementType]
converter?.invoke(chatType, peerId, subPeer, msg)
?: throw UnsupportedOperationException("不支持的消息element类型${msg.elementType}")
}.onSuccess {
messageData.add(it)
}.onFailure {
if (it is UnknownError) {
// 不处理的消息类型抛出unknown error
} else {
LogCenter.log("消息element转换错误$it, elementType: ${msg.elementType}", Level.WARN)
}
}
}
return messageData
}
internal suspend fun List<MsgElement>.toCQCode(chatType: Int, peerId: String, subPeer: String): String {
if (this.isEmpty()) {
return ""
}
return MessageHelper.nativeEncodeCQCode(this.toSegments(chatType, peerId, subPeer).map {
val params = hashMapOf<String, String>()
params["_type"] = it.type
it.data.forEach { (key, value) ->
params[key] = value.toString()
}
params
})
}

View File

@ -1,52 +1,16 @@
package moe.fuqiuluo.qqinterface.servlet.msg.messageelement package moe.fuqiuluo.qqinterface.servlet.msg.converter
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.io.core.readUInt import kotlinx.io.core.readUInt
import moe.fuqiuluo.qqinterface.servlet.msg.MessageSegment import moe.fuqiuluo.qqinterface.servlet.msg.MessageSegment
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.utils.DeflateTools import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.tools.asJsonObject import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asString import moe.fuqiuluo.shamrock.tools.asString
import protobuf.message.MessageElement import protobuf.message.Elem
internal suspend fun List<MessageElement>.toSegments( internal typealias IMessageElementConverter = suspend (Int, String, String, Elem) -> MessageSegment
chatType: Int,
peerId: String,
subPeer: String
): List<MessageSegment> {
val messageData = arrayListOf<MessageSegment>()
this.forEach { msg ->
kotlin.runCatching {
val elementType = if (msg.text != null) {
1
} else if (msg.face != null) {
2
} else if (msg.json != null) {
51
} else if (msg.comm != null) {
53
} else
throw UnsupportedOperationException("不支持的消息element类型$msg")
val converter = MessageElementConverter[elementType]
converter?.invoke(chatType, peerId, subPeer, msg)
?: throw UnsupportedOperationException("不支持的消息element类型$elementType")
}.onSuccess {
messageData.add(it)
}.onFailure {
if (it is UnknownError) {
// 不处理的消息类型抛出unknown error
} else {
LogCenter.log("消息element转换错误$it", Level.WARN)
}
}
}
return messageData
}
internal typealias IMessageElementConverter = suspend (Int, String, String, MessageElement) -> MessageSegment
internal object MessageElementConverter { internal object MessageElementConverter {
private val convertMap = hashMapOf( private val convertMap = hashMapOf(
@ -76,7 +40,7 @@ internal object MessageElementConverter {
chatType: Int, chatType: Int,
peerId: String, peerId: String,
subPeer: String, subPeer: String,
element: MessageElement element: Elem
): MessageSegment { ): MessageSegment {
val text = element.text!! val text = element.text!!
if (text.attr6Buf != null) { if (text.attr6Buf != null) {
@ -89,23 +53,11 @@ internal object MessageElementConverter {
"qq" to uin "qq" to uin
) )
) )
} else if (text.pbReserve != null) {
val resv = text.pbReserve!!
return MessageSegment(
type = "at",
data = hashMapOf(
"qq" to when (resv.atType) {
2 -> resv.atMemberTinyid!!
4 -> resv.atChannelInfo!!.channelId!!
else -> throw UnsupportedOperationException("Unknown at type: ${resv.atType}")
}
)
)
} else { } else {
return MessageSegment( return MessageSegment(
type = "text", type = "text",
data = hashMapOf( data = hashMapOf(
"text" to text.text!! "text" to text.str!!
) )
) )
} }
@ -340,9 +292,9 @@ internal object MessageElementConverter {
chatType: Int, chatType: Int,
peerId: String, peerId: String,
subPeer: String, subPeer: String,
element: MessageElement element: Elem
): MessageSegment { ): MessageSegment {
val data = element.json!!.data!! val data = element.lightApp!!.data!!
val jsonStr = val jsonStr =
(if (data[0].toInt() == 1) DeflateTools.uncompress(data.sliceArray(1 until data.size)) else data.sliceArray(1 until data.size)).toString() (if (data[0].toInt() == 1) DeflateTools.uncompress(data.sliceArray(1 until data.size)) else data.sliceArray(1 until data.size)).toString()
val json = jsonStr.asJsonObject val json = jsonStr.asJsonObject

View File

@ -1,8 +1,11 @@
package moe.fuqiuluo.qqinterface.servlet.msg.msgelement package moe.fuqiuluo.qqinterface.servlet.msg.converter
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import com.tencent.qqnt.kernel.nativeinterface.MsgElement import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import kotlinx.serialization.json.* import kotlinx.serialization.json.add
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonArray
import moe.fuqiuluo.qqinterface.servlet.msg.MessageSegment import moe.fuqiuluo.qqinterface.servlet.msg.MessageSegment
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
import moe.fuqiuluo.shamrock.helper.ContactHelper import moe.fuqiuluo.shamrock.helper.ContactHelper
@ -16,41 +19,6 @@ import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asString import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.hex2ByteArray import moe.fuqiuluo.shamrock.tools.hex2ByteArray
internal suspend fun List<MsgElement>.toSegments(chatType: Int, peerId: String, subPeer: String): List<MessageSegment> {
val messageData = arrayListOf<MessageSegment>()
this.forEach { msg ->
kotlin.runCatching {
val converter = MsgElementConverter[msg.elementType]
converter?.invoke(chatType, peerId, subPeer, msg)
?: throw UnsupportedOperationException("不支持的消息element类型${msg.elementType}")
}.onSuccess {
messageData.add(it)
}.onFailure {
if (it is UnknownError) {
// 不处理的消息类型抛出unknown error
} else {
LogCenter.log("消息element转换错误$it, elementType: ${msg.elementType}", Level.WARN)
}
}
}
return messageData
}
internal suspend fun List<MsgElement>.toCQCode(chatType: Int, peerId: String, subPeer: String): String {
if (this.isEmpty()) {
return ""
}
return MessageHelper.nativeEncodeCQCode(this.toSegments(chatType, peerId, subPeer).map {
val params = hashMapOf<String, String>()
params["_type"] = it.type
it.data.forEach { (key, value) ->
params[key] = value.toString()
}
params
})
}
internal typealias IMsgElementConverter = suspend (Int, String, String, MsgElement) -> MessageSegment internal typealias IMsgElementConverter = suspend (Int, String, String, MsgElement) -> MessageSegment
internal object MsgElementConverter { internal object MsgElementConverter {

View File

@ -0,0 +1,539 @@
package moe.fuqiuluo.qqinterface.servlet.msg.maker
import android.graphics.BitmapFactory
import androidx.exifinterface.media.ExifInterface
import com.tencent.qqnt.kernel.nativeinterface.*
import kotlinx.serialization.json.JsonObject
import moe.fuqiuluo.qqinterface.servlet.CardSvc
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
import moe.fuqiuluo.qqinterface.servlet.transfile.*
import moe.fuqiuluo.qqinterface.servlet.transfile.PictureResource
import moe.fuqiuluo.qqinterface.servlet.transfile.Private
import moe.fuqiuluo.qqinterface.servlet.transfile.Transfer
import moe.fuqiuluo.qqinterface.servlet.transfile.Troop
import moe.fuqiuluo.shamrock.helper.*
import moe.fuqiuluo.shamrock.helper.ActionMsgException
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.LogicException
import moe.fuqiuluo.shamrock.helper.ParamsException
import moe.fuqiuluo.shamrock.tools.*
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import moe.fuqiuluo.shamrock.xposed.helper.msgService
import protobuf.auto.toByteArray
import protobuf.message.Elem
import protobuf.message.element.*
import protobuf.message.element.commelem.*
import java.io.File
import java.nio.ByteBuffer
import kotlin.random.Random
import kotlin.random.nextULong
internal typealias IMessageElementMaker = suspend (Int, Long, String, JsonObject) -> Result<Elem>
internal object MessageElementMaker {
private val makerArray = hashMapOf(
"text" to MessageElementMaker::createTextElem,
"at" to MessageElementMaker::createAtElem,
"face" to MessageElementMaker::createFaceElem,
"pic" to MessageElementMaker::createImageElem,
"image" to MessageElementMaker::createImageElem,
// "voice" to MessageElementMaker::createRecordElem,
// "record" to MessageElementMaker::createRecordElem,
// "video" to MessageElementMaker::createVideoElem,
"markdown" to MessageElementMaker::createMarkdownElem,
"button" to MessageElementMaker::createButtonElem,
"inline_keyboard" to MessageElementMaker::createButtonElem,
// "dice" to MessageElementMaker::createDiceElem,
// "rps" to MessageElementMaker::createRpsElem,
"basketball" to MessageElementMaker::createBasketballElem,
"new_dice" to MessageElementMaker::createNewDiceElem,
"new_rps" to MessageElementMaker::createNewRpsElem,
"poke" to MessageElementMaker::createPokeElem,
// "anonymous" to MessageElementMaker::createAnonymousElem,
// "share" to MessageElementMaker::createShareElem,
// "contact" to MessageElementMaker::createContactElem,
// "location" to MessageElementMaker::createLocationElem,
// "music" to MessageElementMaker::createMusicElem,
"reply" to MessageElementMaker::createReplyElem,
// "touch" to MessageElementMaker::createTouchElem,
// "weather" to MessageElementMaker::createWeatherElem,
"json" to MessageElementMaker::createJsonElem,
//"node" to MessageMaker::createNodeElem,
//"multi_msg" to MessageMaker::createLongMsgStruct,
//"bubble_face" to MessageElementMaker::createBubbleFaceElem,
)
operator fun get(type: String): IMessageElementMaker? = makerArray[type]
private suspend fun createTextElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("text")
val elem = Elem(
text = TextMsg(data["text"].asString)
)
return Result.success(elem)
}
private suspend fun createAtElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
return when (chatType) {
MsgConstant.KCHATTYPEGROUP -> {
data.checkAndThrow("qq")
val qq: Long
val type: Int
val display = when (val qqStr = data["qq"].asString) {
"0", "all" -> {
qq = 0
type = 1
"@全体成员"
}
"online" -> {
qq = 0
type = 64
"@在线成员"
}
else -> {
qq = qqStr.toLong()
type = 0
"@" + (data["name"].asStringOrNull ?: GroupSvc.getTroopMemberInfoByUinV2(peerId, qqStr, true)
.let {
val info = it.getOrNull()
if (info == null)
LogCenter.log("无法获取群成员信息: $qqStr", Level.ERROR)
info?.troopnick
.ifNullOrEmpty(info?.friendnick)
.ifNullOrEmpty(qqStr)
})
}
}
val attr6: ByteBuffer = ByteBuffer.allocate(6)
attr6.put(byteArrayOf(0, 1, 0, 0, 0))
attr6.putChar(display.length.toChar())
attr6.putChar(type.toChar())
attr6.putBuf32Long(qq)
attr6.put(byteArrayOf(0, 0))
val elem = Elem(
text = TextMsg(str = display, attr6Buf = attr6.array())
)
Result.success(elem)
}
MsgConstant.KCHATTYPEC2C -> {
data.checkAndThrow("qq")
val qq = data["qq"].asString
val display =
"@" + (data["name"].asStringOrNull ?: CardSvc.getProfileCard(qq)
.onSuccess {
it.strNick.ifNullOrEmpty(qq)
}.onFailure {
LogCenter.log("无法获取QQ信息: $qq", Level.WARN)
})
val elem = Elem(
text = TextMsg(str = display)
)
Result.success(elem)
}
else -> Result.failure(ActionMsgException)
}
}
private suspend fun createFaceElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("id")
val elem = Elem(
face = FaceMsg(data["id"].asInt)
)
return Result.success(elem)
}
private suspend fun createImageElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
val isOriginal = data["original"].asBooleanOrNull ?: true
val isFlash = data["flash"].asBooleanOrNull ?: false
val filePath = data["file"].asStringOrNull
val url = data["url"].asStringOrNull
var file: File? = null
if (filePath != null) {
val md5 = filePath
.replace(regex = "[{}\\-]".toRegex(), replacement = "")
.split(".")[0].lowercase()
file = if (md5.length == 32) {
FileUtils.getFileByMd5(md5)
} else {
FileUtils.parseAndSave(filePath)
}
}
if ((file == null || !file.exists()) && url != null) {
file = FileUtils.parseAndSave(url)
}
if (file?.exists() == false) {
throw LogicException("Image(${file.name}) file is not exists, please check your filename.")
}
requireNotNull(file)
val md5HexStr = QQNTWrapperUtil.CppProxy.genFileMd5Hex(file.absolutePath)
val msgService = NTServiceFetcher.kernelService.msgService!!
val originalPath = msgService.getRichMediaFilePathForMobileQQSend(
RichMediaFilePathInfo(
2, 0, md5HexStr, file.name, 1, 0, null, "", true
)
)
if (!QQNTWrapperUtil.CppProxy.fileIsExist(originalPath) || QQNTWrapperUtil.CppProxy.getFileSize(
originalPath
) != file.length()
) {
val thumbPath = msgService.getRichMediaFilePathForMobileQQSend(
RichMediaFilePathInfo(
2, 0, md5HexStr, file.name, 2, 720, null, "", true
)
)
QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, originalPath)
QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, thumbPath)
}
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(file.absolutePath, options)
val exifInterface = ExifInterface(file.absolutePath)
val orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED
)
val picWidth: Int
val picHeight: Int
if (orientation != ExifInterface.ORIENTATION_ROTATE_90 && orientation != ExifInterface.ORIENTATION_ROTATE_270) {
picWidth = options.outWidth
picHeight = options.outHeight
} else {
picWidth = options.outHeight
picHeight = options.outWidth
}
val elem = when (chatType) {
MsgConstant.KCHATTYPEGROUP -> {
Transfer with Troop(peerId) trans PictureResource(file)
Elem(
customFace = CustomFace(
filePath = "${md5HexStr.substring(0, 8)}-${md5HexStr.substring(8, 4)}-${
md5HexStr.substring(
12,
4
)
}-${md5HexStr.substring(16, 4)}-${md5HexStr.substring(20, 12)}.${FileUtils.getFileType(file)}",
fileId = 0u,
serverIp = 0u,
serverPort = 0u,
fileType = 1001u,
useful = 1u,
md5 = md5HexStr.hex2ByteArray(),
bizType = data["subType"].asIntOrNull?.toUInt(),
imageType = FileUtils.getPicType(file).toUInt(),
width = picWidth.toUInt(),
height = picHeight.toUInt(),
size = QQNTWrapperUtil.CppProxy.getFileSize(file.absolutePath).toUInt(),
origin = if (isOriginal) 1u else 0u,
thumbWidth = 0u,
thumbHeight = 0u,
pbReserve = CustomFace.Companion.PbReserve(field1 = 0)
)
)
}
MsgConstant.KCHATTYPEC2C -> {
Transfer with Private(peerId) trans PictureResource(file)
Elem(
notOnlineImage = NotOnlineImage(
filePath = "${md5HexStr}.${FileUtils.getFileType(file)}".toByteArray(),
fileLen = QQNTWrapperUtil.CppProxy.getFileSize(file.absolutePath).toUInt(),
downloadPath = "".toByteArray(),
imgType = FileUtils.getPicType(file).toUInt(),
picMd5 = md5HexStr.hex2ByteArray(),
picHeight = picWidth.toUInt(),
picWidth = picHeight.toUInt(),
resId = "".toByteArray(),
original = if (isOriginal) 1u else 0u, // true
pbReserve = NotOnlineImage.Companion.PbReserve(field1 = 0)
)
)
}
else -> throw LogicException("Not supported chatType($chatType) for PictureMsg")
}
return Result.success(elem)
}
private suspend fun createReplyElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("id")
val msgHash = data["id"].asInt
val mapping = MessageHelper.getMsgMappingByHash(msgHash)
?: return Result.failure(Exception("不存在该消息映射,无法回复消息"))
if (mapping.qqMsgId == 0L) {
// 貌似获取失败了555
LogCenter.log("无法获取被回复消息", Level.ERROR)
return Result.failure(Exception("无法获取被回复消息"))
}
val elem = if (data.containsKey("text")) {
data.checkAndThrow("qq", "time", "seq")
Elem(
srcMsg = SourceMsg(
origSeqs = listOf(data["seq"].asInt),
senderUin = data["qq"].asString.toULong(),
time = data["time"].asString.toULong(),
flag = 1u,
elems = listOf(
Elem(
text = TextMsg(
data["text"].asString
)
)
),
type = 0u,
pbReserve = SourceMsg.Companion.PbReserve(
field3 = Random.nextULong(),
field8 = Random.nextInt(0, 10000)
),
)
)
} else {
val msg =
MsgSvc.getMsgByQMsgId(chatType, mapping.peerId, mapping.qqMsgId).getOrNull() ?: return Result.failure(
Exception("无法获取被回复消息")
)
Elem(
srcMsg = SourceMsg(
origSeqs = listOf(msg.msgSeq.toInt()),
senderUin = msg.senderUin.toULong(),
time = msg.msgTime.toULong(),
flag = 1u,
// elems = msg.elements.toSegments(),
type = 0u,
pbReserve = SourceMsg.Companion.PbReserve(
field3 = Random.nextULong(),
senderUid = msg.senderUid,
receiverUid = TicketSvc.getUid(),
field8 = Random.nextInt(0, 10000)
),
)
)
}
return Result.success(elem)
}
private suspend fun createJsonElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("data")
val elem = Elem(
lightApp = LightAppElem(
data = DeflateTools.compress(data.toString().toByteArray())
)
)
return Result.success(elem)
}
private suspend fun createPokeElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("type", "id")
val elem = Elem(
commonElem = CommonElem(
serviceType = 2,
elem = PokeExtra(
type = data["type"].asInt,
field7 = 0,
field8 = 0
).toByteArray(),
businessType = data["id"].asInt
)
)
return Result.success(elem)
}
private suspend fun createBasketballElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
val elem = Elem(
commonElem = CommonElem(
serviceType = 37,
elem = QFaceExtra(
packId = "1",
stickerId = "13",
faceId = 114,
field4 = 1,
field5 = 2,
field6 = "",
faceText = "/篮球",
field9 = 1
).toByteArray(),
businessType = 2
)
)
return Result.success(elem)
}
private suspend fun createNewDiceElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
val elem = Elem(
commonElem = CommonElem(
serviceType = 37,
elem = QFaceExtra(
packId = "1",
stickerId = "33",
faceId = 358,
field4 = 1,
field5 = 2,
field6 = "",
faceText = "/骰子",
field9 = 1
).toByteArray(),
businessType = 2
)
)
return Result.success(elem)
}
private suspend fun createNewRpsElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
val elem = Elem(
commonElem = CommonElem(
serviceType = 37,
elem = QFaceExtra(
packId = "1",
stickerId = "34",
faceId = 359,
field4 = 1,
field5 = 2,
field6 = "",
faceText = "/包剪锤",
field9 = 1
).toByteArray(),
businessType = 1
)
)
return Result.success(elem)
}
private suspend fun createMarkdownElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("content")
val elem = Elem(
commonElem = CommonElem(
serviceType = 45,
elem = MarkdownExtra(data["content"].asString).toByteArray(),
businessType = 1
)
)
return Result.success(elem)
}
private suspend fun createButtonElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<Elem> {
data.checkAndThrow("rows")
val elem = Elem(
commonElem = CommonElem(
serviceType = 46,
elem = ButtonExtra(
field1 = Object1(
rows = data["rows"].asJsonArray.map { row ->
Row(buttons = row.asJsonArray.map {
val button = it.asJsonObject
val renderData = button["render_data"].asJsonObject
val action = button["action"].asJsonObject
Button(
id = button["id"].asIntOrNull,
renderData = RenderData(
label = renderData["label"].asString,
visitedLabel = renderData["visited_label"].asString,
style = renderData["style"].asInt
),
action = Action(
type = action["type"].asInt,
permission = Permission(
type = action["permission"].asJsonObject["type"].asInt,
specifyRoleIds = action["permission"].asJsonObject["specify_role_ids"].asJsonArrayOrNull?.map { id -> id.asString },
specifyUserIds = action["permission"].asJsonObject["specify_user_ids"].asJsonArrayOrNull?.map { id -> id.asString }
),
unsupportTips = action["unsupport_tips"].asString,
data = action["data"].asString,
reply = action["reply"].asBooleanOrNull,
enter = action["enter"].asBooleanOrNull
)
)
})
},
appid = data["appid"].asIntOrNull
)
).toByteArray(),
businessType = 1
)
)
return Result.success(elem)
}
private fun JsonObject.checkAndThrow(vararg key: String) {
key.forEach {
if (!containsKey(it)) throw ParamsException(it)
}
}
}

View File

@ -1,4 +1,4 @@
package moe.fuqiuluo.qqinterface.servlet.msg.msgelement package moe.fuqiuluo.qqinterface.servlet.msg.maker
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import androidx.exifinterface.media.ExifInterface import androidx.exifinterface.media.ExifInterface
@ -85,6 +85,7 @@ internal object MsgElementMaker {
//"node" to MessageMaker::createNodeElem, //"node" to MessageMaker::createNodeElem,
//"multi_msg" to MessageMaker::createLongMsgStruct, //"multi_msg" to MessageMaker::createLongMsgStruct,
"bubble_face" to MsgElementMaker::createBubbleFaceElem, "bubble_face" to MsgElementMaker::createBubbleFaceElem,
"button" to MsgElementMaker::createInlineKeywordElem,
"inline_keyboard" to MsgElementMaker::createInlineKeywordElem "inline_keyboard" to MsgElementMaker::createInlineKeywordElem
) )

View File

@ -1,183 +0,0 @@
package moe.fuqiuluo.qqinterface.servlet.msg.messageelement
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.serialization.json.JsonObject
import moe.fuqiuluo.qqinterface.servlet.GProSvc
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.shamrock.helper.*
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.ParamsException
import moe.fuqiuluo.shamrock.tools.*
import moe.fuqiuluo.shamrock.utils.DeflateTools
import protobuf.message.MessageElement
import protobuf.message.element.FaceElement
import protobuf.message.element.JsonElement
import protobuf.message.element.TextElement
import java.nio.ByteBuffer
internal typealias IMessageElementMaker = suspend (Int, Long, String, JsonObject) -> Result<MessageElement>
internal object MessageElementMaker {
private val makerArray = hashMapOf(
"text" to MessageElementMaker::createTextElem,
"face" to MessageElementMaker::createFaceElem,
// "pic" to MessageElementMaker::createImageElem,
// "image" to MessageElementMaker::createImageElem,
// "voice" to MessageElementMaker::createRecordElem,
// "record" to MessageElementMaker::createRecordElem,
"at" to MessageElementMaker::createAtElem,
// "video" to MessageElementMaker::createVideoElem,
// "markdown" to MessageElementMaker::createMarkdownElem,
// "dice" to MessageElementMaker::createDiceElem,
// "rps" to MessageElementMaker::createRpsElem,
// "poke" to MessageElementMaker::createPokeElem,
// "anonymous" to MessageElementMaker::createAnonymousElem,
// "share" to MessageElementMaker::createShareElem,
// "contact" to MessageElementMaker::createContactElem,
// "location" to MessageElementMaker::createLocationElem,
// "music" to MessageElementMaker::createMusicElem,
// "reply" to MessageElementMaker::createReplyElem,
// "touch" to MessageElementMaker::createTouchElem,
// "weather" to MessageElementMaker::createWeatherElem,
"json" to MessageElementMaker::createJsonElem,
//"new_dice" to MessageElementMaker::createNewDiceElem,
//"new_rps" to MessageElementMaker::createNewRpsElem,
//"basketball" to MessageElementMaker::createBasketballElem,
//"node" to MessageMaker::createNodeElem,
//"multi_msg" to MessageMaker::createLongMsgStruct,
//"bubble_face" to MessageElementMaker::createBubbleFaceElem,
)
operator fun get(type: String): IMessageElementMaker? = makerArray[type]
private suspend fun createTextElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<MessageElement> {
data.checkAndThrow("text")
val elem = MessageElement(
text = TextElement(data["text"].asString)
)
return Result.success(elem)
}
private suspend fun createFaceElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<MessageElement> {
data.checkAndThrow("id")
val elem = MessageElement(
face = FaceElement(data["id"].asInt)
)
return Result.success(elem)
}
private suspend fun createAtElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<MessageElement> {
return if (chatType == MsgConstant.KCHATTYPEGROUP) {
data.checkAndThrow("qq")
val qq: Long
val type: Int
lateinit var display: String
when (val qqStr = data["qq"].asString) {
"0", "all" -> {
qq = 0
type = 1
display = "@全体成员"
}
"online" -> {
qq = 0
type = 64
display = "@在线成员"
}
else -> {
qq = qqStr.toLong()
type = 0
display =
"@" + (data["name"].asStringOrNull ?: GroupSvc.getTroopMemberInfoByUinV2(peerId, qqStr, true)
.onSuccess {
it.troopnick
.ifEmpty { it.friendnick }
.ifEmpty { qqStr }
}.onFailure {
LogCenter.log("无法获取群成员信息: $qqStr", Level.ERROR)
})
}
}
val attr6: ByteBuffer = ByteBuffer.allocate(6)
attr6.put(byteArrayOf(0, 1, 0, 0, 0))
attr6.putChar(display.length.toChar())
attr6.putChar(type.toChar())
attr6.putBuf32Long(qq)
attr6.put(byteArrayOf(0, 0))
val elem = MessageElement(
text = TextElement(text = display, attr6Buf = attr6.array())
)
Result.success(elem)
} else if (chatType == MsgConstant.KCHATTYPEGUILD) {
data.checkAndThrow("qq")
val qq: Long
val type: Int
lateinit var display: String
when (val qqStr = data["qq"].asString) {
"0", "all" -> {
type = 2
display = "@全体成员"
}
else -> {
qq = qqStr.toLong()
type = 2
display =
"@" + (data["name"].asStringOrNull ?: GProSvc.getUserGuildInfo(0UL, 0UL)
.onSuccess {
it.nickName.ifNullOrEmpty(qqStr)
}.onFailure {
LogCenter.log("无法获取频道组成员信息: $qqStr", Level.ERROR)
})
}
}
val elem = MessageElement(
text = TextElement(text = display, pbReserve = TextElement.Companion.TextResvAttr(atType = type))
)
Result.success(elem)
} else Result.failure(ActionMsgException)
}
private suspend fun createJsonElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<MessageElement> {
data.checkAndThrow("data")
val elem = MessageElement(
json = JsonElement(
data = DeflateTools.compress(data.toString().toByteArray())
)
)
return Result.success(elem)
}
private fun JsonObject.checkAndThrow(vararg key: String) {
key.forEach {
if (!containsKey(it)) throw ParamsException(it)
}
}
}

View File

@ -16,8 +16,8 @@ import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import moe.fuqiuluo.qqinterface.servlet.MsgSvc import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.qqinterface.servlet.msg.messageelement.MessageElementMaker import moe.fuqiuluo.qqinterface.servlet.msg.maker.MessageElementMaker
import moe.fuqiuluo.qqinterface.servlet.msg.msgelement.MsgElementMaker import moe.fuqiuluo.qqinterface.servlet.msg.maker.MsgElementMaker
import moe.fuqiuluo.shamrock.helper.db.MessageDB import moe.fuqiuluo.shamrock.helper.db.MessageDB
import moe.fuqiuluo.shamrock.helper.db.MessageMapping import moe.fuqiuluo.shamrock.helper.db.MessageMapping
import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult
@ -26,7 +26,7 @@ import moe.fuqiuluo.shamrock.tools.asJsonObjectOrNull
import moe.fuqiuluo.shamrock.tools.asString import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.json import moe.fuqiuluo.shamrock.tools.json
import moe.fuqiuluo.shamrock.tools.jsonArray import moe.fuqiuluo.shamrock.tools.jsonArray
import protobuf.message.MessageElement import protobuf.message.Elem
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.math.abs import kotlin.math.abs
@ -323,8 +323,8 @@ internal object MessageHelper {
msgId: Long, msgId: Long,
targetUin: String, targetUin: String,
messageList: JsonArray messageList: JsonArray
): Pair<Boolean, ArrayList<MessageElement>> { ): Pair<Boolean, ArrayList<Elem>> {
val msgList = arrayListOf<MessageElement>() val msgList = arrayListOf<Elem>()
var hasActionMsg = false var hasActionMsg = false
messageList.forEach { messageList.forEach {
val msg = it.jsonObject val msg = it.jsonObject

View File

@ -6,7 +6,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.MsgSvc import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.qqinterface.servlet.msg.msgelement.toSegments import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
import moe.fuqiuluo.qqinterface.servlet.msg.toListMap import moe.fuqiuluo.qqinterface.servlet.msg.toListMap
import moe.fuqiuluo.shamrock.helper.MessageHelper import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.helper.db.MessageDB import moe.fuqiuluo.shamrock.helper.db.MessageDB

View File

@ -8,7 +8,7 @@ import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.data.MessageDetail import moe.fuqiuluo.shamrock.remote.service.data.MessageDetail
import moe.fuqiuluo.shamrock.remote.service.data.MessageSender import moe.fuqiuluo.shamrock.remote.service.data.MessageSender
import moe.fuqiuluo.qqinterface.servlet.MsgSvc import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.qqinterface.servlet.msg.msgelement.toSegments import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
import moe.fuqiuluo.qqinterface.servlet.msg.toListMap import moe.fuqiuluo.qqinterface.servlet.msg.toListMap
import moe.fuqiuluo.shamrock.tools.EmptyJsonString import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.symbols.OneBotHandler import moe.fuqiuluo.symbols.OneBotHandler

View File

@ -4,7 +4,7 @@ import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.serialization.json.* import kotlinx.serialization.json.*
import moe.fuqiuluo.qqinterface.servlet.MsgSvc import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.qqinterface.servlet.TicketSvc import moe.fuqiuluo.qqinterface.servlet.TicketSvc
import moe.fuqiuluo.qqinterface.servlet.msg.msgelement.toSegments import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.MessageHelper import moe.fuqiuluo.shamrock.helper.MessageHelper
@ -15,7 +15,6 @@ import moe.fuqiuluo.shamrock.remote.service.data.ForwardMessageResult
import moe.fuqiuluo.shamrock.tools.* import moe.fuqiuluo.shamrock.tools.*
import moe.fuqiuluo.symbols.OneBotHandler import moe.fuqiuluo.symbols.OneBotHandler
import protobuf.message.* import protobuf.message.*
import protobuf.message.longmsg.PushMsgBody
import java.util.* import java.util.*
import kotlin.random.Random import kotlin.random.Random
@ -96,20 +95,21 @@ internal object SendForwardMessage : IActionHandler() {
return@map null return@map null
} }
if (record.chatType == MsgConstant.KCHATTYPEGROUP) groupUin = record.peerUin.toString() if (record.chatType == MsgConstant.KCHATTYPEGROUP) groupUin = record.peerUin.toString()
if (record.chatType == MsgConstant.KCHATTYPEC2C) uid = record.peerUid
PushMsgBody( PushMsgBody(
head = MessageHead( msgHead = ResponseHead(
peerUid = record.senderUid, peerUid = record.senderUid,
receiverUid = record.peerUid, receiverUid = record.peerUid,
forward = MessageForward( forward = ResponseForward(
friendName = record.sendNickName friendName = record.sendNickName
), ),
groupInfo = if (record.chatType == MsgConstant.KCHATTYPEGROUP) GroupInfo( responseGrp = if (record.chatType == MsgConstant.KCHATTYPEGROUP) ResponseGrp(
groupCode = record.peerUin.toULong(), groupCode = record.peerUin.toULong(),
memberCard = record.sendMemberName, memberCard = record.sendMemberName,
u1 = 2 u1 = 2
) else null ) else null
), ),
content = MessageContent( contentHead = ContentHead(
msgType = when (record.chatType) { msgType = when (record.chatType) {
MsgConstant.KCHATTYPEC2C -> 9 MsgConstant.KCHATTYPEC2C -> 9
MsgConstant.KCHATTYPEGROUP -> 82 MsgConstant.KCHATTYPEGROUP -> 82
@ -118,9 +118,9 @@ internal object SendForwardMessage : IActionHandler() {
) )
}, },
msgSubType = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null, msgSubType = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null,
u1 = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null, divSeq = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null,
msgViaRandom = record.msgId, msgViaRandom = record.msgId,
msgSeq_ = record.msgSeq, // idk what this is(i++) sequence = record.msgSeq, // idk what this is(i++)
msgTime = record.msgTime, msgTime = record.msgTime,
u2 = 1, u2 = 1,
u6 = 0, u6 = 0,
@ -131,11 +131,11 @@ internal object SendForwardMessage : IActionHandler() {
u2 = 0, u2 = 0,
u3 = 0, u3 = 0,
ub641 = "", ub641 = "",
Avatar = "" avatar = ""
) )
), ),
body = MessageBody( body = MsgBody(
rich = RichMessage( richText = RichText(
elements = MessageHelper.messageArrayToMessageElements( elements = MessageHelper.messageArrayToMessageElements(
record.chatType, record.chatType,
record.msgId, record.msgId,
@ -168,20 +168,20 @@ internal object SendForwardMessage : IActionHandler() {
) )
} else if (data.containsKey("content")) { } else if (data.containsKey("content")) {
PushMsgBody( PushMsgBody(
head = MessageHead( msgHead = ResponseHead(
peer = data["uin"]?.asLong ?: TicketSvc.getUin().toLong(), peer = data["uin"]?.asLong ?: TicketSvc.getUin().toLong(),
peerUid = data["uid"]?.asString ?: TicketSvc.getUid(), peerUid = data["uid"]?.asString ?: TicketSvc.getUid(),
receiverUid = TicketSvc.getUid(), receiverUid = TicketSvc.getUid(),
forward = MessageForward( forward = ResponseForward(
friendName = data["name"]?.asStringOrNull ?: TicketSvc.getNickname() friendName = data["name"]?.asStringOrNull ?: TicketSvc.getNickname()
) )
), ),
content = MessageContent( contentHead = ContentHead(
msgType = 9, msgType = 9,
msgSubType = 175, msgSubType = 175,
u1 = 175, divSeq = 175,
msgViaRandom = Random.nextLong(), msgViaRandom = Random.nextLong(),
msgSeq_ = data["seq"]?.asLong ?: Random.nextLong(), sequence = data["seq"]?.asLong ?: Random.nextLong(),
msgTime = data["time"]?.asLong ?: (System.currentTimeMillis() / 1000), msgTime = data["time"]?.asLong ?: (System.currentTimeMillis() / 1000),
u2 = 1, u2 = 1,
u6 = 0, u6 = 0,
@ -192,11 +192,11 @@ internal object SendForwardMessage : IActionHandler() {
u2 = 0, u2 = 0,
u3 = 2, u3 = 2,
ub641 = "", ub641 = "",
Avatar = "" avatar = ""
) )
), ),
body = MessageBody( body = MsgBody(
rich = RichMessage( richText = RichText(
elements = MessageHelper.messageArrayToMessageElements( elements = MessageHelper.messageArrayToMessageElements(
1, 1,
Random.nextLong(), Random.nextLong(),
@ -211,15 +211,14 @@ internal object SendForwardMessage : IActionHandler() {
?: TicketSvc.getNickname() ?: TicketSvc.getNickname()
}: " }: "
}.onEach { }.onEach {
when (it.asJsonObject["type"].asString) { val type = it.asJsonObject["type"].asString
"text" -> desc[i] += it.asJsonObject["data"].asJsonObject["text"].asString val itData = it.asJsonObject["data"].asJsonObject
when (type) {
"at" -> desc[i] += "@${it.asJsonObject["data"].asJsonObject["name"].asStringOrNull ?: it.asJsonObject["data"].asJsonObject["qq"].asString}" "text" -> desc[i] += itData["text"].asString
"at" -> desc[i] += "@${itData["name"].asStringOrNull ?: itData["qq"].asString}"
"face" -> desc[i] += "[表情]" "face" -> desc[i] += "[表情]"
"image" -> desc[i] += "[图片]"
"voice" -> desc[i] += "[语音]" "voice" -> desc[i] += "[语音]"
"node" -> desc[i] += "[合并转发消息]" "node" -> desc[i] += "[合并转发消息]"
} }
} }

View File

@ -1,50 +1,46 @@
package moe.fuqiuluo.shamrock.remote.action.handlers package moe.fuqiuluo.shamrock.remote.action.handlers
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic
import kotlinx.serialization.encodeToByteArray
import moe.fuqiuluo.qqinterface.servlet.BaseSvc import moe.fuqiuluo.qqinterface.servlet.BaseSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.symbols.OneBotHandler import moe.fuqiuluo.symbols.OneBotHandler
import protobuf.auto.toByteArray import protobuf.auto.toByteArray
import protobuf.msg.C2C import protobuf.message.*
import protobuf.msg.ContentHead import protobuf.message.element.GeneralFlags
import protobuf.msg.Elem import protobuf.message.routing.C2C
import protobuf.msg.GeneralFlags import protobuf.message.routing.Grp
import protobuf.msg.Grp
import protobuf.msg.MsgBody
import protobuf.msg.PbSendMsgReq
import protobuf.msg.RichText
import protobuf.msg.RoutingHead
import kotlin.random.Random import kotlin.random.Random
import kotlin.random.nextUInt import kotlin.random.nextUInt
@OneBotHandler("send_msg_by_resid") @OneBotHandler("send_msg_by_resid")
internal object SendMsgByResid: IActionHandler() { internal object SendMsgByResid : IActionHandler() {
private val msgSeq = atomic(1000) private val msgSeq = atomic(1000)
override suspend fun internalHandle(session: ActionSession): String { override suspend fun internalHandle(session: ActionSession): String {
val resid = session.getString("resid") val resid = session.getString("resid")
val peerId = session.getString("peer") val peerId = session.getString("peer")
val req = PbSendMsgReq( val req = PbSendMsgReq(
routingHead = RoutingHead().apply { routingHead = when (session.getStringOrNull("message_type")) {
when(session.getStringOrNull("message_type")) { "group" ->RoutingHead(grp = Grp(peerId.toUInt()))
"group" -> grp = Grp(peerId.toULong()) "private" ->RoutingHead( c2c = C2C(peerId.toUInt()))
"private" -> c2c = C2C(peerId.toULong()) else ->RoutingHead( grp = Grp(peerId.toUInt()))
else -> grp = Grp(peerId.toULong())
}
}, },
contentHead = ContentHead(1u, 0u, 0u, 0u), contentHead = ContentHead(1, 0, 0, 0),
msgBody = MsgBody( msgBody = MsgBody(
richText = RichText(arrayListOf(Elem( richText = RichText(
elements = arrayListOf(
Elem(
generalFlags = GeneralFlags( generalFlags = GeneralFlags(
long_text_flag = 1u, longTextFlag = 1u,
long_text_resid = resid.toByteArray() longTextResid = resid.toByteArray()
)
)
)
) )
)))
), ),
msgSeq = msgSeq.incrementAndGet().toULong(), msgSeq = msgSeq.incrementAndGet().toUInt(),
msgRand = Random.nextUInt(), msgRand = Random.nextUInt(),
msgVia = 0u msgVia = 0u
) )

View File

@ -12,7 +12,7 @@ import kotlinx.coroutines.launch
import moe.fuqiuluo.qqinterface.servlet.BaseSvc import moe.fuqiuluo.qqinterface.servlet.BaseSvc
import moe.fuqiuluo.qqinterface.servlet.CardSvc import moe.fuqiuluo.qqinterface.servlet.CardSvc
import moe.fuqiuluo.qqinterface.servlet.GroupSvc import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.msg.msgelement.toSegments import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
import moe.fuqiuluo.qqinterface.servlet.msg.toJson import moe.fuqiuluo.qqinterface.servlet.msg.toJson
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
import moe.fuqiuluo.shamrock.remote.service.data.push.GroupFileMsg import moe.fuqiuluo.shamrock.remote.service.data.push.GroupFileMsg

View File

@ -9,7 +9,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import moe.fuqiuluo.qqinterface.servlet.MsgSvc import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.qqinterface.servlet.TicketSvc import moe.fuqiuluo.qqinterface.servlet.TicketSvc
import moe.fuqiuluo.qqinterface.servlet.msg.msgelement.toCQCode import moe.fuqiuluo.qqinterface.servlet.msg.toCQCode
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.Level

View File

@ -1,54 +1,37 @@
@file:OptIn(DelicateCoroutinesApi::class, ExperimentalSerializationApi::class)
package moe.fuqiuluo.shamrock.remote.service.listener package moe.fuqiuluo.shamrock.remote.service.listener
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.coroutines.DelicateCoroutinesApi
import moe.fuqiuluo.shamrock.helper.ContactHelper
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.FriendSvc.requestFriendSystemMsgNew import moe.fuqiuluo.qqinterface.servlet.FriendSvc.requestFriendSystemMsgNew
import moe.fuqiuluo.qqinterface.servlet.GroupSvc import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.GroupSvc.requestGroupSystemMsgNew import moe.fuqiuluo.qqinterface.servlet.GroupSvc.requestGroupSystemMsgNew
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getLongUin import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getLongUin
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
import moe.fuqiuluo.shamrock.helper.MessageHelper import moe.fuqiuluo.shamrock.helper.ContactHelper
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeSubType
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeSubType
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType
import moe.fuqiuluo.shamrock.remote.service.data.push.RequestSubType import moe.fuqiuluo.shamrock.remote.service.data.push.RequestSubType
import moe.fuqiuluo.shamrock.tools.asJsonObject import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asString import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.readBuf32Long import moe.fuqiuluo.shamrock.tools.readBuf32Long
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.xposed.helper.PacketHandler import moe.fuqiuluo.shamrock.xposed.helper.PacketHandler
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.message.MessageContent import protobuf.message.ContentHead
import protobuf.message.MessageHead import protobuf.message.MsgBody
import protobuf.message.MessageBody import protobuf.message.ResponseHead
import protobuf.message.multimedia.RichMediaForPicData import protobuf.message.multimedia.RichMediaForPicData
import protobuf.push.C2CCommonTipsEvent import protobuf.push.*
import protobuf.push.C2CRecallEvent
import protobuf.push.FriendApplyEvent
import protobuf.push.GroupAdminChangeEvent
import protobuf.push.GroupApplyEvent
import protobuf.push.GroupBanEvent
import protobuf.push.GroupCommonTipsEvent
import protobuf.push.GroupInviteEvent
import protobuf.push.GroupInvitedApplyEvent
import protobuf.push.GroupListChangeEvent
import protobuf.push.MessagePush
import protobuf.push.MessagePushClientInfo
import java.util.regex.Pattern import java.util.regex.Pattern
private val RKEY_PATTERN = Pattern.compile("rkey=([A-Za-z0-9_-]+)") private val RKEY_PATTERN = Pattern.compile("rkey=([A-Za-z0-9_-]+)")
@ -106,16 +89,16 @@ internal object PrimitiveListener {
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
LogCenter.log("onMsgPush(msgType: $msgType, subType: $subType): "+e.stackTraceToString(), Level.WARN) LogCenter.log("onMsgPush(msgType: $msgType, subType: $subType): " + e.stackTraceToString(), Level.WARN)
} }
} }
private fun onGroupMessage(msgTime: Long, body: MessageBody) { private fun onGroupMessage(msgTime: Long, body: MsgBody) {
/*runCatching { /*runCatching {
body.rich?.elements?.filter { body.richText?.elements?.filter {
it.comm != null && it.comm!!.type == 48 it.commonElem != null && it.commonElem!!.serviceType == 48
}?.map { }?.map {
it.comm!!.data!!.decodeProtobuf<RichMediaForPicData>() it.commonElem!!.elem!!.decodeProtobuf<RichMediaForPicData>()
}?.forEach { }?.forEach {
it.display?.show?.download?.url?.let { it.display?.show?.download?.url?.let {
RKEY_PATTERN.matcher(it).takeIf { RKEY_PATTERN.matcher(it).takeIf {
@ -129,8 +112,8 @@ internal object PrimitiveListener {
}*/ }*/
} }
private suspend fun onC2CPoke(msgTime: Long, richMsg: MessageBody) { private suspend fun onC2CPoke(msgTime: Long, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<C2CCommonTipsEvent>() val event = body.msgContent!!.decodeProtobuf<C2CCommonTipsEvent>()
if (event.params == null) return if (event.params == null) return
val params = event.params!!.associate { val params = event.params!!.associate {
@ -155,9 +138,9 @@ internal object PrimitiveListener {
private suspend fun onFriendApply( private suspend fun onFriendApply(
msgTime: Long, msgTime: Long,
clientInfo: MessagePushClientInfo, clientInfo: MessagePushClientInfo,
richMsg: MessageBody body: MsgBody
) { ) {
val event = richMsg.rawBuffer!!.decodeProtobuf<FriendApplyEvent>() val event = body.msgContent!!.decodeProtobuf<FriendApplyEvent>()
if (event.head == null) return if (event.head == null) return
val head = event.head!! val head = event.head!!
val applierUid = head.applierUid val applierUid = head.applierUid
@ -188,55 +171,46 @@ internal object PrimitiveListener {
} }
private suspend fun onCardChange(msgTime: Long, richMsg: MessageBody) { private suspend fun onCardChange(msgTime: Long, body: MsgBody) {
LogCenter.log("群名片事件异常请尝试提交issue", Level.WARN) // val event = runCatching {
/*try { // body.msgContent!!.decodeProtobuf<GroupCardChangeEvent>()
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) // }.getOrElse {
if(readPacket.readBuf32Long() == // val readPacket = ByteReadPacket(body.msgContent!!)
readPacket.discardExact(1) // readPacket.readBuf32Long()
detail = ProtoUtils.decodeFromByteArray(readPacket.readBytes(readPacket.readShort().toInt())) // readPacket.discardExact(1)
readPacket.release() //
} catch (e: Exception) { // readPacket.readBytes(readPacket.readShort().toInt()).also {
LogCenter.log("onCardChange error: ${e.stackTraceToString()}", Level.WARN) // readPacket.release()
} // }.decodeProtobuf<GroupCommonTipsEvent>()
// }
var detail = pb[1, 3, 2] //
if (detail !is ProtoMap) { // val targetId = detail[1, 13, 2].asUtf8String
// val newCardList = detail[1, 13, 3].asList
} // var newCard = ""
// newCardList
val targetId = detail[1, 13, 2].asUtf8String // .value
val newCardList = detail[1, 13, 3].asList // .forEach {
var newCard = "" // if (it[1].asInt == 1) {
newCardList // newCard = it[2].asUtf8String
.value // }
.forEach { // }
if (it[1].asInt == 1) { // val groupId = detail[1, 13, 4].asLong
newCard = it[2].asUtf8String // var oldCard = ""
} // val targetQQ = ContactHelper.getUinByUidAsync(targetId).toLong()
} // LogCenter.log("群组[$groupId]成员$targetQQ 群名片变动 -> $newCard")
val groupId = detail[1, 13, 4].asLong // // oldCard暂时获取不到
var oldCard = "" // if (!GlobalEventTransmitter.GroupNoticeTransmitter
val targetQQ = ContactHelper.getUinByUidAsync(targetId).toLong() // .transCardChange(msgTime, targetQQ, oldCard, newCard, groupId)
LogCenter.log("群组[$groupId]成员$targetQQ 群名片变动 -> $newCard") // ) {
// oldCard暂时获取不到 // LogCenter.log("群名片变动推送失败!", Level.WARN)
// GroupSvc.getTroopMemberInfoByUin(groupId.toString(), targetQQ.toString()).onSuccess {
// oldCard = it.troopnick
// }.onFailure {
// LogCenter.log("获取群成员信息失败!", Level.WARN)
// } // }
if (!GlobalEventTransmitter.GroupNoticeTransmitter
.transCardChange(msgTime, targetQQ, oldCard, newCard, groupId)
) {
LogCenter.log("群名片变动推送失败!", Level.WARN)
}*/
} }
private suspend fun onGroupUniqueTitleChange(msgTime: Long, richMsg: MessageBody) { private suspend fun onGroupUniqueTitleChange(msgTime: Long, body: MsgBody) {
val event = runCatching { val event = runCatching {
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>() body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(body.msgContent!!)
readPacket.readBuf32Long() readPacket.readBuf32Long()
readPacket.discardExact(1) readPacket.discardExact(1)
@ -276,13 +250,13 @@ internal object PrimitiveListener {
private suspend fun onEssenceMessage( private suspend fun onEssenceMessage(
msgTime: Long, msgTime: Long,
clientInfo: MessagePushClientInfo?, clientInfo: MessagePushClientInfo?,
richMsg: MessageBody body: MsgBody
) { ) {
if (clientInfo == null) return if (clientInfo == null) return
val event = runCatching { val event = runCatching {
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>() body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(body.msgContent!!)
readPacket.readBuf32Long() readPacket.readBuf32Long()
readPacket.discardExact(1) readPacket.discardExact(1)
@ -325,11 +299,11 @@ internal object PrimitiveListener {
} }
private suspend fun onGroupPokeAndGroupSign(time: Long, richMsg: MessageBody) { private suspend fun onGroupPokeAndGroupSign(time: Long, body: MsgBody) {
val event = runCatching { val event = runCatching {
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>() body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(body.msgContent!!)
readPacket.discardExact(4) readPacket.discardExact(4)
readPacket.discardExact(1) readPacket.discardExact(1)
@ -379,8 +353,8 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onC2CRecall(time: Long, richMsg: MessageBody) { private suspend fun onC2CRecall(time: Long, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<C2CRecallEvent>() val event = body.msgContent!!.decodeProtobuf<C2CRecallEvent>()
val head = event.head!! val head = event.head!!
val operationUid = head.operator!! val operationUid = head.operator!!
@ -404,8 +378,8 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onGroupMemIncreased(time: Long, richMsg: MessageBody) { private suspend fun onGroupMemIncreased(time: Long, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupListChangeEvent>() val event = body.msgContent!!.decodeProtobuf<GroupListChangeEvent>()
val groupCode = event.groupCode val groupCode = event.groupCode
val targetUid = event.memberUid val targetUid = event.memberUid
val type = event.type val type = event.type
@ -423,7 +397,14 @@ internal object PrimitiveListener {
if (!GlobalEventTransmitter.GroupNoticeTransmitter if (!GlobalEventTransmitter.GroupNoticeTransmitter
.transGroupMemberNumChanged( .transGroupMemberNumChanged(
time, target, targetUid, groupCode, operator, operatorUid, NoticeType.GroupMemIncrease, when (type) { time,
target,
targetUid,
groupCode,
operator,
operatorUid,
NoticeType.GroupMemIncrease,
when (type) {
130 -> NoticeSubType.Approve 130 -> NoticeSubType.Approve
131 -> NoticeSubType.Invite 131 -> NoticeSubType.Invite
else -> NoticeSubType.Approve else -> NoticeSubType.Approve
@ -434,8 +415,8 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onGroupMemberDecreased(time: Long, richMsg: MessageBody) { private suspend fun onGroupMemberDecreased(time: Long, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupListChangeEvent>() val event = body.msgContent!!.decodeProtobuf<GroupListChangeEvent>()
val groupCode = event.groupCode val groupCode = event.groupCode
val targetUid = event.memberUid val targetUid = event.memberUid
val type = event.type val type = event.type
@ -461,14 +442,23 @@ internal object PrimitiveListener {
LogCenter.log("群成员减少($groupCode): $target, type = $subtype ($type)") LogCenter.log("群成员减少($groupCode): $target, type = $subtype ($type)")
if (!GlobalEventTransmitter.GroupNoticeTransmitter if (!GlobalEventTransmitter.GroupNoticeTransmitter
.transGroupMemberNumChanged(time, target, targetUid, groupCode, operator, operatorUid, NoticeType.GroupMemDecrease, subtype) .transGroupMemberNumChanged(
time,
target,
targetUid,
groupCode,
operator,
operatorUid,
NoticeType.GroupMemDecrease,
subtype
)
) { ) {
LogCenter.log("群成员减少推送失败!", Level.WARN) LogCenter.log("群成员减少推送失败!", Level.WARN)
} }
} }
private suspend fun onGroupAdminChange(msgTime: Long, richMsg: MessageBody) { private suspend fun onGroupAdminChange(msgTime: Long, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupAdminChangeEvent>() val event = body.msgContent!!.decodeProtobuf<GroupAdminChangeEvent>()
val groupCode = event.groupCode val groupCode = event.groupCode
if (event.operation == null) return if (event.operation == null) return
val operation = event.operation!! val operation = event.operation!!
@ -494,8 +484,8 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onGroupBan(msgTime: Long, richMsg: MessageBody) { private suspend fun onGroupBan(msgTime: Long, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupBanEvent>() val event = body.msgContent!!.decodeProtobuf<GroupBanEvent>()
val groupCode = event.groupCode.toLong() val groupCode = event.groupCode.toLong()
val operatorUid = event.operatorUid val operatorUid = event.operatorUid
val wholeBan = event.target?.target?.targetUid == null val wholeBan = event.target?.target?.targetUid == null
@ -519,11 +509,11 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onGroupRecall(time: Long, richMsg: MessageBody) { private suspend fun onGroupRecall(time: Long, body: MsgBody) {
val event = runCatching { val event = runCatching {
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>() body.msgContent!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(body.msgContent!!)
readPacket.discardExact(4) readPacket.discardExact(4)
readPacket.discardExact(1) readPacket.discardExact(1)
readPacket.readBytes(readPacket.readShort().toInt()).also { readPacket.readBytes(readPacket.readShort().toInt()).also {
@ -553,10 +543,10 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onGroupApply(time: Long, contentHead: MessageContent, richMsg: MessageBody) { private suspend fun onGroupApply(time: Long, contentHead: ContentHead, body: MsgBody) {
when (contentHead.msgType) { when (contentHead.msgType) {
84 -> { 84 -> {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupApplyEvent>() val event = body.msgContent!!.decodeProtobuf<GroupApplyEvent>()
val groupCode = event.groupCode val groupCode = event.groupCode
val applierUid = event.applierUid val applierUid = event.applierUid
val reason = event.applyMsg ?: "" val reason = event.applyMsg ?: ""
@ -587,8 +577,9 @@ internal object PrimitiveListener {
LogCenter.log("入群申请推送失败!", Level.WARN) LogCenter.log("入群申请推送失败!", Level.WARN)
} }
} }
528 -> { 528 -> {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupInvitedApplyEvent>() val event = body.msgContent!!.decodeProtobuf<GroupInvitedApplyEvent>()
val groupCode = event.applyInfo?.groupCode ?: return val groupCode = event.applyInfo?.groupCode ?: return
val applierUid = event.applyInfo?.applierUid ?: return val applierUid = event.applyInfo?.applierUid ?: return
var applier = ContactHelper.getUinByUidAsync(applierUid).toLong() var applier = ContactHelper.getUinByUidAsync(applierUid).toLong()
@ -624,8 +615,8 @@ internal object PrimitiveListener {
} }
} }
private suspend fun onInviteGroup(time: Long, msgHead: MessageHead, richMsg: MessageBody) { private suspend fun onInviteGroup(time: Long, msgHead: ResponseHead, body: MsgBody) {
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupInviteEvent>() val event = body.msgContent!!.decodeProtobuf<GroupInviteEvent>()
val groupCode = event.groupCode val groupCode = event.groupCode
val invitorUid = event.inviterUid val invitorUid = event.inviterUid
val invitor = ContactHelper.getUinByUidAsync(invitorUid).toLong() val invitor = ContactHelper.getUinByUidAsync(invitorUid).toLong()