Shamrock: 快速序列化/反序列化 Protobuf

Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
白池 2024-02-23 18:23:02 +08:00
parent 9bbcc2f160
commit b4c40e236a
54 changed files with 380 additions and 175 deletions

View File

@ -6,4 +6,9 @@ plugins {
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies {
implementation(DEPENDENCY_PROTOBUF)
implementation(kotlinx("serialization-protobuf", "1.6.2"))
}

View File

@ -0,0 +1,16 @@
package moe.fuqiuluo.symbols
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import kotlin.reflect.KClass
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 {
return ProtoBuf.decodeFromByteArray(this)
}

View File

@ -1,6 +1,7 @@
plugins {
kotlin("jvm")
id("com.google.devtools.ksp") version "1.9.21-1.0.15"
kotlin("plugin.serialization") version "1.9.21"
}
ksp {
@ -14,5 +15,8 @@ dependencies {
implementation("com.google.devtools.ksp:symbol-processing-api:1.9.21-1.0.15")
implementation("com.squareup:kotlinpoet:1.14.2")
implementation(DEPENDENCY_PROTOBUF)
implementation(kotlinx("serialization-protobuf", "1.6.2"))
ksp("dev.zacsweers.autoservice:auto-service-ksp:1.1.0")
}

View File

@ -6,6 +6,7 @@ package moe.fuqiuluo.ksp.impl
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.getAnnotationsByType
import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.getKotlinClassByName
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
@ -26,18 +27,18 @@ class OneBotHandlerProcessor(
): SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> {
val ActionManagerNode = resolver.getClassDeclarationByName("moe.fuqiuluo.shamrock.remote.action.ActionManager")
if (ActionManagerNode == null) {
logger.error("OneBotHandlerProcessor: ActionManager not found")
return emptyList()
}
?: resolver.getKotlinClassByName("moe.fuqiuluo.shamrock.remote.action.ActionManager")
?: resolver.getClassDeclarationByName("ActionManager")
val symbols = resolver.getSymbolsWithAnnotation(OneBotHandler::class.qualifiedName!!)
val unableToProcess = symbols.filterNot { it.validate() }
val oneBotHandlers = (symbols.filter {
it is KSClassDeclaration && it.validate() && it.classKind == ClassKind.OBJECT
} as Sequence<KSClassDeclaration>).toList()
if (ActionManagerNode != null) {
val oneBotHandlers = (symbols.filter {
it is KSClassDeclaration && it.validate() && it.classKind == ClassKind.OBJECT
} as Sequence<KSClassDeclaration>).toList()
if (oneBotHandlers.isNotEmpty()) {
ActionManagerNode.accept(ActionManagerVisitor(oneBotHandlers), Unit)
if (oneBotHandlers.isNotEmpty()) {
ActionManagerNode.accept(ActionManagerVisitor(oneBotHandlers), Unit)
}
}
return unableToProcess.toList()

View File

@ -0,0 +1,77 @@
@file:Suppress("UNCHECKED_CAST")
package moe.fuqiuluo.ksp.impl
import com.google.devtools.ksp.isInternal
import com.google.devtools.ksp.isPrivate
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.validate
import com.squareup.kotlinpoet.FileSpec
import kotlinx.serialization.Serializable
class ProtobufProcessor(
private val codeGenerator: CodeGenerator,
private val logger: KSPLogger
): SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> {
val symbols = resolver.getSymbolsWithAnnotation(Serializable::class.qualifiedName!!)
val unableToProcess = symbols.filterNot { it.validate() }
val actions = (symbols.filter {
it is KSClassDeclaration && it.validate() && it.classKind == ClassKind.CLASS
} as Sequence<KSClassDeclaration>).filter {
it.superTypes.any { superType ->
superType.resolve().declaration.qualifiedName?.asString() == "moe.fuqiuluo.symbols.Protobuf"
}
}.toList()
if (actions.isNotEmpty()) {
actions.forEach { clz ->
if (clz.isInternal()) return@forEach
if (clz.isPrivate()) return@forEach
val packageName = "protobuf.auto"
val fileSpecBuilder = FileSpec.scriptBuilder("FastProtobuf", packageName)
fileSpecBuilder.addImport("kotlinx.serialization.protobuf", "ProtoBuf")
fileSpecBuilder.addImport("kotlinx.serialization", "decodeFromByteArray")
fileSpecBuilder.addImport("kotlinx.serialization", "encodeToByteArray")
if (clz.parentDeclaration != null) {
fileSpecBuilder.addImport(clz.importPackage, clz.simpleName.asString())
} else {
fileSpecBuilder.addImport(clz.packageName.asString(), clz.simpleName.asString())
}
if (clz.typeParameters.isNotEmpty()) {
val genericType = clz.typeParameters.joinToString(", ") { it.name.asString() }
fileSpecBuilder.addStatement("""inline fun <$genericType> ${clz.simpleName.asString()}<$genericType>.toByteArray() = ProtoBuf.encodeToByteArray(this)""")
} else {
fileSpecBuilder.addStatement("inline fun ${clz.simpleName.asString()}.toByteArray() = ProtoBuf.encodeToByteArray(this)")
}
codeGenerator.createNewFile(
dependencies = Dependencies.ALL_FILES,
packageName = packageName,
fileName = clz.simpleName.asString() + "\$FP"
).use { outputStream ->
outputStream.writer().use {
fileSpecBuilder.build().writeTo(it)
}
}
}
}
return unableToProcess.toList()
}
private val KSDeclaration.importPackage: String
get() = if (parentDeclaration != null) {
parentDeclaration!!.importPackage + "." + parentDeclaration!!.simpleName.asString()
} else packageName.asString()
}

View File

@ -0,0 +1,17 @@
package moe.fuqiuluo.ksp.providers
import com.google.auto.service.AutoService
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
import moe.fuqiuluo.ksp.impl.ProtobufProcessor
@AutoService(SymbolProcessorProvider::class)
class ProtobufProvider: SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
return ProtobufProcessor(
environment.codeGenerator,
environment.logger
)
}
}

View File

@ -2,6 +2,7 @@ plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
kotlin("plugin.serialization") version "1.9.21"
id("com.google.devtools.ksp") version "1.9.21-1.0.15"
}
android {
@ -38,4 +39,7 @@ dependencies {
implementation(kotlinx("serialization-protobuf", "1.6.2"))
implementation(kotlinx("serialization-json", "1.6.2"))
implementation(project(":annotations"))
ksp(project(":processor"))
}

View File

@ -2,9 +2,10 @@ package protobuf.fav
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class WeiyunComm(
@ProtoNumber(1) val req: WeiyunCommonReq? = null,
@ProtoNumber(2) val resp: WeiyunCommonResp? = null
)
): Protobuf<WeiyunComm>

