5 Commits

Author SHA1 Message Date
46ed966c18 Shamrock: recommend Lagrange
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-24 01:01:41 +08:00
623dc5da07 Shamrock: fix all multimedia pic fetch
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-24 00:34:28 +08:00
bd6d4f046c Shamrock: Remove rkey cache
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-23 20:52:44 +08:00
9ad66f2f92 Shamrock: fix #251
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-23 19:33:36 +08:00
b4c40e236a Shamrock: 快速序列化/反序列化 Protobuf
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-23 18:23:02 +08:00
60 changed files with 1016 additions and 216 deletions

View File

@ -29,6 +29,7 @@
- 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。 - 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。
- 平行部署:可多平台部署,未来将会支持 Docker 部署的教程。 - 平行部署:可多平台部署,未来将会支持 Docker 部署的教程。
- 替代方案:[Lagrange.Core](https://github.com/LagrangeDev/Lagrange.Core)
## 权限声明 ## 权限声明

View File

@ -7,3 +7,8 @@ java {
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = 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 { plugins {
kotlin("jvm") kotlin("jvm")
id("com.google.devtools.ksp") version "1.9.21-1.0.15" id("com.google.devtools.ksp") version "1.9.21-1.0.15"
kotlin("plugin.serialization") version "1.9.21"
} }
ksp { ksp {
@ -14,5 +15,8 @@ dependencies {
implementation("com.google.devtools.ksp:symbol-processing-api:1.9.21-1.0.15") implementation("com.google.devtools.ksp:symbol-processing-api:1.9.21-1.0.15")
implementation("com.squareup:kotlinpoet:1.14.2") 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") 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.KspExperimental
import com.google.devtools.ksp.getAnnotationsByType import com.google.devtools.ksp.getAnnotationsByType
import com.google.devtools.ksp.getClassDeclarationByName 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.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.processing.KSPLogger
@ -26,12 +27,11 @@ class OneBotHandlerProcessor(
): SymbolProcessor { ): SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> { override fun process(resolver: Resolver): List<KSAnnotated> {
val ActionManagerNode = resolver.getClassDeclarationByName("moe.fuqiuluo.shamrock.remote.action.ActionManager") val ActionManagerNode = resolver.getClassDeclarationByName("moe.fuqiuluo.shamrock.remote.action.ActionManager")
if (ActionManagerNode == null) { ?: resolver.getKotlinClassByName("moe.fuqiuluo.shamrock.remote.action.ActionManager")
logger.error("OneBotHandlerProcessor: ActionManager not found") ?: resolver.getClassDeclarationByName("ActionManager")
return emptyList()
}
val symbols = resolver.getSymbolsWithAnnotation(OneBotHandler::class.qualifiedName!!) val symbols = resolver.getSymbolsWithAnnotation(OneBotHandler::class.qualifiedName!!)
val unableToProcess = symbols.filterNot { it.validate() } val unableToProcess = symbols.filterNot { it.validate() }
if (ActionManagerNode != null) {
val oneBotHandlers = (symbols.filter { val oneBotHandlers = (symbols.filter {
it is KSClassDeclaration && it.validate() && it.classKind == ClassKind.OBJECT it is KSClassDeclaration && it.validate() && it.classKind == ClassKind.OBJECT
} as Sequence<KSClassDeclaration>).toList() } as Sequence<KSClassDeclaration>).toList()
@ -39,6 +39,7 @@ class OneBotHandlerProcessor(
if (oneBotHandlers.isNotEmpty()) { if (oneBotHandlers.isNotEmpty()) {
ActionManagerNode.accept(ActionManagerVisitor(oneBotHandlers), Unit) ActionManagerNode.accept(ActionManagerVisitor(oneBotHandlers), Unit)
} }
}
return unableToProcess.toList() 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.forEachIndexed { index, clz ->
if (clz.isInternal()) return@forEachIndexed
if (clz.isPrivate()) return@forEachIndexed
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 = "FP${clz.simpleName.asString().hashCode()}"
).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("com.android.library")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
kotlin("plugin.serialization") version "1.9.21" kotlin("plugin.serialization") version "1.9.21"
id("com.google.devtools.ksp") version "1.9.21-1.0.15"
} }
android { android {
@ -38,4 +39,7 @@ dependencies {
implementation(kotlinx("serialization-protobuf", "1.6.2")) implementation(kotlinx("serialization-protobuf", "1.6.2"))
implementation(kotlinx("serialization-json", "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.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
data class WeiyunComm( data class WeiyunComm(
@ProtoNumber(1) val req: WeiyunCommonReq? = null, @ProtoNumber(1) val req: WeiyunCommonReq? = null,
@ProtoNumber(2) val resp: WeiyunCommonResp? = 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.ExperimentalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
data class WeiyunMsgHead( data class WeiyunMsgHead(
@ -27,4 +28,5 @@ data class WeiyunMsgHead(
@ProtoNumber(103) val promptMsg: String? = null, @ProtoNumber(103) val promptMsg: String? = null,
@ProtoNumber(111) val totalSpace: ULong = ULong.MIN_VALUE, @ProtoNumber(111) val totalSpace: ULong = ULong.MIN_VALUE,
@ProtoNumber(112) val usedSpace: 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.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
import protobuf.qweb.QWebExtInfo import protobuf.qweb.QWebExtInfo
@Serializable @Serializable
@ -19,7 +20,7 @@ data class GetGuildFeedsReq(
@ProtoNumber(7) var u7: Int? = null, @ProtoNumber(7) var u7: Int? = null,
@ProtoNumber(8) var u8: Int? = null, @ProtoNumber(8) var u8: Int? = null,
@ProtoNumber(9) var u9: ByteArray? = null, @ProtoNumber(9) var u9: ByteArray? = null,
) ): Protobuf<GetGuildFeedsReq>
@Serializable @Serializable
data class GetGuildFeedsRsp( data class GetGuildFeedsRsp(
@ -27,7 +28,7 @@ data class GetGuildFeedsRsp(
@ProtoNumber(2) var isFinish: Int = 0, @ProtoNumber(2) var isFinish: Int = 0,
//@ProtoNumber(3) var feedAttchInfo: ByteArray? = null, //@ProtoNumber(3) var feedAttchInfo: ByteArray? = null,
//@ProtoNumber(4) var traceId: String? = null, //@ProtoNumber(4) var traceId: String? = null,
) ): Protobuf<GetGuildFeedsRsp>
@Serializable @Serializable
data class StFeed( 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.ExperimentalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
@ -39,14 +40,14 @@ data class LongMsgReq(
@ProtoNumber(1) val recvInfo: RecvLongMsgInfo? = null, @ProtoNumber(1) val recvInfo: RecvLongMsgInfo? = null,
@ProtoNumber(2) val sendInfo: SendLongMsgInfo? = null, @ProtoNumber(2) val sendInfo: SendLongMsgInfo? = null,
@ProtoNumber(15) val setting: LongMsgSettings? = null, @ProtoNumber(15) val setting: LongMsgSettings? = null,
) ): Protobuf<LongMsgReq>
@Serializable @Serializable
data class LongMsgRsp( data class LongMsgRsp(
@ProtoNumber(1) val recvResult: RecvLongMsgResult? = null, @ProtoNumber(1) val recvResult: RecvLongMsgResult? = null,
@ProtoNumber(2) val sendResult: SendLongMsgResult? = null, @ProtoNumber(2) val sendResult: SendLongMsgResult? = null,
@ProtoNumber(15) val setting: LongMsgSettings? = null @ProtoNumber(15) val setting: LongMsgSettings? = null
) { ): Protobuf<LongMsgRsp> {
companion object { companion object {
@Serializable @Serializable
data class SendLongMsgResult( data class SendLongMsgResult(

View File

@ -5,6 +5,7 @@ package protobuf.message.longmsg
import kotlinx.serialization.ExperimentalSerializationApi 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 protobuf.message.MessageBody import protobuf.message.MessageBody
import protobuf.message.MessageContent import protobuf.message.MessageContent
import protobuf.message.MessageHead import protobuf.message.MessageHead
@ -29,4 +30,4 @@ data class LongMsgAction(
@Serializable @Serializable
data class LongMsgPayload( data class LongMsgPayload(
@ProtoNumber(2) val action: List<LongMsgAction>? = null @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.ExperimentalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
data class RichMediaForPicData( data class RichMediaForPicData(
@ProtoNumber(1) val info: MediaInfo?, @ProtoNumber(1) val info: MediaInfo?,
@ProtoNumber(2) val display: DisplayMediaInfo?, @ProtoNumber(2) val display: DisplayMediaInfo?,
) { ): Protobuf<RichMediaForPicData> {
companion object { companion object {
@Serializable @Serializable
data class MediaInfo( data class MediaInfo(

View File

@ -2,6 +2,7 @@ package protobuf.msg
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
class PbSendMsgReq( class PbSendMsgReq(
@ -19,7 +20,7 @@ class PbSendMsgReq(
//@ProtoNumber(12) var msgCtrl: MsgCtrl? = null, //@ProtoNumber(12) var msgCtrl: MsgCtrl? = null,
//@ProtoNumber(13) var receipt_req: ReceiptReq? = null, //@ProtoNumber(13) var receipt_req: ReceiptReq? = null,
//@ProtoNumber(14) var multi_send_seq: UInt = 0u, //@ProtoNumber(14) var multi_send_seq: UInt = 0u,
) ): Protobuf<PbSendMsgReq>
@Serializable @Serializable
data class ContentHead( data class ContentHead(

View File

@ -2,11 +2,13 @@ package protobuf.oidb
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
data class TrpcOidb( data class TrpcOidb(
@ProtoNumber(1) val cmd: Int = Int.MIN_VALUE, @ProtoNumber(1) val cmd: Int = Int.MIN_VALUE,
@ProtoNumber(2) val service: Int = Int.MIN_VALUE, @ProtoNumber(2) val service: Int = Int.MIN_VALUE,
@ProtoNumber(4) val buffer: ByteArray, @ProtoNumber(4) val buffer: ByteArray,
//@ProtoNumber(11) val traceParams: Map<String, String> = mapOf(),
@ProtoNumber(12) val flag: Int = Int.MIN_VALUE, @ProtoNumber(12) val flag: Int = Int.MIN_VALUE,
) ): Protobuf<TrpcOidb>

View File

@ -0,0 +1,272 @@
@file:OptIn(ExperimentalSerializationApi::class)
package protobuf.oidb.cmd0x11c5
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class NtV2RichMediaReq(
@ProtoNumber(1) val head: MultiMediaReqHead,
@ProtoNumber(2) val upload: UploadReq? = null, // 100
@ProtoNumber(3) val download: DownloadReq? = null,
@ProtoNumber(4) val downloadRkey: DownloadRkeyReq? = null,
@ProtoNumber(5) val delete: DeleteReq? = null,
@ProtoNumber(6) val uploadCompleted: UploadCompletedReq? = null,
@ProtoNumber(7) val msgInfoAuth: MsgInfoAuthReq? = null,
@ProtoNumber(8) val uploadKeyRenewal: UploadKeyRenewalReq? = null,
@ProtoNumber(9) val downloadSafe: DownloadSafeReq? = null,
@ProtoNumber(99) val extension: ByteArray? = null,
): Protobuf<NtV2RichMediaReq>
@Serializable
data class DownloadSafeReq(
@ProtoNumber(1) val index: IndexNode,
)
@Serializable
data class UploadKeyRenewalReq(
@ProtoNumber(1) val oldUkey: String,
@ProtoNumber(2) val subType: UInt,
)
@Serializable
data class MsgInfoAuthReq(
@ProtoNumber(1) val msg: ByteArray,
@ProtoNumber(2) val authTime: ULong,
)
@Serializable
data class UploadCompletedReq(
@ProtoNumber(1) val srvSendMsg: Boolean,
@ProtoNumber(2) val clientRandomId: ULong,
@ProtoNumber(3) val msgInfo: MsgInfo,
@ProtoNumber(4) val clientSeq: UInt,
)
@Serializable
data class MsgInfo(
@ProtoNumber(1) val msgInfoBody: List<MsgInfoBody>,
@ProtoNumber(2) val extBizInfo: ExtBizInfo,
)
@Serializable
data class MsgInfoBody(
@ProtoNumber(1) val index: IndexNode? = null,
@ProtoNumber(2) val picture: PictureInfo? = null,
@ProtoNumber(3) val video: VideoInfo? = null,
@ProtoNumber(4) val audio: AudioInfo? = null,
@ProtoNumber(5) val fileExist: Boolean? = null,
@ProtoNumber(6) val hashSum: ByteArray? = null,
)
@Serializable
class VideoInfo
@Serializable
class AudioInfo
@Serializable
data class PictureInfo(
@ProtoNumber(1) val urlPath: String,
@ProtoNumber(2) val ext: PicUrlExtInfo? = null,
@ProtoNumber(3) val domain: String? = null
)
@Serializable
data class PicUrlExtInfo(
@ProtoNumber(1) val originalParameter: String? = null,
@ProtoNumber(2) val bigParameter: String? = null,
@ProtoNumber(3) val thumbParameter: String? = null
)
@Serializable
data class DeleteReq(
@ProtoNumber(1) val index: List<IndexNode>,
@ProtoNumber(2) val needRecallMsg: Boolean? = null,
@ProtoNumber(3) val msgSeq: ULong? = null,
@ProtoNumber(4) val msgRandom: ULong? = null,
@ProtoNumber(5) val msgTime: ULong? = null,
)
@Serializable
data class DownloadRkeyReq(
@ProtoNumber(1) val types: List<Int>
)
@Serializable
data class UploadReq(
@ProtoNumber(1) val uploadInfo: List<UploadInfo>,
@ProtoNumber(2) val tryFastUploadCompleted: Boolean? = null,
@ProtoNumber(3) val srvSendMsg: Boolean? = null,
@ProtoNumber(4) val clientRandomId: ULong = ULong.MIN_VALUE,
@ProtoNumber(5) val compatQMsgSceneType: UInt? = null,
@ProtoNumber(6) val extBizInfo: ExtBizInfo? = null,
@ProtoNumber(7) val clientSeq: UInt? = null,
@ProtoNumber(8) val noNeedCompatMsg: Boolean = false,
)
@Serializable
data class ExtBizInfo(
@ProtoNumber(1) val pic: PicExtBizInfo? = null,
@ProtoNumber(2) val video: VideoExtBizInfo? = null,
@ProtoNumber(3) val ptt: PttExtBizInfo? = null,
@ProtoNumber(10) val busiType: UInt,
)
@Serializable
data class PttExtBizInfo(
@ProtoNumber(1) val srcUin: ULong,
@ProtoNumber(2) val pttScene: UInt,
@ProtoNumber(3) val pttType: UInt,
@ProtoNumber(4) val changeVoice: UInt,
@ProtoNumber(5) val waveform: ByteArray? = null,
@ProtoNumber(6) val autoConvertText: UInt? = null,
@ProtoNumber(11) val bytesReserve: ByteArray? = null,
@ProtoNumber(12) val bytesPbReserve: ByteArray? = null,
@ProtoNumber(13) val bytesGeneralFlags: ByteArray? = null,
)
@Serializable
data class VideoExtBizInfo(
@ProtoNumber(1) val fromScene: UInt,
@ProtoNumber(2) val toScene: UInt,
@ProtoNumber(3) val bytesPbReserve: ByteArray,
)
@Serializable
data class PicExtBizInfo(
@ProtoNumber(1) val bizType: UInt,
@ProtoNumber(2) val textSummary: String,
@ProtoNumber(11) val bytesPbReserveC2c: ByteArray? = null,
@ProtoNumber(12) val bytesPbReserveTroop: ByteArray? = null,
@ProtoNumber(1001) val fromScene: UInt? = null,
@ProtoNumber(1002) val toScene: UInt? = null,
@ProtoNumber(1003) val oldFileId: UInt? = null,
)
@Serializable
data class UploadInfo(
@ProtoNumber(1) val fileInfo: FileInfo,
@ProtoNumber(2) val subFileType: UInt
)
@Serializable
data class FileInfo(
@ProtoNumber(1) val fileSize: ULong,
@ProtoNumber(2) val md5: String,
@ProtoNumber(3) val sha1: String,
@ProtoNumber(4) val name: String,
@ProtoNumber(5) val fileType: FileType,
@ProtoNumber(6) val width: UInt,
@ProtoNumber(7) val height: UInt,
@ProtoNumber(8) val time: UInt,
@ProtoNumber(9) val original: UInt,
)
@Serializable
data class FileType(
@ProtoNumber(1) val fileType: UInt = 0u,
@ProtoNumber(2) val picFormat: UInt = 0u,
@ProtoNumber(3) val videoFormat: UInt? = null,
@ProtoNumber(4) val voiceFormat: UInt? = null,
)
@Serializable
data class DownloadReq(
@ProtoNumber(1) val index: IndexNode,
@ProtoNumber(2) val ext: DownloadExt,
)
@Serializable
data class DownloadExt(
@ProtoNumber(1) val pic: PicDownloadExt? = null,
@ProtoNumber(2) val video: VideoDownloadExt,
@ProtoNumber(3) val voice: PttDownloadExt? = null,
)
@Serializable
class PicDownloadExt
@Serializable
class PttDownloadExt
@Serializable
data class VideoDownloadExt(
@ProtoNumber(1) val busiType: UInt?,
@ProtoNumber(2) val sceneType: UInt? = null,
@ProtoNumber(3) val subBusiType: UInt?,
@ProtoNumber(4) val msgCodecConfig: CodecConfigReq,
@ProtoNumber(5) val flag: UInt?,
)
@Serializable
data class CodecConfigReq(
@ProtoNumber(1) val platformChipinfo: String,
@ProtoNumber(2) val osVer: String,
@ProtoNumber(3) val deviceName: String,
)
@Serializable
data class IndexNode(
@ProtoNumber(1) val fileInfo: FileInfo,
@ProtoNumber(2) val fileUuid: String,
@ProtoNumber(3) val storeId: UInt, // 0为旧服务器 1为nt服务器
@ProtoNumber(4) val uploadTime: ULong,
@ProtoNumber(5) val ttl: ULong,
@ProtoNumber(6) val subType: UInt,
@ProtoNumber(7) val storeAppId: UInt? = null
)
@Serializable
data class MultiMediaReqHead(
@ProtoNumber(1) val commonHead: CommonHead,
@ProtoNumber(2) val sceneInfo: SceneInfo,
@ProtoNumber(3) val clientMeta: ClientMeta
)
@Serializable
data class ClientMeta(
@ProtoNumber(1) val agentType: UInt,
)
@Serializable
data class SceneInfo(
@ProtoNumber(101) val requestType: UInt,
@ProtoNumber(102) val businessType: UInt,
@ProtoNumber(103) val appType: UInt? = null,
@ProtoNumber(200) var sceneType: UInt? = null,
@ProtoNumber(201) var c2c: C2CUserInfo? = null,
@ProtoNumber(202) var grp: GroupUserInfo? = null,
@ProtoNumber(203) var channel: ChannelUserInfo? = null,
@ProtoNumber(205) val byteArr: ByteArray?= null
)
@Serializable
data class ChannelUserInfo(
@ProtoNumber(1) val guildId: ULong,
@ProtoNumber(2) val channelId: ULong,
@ProtoNumber(3) val channelType: UInt,
)
@Serializable
data class GroupUserInfo(
@ProtoNumber(1) val uin: ULong,
)
@Serializable
data class C2CUserInfo(
@ProtoNumber(1) val accountType: UInt,
@ProtoNumber(2) val uid: String,
@ProtoNumber(3) val byteArr: ByteArray? = null
)
@Serializable
data class CommonHead(
@ProtoNumber(1) val requestId: ULong,
@ProtoNumber(2) val cmd: UInt,
@ProtoNumber(3) val msg: String? = null
)

View File

@ -0,0 +1,139 @@
@file:OptIn(ExperimentalSerializationApi::class)
package protobuf.oidb.cmd0x11c5
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable
data class NtV2RichMediaRsp(
@ProtoNumber(1) val head: RspHead,
@ProtoNumber(2) val upload: UploadRsp?,
@ProtoNumber(3) val download: DownloadRsp?,
@ProtoNumber(4) val downloadRkeyRsp: DownloadRkeyRsp?,
@ProtoNumber(5) val delete: DeleteRsp?,
@ProtoNumber(6) val uploadCompleted: UploadCompletedRsp?,
@ProtoNumber(7) val msgInfoAuth: MsgInfoAuthRsp?,
@ProtoNumber(8) val uploadKeyRenew: UploadKeyRenewalRsp?,
@ProtoNumber(9) val downloadSafe: DownloadSafeRsp?,
@ProtoNumber(99) val extension: ByteArray? = null,
): Protobuf<NtV2RichMediaRsp>
@Serializable
class DownloadSafeRsp
@Serializable
data class UploadKeyRenewalRsp(
@ProtoNumber(1) val ukey: String,
@ProtoNumber(2) val ukeyTtlSec: ULong,
)
@Serializable
data class MsgInfoAuthRsp(
@ProtoNumber(1) val authCode: UInt = 0u,
@ProtoNumber(2) val msg: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(3) val resultTime: ULong = 0u,
)
@Serializable
data class UploadCompletedRsp(
@ProtoNumber(1) val msgSeq: ULong
)
@Serializable
class DeleteRsp
@Serializable
data class DownloadRkeyRsp(
@ProtoNumber(1) val rkeys: List<RKeyInfo>
)
@Serializable
data class RKeyInfo(
@ProtoNumber(1) val rkey: String,
@ProtoNumber(2) val rkeyTtlSec: ULong,
@ProtoNumber(3) val storeId: UInt = 0u,
@ProtoNumber(4) val rkeyCreateTime: UInt?,
@ProtoNumber(4) val type: UInt?,
)
@Serializable
data class DownloadRsp(
@ProtoNumber(1) val rkeyParam: String,
@ProtoNumber(2) val rkeyTtlSec: ULong,
@ProtoNumber(3) val downloadInfo: DownloadInfo?,
@ProtoNumber(4) val rkeyCreateTime: UInt?
)
@Serializable
data class DownloadInfo(
@ProtoNumber(1) val domain: String,
@ProtoNumber(2) val urlPath: String? = null,
@ProtoNumber(3) val httpsPort: Int = Int.MIN_VALUE,
@ProtoNumber(4) val ipv4: List<Ipv4>,
@ProtoNumber(5) val ipv6: List<Ipv6>,
@ProtoNumber(6) val picUrlExtInfo: PicUrlExtInfo?,
@ProtoNumber(7) val videoExtInfo: VideoExtInfo? = null,
)
@Serializable
data class VideoExtInfo(
@ProtoNumber(1) val videoCodecFormat: UInt,
)
@Serializable
data class UploadRsp(
@ProtoNumber(1) val ukey: String,
@ProtoNumber(2) val ukeyTtlSec: ULong,
@ProtoNumber(3) val ipv4: List<Ipv4>,
@ProtoNumber(4) val ipv6: List<Ipv6>,
@ProtoNumber(5) val msgSeq: ULong,
@ProtoNumber(6) val msgInfo: MsgInfo? = null,
@ProtoNumber(7) val ext: List<RichmediaStorageTransInfo>? = null,
@ProtoNumber(8) val compatQMsg: ByteArray? = null,
@ProtoNumber(10) val subFileInfos: List<SubFileInfo>? = null,
)
@Serializable
data class SubFileInfo(
@ProtoNumber(1) val subType: UInt,
@ProtoNumber(2) val ukey: String,
@ProtoNumber(3) val ukeyTTLSec: ULong,
@ProtoNumber(4) val ipv4: List<Ipv4>,
@ProtoNumber(5) val ipv6: List<Ipv6>,
)
@Serializable
data class RichmediaStorageTransInfo(
@ProtoNumber(1) val subType: UInt = UInt.MIN_VALUE,
@ProtoNumber(2) val extType: UInt = UInt.MIN_VALUE,
@ProtoNumber(3) val extValue: ByteArray? = null,
)
@Serializable
data class Ipv4(
@ProtoNumber(1) val outIp: Int = Int.MIN_VALUE,
@ProtoNumber(2) val outPort: Int = Int.MIN_VALUE,
@ProtoNumber(3) val inIp: Int = Int.MIN_VALUE,
@ProtoNumber(4) val inPort: Int = Int.MIN_VALUE,
@ProtoNumber(5) val ipType: Int = Int.MIN_VALUE,
)
@Serializable
data class Ipv6(
@ProtoNumber(1) val outIp: ByteArray? = null,
@ProtoNumber(2) val outPort: Int = Int.MIN_VALUE,
@ProtoNumber(3) val inIp: ByteArray? = null,
@ProtoNumber(4) val inPort: Int = Int.MIN_VALUE,
@ProtoNumber(5) val ipType: Int = Int.MIN_VALUE,
)
@Serializable
data class RspHead(
@ProtoNumber(1) val commonHead: CommonHead,
@ProtoNumber(2) val retCode: UInt = 0u,
@ProtoNumber(3) val msg: String
)

View File

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

View File

@ -2,6 +2,7 @@ package protobuf.oidb.cmd0x9082
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
data class Oidb0x9082( data class Oidb0x9082(
@ -11,4 +12,4 @@ data class Oidb0x9082(
@ProtoNumber(5) val flag: UInt = UInt.MIN_VALUE, @ProtoNumber(5) val flag: UInt = UInt.MIN_VALUE,
@ProtoNumber(6) val u1: UInt = UInt.MIN_VALUE, @ProtoNumber(6) val u1: UInt = UInt.MIN_VALUE,
@ProtoNumber(7) val u2: 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.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf
@Serializable @Serializable
data class Oidb0xf16( data class Oidb0xf16(
@ProtoNumber(1) var setGroupRemarkReq: SetGroupRemarkReq? = null, @ProtoNumber(1) var setGroupRemarkReq: SetGroupRemarkReq? = null,
) ): Protobuf<Oidb0xf16>
@Serializable @Serializable
data class SetGroupRemarkReq( data class SetGroupRemarkReq(

View File

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

View File

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

View File

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

View File

@ -2,12 +2,13 @@ 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
@Serializable @Serializable
data class C2CCommonTipsEvent( data class C2CCommonTipsEvent(
@ProtoNumber(7) val params: List<PokeParam>? = null, @ProtoNumber(7) val params: List<PokeParam>? = null,
@ProtoNumber(8) val xmlTips: String? = null, @ProtoNumber(8) val xmlTips: String? = null,
) ): Protobuf<C2CCommonTipsEvent>
@Serializable @Serializable
data class PokeParam( data class PokeParam(

View File

@ -2,11 +2,12 @@ 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
@Serializable @Serializable
data class C2CRecallEvent( data class C2CRecallEvent(
@ProtoNumber(1) val head: C2CRecallHead? = null, @ProtoNumber(1) val head: C2CRecallHead? = null,
) ): Protobuf<C2CRecallEvent>
@Serializable @Serializable
data class C2CRecallHead( data class C2CRecallHead(

View File

@ -2,11 +2,12 @@ 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
@Serializable @Serializable
data class FriendApplyEvent( data class FriendApplyEvent(
@ProtoNumber(1) val head: FriendApplyHead? = null, @ProtoNumber(1) val head: FriendApplyHead? = null,
) ): Protobuf<FriendApplyEvent>
@Serializable @Serializable

View File

@ -2,10 +2,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
@Serializable @Serializable
data class GroupAdminChangeEvent( data class GroupAdminChangeEvent(
@ProtoNumber(1) val groupCode: Long, @ProtoNumber(1) val groupCode: Long,
@ProtoNumber(4) val operation: GroupAdminChangedOperation? = null @ProtoNumber(4) val operation: GroupAdminChangedOperation? = null
) ): Protobuf<GroupAdminChangeEvent>

View File

@ -2,10 +2,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
@Serializable @Serializable
data class GroupApplyEvent( data class GroupApplyEvent(
@ProtoNumber(1) val groupCode: Long = Long.MIN_VALUE, @ProtoNumber(1) val groupCode: Long = Long.MIN_VALUE,
@ProtoNumber(3) val applierUid: String = "", @ProtoNumber(3) val applierUid: String = "",
@ProtoNumber(5) val applyMsg: String? = null, @ProtoNumber(5) val applyMsg: String? = null,
) ): Protobuf<GroupApplyEvent>

View File

@ -2,13 +2,14 @@ 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
@Serializable @Serializable
data class GroupBanEvent( data class GroupBanEvent(
@ProtoNumber(1) val groupCode: ULong = ULong.MIN_VALUE, @ProtoNumber(1) val groupCode: ULong = ULong.MIN_VALUE,
@ProtoNumber(4) val operatorUid: String = "", @ProtoNumber(4) val operatorUid: String = "",
@ProtoNumber(5) val target: GroupBanTarget? = null, @ProtoNumber(5) val target: GroupBanTarget? = null,
) ): Protobuf<GroupBanEvent>
@Serializable @Serializable
data class GroupBanTarget( data class GroupBanTarget(

View File

@ -2,6 +2,7 @@ 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
@Serializable @Serializable
data class GroupCommonTipsEvent( data class GroupCommonTipsEvent(
@ -11,7 +12,7 @@ data class GroupCommonTipsEvent(
@ProtoNumber(26) val baseTips: List<GroupBaseTips>? = null, @ProtoNumber(26) val baseTips: List<GroupBaseTips>? = null,
@ProtoNumber(33) val essenceMsgInfo: List<EssenceMsgInfo>? = null, @ProtoNumber(33) val essenceMsgInfo: List<EssenceMsgInfo>? = null,
@ProtoNumber(37) val msgSeq: ULong = ULong.MIN_VALUE, @ProtoNumber(37) val msgSeq: ULong = ULong.MIN_VALUE,
) ): Protobuf<GroupCommonTipsEvent>
@Serializable @Serializable
data class EssenceMsgInfo( data class EssenceMsgInfo(

View File

@ -2,9 +2,10 @@ 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
@Serializable @Serializable
data class GroupInviteEvent( data class GroupInviteEvent(
@ProtoNumber(1) val groupCode: Long, @ProtoNumber(1) val groupCode: Long,
@ProtoNumber(5) val inviterUid: String, @ProtoNumber(5) val inviterUid: String,
) ): Protobuf<GroupInviteEvent>

View File

@ -2,11 +2,12 @@ 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
@Serializable @Serializable
data class GroupInvitedApplyEvent( data class GroupInvitedApplyEvent(
@ProtoNumber(2) val applyInfo: GroupInvitedApplyInfo? = null, @ProtoNumber(2) val applyInfo: GroupInvitedApplyInfo? = null,
) ): Protobuf<GroupInvitedApplyEvent>
@Serializable @Serializable
data class GroupInvitedApplyInfo( data class GroupInvitedApplyInfo(

View File

@ -2,6 +2,7 @@ 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
@Serializable @Serializable
data class GroupListChangeEvent( data class GroupListChangeEvent(
@ -9,4 +10,4 @@ data class GroupListChangeEvent(
@ProtoNumber(3) val memberUid: String = "", @ProtoNumber(3) val memberUid: String = "",
@ProtoNumber(4) val type: Int = Int.MIN_VALUE, @ProtoNumber(4) val type: Int = Int.MIN_VALUE,
@ProtoNumber(5) val operatorUid: String = "", @ProtoNumber(5) val operatorUid: String = "",
) ): Protobuf<GroupListChangeEvent>

View File

@ -2,13 +2,14 @@ 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 protobuf.message.NtMessage import protobuf.message.NtMessage
@Serializable @Serializable
data class MessagePush( data class MessagePush(
@ProtoNumber(1) val msgBody: NtMessage? = null, @ProtoNumber(1) val msgBody: NtMessage? = null,
@ProtoNumber(4) val clientInfo: MessagePushClientInfo? = null, @ProtoNumber(4) val clientInfo: MessagePushClientInfo? = null,
) ): Protobuf<MessagePush>
@Serializable @Serializable
data class MessagePushClientInfo( data class MessagePushClientInfo(

View File

@ -5,6 +5,7 @@ package protobuf.qweb
import kotlinx.serialization.ExperimentalSerializationApi 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
@Serializable @Serializable
data class QWebReq( data class QWebReq(
@ -19,7 +20,7 @@ data class QWebReq(
//@ProtoNumber(9) var Crypto: Any? = null, //@ProtoNumber(9) var Crypto: Any? = null,
@ProtoNumber(10) var extinfo: List<QWebExtInfo>? = null, @ProtoNumber(10) var extinfo: List<QWebExtInfo>? = null,
//@ProtoNumber(11) var contentType: Any? = null, //@ProtoNumber(11) var contentType: Any? = null,
) ): Protobuf<QWebReq>
@Serializable @Serializable
data class QWebExtInfo( data class QWebExtInfo(
@ -34,4 +35,4 @@ data class QWebRsp(
//@ProtoNumber(3) var errMsg: String? = null, //@ProtoNumber(3) var errMsg: String? = null,
@ProtoNumber(4) var buffer: ByteArray? = null, @ProtoNumber(4) var buffer: ByteArray? = null,
//@ProtoNumber(5) var Extinfo: List<QWebExtInfo>? = 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.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.encodeToByteArray import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.shamrock.tools.slice import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.utils.DeflateTools import moe.fuqiuluo.shamrock.utils.DeflateTools
import moe.fuqiuluo.shamrock.utils.PlatformUtils 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 moe.fuqiuluo.shamrock.xposed.helper.internal.IPCRequest
import protobuf.oidb.TrpcOidb import protobuf.oidb.TrpcOidb
import mqq.app.MobileQQ import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import tencent.im.oidb.oidb_sso import tencent.im.oidb.oidb_sso
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume import kotlin.coroutines.resume
@ -127,9 +128,9 @@ internal abstract class BaseSvc {
cmd = cmdId, cmd = cmdId,
service = serviceId, service = serviceId,
buffer = buffer, buffer = buffer,
flag = 0 flag = 1
) )
to.putWupBuffer(ProtoBuf.encodeToByteArray(oidb)) to.putWupBuffer(oidb.toByteArray())
to.addAttribute("req_pb_protocol_flag", true) to.addAttribute("req_pb_protocol_flag", true)
if (seq != -1) { if (seq != -1) {

View File

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

View File

@ -1,9 +1,6 @@
package moe.fuqiuluo.qqinterface.servlet package moe.fuqiuluo.qqinterface.servlet
import com.tencent.mobileqq.pb.ByteStringMicro 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.structures.*
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
import moe.fuqiuluo.shamrock.helper.Level 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.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 protobuf.oidb.cmd0x6d7.CreateFolderReq import protobuf.oidb.cmd0x6d7.CreateFolderReq
import protobuf.oidb.cmd0x6d7.DeleteFolderReq import protobuf.oidb.cmd0x6d7.DeleteFolderReq
import protobuf.oidb.cmd0x6d7.MoveFolderReq 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.cmd0x6d8.oidb_0x6d8
import tencent.im.oidb.oidb_sso import tencent.im.oidb.oidb_sso
import protobuf.group_file_common.FolderInfo as GroupFileCommonFolderInfo import protobuf.group_file_common.FolderInfo as GroupFileCommonFolderInfo
import protobuf.auto.toByteArray
internal object FileSvc: BaseSvc() { internal object FileSvc: BaseSvc() {
suspend fun createFileFolder(groupId: String, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> { suspend fun createFileFolder(groupId: String, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> {
val data = ProtoBuf.encodeToByteArray( val data = Oidb0x6d7ReqBody(
Oidb0x6d7ReqBody(
createFolder = CreateFolderReq( createFolder = CreateFolderReq(
groupCode = groupId.toULong(), groupCode = groupId.toULong(),
appId = 3u, appId = 3u,
parentFolderId = parentFolderId, parentFolderId = parentFolderId,
folderName = folderName folderName = folderName
) )
) ).toByteArray()
)
val resultBuffer = sendOidbAW("OidbSvc.0x6d7_0", 1751, 0, data) val resultBuffer = sendOidbAW("OidbSvc.0x6d7_0", 1751, 0, data)
?: return Result.failure(Exception("unable to fetch result")) ?: return Result.failure(Exception("unable to fetch result"))
val oidbPkg = oidb_sso.OIDBSSOPkg() val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(resultBuffer.slice(4)) 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) { if (rsp.createFolder?.retCode != 0) {
return Result.failure(Exception("unable to create folder: ${rsp.createFolder?.retCode}")) 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 { suspend fun deleteGroupFolder(groupId: String, folderUid: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, ProtoBuf.encodeToByteArray( val buffer = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
Oidb0x6d7ReqBody(
deleteFolder = DeleteFolderReq( deleteFolder = DeleteFolderReq(
groupCode = groupId.toULong(), groupCode = groupId.toULong(),
appId = 3u, appId = 3u,
folderId = folderUid folderId = folderUid
) )
) ).toByteArray()) ?: return false
)) ?: return false
val oidbPkg = oidb_sso.OIDBSSOPkg() val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(buffer.slice(4)) 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 return rsp.deleteFolder?.retCode == 0
} }
suspend fun moveGroupFolder(groupId: String, folderUid: String, newParentFolderUid: String): Boolean { suspend fun moveGroupFolder(groupId: String, folderUid: String, newParentFolderUid: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, ProtoBuf.encodeToByteArray( val buffer = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, Oidb0x6d7ReqBody(
Oidb0x6d7ReqBody(
moveFolder = MoveFolderReq( moveFolder = MoveFolderReq(
groupCode = groupId.toULong(), groupCode = groupId.toULong(),
appId = 3u, appId = 3u,
folderId = folderUid, folderId = folderUid,
parentFolderId = "/" parentFolderId = "/"
) )
) ).toByteArray()) ?: return false
)) ?: return false
val oidbPkg = oidb_sso.OIDBSSOPkg() val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(buffer.slice(4)) 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 return rsp.moveFolder?.retCode == 0
} }
suspend fun renameFolder(groupId: String, folderUid: String, name: String): Boolean { suspend fun renameFolder(groupId: String, folderUid: String, name: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, ProtoBuf.encodeToByteArray( val buffer = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
Oidb0x6d7ReqBody(
renameFolder = RenameFolderReq( renameFolder = RenameFolderReq(
groupCode = groupId.toULong(), groupCode = groupId.toULong(),
appId = 3u, appId = 3u,
folderId = folderUid, folderId = folderUid,
folderName = name folderName = name
) )
) ).toByteArray()) ?: return false
)) ?: return false
val oidbPkg = oidb_sso.OIDBSSOPkg() val oidbPkg = oidb_sso.OIDBSSOPkg()
oidbPkg.mergeFrom(buffer.slice(4)) 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 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.GProRoleCreateInfo
import com.tencent.qqnt.kernel.nativeinterface.GProRoleMemberList import com.tencent.qqnt.kernel.nativeinterface.GProRoleMemberList
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission 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.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.ExperimentalSerializationApi 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.GProChannelInfo
import moe.fuqiuluo.qqinterface.servlet.structures.GetGuildMemberListNextToken import moe.fuqiuluo.qqinterface.servlet.structures.GetGuildMemberListNextToken
import moe.fuqiuluo.qqinterface.servlet.structures.GuildInfo 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.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY 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.utils.DeflateTools
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 protobuf.auto.toByteArray
import protobuf.guild.GetGuildFeedsReq import protobuf.guild.GetGuildFeedsReq
import protobuf.guild.GetGuildFeedsRsp import protobuf.guild.GetGuildFeedsRsp
import protobuf.oidb.cmd0xf88.GProFilter import protobuf.oidb.cmd0xf88.GProFilter
@ -54,33 +51,31 @@ internal object GProSvc: BaseSvc() {
} }
suspend fun getGuildInfo(guildId: ULong): Result<Oidb0xf57MetaInfo> { suspend fun getGuildInfo(guildId: ULong): Result<Oidb0xf57MetaInfo> {
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf57_9", 0xf57, 9, ProtoBuf.encodeToByteArray( val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf57_9", 0xf57, 9, Oidb0xf57Req(
Oidb0xf57Req(
filter = Oidb0xf57Filter( 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), 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) u2 = Oidb0xf57U2(1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u)
), ),
guildInfo = Oidb0xf57GuildInfo(guildId = guildId) guildInfo = Oidb0xf57GuildInfo(guildId = guildId)
) ).toByteArray())
))
val body = oidb_sso.OIDBSSOPkg() val body = oidb_sso.OIDBSSOPkg()
if (respBuffer == null) { if (respBuffer == null) {
return Result.failure(Exception("unable to send packet")) return Result.failure(Exception("unable to send packet"))
} }
body.mergeFrom(respBuffer.slice(4)) body.mergeFrom(respBuffer.slice(4))
return runCatching { return runCatching {
ProtoBuf.decodeFromByteArray<Oidb0xf57Rsp>( body.bytes_bodybuffer.get()
body.bytes_bodybuffer.get().toByteArray() .toByteArray()
).metaInfo .decodeProtobuf<Oidb0xf57Rsp>().metaInfo
} }
} }
suspend fun getGuildFeeds(guildId: ULong, channelId: ULong, startIndex: Int): Result<GetGuildFeedsRsp> { 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, seq = 10,
qua = PlatformUtils.getQUA(), 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", 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, count = 12,
from = startIndex, from = startIndex,
feedAttchInfo = EMPTY_BYTE_ARRAY, feedAttchInfo = EMPTY_BYTE_ARRAY,
@ -89,18 +84,18 @@ internal object GProSvc: BaseSvc() {
u7 = 0, u7 = 0,
u8 = 1, u8 = 1,
u9 = EMPTY_BYTE_ARRAY u9 = EMPTY_BYTE_ARRAY
)), ).toByteArray(),
traceId = app.account + "_0_0", traceId = app.account + "_0_0",
extinfo = listOf( extinfo = listOf(
QWebExtInfo("fc-appid", "96"), QWebExtInfo("fc-appid", "96"),
QWebExtInfo("environment_id", "shamrock"), QWebExtInfo("environment_id", "shamrock"),
QWebExtInfo("tiny_id", getSelfTinyId().toString()), QWebExtInfo("tiny_id", getSelfTinyId().toString()),
) )
))) ?: return Result.failure(Exception("unable to send packet")) ).toByteArray()) ?: return Result.failure(Exception("unable to send packet"))
val webRsp = ProtoBuf.decodeFromByteArray<QWebRsp>(buffer.slice(4)) val webRsp = buffer.slice(4).decodeProtobuf<QWebRsp>()
if(webRsp.buffer == null) return Result.failure(Exception("server error")) if(webRsp.buffer == null) return Result.failure(Exception("server error"))
val wupBuffer = webRsp.buffer!! val wupBuffer = webRsp.buffer!!
val feeds = ProtoBuf.decodeFromByteArray<GetGuildFeedsRsp>(wupBuffer) val feeds = wupBuffer.decodeProtobuf<GetGuildFeedsRsp>()
return Result.success(feeds) return Result.success(feeds)
} }
@ -188,23 +183,19 @@ internal object GProSvc: BaseSvc() {
guildId: ULong, guildId: ULong,
memberTinyId: ULong memberTinyId: ULong
): Result<GProUserInfo> { ): Result<GProUserInfo> {
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf88_1", 0xf88, 1, ProtoBuf.encodeToByteArray( val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf88_1", 0xf88, 1, Oidb0xf88Req(
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), 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, memberId = 0uL,
tinyId = memberTinyId, tinyId = memberTinyId,
guildId = guildId guildId = guildId
) ).toByteArray())
))
val body = oidb_sso.OIDBSSOPkg() val body = oidb_sso.OIDBSSOPkg()
if (respBuffer == null) { if (respBuffer == null) {
return Result.failure(Exception("unable to send packet")) return Result.failure(Exception("unable to send packet"))
} }
body.mergeFrom(respBuffer.slice(4)) body.mergeFrom(respBuffer.slice(4))
return runCatching { return runCatching {
ProtoBuf.decodeFromByteArray<Oidb0xf88Rsp>( body.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0xf88Rsp>().userInfo!!
body.bytes_bodybuffer.get().toByteArray()
).userInfo!!
} }
} }

View File

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

View File

@ -11,10 +11,8 @@ 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.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.msg.messageelement.toSegments 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.shamrock.helper.ContactHelper 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.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 protobuf.auto.toByteArray
import protobuf.message.longmsg.* import protobuf.message.longmsg.*
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine 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( val req = LongMsgReq(
sendInfo = SendLongMsgInfo( sendInfo = SendLongMsgInfo(
type = if (groupUin == null) 1 else 3, type = if (groupUin == null) 1 else 3,
uid = LongMsgUid(groupUin ?: uid), uid = LongMsgUid(groupUin ?: uid),
groupUin = groupUin?.toInt(), groupUin = groupUin?.toInt(),
payload = DeflateTools.gzip(ProtoBuf.encodeToByteArray(payload)) payload = DeflateTools.gzip(payload.toByteArray())
), ),
setting = LongMsgSettings( setting = LongMsgSettings(
field1 = 4, field1 = 4,
@ -258,9 +259,9 @@ internal object MsgSvc : BaseSvc() {
val buffer = sendBufferAW( val buffer = sendBufferAW(
"trpc.group.long_msg_interface.MsgService.SsoSendLongMsg", "trpc.group.long_msg_interface.MsgService.SsoSendLongMsg",
true, true,
ProtoBuf.encodeToByteArray(req) req.toByteArray()
) ?: return Result.failure(Exception("unable to upload multi message")) ) ?: 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) } return rsp.sendResult?.resId?.let { Result.success(it) }
?: Result.failure(Exception("unable to upload multi message")) ?: Result.failure(Exception("unable to upload multi message"))
} }
@ -282,14 +283,14 @@ internal object MsgSvc : BaseSvc() {
val buffer = sendBufferAW( val buffer = sendBufferAW(
"trpc.group.long_msg_interface.MsgService.SsoRecvLongMsg", "trpc.group.long_msg_interface.MsgService.SsoRecvLongMsg",
true, true,
ProtoBuf.encodeToByteArray(req) req.toByteArray()
) ?: return Result.failure(Exception("unable to get multi message")) ) ?: 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( val zippedPayload = DeflateTools.ungzip(
rsp.recvResult?.payload ?: return Result.failure(Exception("unable to get multi message")) rsp.recvResult?.payload ?: return Result.failure(Exception("unable to get multi message"))
) )
LogCenter.log(zippedPayload.toHexString(), Level.DEBUG) LogCenter.log(zippedPayload.toHexString(), Level.DEBUG)
val payload = ProtoBuf.decodeFromByteArray<LongMsgPayload>(zippedPayload) val payload = zippedPayload.decodeProtobuf<LongMsgPayload>()
payload.action?.forEach { payload.action?.forEach {
if (it.command == "MultiMsg") { if (it.command == "MultiMsg") {
return Result.success(it.data?.body?.map { msg -> 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.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.encodeToByteArray import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
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
@ -24,6 +24,7 @@ import protobuf.message.MessageHead
import protobuf.message.MessageBody import protobuf.message.MessageBody
import protobuf.push.MessagePush import protobuf.push.MessagePush
import mqq.app.MobileQQ import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import kotlin.coroutines.resume import kotlin.coroutines.resume
internal object PacketSvc: BaseSvc() { 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) { return withTimeoutOrNull(5000L) {
suspendCancellableCoroutine { suspendCancellableCoroutine {
AioListener.registerTemporaryMsgListener(msgSeq) { AioListener.registerTemporaryMsgListener(msgSeq) {

View File

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

View File

@ -26,4 +26,12 @@ sealed class ArkAppInfo(
signature = "7194d531cbe7960a22007b9f6bdaa38b", signature = "7194d531cbe7960a22007b9f6bdaa38b",
miniAppId = 1109937557 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()) sendOidb("OidbSvc.0xb77_9", 0xb77, 9, req.toByteArray())
} }
/*
suspend fun tryShareJsonMessage( suspend fun tryShareJsonMessage(
jsonString: String, jsonString: String,
arkAppInfo: ArkAppInfo = ArkAppInfo.DanMaKu, arkAppInfo: ArkAppInfo = ArkAppInfo.DanMaKu,
@ -96,5 +97,5 @@ internal object ArkMsgSvc: BaseSvc() {
} }
} ?: return Result.failure(Exception("unable to sign json")) } ?: return Result.failure(Exception("unable to sign json"))
return Result.success(signedJson) 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

@ -184,19 +184,20 @@ internal object MsgElementConverter {
element: MsgElement element: MsgElement
): MessageSegment { ): MessageSegment {
val image = element.picElement val image = element.picElement
val md5 = image.md5HexStr ?: image.fileName val md5 = (image.md5HexStr ?: image.fileName
.replace("{", "") .replace("{", "")
.replace("}", "") .replace("}", "")
.replace("-", "").split(".")[0] .replace("-", "").split(".")[0])
.uppercase()
ImageDB.getInstance().imageMappingDao().insert( ImageDB.getInstance().imageMappingDao().insert(
ImageMapping(md5.uppercase(), chatType, image.fileSize) ImageMapping(md5, chatType, image.fileSize)
) )
//LogCenter.log(image.toString()) //LogCenter.log(image.toString())
val originalUrl = image.originImageUrl ?: "" val originalUrl = image.originImageUrl ?: ""
//LogCenter.log({ "receive image: $image" }, Level.DEBUG) LogCenter.log({ "receive image: $image" }, Level.DEBUG)
return MessageSegment( return MessageSegment(
type = "image", type = "image",
@ -204,12 +205,37 @@ internal object MsgElementConverter {
"file" to md5, "file" to md5,
"url" to when (chatType) { "url" to when (chatType) {
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl( MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
originalUrl, originalUrl = originalUrl,
md5 md5 = md5,
fileId = image.fileUuid,
width = image.picWidth.toUInt(),
height = image.picHeight.toUInt(),
sha = "",
fileSize = image.fileSize.toULong(),
peer = peerId
) )
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(originalUrl, md5) MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGuildPicDownUrl(originalUrl, md5) originalUrl = originalUrl,
md5 = md5,
fileId = image.fileUuid,
width = image.picWidth.toUInt(),
height = image.picHeight.toUInt(),
sha = "",
fileSize = image.fileSize.toULong(),
peer = peerId,
)
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGuildPicDownUrl(
originalUrl = originalUrl,
md5 = md5,
fileId = image.fileUuid,
width = image.picWidth.toUInt(),
height = image.picHeight.toUInt(),
sha = "",
fileSize = image.fileSize.toULong(),
peer = peerId,
subPeer = subPeer
)
else -> throw UnsupportedOperationException("Not supported chat type: $chatType") else -> throw UnsupportedOperationException("Not supported chat type: $chatType")
}, },
"subType" to image.picSubType, "subType" to image.picSubType,

View File

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

View File

@ -14,7 +14,6 @@ import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.shamrock.utils.MD5 import moe.fuqiuluo.shamrock.utils.MD5
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
import mqq.app.AppRuntime import mqq.app.AppRuntime
import mqq.app.MobileQQ
import java.io.File import java.io.File
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.math.abs import kotlin.math.abs
@ -162,6 +161,17 @@ internal abstract class FileTransfer {
const val BUSI_TYPE_VIDEO_EMOTICON_PIC = 1022 const val BUSI_TYPE_VIDEO_EMOTICON_PIC = 1022
const val BUSI_TYPE_VIDEO_EMOTICON_VIDEO = 1021 const val BUSI_TYPE_VIDEO_EMOTICON_VIDEO = 1021
const val TRANSFILE_TYPE_PIC = 1
const val TRANSFILE_TYPE_PIC_EMO = 65538
const val TRANSFILE_TYPE_PIC_THUMB = 65537
const val TRANSFILE_TYPE_PISMA = 49
const val TRANSFILE_TYPE_RAWPIC = 131075
const val TRANSFILE_TYPE_PROFILE_COVER = 35
const val TRANSFILE_TYPE_PTT = 2
const val TRANSFILE_TYPE_PTT_SLICE_TO_TEXT = 327696
const val TRANSFILE_TYPE_QQHEAD_PIC = 131074
internal fun createMessageUniseq(time: Long = System.currentTimeMillis()): Long { internal fun createMessageUniseq(time: Long = System.currentTimeMillis()): Long {
var uniseq = (time / 1000).toInt().toLong() var uniseq = (time / 1000).toInt().toLong()
uniseq = uniseq shl 32 or abs(Random.nextInt()).toLong() uniseq = uniseq shl 32 or abs(Random.nextInt()).toLong()

View File

@ -6,12 +6,11 @@ import com.tencent.mobileqq.transfile.FileMsg
import com.tencent.mobileqq.transfile.api.IProtoReqManager import com.tencent.mobileqq.transfile.api.IProtoReqManager
import com.tencent.mobileqq.transfile.protohandler.RichProto import com.tencent.mobileqq.transfile.protohandler.RichProto
import com.tencent.mobileqq.transfile.protohandler.RichProtoProc import com.tencent.mobileqq.transfile.protohandler.RichProtoProc
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.ExperimentalSerializationApi 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.qqinterface.servlet.BaseSvc
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
import moe.fuqiuluo.shamrock.tools.hex2ByteArray import moe.fuqiuluo.shamrock.tools.hex2ByteArray
@ -19,7 +18,26 @@ import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.tools.toHexString import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.PlatformUtils import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
import moe.fuqiuluo.symbols.decodeProtobuf
import mqq.app.MobileQQ import mqq.app.MobileQQ
import protobuf.auto.toByteArray
import protobuf.oidb.TrpcOidb
import protobuf.oidb.cmd0x11c5.C2CUserInfo
import protobuf.oidb.cmd0x11c5.ChannelUserInfo
import protobuf.oidb.cmd0x11c5.ClientMeta
import protobuf.oidb.cmd0x11c5.CodecConfigReq
import protobuf.oidb.cmd0x11c5.CommonHead
import protobuf.oidb.cmd0x11c5.DownloadExt
import protobuf.oidb.cmd0x11c5.DownloadReq
import protobuf.oidb.cmd0x11c5.FileInfo
import protobuf.oidb.cmd0x11c5.FileType
import protobuf.oidb.cmd0x11c5.GroupUserInfo
import protobuf.oidb.cmd0x11c5.IndexNode
import protobuf.oidb.cmd0x11c5.MultiMediaReqHead
import protobuf.oidb.cmd0x11c5.NtV2RichMediaReq
import protobuf.oidb.cmd0x11c5.NtV2RichMediaRsp
import protobuf.oidb.cmd0x11c5.SceneInfo
import protobuf.oidb.cmd0x11c5.VideoDownloadExt
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ChannelInfo import protobuf.oidb.cmd0xfc2.Oidb0xfc2ChannelInfo
import protobuf.oidb.cmd0xfc2.Oidb0xfc2MsgApplyDownloadReq import protobuf.oidb.cmd0xfc2.Oidb0xfc2MsgApplyDownloadReq
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ReqBody import protobuf.oidb.cmd0xfc2.Oidb0xfc2ReqBody
@ -31,26 +49,14 @@ import tencent.im.oidb.oidb_sso
import kotlin.coroutines.resume import kotlin.coroutines.resume
private const val GPRO_PIC = "gchat.qpic.cn" private const val GPRO_PIC = "gchat.qpic.cn"
private const val GPRO_PIC_NT = "multimedia.nt.qq.com.cn" private const val MULTIMEDIA_DOMAIN = "multimedia.nt.qq.com.cn"
private const val C2C_PIC = "c2cpicdw.qpic.cn" private const val C2C_PIC = "c2cpicdw.qpic.cn"
internal object RichProtoSvc: BaseSvc() { internal object RichProtoSvc: BaseSvc() {
var multiMediaRKey = "CAQSKAB6JWENi5LMk0kc62l8Pm3Jn1dsLZHyRLAnNmHGoZ3y_gDZPqZt-64" private val requestId = atomic(2L)
/*@Deprecated("Use RichProtoSvc.getQQDns instead", ReplaceWith("getQQDns(domain)"))
fun getQQDns(domain: String) {
val bundle = Bundle()
bundle.putString("domain", "xxx")
bundle.putInt("businessType", 1)
val result = BinderMethodProxy
.callServer(QIPCClientHelper.getInstance().client, "InnerDnsModule", "reqDomain2IpList", bundle)
if (result.isSuccess) {
val ipList: ArrayList<IpData> = result.data.getParcelableArrayList("ip")!!
}
}*/
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String { suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, ProtoBuf.encodeToByteArray( val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, Oidb0xfc2ReqBody(
Oidb0xfc2ReqBody(
msgCmd = 1200, msgCmd = 1200,
msgBusType = 4202, msgBusType = 4202,
msgChannelInfo = Oidb0xfc2ChannelInfo( msgChannelInfo = Oidb0xfc2ChannelInfo(
@ -62,11 +68,13 @@ internal object RichProtoSvc: BaseSvc() {
fieldId = fileId, fieldId = fileId,
supportEncrypt = 0 supportEncrypt = 0
) )
) ).toByteArray()) ?: return ""
)) ?: return ""
val body = oidb_sso.OIDBSSOPkg() val body = oidb_sso.OIDBSSOPkg()
body.mergeFrom(buffer.slice(4)) body.mergeFrom(buffer.slice(4))
ProtoBuf.decodeFromByteArray<Oidb0xfc2RspBody>(body.bytes_bodybuffer.get().toByteArray()).msgApplyDownloadRsp?.let { body.bytes_bodybuffer
.get().toByteArray()
.decodeProtobuf<Oidb0xfc2RspBody>()
.msgApplyDownloadRsp?.let {
it.msgDownloadInfo?.let { it.msgDownloadInfo?.let {
return "https://${it.downloadDomain}${it.downloadUrl}&fname=$fileId&isthumb=0" return "https://${it.downloadDomain}${it.downloadUrl}&fname=$fileId&isthumb=0"
} }
@ -158,51 +166,194 @@ internal object RichProtoSvc: BaseSvc() {
} }
} }
fun getGroupPicDownUrl( suspend fun getGroupPicDownUrl(
originalUrl: String, originalUrl: String,
md5: String, md5: String,
peer: String = "",
fileId: String = "",
sha: String = "",
fileSize: ULong = 0uL,
width: UInt = 0u,
height: UInt = 0u
): String { ): String {
val isNtServer = originalUrl.startsWith("/download") val isNtServer = originalUrl.startsWith("/download")
val domain = if (isNtServer) GPRO_PIC_NT else GPRO_PIC val domain = if (isNtServer) MULTIMEDIA_DOMAIN else GPRO_PIC
if (originalUrl.isNotEmpty()) { if (originalUrl.isNotEmpty()) {
if (isNtServer && !originalUrl.contains("rkey=")) { if (isNtServer && !originalUrl.contains("rkey=")) {
return "https://$domain$originalUrl&rkey=$multiMediaRKey" getNtPicRKey(
fileId = fileId,
md5 = md5,
sha = sha,
fileSize = fileSize,
width = width,
height = height
) {
sceneType = 2u
grp = GroupUserInfo(peer.toULong())
}.onSuccess {
return "https://$domain$originalUrl$it"
}.onFailure {
LogCenter.log("getGroupPicDownUrl: ${it.stackTraceToString()}", Level.WARN)
}
} }
return "https://$domain$originalUrl" return "https://$domain$originalUrl"
} }
return "https://$domain/gchatpic_new/0/0-0-${md5.uppercase()}/0?term=2" return "https://$domain/gchatpic_new/0/0-0-${md5.uppercase()}/0?term=2"
} }
fun getC2CPicDownUrl( suspend fun getC2CPicDownUrl(
originalUrl: String, originalUrl: String,
md5: String md5: String,
peer: String = "",
fileId: String = "",
sha: String = "",
fileSize: ULong = 0uL,
width: UInt = 0u,
height: UInt = 0u
): String { ): String {
val isNtServer = originalUrl.startsWith("/download") val isNtServer = originalUrl.startsWith("/download")
val domain = if (isNtServer) GPRO_PIC_NT else C2C_PIC val domain = if (isNtServer) MULTIMEDIA_DOMAIN else C2C_PIC
if (originalUrl.isNotEmpty()) { if (originalUrl.isNotEmpty()) {
if (fileId.isNotEmpty()) getNtPicRKey(
fileId = fileId,
md5 = md5,
sha = sha,
fileSize = fileSize,
width = width,
height = height
) {
sceneType = 1u
c2c = C2CUserInfo(
accountType = 2u,
uid = ContactHelper.getUidByUinAsync(peer.toLong())
)
}.onSuccess {
if (isNtServer && !originalUrl.contains("rkey=")) { if (isNtServer && !originalUrl.contains("rkey=")) {
return "https://$domain$originalUrl&rkey=$multiMediaRKey" return "https://$domain$originalUrl$it"
}
}.onFailure {
LogCenter.log("getC2CPicDownUrl: ${it.stackTraceToString()}", Level.WARN)
}
if (isNtServer && !originalUrl.contains("rkey=")) {
return "https://$domain$originalUrl&rkey="
} }
return "https://$domain$originalUrl" return "https://$domain$originalUrl"
} }
return "https://$$domain/offpic_new/0/123-0-${md5.uppercase()}/0?term=2" return "https://$$domain/offpic_new/0/123-0-${md5}/0?term=2"
} }
fun getGuildPicDownUrl( suspend fun getGuildPicDownUrl(
originalUrl: String, originalUrl: String,
md5: String md5: String,
peer: String = "",
subPeer: String = "",
fileId: String = "",
sha: String = "",
fileSize: ULong = 0uL,
width: UInt = 0u,
height: UInt = 0u
): String { ): String {
val isNtServer = originalUrl.startsWith("/download") val isNtServer = originalUrl.startsWith("/download")
val domain = if (isNtServer) GPRO_PIC_NT else GPRO_PIC val domain = if (isNtServer) MULTIMEDIA_DOMAIN else GPRO_PIC
if (originalUrl.isNotEmpty()) { if (originalUrl.isNotEmpty()) {
if (isNtServer && !originalUrl.contains("rkey=")) { if (isNtServer && !originalUrl.contains("rkey=")) {
return "https://$domain$originalUrl&rkey=$multiMediaRKey" getNtPicRKey(
fileId = fileId,
md5 = md5,
sha = sha,
fileSize = fileSize,
width = width,
height = height
) {
sceneType = 3u
channel = ChannelUserInfo(peer.toULong(), subPeer.toULong(), 1u)
}.onSuccess {
return "https://$domain$originalUrl$it"
}.onFailure {
LogCenter.log("getGuildPicDownUrl: ${it.stackTraceToString()}", Level.WARN)
}
return "https://$domain$originalUrl&rkey="
} }
return "https://$domain$originalUrl" return "https://$domain$originalUrl"
} }
return "https://$domain/qmeetpic/0/0-0-${md5.uppercase()}/0?term=2" return "https://$domain/qmeetpic/0/0-0-${md5.uppercase()}/0?term=2"
} }
suspend fun getNtPicRKey(
fileId: String,
md5: String,
sha: String,
fileSize: ULong,
width: UInt,
height: UInt,
sceneBuilder: suspend SceneInfo.() -> Unit
): Result<String> {
runCatching {
val req = run {
NtV2RichMediaReq(
head = MultiMediaReqHead(
commonHead = CommonHead(
requestId = requestId.incrementAndGet().toULong(),
cmd = 200u
),
sceneInfo = SceneInfo(
requestType = 2u,
businessType = 1u,
).apply {
sceneBuilder()
},
clientMeta = ClientMeta(2u)
),
download = DownloadReq(
IndexNode(
FileInfo(
fileSize = fileSize,
md5 = md5.lowercase(),
sha1 = sha.lowercase(),
name = "${md5}.jpg",
fileType = FileType(
fileType = 1u,
picFormat = 1000u,
videoFormat = 0u,
voiceFormat = 0u
),
width = width,
height = height,
time = 0u,
original = 1u
),
fileUuid = fileId,
storeId = 1u,
uploadTime = 0u,
ttl = 0u,
subType = 0u,
storeAppId = 0u
),
DownloadExt(
video = VideoDownloadExt(
busiType = 0u,
subBusiType = 0u,
msgCodecConfig = CodecConfigReq(
platformChipinfo = "",
osVer = "",
deviceName = ""
),
flag = 1u
)
)
)
)
}.toByteArray()
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)?.slice(4)
buffer?.decodeProtobuf<TrpcOidb>()?.buffer?.decodeProtobuf<NtV2RichMediaRsp>()?.download?.rkeyParam?.let {
return Result.success(it)
}
}.onFailure {
return Result.failure(it)
}
return Result.failure(Exception("unable to get c2c nt pic"))
}
suspend fun getC2CVideoDownUrl( suspend fun getC2CVideoDownUrl(
peerId: String, peerId: String,
md5: ByteArray, md5: ByteArray,

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromByteArray import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.protobuf.ProtoBuf
import moe.fuqiuluo.qqinterface.servlet.GProSvc import moe.fuqiuluo.qqinterface.servlet.GProSvc
import moe.fuqiuluo.qqinterface.servlet.structures.GetGuildMemberListNextToken import moe.fuqiuluo.qqinterface.servlet.structures.GetGuildMemberListNextToken
import moe.fuqiuluo.qqinterface.servlet.structures.GuildMemberInfo 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.hex2ByteArray
import moe.fuqiuluo.shamrock.tools.toHexString import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.symbols.OneBotHandler import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.auto.toByteArray
@OneBotHandler("get_guild_member_list") @OneBotHandler("get_guild_member_list")
internal object GetGuildMemberList: IActionHandler() { 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 { 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( val result = GProSvc.getGuildMemberList(
guildId = guildId, guildId = guildId,
fetchAll = all, fetchAll = all,
@ -62,7 +64,7 @@ internal object GetGuildMemberList: IActionHandler() {
return ok(GetGuildMemberListResult( return ok(GetGuildMemberListResult(
members = members, members = members,
finish = nextToken.finish, finish = nextToken.finish,
nextToken = ProtoBuf.encodeToByteArray(nextToken).toHexString(), nextToken = nextToken.toByteArray().toHexString(),
), echo) ), echo)
} }

View File

@ -18,7 +18,7 @@ internal object GetImage: IActionHandler() {
return invoke(file, echo) return invoke(file, echo)
} }
operator fun invoke(file: String, echo: JsonElement = EmptyJsonString): String { suspend operator fun invoke(file: String, echo: JsonElement = EmptyJsonString): String {
val fileMd5 = file val fileMd5 = file
.replace("{", "") .replace("{", "")
.replace("}", "") .replace("}", "")

View File

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

View File

@ -13,7 +13,7 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray 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 kotlinx.serialization.protobuf.ProtoBuf
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
@ -31,6 +31,8 @@ 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.xposed.helper.PacketHandler import moe.fuqiuluo.shamrock.xposed.helper.PacketHandler
import moe.fuqiuluo.symbols.decode
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.message.MessageContent import protobuf.message.MessageContent
import protobuf.message.MessageHead import protobuf.message.MessageHead
import protobuf.message.MessageBody import protobuf.message.MessageBody
@ -56,7 +58,7 @@ internal object PrimitiveListener {
PacketHandler.register("trpc.msg.olpush.OlPushService.MsgPush") { _, buffer -> PacketHandler.register("trpc.msg.olpush.OlPushService.MsgPush") { _, buffer ->
GlobalScope.launch { GlobalScope.launch {
try { try {
val push = ProtoBuf.decodeFromByteArray<MessagePush>(buffer.slice(4)) val push = buffer.slice(4).decodeProtobuf<MessagePush>()
onMsgPush(push) onMsgPush(push)
} catch (e: Exception) { } catch (e: Exception) {
LogCenter.log(e.stackTraceToString(), Level.WARN) LogCenter.log(e.stackTraceToString(), Level.WARN)
@ -109,11 +111,11 @@ internal object PrimitiveListener {
} }
private fun onGroupMessage(msgTime: Long, body: MessageBody) { private fun onGroupMessage(msgTime: Long, body: MessageBody) {
runCatching { /*runCatching {
body.rich?.elements?.filter { body.rich?.elements?.filter {
it.comm != null && it.comm!!.type == 48 it.comm != null && it.comm!!.type == 48
}?.map { }?.map {
ProtoBuf.decodeFromByteArray<RichMediaForPicData>(it.comm!!.data!!) it.comm!!.data!!.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 {
@ -124,12 +126,11 @@ internal object PrimitiveListener {
} }
} }
} }
}*/
}
} }
private suspend fun onC2CPoke(msgTime: Long, richMsg: MessageBody) { 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 if (event.params == null) return
val params = event.params!!.associate { val params = event.params!!.associate {
@ -156,7 +157,7 @@ internal object PrimitiveListener {
clientInfo: MessagePushClientInfo, clientInfo: MessagePushClientInfo,
richMsg: MessageBody richMsg: MessageBody
) { ) {
val event = ProtoBuf.decodeFromByteArray<FriendApplyEvent>(richMsg.rawBuffer!!) val event = richMsg.rawBuffer!!.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
@ -233,15 +234,15 @@ internal object PrimitiveListener {
private suspend fun onGroupUniqueTitleChange(msgTime: Long, richMsg: MessageBody) { private suspend fun onGroupUniqueTitleChange(msgTime: Long, richMsg: MessageBody) {
val event = runCatching { val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!) richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.readBuf32Long() readPacket.readBuf32Long()
readPacket.discardExact(1) readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also { readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release() readPacket.release()
}) }.decodeProtobuf<GroupCommonTipsEvent>()
} }
val groupId = event.groupCode.toLong() val groupId = event.groupCode.toLong()
val detail = event.uniqueTitleChangeDetail!!.first() val detail = event.uniqueTitleChangeDetail!!.first()
@ -279,15 +280,15 @@ internal object PrimitiveListener {
) { ) {
if (clientInfo == null) return if (clientInfo == null) return
val event = runCatching { val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!) richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.readBuf32Long() readPacket.readBuf32Long()
readPacket.discardExact(1) readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also { readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release() readPacket.release()
}) }.decodeProtobuf<GroupCommonTipsEvent>()
} }
val groupId = event.groupCode.toLong() val groupId = event.groupCode.toLong()
val detail = event.essenceMsgInfo!!.first() val detail = event.essenceMsgInfo!!.first()
@ -326,15 +327,15 @@ internal object PrimitiveListener {
private suspend fun onGroupPokeAndGroupSign(time: Long, richMsg: MessageBody) { private suspend fun onGroupPokeAndGroupSign(time: Long, richMsg: MessageBody) {
val event = runCatching { val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!) richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.discardExact(4) readPacket.discardExact(4)
readPacket.discardExact(1) readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also { readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release() readPacket.release()
}) }.decodeProtobuf<GroupCommonTipsEvent>()
} }
val groupId = event.groupCode.toLong() val groupId = event.groupCode.toLong()
val detail = event.baseTips!!.first() val detail = event.baseTips!!.first()
@ -379,7 +380,7 @@ internal object PrimitiveListener {
} }
private suspend fun onC2CRecall(time: Long, richMsg: MessageBody) { 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 head = event.head!!
val operationUid = head.operator!! val operationUid = head.operator!!
@ -404,7 +405,7 @@ internal object PrimitiveListener {
} }
private suspend fun onGroupMemIncreased(time: Long, richMsg: MessageBody) { 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 groupCode = event.groupCode
val targetUid = event.memberUid val targetUid = event.memberUid
val type = event.type val type = event.type
@ -434,7 +435,7 @@ internal object PrimitiveListener {
} }
private suspend fun onGroupMemberDecreased(time: Long, richMsg: MessageBody) { 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 groupCode = event.groupCode
val targetUid = event.memberUid val targetUid = event.memberUid
val type = event.type val type = event.type
@ -467,7 +468,7 @@ internal object PrimitiveListener {
} }
private suspend fun onGroupAdminChange(msgTime: Long, richMsg: MessageBody) { 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 val groupCode = event.groupCode
if (event.operation == null) return if (event.operation == null) return
val operation = event.operation!! val operation = event.operation!!
@ -494,7 +495,7 @@ internal object PrimitiveListener {
} }
private suspend fun onGroupBan(msgTime: Long, richMsg: MessageBody) { 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 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
@ -520,14 +521,14 @@ internal object PrimitiveListener {
private suspend fun onGroupRecall(time: Long, richMsg: MessageBody) { private suspend fun onGroupRecall(time: Long, richMsg: MessageBody) {
val event = runCatching { val event = runCatching {
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(richMsg.rawBuffer!!) richMsg.rawBuffer!!.decodeProtobuf<GroupCommonTipsEvent>()
}.getOrElse { }.getOrElse {
val readPacket = ByteReadPacket(richMsg.rawBuffer!!) val readPacket = ByteReadPacket(richMsg.rawBuffer!!)
readPacket.discardExact(4) readPacket.discardExact(4)
readPacket.discardExact(1) readPacket.discardExact(1)
ProtoBuf.decodeFromByteArray<GroupCommonTipsEvent>(readPacket.readBytes(readPacket.readShort().toInt()).also { readPacket.readBytes(readPacket.readShort().toInt()).also {
readPacket.release() readPacket.release()
}) }.decodeProtobuf<GroupCommonTipsEvent>()
} }
val groupCode = event.groupCode.toLong() val groupCode = event.groupCode.toLong()
val detail = event.recallDetails!! val detail = event.recallDetails!!
@ -555,7 +556,7 @@ internal object PrimitiveListener {
private suspend fun onGroupApply(time: Long, contentHead: MessageContent, richMsg: MessageBody) { private suspend fun onGroupApply(time: Long, contentHead: MessageContent, richMsg: MessageBody) {
when (contentHead.msgType) { when (contentHead.msgType) {
84 -> { 84 -> {
val event = ProtoBuf.decodeFromByteArray<GroupApplyEvent>(richMsg.rawBuffer!!) val event = richMsg.rawBuffer!!.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,7 +588,7 @@ internal object PrimitiveListener {
} }
} }
528 -> { 528 -> {
val event = ProtoBuf.decodeFromByteArray<GroupInvitedApplyEvent>(richMsg.rawBuffer!!) val event = richMsg.rawBuffer!!.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,7 +625,7 @@ internal object PrimitiveListener {
} }
private suspend fun onInviteGroup(time: Long, msgHead: MessageHead, richMsg: MessageBody) { 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 groupCode = event.groupCode
val invitorUid = event.inviterUid val invitorUid = event.inviterUid
val invitor = ContactHelper.getUinByUidAsync(invitorUid).toLong() val invitor = ContactHelper.getUinByUidAsync(invitorUid).toLong()