View File

@ -6,6 +6,7 @@ package protobuf.fav
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class WeiyunMsgHead(
@ -27,4 +28,5 @@ data class WeiyunMsgHead(
@ProtoNumber(103) val promptMsg: String? = null,
@ProtoNumber(111) val totalSpace: ULong = ULong.MIN_VALUE,
@ProtoNumber(112) val usedSpace: ULong = ULong.MIN_VALUE,
)
): Protobuf<WeiyunMsgHead>

View File

@ -6,6 +6,7 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
import protobuf.qweb.QWebExtInfo
@Serializable
@ -19,7 +20,7 @@ data class GetGuildFeedsReq(
@ProtoNumber(7) var u7: Int? = null,
@ProtoNumber(8) var u8: Int? = null,
@ProtoNumber(9) var u9: ByteArray? = null,
)
): Protobuf<GetGuildFeedsReq>
@Serializable
data class GetGuildFeedsRsp(
@ -27,7 +28,7 @@ data class GetGuildFeedsRsp(
@ProtoNumber(2) var isFinish: Int = 0,
//@ProtoNumber(3) var feedAttchInfo: ByteArray? = null,
//@ProtoNumber(4) var traceId: String? = null,
)
): Protobuf<GetGuildFeedsRsp>
@Serializable
data class StFeed(

View File

@ -0,0 +1,37 @@
@file:OptIn(ExperimentalSerializationApi::class)
package protobuf.lightapp
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class AdaptShareInfoReq(
//@ProtoNumber(1) var extInfo: Any? = null,
@ProtoNumber(2) var appid: String? = null,
@ProtoNumber(3) var title: String? = null,
@ProtoNumber(4) var desc: String? = null,
@ProtoNumber(5) var time: ULong? = null,
@ProtoNumber(6) var scene: UInt? = null,
@ProtoNumber(7) var templetType: UInt? = null,
@ProtoNumber(8) var businessType: UInt? = null,
@ProtoNumber(9) var picUrl: String? = null,
@ProtoNumber(10) var vidUrl: String? = null,
@ProtoNumber(11) var jumpUrl: String? = null,
@ProtoNumber(12) var iconUrl: String? = null,
@ProtoNumber(13) var verType: UInt? = null,
@ProtoNumber(14) var shareType: UInt? = null,
@ProtoNumber(15) var versionId: String? = null,
@ProtoNumber(16) var withShareTicket: UInt? = null,
@ProtoNumber(17) var webURL: String? = null,
//@ProtoNumber(18) var appidRich: Any? = null,
@ProtoNumber(19) var template: Template? = null,
//@ProtoNumber(20) var rcvOpenId: Any? = null,
): Protobuf<AdaptShareInfoReq>
@Serializable
data class Template(
@ProtoNumber(1) var templateId: UInt? = null,
@ProtoNumber(2) var templateData: ByteArray? = null,
)

View File

@ -4,6 +4,7 @@ package protobuf.message.longmsg
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
@ -39,14 +40,14 @@ data class LongMsgReq(
@ProtoNumber(1) val recvInfo: RecvLongMsgInfo? = null,
@ProtoNumber(2) val sendInfo: SendLongMsgInfo? = null,
@ProtoNumber(15) val setting: LongMsgSettings? = null,
)
): Protobuf<LongMsgReq>
@Serializable
data class LongMsgRsp(
@ProtoNumber(1) val recvResult: RecvLongMsgResult? = null,
@ProtoNumber(2) val sendResult: SendLongMsgResult? = null,
@ProtoNumber(15) val setting: LongMsgSettings? = null
) {
): Protobuf<LongMsgRsp> {
companion object {
@Serializable
data class SendLongMsgResult(

View File

@ -5,6 +5,7 @@ package protobuf.message.longmsg
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
import protobuf.message.MessageBody
import protobuf.message.MessageContent
import protobuf.message.MessageHead
@ -29,4 +30,4 @@ data class LongMsgAction(
@Serializable
data class LongMsgPayload(
@ProtoNumber(2) val action: List<LongMsgAction>? = null
)
): Protobuf<LongMsgPayload>

View File

@ -4,12 +4,13 @@ package protobuf.message.multimedia
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class RichMediaForPicData(
@ProtoNumber(1) val info: MediaInfo?,
@ProtoNumber(2) val display: DisplayMediaInfo?,
) {
): Protobuf<RichMediaForPicData> {
companion object {
@Serializable
data class MediaInfo(

View File

@ -2,6 +2,7 @@ package protobuf.msg
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
class PbSendMsgReq(
@ -19,7 +20,7 @@ class PbSendMsgReq(
//@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(

View File

@ -2,6 +2,7 @@ package protobuf.oidb
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class TrpcOidb(
@ -9,4 +10,4 @@ data class TrpcOidb(
@ProtoNumber(2) val service: Int = Int.MIN_VALUE,
@ProtoNumber(4) val buffer: ByteArray,
@ProtoNumber(12) val flag: Int = Int.MIN_VALUE,
)
): Protobuf<TrpcOidb>

View File

@ -5,6 +5,7 @@ package protobuf.oidb.cmd0x6d7
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
import protobuf.group_file_common.FolderInfo
@Serializable
@ -13,7 +14,7 @@ data class Oidb0x6d7ReqBody(
@ProtoNumber(2) val deleteFolder: DeleteFolderReq? = null,
@ProtoNumber(3) val moveFolder: MoveFolderReq? = null,
@ProtoNumber(4) val renameFolder: RenameFolderReq? = null,
)
): Protobuf<Oidb0x6d7ReqBody>
@Serializable
data class CreateFolderReq(
@ -53,7 +54,7 @@ data class Oidb0x6d7RespBody(
@ProtoNumber(2) val deleteFolder: DeleteFolderResp? = null,
@ProtoNumber(3) val moveFolder: MoveFolderResp? = null,
@ProtoNumber(4) val renameFolder: RenameFolderResp? = null,
)
): Protobuf<Oidb0x6d7RespBody>
@Serializable
data class CreateFolderResp(

View File

@ -2,6 +2,7 @@ package protobuf.oidb.cmd0x9082
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class Oidb0x9082(
@ -11,4 +12,4 @@ data class Oidb0x9082(
@ProtoNumber(5) val flag: UInt = UInt.MIN_VALUE,
@ProtoNumber(6) val u1: UInt = UInt.MIN_VALUE,
@ProtoNumber(7) val u2: UInt = UInt.MIN_VALUE,
)
): Protobuf<Oidb0x9082>

View File

@ -2,11 +2,12 @@ package protobuf.oidb.cmd0xf16
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class Oidb0xf16(
@ProtoNumber(1) var setGroupRemarkReq: SetGroupRemarkReq? = null,
)
): Protobuf<Oidb0xf16>
@Serializable
data class SetGroupRemarkReq(

View File

@ -5,6 +5,7 @@ package protobuf.oidb.cmd0xf88
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class Oidb0xf88Req(
@ -12,12 +13,12 @@ data class Oidb0xf88Req(
@ProtoNumber(2) val memberId: ULong,
@ProtoNumber(3) val tinyId: ULong,
@ProtoNumber(4) val guildId: ULong,
)
): Protobuf<Oidb0xf88Req>
@Serializable
data class Oidb0xf88Rsp(
@ProtoNumber(1) val userInfo: GProUserInfo?
)
): Protobuf<Oidb0xf88Rsp>
@Serializable
data class GProUserInfo(

View File

@ -4,6 +4,7 @@ package protobuf.oidb.cmd0xfc2
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class Oidb0xfc2ReqBody(
@ -16,7 +17,7 @@ data class Oidb0xfc2ReqBody(
@ProtoNumber(300) var msgApplyDownloadReq: Oidb0xfc2MsgApplyDownloadReq? = null,
//@ProtoNumber(400) var msg_apply_preview_req: Any? = null,
//@ProtoNumber(500) var msg_apply_security_strike_req: Any? = null,
)
): Protobuf<Oidb0xfc2ReqBody>
@Serializable
data class Oidb0xfc2RspBody(
@ -27,7 +28,7 @@ data class Oidb0xfc2RspBody(
@ProtoNumber(310) var msgApplyDownloadRsp: Oidb0xfc2MsgApplyDownloadRsp? = null,
//@ProtoNumber(410) var msg_apply_preview_rsp: Any? = null,
//@ProtoNumber(510) var msg_apply_security_strike_rsp: Any? = null,
)
): Protobuf<Oidb0xfc2RspBody>
@Serializable
data class Oidb0xfc2MsgApplyDownloadRsp(

View File

@ -5,17 +5,18 @@ package protobuf.oidb.cmx0xf57
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class Oidb0xf57Req(
@ProtoNumber(1) val filter: Oidb0xf57Filter,
@ProtoNumber(2) val guildInfo: Oidb0xf57GuildInfo,
)
): Protobuf<Oidb0xf57Req>
@Serializable
data class Oidb0xf57Rsp(
@ProtoNumber(1) val metaInfo: Oidb0xf57MetaInfo,
)
): Protobuf<Oidb0xf57Rsp>
@Serializable
data class Oidb0xf57MetaInfo(

View File

@ -2,12 +2,13 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class C2CCommonTipsEvent(
@ProtoNumber(7) val params: List<PokeParam>? = null,
@ProtoNumber(8) val xmlTips: String? = null,
)
): Protobuf<C2CCommonTipsEvent>
@Serializable
data class PokeParam(

View File

@ -2,11 +2,12 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class C2CRecallEvent(
@ProtoNumber(1) val head: C2CRecallHead? = null,
)
): Protobuf<C2CRecallEvent>
@Serializable
data class C2CRecallHead(

View File

@ -2,11 +2,12 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class FriendApplyEvent(
@ProtoNumber(1) val head: FriendApplyHead? = null,
)
): Protobuf<FriendApplyEvent>
@Serializable

View File

@ -2,10 +2,11 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupAdminChangeEvent(
@ProtoNumber(1) val groupCode: Long,
@ProtoNumber(4) val operation: GroupAdminChangedOperation? = null
)
): Protobuf<GroupAdminChangeEvent>

View File

@ -2,10 +2,11 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupApplyEvent(
@ProtoNumber(1) val groupCode: Long = Long.MIN_VALUE,
@ProtoNumber(3) val applierUid: String = "",
@ProtoNumber(5) val applyMsg: String? = null,
)
): Protobuf<GroupApplyEvent>

View File

@ -2,13 +2,14 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupBanEvent(
@ProtoNumber(1) val groupCode: ULong = ULong.MIN_VALUE,
@ProtoNumber(4) val operatorUid: String = "",
@ProtoNumber(5) val target: GroupBanTarget? = null,
)
): Protobuf<GroupBanEvent>
@Serializable
data class GroupBanTarget(

View File

@ -2,6 +2,7 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupCommonTipsEvent(
@ -11,7 +12,7 @@ data class GroupCommonTipsEvent(
@ProtoNumber(26) val baseTips: List<GroupBaseTips>? = null,
@ProtoNumber(33) val essenceMsgInfo: List<EssenceMsgInfo>? = null,
@ProtoNumber(37) val msgSeq: ULong = ULong.MIN_VALUE,
)
): Protobuf<GroupCommonTipsEvent>
@Serializable
data class EssenceMsgInfo(

View File

@ -2,9 +2,10 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupInviteEvent(
@ProtoNumber(1) val groupCode: Long,
@ProtoNumber(5) val inviterUid: String,
)
): Protobuf<GroupInviteEvent>

View File

@ -2,11 +2,12 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupInvitedApplyEvent(
@ProtoNumber(2) val applyInfo: GroupInvitedApplyInfo? = null,
)
): Protobuf<GroupInvitedApplyEvent>
@Serializable
data class GroupInvitedApplyInfo(

View File

@ -2,6 +2,7 @@ package protobuf.push
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GroupListChangeEvent(
@ -9,4 +10,4 @@ data class GroupListChangeEvent(
@ProtoNumber(3) val memberUid: String = "",
@ProtoNumber(4) val type: Int = Int.MIN_VALUE,
@ProtoNumber(5) val operatorUid: String = "",
)
): Protobuf<GroupListChangeEvent>

View File

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

View File

@ -5,6 +5,7 @@ package protobuf.qweb
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class QWebReq(
@ -19,7 +20,7 @@ data class QWebReq(
//@ProtoNumber(9) var Crypto: Any? = null,
@ProtoNumber(10) var extinfo: List<QWebExtInfo>? = null,
//@ProtoNumber(11) var contentType: Any? = null,
)
): Protobuf<QWebReq>
@Serializable
data class QWebExtInfo(
@ -34,4 +35,4 @@ data class QWebRsp(
//@ProtoNumber(3) var errMsg: String? = null,
@ProtoNumber(4) var buffer: ByteArray? = null,
//@ProtoNumber(5) var Extinfo: List<QWebExtInfo>? = null,
)
): Protobuf<QWebRsp>

View File

@ -19,7 +19,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.utils.PlatformUtils
@ -28,6 +28,7 @@ import moe.fuqiuluo.shamrock.xposed.helper.internal.DynamicReceiver
import moe.fuqiuluo.shamrock.xposed.helper.internal.IPCRequest
import protobuf.oidb.TrpcOidb
import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import tencent.im.oidb.oidb_sso
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
@ -129,7 +130,7 @@ internal abstract class BaseSvc {
buffer = buffer,
flag = 0
)
to.putWupBuffer(ProtoBuf.encodeToByteArray(oidb))
to.putWupBuffer(oidb.toByteArray())
to.addAttribute("req_pb_protocol_flag", true)
if (seq != -1) {

View File

@ -1,21 +1,20 @@
package moe.fuqiuluo.qqinterface.servlet
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import protobuf.auto.toByteArray
import protobuf.oidb.cmd0x9082.Oidb0x9082
internal object ChatSvc: BaseSvc() {
fun setGroupMessageCommentFace(peer: Long, msgSeq: ULong, faceIndex: String, isSet: Boolean) {
val serviceId = if (isSet) 1 else 2
sendOidb("OidbSvcTrpcTcp.0x9082_$serviceId", 36994, serviceId, ProtoBuf.encodeToByteArray(
Oidb0x9082(
sendOidb("OidbSvcTrpcTcp.0x9082_$serviceId", 36994, serviceId, Oidb0x9082(
peer = peer.toULong(),
msgSeq = msgSeq,
faceIndex = faceIndex,
flag = 1u,
u1 = 0u,
u2 = 0u
)
))
).toByteArray())
}
}
}

View File

@ -1,9 +1,6 @@
package moe.fuqiuluo.qqinterface.servlet
import com.tencent.mobileqq.pb.ByteStringMicro
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.structures.*
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
import moe.fuqiuluo.shamrock.helper.Level
@ -12,6 +9,8 @@ import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.oidb.cmd0x6d7.CreateFolderReq
import protobuf.oidb.cmd0x6d7.DeleteFolderReq
import protobuf.oidb.cmd0x6d7.MoveFolderReq
@ -22,24 +21,25 @@ import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
import tencent.im.oidb.oidb_sso
import protobuf.group_file_common.FolderInfo as GroupFileCommonFolderInfo
import protobuf.auto.toByteArray
internal object FileSvc: BaseSvc() {
suspend fun createFileFolder(groupId: String, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> {
val data = ProtoBuf.encodeToByteArray(
Oidb0x6d7ReqBody(
val data = Oidb0x6d7ReqBody(
createFolder = CreateFolderReq(
groupCode = groupId.toULong(),
appId = 3u,
parentFolderId = parentFolderId,
folderName = folderName
)
)
)
).toByteArray()
val resultBuffer = sendOidbAW("OidbSvc.0x6d7_0", 1751, 0, data)
?: return Result.failure(Exception("unable to fetch result"))
val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(resultBuffer.slice(4))
val rsp = ProtoBuf.decodeFromByteArray<Oidb0x6d7RespBody>(oidbPkg.bytes_bodybuffer.get().toByteArray())
val rsp = oidbPkg.bytes_bodybuffer.get()
.toByteArray()
.decodeProtobuf<Oidb0x6d7RespBody>()
if (rsp.createFolder?.retCode != 0) {
return Result.failure(Exception("unable to create folder: ${rsp.createFolder?.retCode}"))
}
@ -47,52 +47,46 @@ internal object FileSvc: BaseSvc() {
}
suspend fun deleteGroupFolder(groupId: String, folderUid: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, ProtoBuf.encodeToByteArray(
Oidb0x6d7ReqBody(
val buffer = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
deleteFolder = DeleteFolderReq(
groupCode = groupId.toULong(),
appId = 3u,
folderId = folderUid
)
)
)) ?: return false
).toByteArray()) ?: return false
val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(buffer.slice(4))
val rsp = ProtoBuf.decodeFromByteArray<Oidb0x6d7RespBody>(oidbPkg.bytes_bodybuffer.get().toByteArray())
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
return rsp.deleteFolder?.retCode == 0
}
suspend fun moveGroupFolder(groupId: String, folderUid: String, newParentFolderUid: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, ProtoBuf.encodeToByteArray(
Oidb0x6d7ReqBody(
val buffer = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, Oidb0x6d7ReqBody(
moveFolder = MoveFolderReq(
groupCode = groupId.toULong(),
appId = 3u,
folderId = folderUid,
parentFolderId = "/"
)
)
)) ?: return false
).toByteArray()) ?: return false
val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(buffer.slice(4))
val rsp = ProtoBuf.decodeFromByteArray<Oidb0x6d7RespBody>(oidbPkg.bytes_bodybuffer.get().toByteArray())
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
return rsp.moveFolder?.retCode == 0
}
suspend fun renameFolder(groupId: String, folderUid: String, name: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, ProtoBuf.encodeToByteArray(
Oidb0x6d7ReqBody(
val buffer = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
renameFolder = RenameFolderReq(
groupCode = groupId.toULong(),
appId = 3u,
folderId = folderUid,
folderName = name
)
)
)) ?: return false
).toByteArray()) ?: return false
val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(buffer.slice(4))
val rsp = ProtoBuf.decodeFromByteArray<Oidb0x6d7RespBody>(oidbPkg.bytes_bodybuffer.get().toByteArray())
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
return rsp.renameFolder?.retCode == 0
}

View File

@ -7,14 +7,10 @@ import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole
import com.tencent.qqnt.kernel.nativeinterface.GProRoleCreateInfo
import com.tencent.qqnt.kernel.nativeinterface.GProRoleMemberList
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.readBytes
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.structures.GProChannelInfo
import moe.fuqiuluo.qqinterface.servlet.structures.GetGuildMemberListNextToken
import moe.fuqiuluo.qqinterface.servlet.structures.GuildInfo
@ -24,10 +20,11 @@ import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.auto.toByteArray
import protobuf.guild.GetGuildFeedsReq
import protobuf.guild.GetGuildFeedsRsp
import protobuf.oidb.cmd0xf88.GProFilter
@ -54,33 +51,31 @@ internal object GProSvc: BaseSvc() {
}
suspend fun getGuildInfo(guildId: ULong): Result<Oidb0xf57MetaInfo> {
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf57_9", 0xf57, 9, ProtoBuf.encodeToByteArray(
Oidb0xf57Req(
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf57_9", 0xf57, 9, Oidb0xf57Req(
filter = Oidb0xf57Filter(
u1 = Oidb0xf57U1(1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u),
u2 = Oidb0xf57U2(1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u)
),
guildInfo = Oidb0xf57GuildInfo(guildId = guildId)
)
))
).toByteArray())
val body = oidb_sso.OIDBSSOPkg()
if (respBuffer == null) {
return Result.failure(Exception("unable to send packet"))
}
body.mergeFrom(respBuffer.slice(4))
return runCatching {
ProtoBuf.decodeFromByteArray<Oidb0xf57Rsp>(
body.bytes_bodybuffer.get().toByteArray()
).metaInfo
body.bytes_bodybuffer.get()
.toByteArray()
.decodeProtobuf<Oidb0xf57Rsp>().metaInfo
}
}
suspend fun getGuildFeeds(guildId: ULong, channelId: ULong, startIndex: Int): Result<GetGuildFeedsRsp> {
val buffer = sendBufferAW("QChannelSvr.trpc.qchannel.commreader.ComReader.GetGuildFeeds", true, ProtoBuf.encodeToByteArray(QWebReq(
val buffer = sendBufferAW("QChannelSvr.trpc.qchannel.commreader.ComReader.GetGuildFeeds", true, QWebReq(
seq = 10,
qua = PlatformUtils.getQUA(),
deviceInfo = "i=&imsi=&mac=02:00:00:00:00:00&m=Shamrock&o=114514&a=1919810&sd=0&c64=1&sc=1&p=8000*8000&aid=123456789012345678901234567890abcdef&f=Tencent&mm=5610&cf=1726&cc=8&qimei=&qimei36=&sharpP=1&n=nether_world&support_xsj_live=false&client_mod=concise&timezone=America/La_Paz&material_sdk_version=&vh265=&refreshrate=10086&hwlevel=9&suphdr=1&is_teenager_mod=8&liveH265=&bmst=5&AV1=0",
buffer = ProtoBuf.encodeToByteArray(GetGuildFeedsReq(
buffer = GetGuildFeedsReq(
count = 12,
from = startIndex,
feedAttchInfo = EMPTY_BYTE_ARRAY,
@ -89,18 +84,18 @@ internal object GProSvc: BaseSvc() {
u7 = 0,
u8 = 1,
u9 = EMPTY_BYTE_ARRAY
)),
).toByteArray(),
traceId = app.account + "_0_0",
extinfo = listOf(
QWebExtInfo("fc-appid", "96"),
QWebExtInfo("environment_id", "shamrock"),
QWebExtInfo("tiny_id", getSelfTinyId().toString()),
)
))) ?: return Result.failure(Exception("unable to send packet"))
val webRsp = ProtoBuf.decodeFromByteArray<QWebRsp>(buffer.slice(4))
).toByteArray()) ?: return Result.failure(Exception("unable to send packet"))
val webRsp = buffer.slice(4).decodeProtobuf<QWebRsp>()
if(webRsp.buffer == null) return Result.failure(Exception("server error"))
val wupBuffer = webRsp.buffer!!
val feeds = ProtoBuf.decodeFromByteArray<GetGuildFeedsRsp>(wupBuffer)
val feeds = wupBuffer.decodeProtobuf<GetGuildFeedsRsp>()
return Result.success(feeds)
}
@ -188,23 +183,19 @@ internal object GProSvc: BaseSvc() {
guildId: ULong,
memberTinyId: ULong
): Result<GProUserInfo> {
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf88_1", 0xf88, 1, ProtoBuf.encodeToByteArray(
Oidb0xf88Req(
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf88_1", 0xf88, 1, Oidb0xf88Req(
filter = GProFilter(1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u),
memberId = 0uL,
tinyId = memberTinyId,
guildId = guildId
)
))
).toByteArray())
val body = oidb_sso.OIDBSSOPkg()
if (respBuffer == null) {
return Result.failure(Exception("unable to send packet"))
}
body.mergeFrom(respBuffer.slice(4))
return runCatching {
ProtoBuf.decodeFromByteArray<Oidb0xf88Rsp>(
body.bytes_bodybuffer.get().toByteArray()
).userInfo!!
body.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0xf88Rsp>().userInfo!!
}
}

View File

@ -46,7 +46,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getLongUin
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getUin
import moe.fuqiuluo.qqinterface.servlet.structures.GroupAtAllRemainInfo
@ -78,6 +78,7 @@ import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import protobuf.oidb.cmd0xf16.Oidb0xf16
import protobuf.oidb.cmd0xf16.SetGroupRemarkReq
import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import tencent.im.group.group_member_info
import tencent.im.oidb.cmd0x88d.oidb_0x88d
import tencent.im.oidb.cmd0x899.oidb_0x899
@ -274,15 +275,13 @@ internal object GroupSvc: BaseSvc() {
}
fun modifyGroupRemark(groupId: Long, remark: String): Boolean {
sendOidb("OidbSvc.0xf16_1", 3862, 1, ProtoBuf.encodeToByteArray(
Oidb0xf16(
sendOidb("OidbSvc.0xf16_1", 3862, 1, Oidb0xf16(
setGroupRemarkReq = SetGroupRemarkReq(
groupCode = groupId.toULong(),
groupUin = groupCode2GroupUin(groupId).toULong(),
groupRemark = remark
)
)
))
).toByteArray())
return true
}

View File

@ -11,10 +11,8 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.msg.messageelement.toSegments
import moe.fuqiuluo.qqinterface.servlet.msg.toListMap
import moe.fuqiuluo.shamrock.helper.ContactHelper
@ -28,6 +26,9 @@ import moe.fuqiuluo.shamrock.tools.*
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import moe.fuqiuluo.shamrock.xposed.helper.msgService
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.auto.toByteArray
import protobuf.message.longmsg.*
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
@ -239,14 +240,14 @@ internal object MsgSvc : BaseSvc() {
)
)
)
LogCenter.log(ProtoBuf.encodeToByteArray(payload).toHexString(), Level.DEBUG)
LogCenter.log(payload.toByteArray().toHexString(), Level.DEBUG)
val req = LongMsgReq(
sendInfo = SendLongMsgInfo(
type = if (groupUin == null) 1 else 3,
uid = LongMsgUid(groupUin ?: uid),
groupUin = groupUin?.toInt(),
payload = DeflateTools.gzip(ProtoBuf.encodeToByteArray(payload))
payload = DeflateTools.gzip(payload.toByteArray())
),
setting = LongMsgSettings(
field1 = 4,
@ -258,9 +259,9 @@ internal object MsgSvc : BaseSvc() {
val buffer = sendBufferAW(
"trpc.group.long_msg_interface.MsgService.SsoSendLongMsg",
true,
ProtoBuf.encodeToByteArray(req)
req.toByteArray()
) ?: return Result.failure(Exception("unable to upload multi message"))
val rsp = ProtoBuf.decodeFromByteArray<LongMsgRsp>(buffer.slice(4))
val rsp = buffer.slice(4).decodeProtobuf<LongMsgRsp>()
return rsp.sendResult?.resId?.let { Result.success(it) }
?: Result.failure(Exception("unable to upload multi message"))
}
@ -282,14 +283,14 @@ internal object MsgSvc : BaseSvc() {
val buffer = sendBufferAW(
"trpc.group.long_msg_interface.MsgService.SsoRecvLongMsg",
true,
ProtoBuf.encodeToByteArray(req)
req.toByteArray()
) ?: return Result.failure(Exception("unable to get multi message"))
val rsp = ProtoBuf.decodeFromByteArray<LongMsgRsp>(buffer.slice(4))
val rsp = buffer.slice(4).decodeProtobuf<LongMsgRsp>()
val zippedPayload = DeflateTools.ungzip(
rsp.recvResult?.payload ?: return Result.failure(Exception("unable to get multi message"))
)
LogCenter.log(zippedPayload.toHexString(), Level.DEBUG)
val payload = ProtoBuf.decodeFromByteArray<LongMsgPayload>(zippedPayload)
val payload = zippedPayload.decodeProtobuf<LongMsgPayload>()
payload.action?.forEach {
if (it.command == "MultiMsg") {
return Result.success(it.data?.body?.map { msg ->

View File

@ -10,7 +10,7 @@ import io.ktor.utils.io.core.writeInt
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.shamrock.remote.action.handlers.GetHistoryMsg
import moe.fuqiuluo.shamrock.remote.service.listener.AioListener
import moe.fuqiuluo.shamrock.tools.broadcast
@ -24,6 +24,7 @@ import protobuf.message.MessageHead
import protobuf.message.MessageBody
import protobuf.push.MessagePush
import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import kotlin.coroutines.resume
internal object PacketSvc: BaseSvc() {
@ -77,7 +78,7 @@ internal object PacketSvc: BaseSvc() {
)
)
fakeReceive("trpc.msg.olpush.OlPushService.MsgPush", 10000, ProtoBuf.encodeToByteArray(msgPush))
fakeReceive("trpc.msg.olpush.OlPushService.MsgPush", 10000, msgPush.toByteArray())
return withTimeoutOrNull(5000L) {
suspendCancellableCoroutine {
AioListener.registerTemporaryMsgListener(msgSeq) {

View File

@ -15,7 +15,7 @@ import kotlinx.io.core.readBytes
import kotlinx.io.core.writeFully
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
@ -39,6 +39,7 @@ import mqq.manager.TicketManager
import oicq.wlogin_sdk.request.Ticket
import oicq.wlogin_sdk.request.WtTicketPromise
import oicq.wlogin_sdk.tools.ErrMsg
import protobuf.auto.toByteArray
import java.io.ByteArrayOutputStream
import java.io.File
import java.nio.ByteBuffer
@ -329,9 +330,9 @@ internal object QFavSvc: BaseSvc() {
}
val pSKey = getWeiYunPSKey()
httpNetReq.mHttpMethod = HttpNetReq.HTTP_POST
httpNetReq.mSendData = DeflateTools.gzip(packData(packHead(cmd, pSKey), ProtoBuf.encodeToByteArray(
WeiyunComm(req = req)
)))
httpNetReq.mSendData = DeflateTools.gzip(packData(packHead(cmd, pSKey), WeiyunComm(
req = req
).toByteArray()))
httpNetReq.mOutStream = outputStream
httpNetReq.mStartDownOffset = 0L
httpNetReq.mReqProperties["Shamrock"] = "true"
@ -351,8 +352,7 @@ internal object QFavSvc: BaseSvc() {
}
private fun packHead(cmd: Int, pskey: String): ByteArray {
return ProtoBuf.encodeToByteArray(
WeiyunMsgHead(
return WeiyunMsgHead(
uin = app.longAccountUin.toULong(),
seq = seq++.toUInt(),
type = 1u,
@ -364,8 +364,7 @@ internal object QFavSvc: BaseSvc() {
key = pskey.toByteArray(),
majorVersion = MAJOR_VERSION.toUInt(),
minorVersion = MINOR_VERSION.toUInt(),
)
)
).toByteArray()
}
private fun packData(head: ByteArray, body: ByteArray): ByteArray {

View File

@ -26,4 +26,12 @@ sealed class ArkAppInfo(
signature = "7194d531cbe7960a22007b9f6bdaa38b",
miniAppId = 1109937557
)
data object Docs: ArkAppInfo(
appId = 0,
version = "0.0.0",
packageName = "",
signature = "f3da3147654d9a21f3237b88f20dce9c",
miniAppId = 1108338344
)
}

View File

@ -53,6 +53,7 @@ internal object ArkMsgSvc: BaseSvc() {
sendOidb("OidbSvc.0xb77_9", 0xb77, 9, req.toByteArray())
}
/*
suspend fun tryShareJsonMessage(
jsonString: String,
arkAppInfo: ArkAppInfo = ArkAppInfo.DanMaKu,
@ -96,5 +97,5 @@ internal object ArkMsgSvc: BaseSvc() {
}
} ?: return Result.failure(Exception("unable to sign json"))
return Result.success(signedJson)
}
}*/
}

View File

@ -0,0 +1,9 @@
package moe.fuqiuluo.qqinterface.servlet.ark
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
internal object LightAppSvc: BaseSvc() {
suspend fun adaptShare() {
}
}

View File

@ -2,6 +2,7 @@ package moe.fuqiuluo.qqinterface.servlet.structures
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class GuildInfo(
@ -59,7 +60,7 @@ data class GetGuildMemberListNextToken(
@SerialName("role_index") val roleIndex: Long,
@SerialName("seq") val seq: Int,
@SerialName("finish") val finish: Boolean
)
): Protobuf<GetGuildMemberListNextToken>
@Serializable
data class GuildMemberInfo(

View File

@ -6,11 +6,12 @@ import com.tencent.mobileqq.transfile.FileMsg
import com.tencent.mobileqq.transfile.api.IProtoReqManager
import com.tencent.mobileqq.transfile.protohandler.RichProto
import com.tencent.mobileqq.transfile.protohandler.RichProtoProc
import io.ktor.util.Identity.decode
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
@ -19,7 +20,9 @@ import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
import moe.fuqiuluo.symbols.decodeProtobuf
import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ChannelInfo
import protobuf.oidb.cmd0xfc2.Oidb0xfc2MsgApplyDownloadReq
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ReqBody
@ -49,8 +52,7 @@ internal object RichProtoSvc: BaseSvc() {
}*/
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, ProtoBuf.encodeToByteArray(
Oidb0xfc2ReqBody(
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, Oidb0xfc2ReqBody(
msgCmd = 1200,
msgBusType = 4202,
msgChannelInfo = Oidb0xfc2ChannelInfo(
@ -62,14 +64,16 @@ internal object RichProtoSvc: BaseSvc() {
fieldId = fileId,
supportEncrypt = 0
)
)
)) ?: return ""
).toByteArray()) ?: return ""
val body = oidb_sso.OIDBSSOPkg()
body.mergeFrom(buffer.slice(4))
ProtoBuf.decodeFromByteArray<Oidb0xfc2RspBody>(body.bytes_bodybuffer.get().toByteArray()).msgApplyDownloadRsp?.let {
it.msgDownloadInfo?.let {
return "https://${it.downloadDomain}${it.downloadUrl}&fname=$fileId&isthumb=0"
}
body.bytes_bodybuffer
.get().toByteArray()
.decodeProtobuf<Oidb0xfc2RspBody>()
.msgApplyDownloadRsp?.let {
it.msgDownloadInfo?.let {
return "https://${it.downloadDomain}${it.downloadUrl}&fname=$fileId&isthumb=0"
}
}
return ""
}

View File

@ -7,7 +7,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.QFavSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
@ -16,6 +16,7 @@ import moe.fuqiuluo.shamrock.utils.CryptTools
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.fav.WeiyunComm
@OneBotHandler("fav.add_image_msg")
@ -74,7 +75,7 @@ internal object FavAddImageMsg: IActionHandler() {
readPacket.readFully(it, 0, it.size)
}
val resp = ProtoBuf.decodeFromByteArray<WeiyunComm>(data)
val resp = data.decodeProtobuf<WeiyunComm>()
.resp!!.fastUploadResourceResp!!.picResultList!!.first()
val picInfo = resp.picInfo!!
picUrl = picInfo.uri
@ -133,7 +134,7 @@ internal object FavAddImageMsg: IActionHandler() {
val data = ByteArray(dataLength).also {
readPacket.readFully(it, 0, it.size)
}
val resp = ProtoBuf.decodeFromByteArray<WeiyunComm>(data).resp!!
val resp = data.decodeProtobuf<WeiyunComm>().resp!!
itemId = resp.addRichMediaResp!!.cid
}

View File

@ -6,13 +6,14 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.QFavSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.fav.WeiyunComm
@OneBotHandler("fav.add_text_msg")
@ -55,7 +56,7 @@ internal object FavAddTextMsg: IActionHandler() {
val data = ByteArray(dataLength).also {
readPacket.readFully(it, 0, it.size)
}
val resp = ProtoBuf.decodeFromByteArray<WeiyunComm>(data).resp!!.addRichMediaResp!!
val resp = data.decodeProtobuf<WeiyunComm>().resp!!.addRichMediaResp!!
ok(data = QFavItem(resp.cid), echo)
} else {
logic(it.mErrDesc, echo)

View File

@ -9,13 +9,14 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.QFavSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.fav.WeiyunComm
@OneBotHandler("fav.get_item_content")
@ -47,7 +48,7 @@ internal object FavGetItemContent: IActionHandler() {
readPacket.readFully(it, 0, it.size)
}
val resp = ProtoBuf.decodeFromByteArray<WeiyunComm>(data).resp!!
val resp = data.decodeProtobuf<WeiyunComm>().resp!!
return ok(ItemContent(
resp.getFavContentResp!!.content!!.joinToString("") {
String(it.richMedia!!.rawData!!)

View File

@ -6,13 +6,14 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.QFavSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.fav.WeiyunComm
@OneBotHandler("fav.get_item_list")
@ -55,7 +56,7 @@ internal object FavGetItemList: IActionHandler() {
val data = ByteArray(dataLength).also {
readPacket.readFully(it, 0, it.size)
}
val resp = ProtoBuf.decodeFromByteArray<WeiyunComm>(data).resp!!.getFavListResp!!
val resp = data.decodeProtobuf<WeiyunComm>().resp!!.getFavListResp!!
val itemList = arrayListOf<Item>()
val rawItemList = resp.collections!!

View File

@ -8,7 +8,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.GProSvc
import moe.fuqiuluo.qqinterface.servlet.structures.GetGuildMemberListNextToken
import moe.fuqiuluo.qqinterface.servlet.structures.GuildMemberInfo
@ -19,6 +19,8 @@ import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.auto.toByteArray
@OneBotHandler("get_guild_member_list")
internal object GetGuildMemberList: IActionHandler() {
@ -29,7 +31,7 @@ internal object GetGuildMemberList: IActionHandler() {
}
suspend operator fun invoke(guildId: ULong, all: Boolean, nextTokenStr: String, echo: JsonElement = EmptyJsonString): String {
val curNextToken = if (nextTokenStr.isEmpty()) null else ProtoBuf.decodeFromByteArray<GetGuildMemberListNextToken>(nextTokenStr.hex2ByteArray())
val curNextToken = if (nextTokenStr.isEmpty()) null else nextTokenStr.hex2ByteArray().decodeProtobuf<GetGuildMemberListNextToken>()
val result = GProSvc.getGuildMemberList(
guildId = guildId,
fetchAll = all,
@ -62,7 +64,7 @@ internal object GetGuildMemberList: IActionHandler() {
return ok(GetGuildMemberListResult(
members = members,
finish = nextToken.finish,
nextToken = ProtoBuf.encodeToByteArray(nextToken).toHexString(),
nextToken = nextToken.toByteArray().toHexString(),
), echo)
}

View File

@ -2,11 +2,12 @@ package moe.fuqiuluo.shamrock.remote.action.handlers
import kotlinx.atomicfu.atomic
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.symbols.OneBotHandler
import protobuf.auto.toByteArray
import protobuf.msg.C2C
import protobuf.msg.ContentHead
import protobuf.msg.Elem
@ -47,7 +48,7 @@ internal object SendMsgByResid: IActionHandler() {
msgRand = Random.nextUInt(),
msgVia = 0u
)
BaseSvc.sendBufferAW("MessageSvc.PbSendMsg", true, ProtoBuf.encodeToByteArray(req))
BaseSvc.sendBufferAW("MessageSvc.PbSendMsg", true, req.toByteArray())
return ok("ok", session.echo)
}
}

View File

@ -13,7 +13,7 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.FriendSvc.requestFriendSystemMsgNew
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.GroupSvc.requestGroupSystemMsgNew
@ -31,6 +31,8 @@ import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.readBuf32Long
import moe.fuqiuluo.shamrock.xposed.helper.PacketHandler
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.message.MessageContent
import protobuf.message.MessageHead
import protobuf.message.MessageBody
@ -56,7 +58,7 @@ internal object PrimitiveListener {
PacketHandler.register("trpc.msg.olpush.OlPushService.MsgPush") { _, buffer ->
GlobalScope.launch {
try {
val push = ProtoBuf.decodeFromByteArray<MessagePush>(buffer.slice(4))
val push = buffer.slice(4).decodeProtobuf<MessagePush>()
onMsgPush(push)
} catch (e: Exception) {
LogCenter.log(e.stackTraceToString(), Level.WARN)
@ -113,7 +115,7 @@ internal object PrimitiveListener {
body.rich?.elements?.filter {
it.comm != null && it.comm!!.type == 48
}?.map {
ProtoBuf.decodeFromByteArray<RichMediaForPicData>(it.comm!!.data!!)
it.comm!!.data!!.decodeProtobuf<RichMediaForPicData>()
}?.forEach {
it.display?.show?.download?.url?.let {
RKEY_PATTERN.matcher(it).takeIf {
@ -129,7 +131,7 @@ internal object PrimitiveListener {
}
private suspend fun onC2CPoke(msgTime: Long, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<C2CCommonTipsEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<C2CCommonTipsEvent>()
if (event.params == null) return
val params = event.params!!.associate {
@ -156,7 +158,7 @@ internal object PrimitiveListener {
clientInfo: MessagePushClientInfo,
richMsg: MessageBody
) {
val event = ProtoBuf.decodeFromByteArray<FriendApplyEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<FriendApplyEvent>()
if (event.head == null) return
val head = event.head!!
val applierUid = head.applierUid
@ -233,15 +235,15 @@ internal object PrimitiveListener {
private suspend fun onGroupUniqueTitleChange(msgTime: Long, richMsg: MessageBody) {
val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!)
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.readBuf32Long()
readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release()
})
}.decodeProtobuf<GroupCommonTipsEvent>()
}
val groupId = event.groupCode.toLong()
val detail = event.uniqueTitleChangeDetail!!.first()
@ -279,15 +281,15 @@ internal object PrimitiveListener {
) {
if (clientInfo == null) return
val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!)
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.readBuf32Long()
readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release()
})
}.decodeProtobuf<GroupCommonTipsEvent>()
}
val groupId = event.groupCode.toLong()
val detail = event.essenceMsgInfo!!.first()
@ -326,15 +328,15 @@ internal object PrimitiveListener {
private suspend fun onGroupPokeAndGroupSign(time: Long, richMsg: MessageBody) {
val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!)
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.discardExact(4)
readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release()
})
}.decodeProtobuf<GroupCommonTipsEvent>()
}
val groupId = event.groupCode.toLong()
val detail = event.baseTips!!.first()
@ -379,7 +381,7 @@ internal object PrimitiveListener {
}
private suspend fun onC2CRecall(time: Long, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<C2CRecallEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<C2CRecallEvent>()
val head = event.head!!
val operationUid = head.operator!!
@ -404,7 +406,7 @@ internal object PrimitiveListener {
}
private suspend fun onGroupMemIncreased(time: Long, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<GroupListChangeEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupListChangeEvent>()
val groupCode = event.groupCode
val targetUid = event.memberUid
val type = event.type
@ -434,7 +436,7 @@ internal object PrimitiveListener {
}
private suspend fun onGroupMemberDecreased(time: Long, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<GroupListChangeEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupListChangeEvent>()
val groupCode = event.groupCode
val targetUid = event.memberUid
val type = event.type
@ -467,7 +469,7 @@ internal object PrimitiveListener {
}
private suspend fun onGroupAdminChange(msgTime: Long, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<GroupAdminChangeEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupAdminChangeEvent>()
val groupCode = event.groupCode
if (event.operation == null) return
val operation = event.operation!!
@ -494,7 +496,7 @@ internal object PrimitiveListener {
}
private suspend fun onGroupBan(msgTime: Long, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<GroupBanEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupBanEvent>()
val groupCode = event.groupCode.toLong()
val operatorUid = event.operatorUid
val wholeBan = event.target?.target?.targetUid == null
@ -520,14 +522,14 @@ internal object PrimitiveListener {
private suspend fun onGroupRecall(time: Long, richMsg: MessageBody) {
val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!)
richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.discardExact(4)
readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release()
})
}.decodeProtobuf<GroupCommonTipsEvent>()
}
val groupCode = event.groupCode.toLong()
val detail = event.recallDetails!!
@ -555,7 +557,7 @@ internal object PrimitiveListener {
private suspend fun onGroupApply(time: Long, contentHead: MessageContent, richMsg: MessageBody) {
when (contentHead.msgType) {
84 -> {
val event = ProtoBuf.decodeFromByteArray<GroupApplyEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupApplyEvent>()
val groupCode = event.groupCode
val applierUid = event.applierUid
val reason = event.applyMsg ?: ""
@ -587,7 +589,7 @@ internal object PrimitiveListener {
}
}
528 -> {
val event = ProtoBuf.decodeFromByteArray<GroupInvitedApplyEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupInvitedApplyEvent>()
val groupCode = event.applyInfo?.groupCode ?: return
val applierUid = event.applyInfo?.applierUid ?: return
var applier = ContactHelper.getUinByUidAsync(applierUid).toLong()
@ -624,7 +626,7 @@ internal object PrimitiveListener {
}
private suspend fun onInviteGroup(time: Long, msgHead: MessageHead, richMsg: MessageBody) {
val event = ProtoBuf.decodeFromByteArray<GroupInviteEvent>(richMsg.rawBuffer!!)
val event = richMsg.rawBuffer!!.decodeProtobuf<GroupInviteEvent>()
val groupCode = event.groupCode
val invitorUid = event.inviterUid
val invitor = ContactHelper.getUinByUidAsync(invitorUid).toLong()