6 Commits

Author SHA1 Message Date
1afc0ac6a6 Shamrock: 修复服务器TLS异常
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-03-10 07:57:23 +08:00
638bf72392 Shamrock: 修复配置文件下发
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-03-10 07:44:02 +08:00
07364c8298 Shamrock: 修复kritor构建错误
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-03-10 02:26:53 +08:00
ee6e13a5bb Shamrock: 修正频道proto文件错误
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-03-10 01:58:18 +08:00
c3934778c7 Shamrock: 修正频道proto文件错误
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-03-10 01:56:02 +08:00
13a49dd70b Shamrock: 添加对kritor的依赖
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-03-10 01:00:20 +08:00
25 changed files with 610 additions and 24 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "kritor"]
path = kritor
url = https://github.com/KarinJS/kritor

View File

@ -9,6 +9,6 @@ java {
} }
dependencies { dependencies {
implementation(DEPENDENCY_PROTOBUF) //implementation(DEPENDENCY_PROTOBUF)
implementation(kotlinx("serialization-protobuf", "1.6.2")) implementation(kotlinx("serialization-protobuf", "1.6.2"))
} }

View File

@ -0,0 +1,7 @@
package kritor.service
@Target(AnnotationTarget.FUNCTION)
annotation class Grpc(
val serviceName: String,
val funcName: String
)

View File

@ -5,6 +5,8 @@ import kotlinx.serialization.protobuf.ProtoBuf
import kotlin.reflect.KClass import kotlin.reflect.KClass
val EMPTY_BYTE_ARRAY = ByteArray(0)
interface Protobuf<T: Protobuf<T>> interface Protobuf<T: Protobuf<T>>
inline fun <reified T: Protobuf<T>> ByteArray.decodeProtobuf(to: KClass<T>? = null): T { inline fun <reified T: Protobuf<T>> ByteArray.decodeProtobuf(to: KClass<T>? = null): T {

View File

@ -18,12 +18,17 @@ internal object InitHandler: ModuleHandler() {
val maps = hashMapOf<String, Any?>() val maps = hashMapOf<String, Any?>()
RPCPort.update(context, maps)
RPCAddress.update(context, maps)
ForceTablet.update(context, maps)
ActiveRPC.update(context, maps) ActiveRPC.update(context, maps)
AliveReply.update(context, maps)
AntiJvmTrace.update(context, maps)
DebugMode.update(context, maps)
EnableOldBDH.update(context, maps)
EnableSelfMessage.update(context, maps)
ForceTablet.update(context, maps)
PassiveRPC.update(context, maps) PassiveRPC.update(context, maps)
ResourceGroup.update(context, maps) ResourceGroup.update(context, maps)
RPCAddress.update(context, maps)
RPCPort.update(context, maps)
callback(context, 1, maps) callback(context, 1, maps)
} }

View File

@ -7,9 +7,6 @@ val DEPENDENCY_ANDROIDX = arrayOf(
"androidx.activity:activity-compose:1.7.2", "androidx.activity:activity-compose:1.7.2",
) )
const val DEPENDENCY_PROTOBUF = "com.google.protobuf:protobuf-java:3.24.0"
fun room(name: String) = "androidx.room:room-$name:${Versions.roomVersion}" fun room(name: String) = "androidx.room:room-$name:${Versions.roomVersion}"
fun kotlinx(name: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$name:$version" fun kotlinx(name: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$name:$version"

1
kritor Submodule

Submodule kritor added at f4fa15754e

View File

@ -15,7 +15,7 @@ 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(DEPENDENCY_PROTOBUF)
implementation(kotlinx("serialization-protobuf", "1.6.2")) 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

@ -37,7 +37,7 @@ android {
} }
dependencies { dependencies {
implementation(DEPENDENCY_PROTOBUF) //implementation(DEPENDENCY_PROTOBUF)
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"))

View File

@ -1,7 +1,7 @@
@file:OptIn(ExperimentalSerializationApi::class) @file:OptIn(ExperimentalSerializationApi::class)
package protobuf.oidb.cmd0x11c5 package protobuf.oidb.cmd0x11c5
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY import moe.fuqiuluo.symbols.EMPTY_BYTE_ARRAY
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

View File

@ -1,6 +1,6 @@
package protobuf.oidb.cmd0x388 package protobuf.oidb.cmd0x388
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY import moe.fuqiuluo.symbols.EMPTY_BYTE_ARRAY
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import moe.fuqiuluo.symbols.Protobuf import moe.fuqiuluo.symbols.Protobuf

View File

@ -2,7 +2,7 @@
package protobuf.oidb.cmd0x388 package protobuf.oidb.cmd0x388
import com.google.protobuf.Internal.EMPTY_BYTE_ARRAY import moe.fuqiuluo.symbols.EMPTY_BYTE_ARRAY
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

View File

@ -39,3 +39,6 @@ include(
include(":protobuf") include(":protobuf")
include(":processor") include(":processor")
include(":annotations") include(":annotations")
include(":kritor")
project(":kritor").projectDir = file("kritor/protos")

View File

@ -5,6 +5,7 @@ plugins {
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id("kotlin-kapt") id("kotlin-kapt")
id("com.google.devtools.ksp") version "1.9.22-1.0.17" id("com.google.devtools.ksp") version "1.9.22-1.0.17"
id("com.google.protobuf") version "0.9.4"
kotlin("plugin.serialization") version "1.9.22" kotlin("plugin.serialization") version "1.9.22"
} }
@ -63,6 +64,8 @@ dependencies {
compileOnly ("de.robv.android.xposed:api:82") compileOnly ("de.robv.android.xposed:api:82")
compileOnly (project(":qqinterface")) compileOnly (project(":qqinterface"))
protobuf(project(":kritor"))
implementation(project(":protobuf")) implementation(project(":protobuf"))
implementation(project(":annotations")) implementation(project(":annotations"))
ksp(project(":processor")) ksp(project(":processor"))
@ -72,7 +75,7 @@ dependencies {
DEPENDENCY_ANDROIDX.forEach { DEPENDENCY_ANDROIDX.forEach {
implementation(it) implementation(it)
} }
implementation(DEPENDENCY_PROTOBUF) //implementation(DEPENDENCY_PROTOBUF)
implementation(room("runtime")) implementation(room("runtime"))
kapt(room("compiler")) kapt(room("compiler"))
@ -84,7 +87,12 @@ dependencies {
implementation(ktor("client", "core")) implementation(ktor("client", "core"))
implementation(ktor("client", "okhttp")) implementation(ktor("client", "okhttp"))
implementation(ktor("serialization", "kotlinx-json")) implementation(ktor("serialization", "kotlinx-json"))
implementation(ktor("network", "tls-certificates"))
implementation("io.grpc:grpc-stub:1.62.2")
implementation("io.grpc:grpc-protobuf-lite:1.62.2")
implementation("com.google.protobuf:protobuf-kotlin-lite:3.25.3")
implementation("io.grpc:grpc-kotlin-stub:1.4.1")
implementation("io.grpc:grpc-okhttp:1.62.2")
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.ext:junit:1.1.5")
@ -92,3 +100,46 @@ dependencies {
androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01")) androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4") androidTestImplementation("androidx.compose.ui:ui-test-junit4")
} }
tasks.withType<KotlinCompile>().all {
kotlinOptions {
freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn")
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.25.3"
}
plugins {
create("java") {
artifact = "io.grpc:protoc-gen-grpc-java:1.62.2"
}
create("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:1.62.2"
}
create("grpckt") {
artifact = "io.grpc:protoc-gen-grpc-kotlin:1.4.1:jdk8@jar"
}
}
generateProtoTasks {
all().forEach {
it.plugins {
create("java") {
option("lite")
}
create("grpc") {
option("lite")
}
create("grpckt") {
option("lite")
}
}
it.builtins {
create("kotlin") {
option("lite")
}
}
}
}
}

View File

@ -0,0 +1,43 @@
# Shamrock Config
# 资源上传群组
resource_group=883536416
# 强制使用平板模式
force_tablet=false
# 被动反向RPC开关
passive_rpc=false
# 被动反向RPC地址
rpc_address=
# 第一个被动RPC鉴权token
rpc_address.ticket=
# 如果有多个请使用
# 我是第二个地址
#rpc_address.1=
# 第二个被动RPC鉴权token
#rpc_address.1.ticket=
# 主动正向RPC开关
active_rpc=false
# 主动正向RPC端口
rpc_port=5700
# 主动RPC鉴权token
active_ticket=
# 多鉴权token支持
# 第二个主动RPC鉴权token
#active_ticket.1=
# 自回复开关
#alive_reply=false
# 自回复消息
enable_self_message=false
# 旧BDH兼容开关
enable_old_bdh=false
# 反JVM调用栈跟踪
anti_jvm_trace=true
# 调试模式
#debug=false

View File

@ -0,0 +1,33 @@
@file:OptIn(ExperimentalCoroutinesApi::class)
package kritor.server
import io.grpc.Grpc
import io.grpc.InsecureServerCredentials
import io.grpc.ServerBuilder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kritor.service.*
import moe.fuqiuluo.shamrock.helper.LogCenter
import kotlin.coroutines.CoroutineContext
class KritorServer(
private val port: Int
): CoroutineScope {
private val server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
.addService(Authentication)
.build()!!
fun start(block: Boolean = false) {
LogCenter.log("KritorServer started at port $port.")
server.start()
if (block) {
server.awaitTermination()
}
}
override val coroutineContext: CoroutineContext =
Dispatchers.IO.limitedParallelism(12)
}

View File

@ -0,0 +1,49 @@
package kritor.service
import io.kritor.AuthCode
import io.kritor.AuthReq
import io.kritor.AuthRsp
import io.kritor.AuthenticationGrpcKt
import io.kritor.authRsp
import moe.fuqiuluo.shamrock.config.ActiveTicket
import moe.fuqiuluo.shamrock.config.ShamrockConfig
import qq.service.QQInterfaces
object Authentication: AuthenticationGrpcKt.AuthenticationCoroutineImplBase() {
@Grpc("Authentication", "Auth")
override suspend fun auth(request: AuthReq): AuthRsp {
if (QQInterfaces.app.account != request.account) {
return authRsp {
code = AuthCode.NO_ACCOUNT
msg = "No such account"
}
}
val activeTicketName = ActiveTicket.name()
var index = 0
while (true) {
val ticket = ShamrockConfig.getProperty(activeTicketName + if (index == 0) "" else ".$index", null)
if (ticket.isNullOrEmpty()) {
if (index == 0) {
return authRsp {
code = AuthCode.OK
msg = "OK"
}
} else {
break
}
} else if (ticket == request.ticket) {
return authRsp {
code = AuthCode.OK
msg = "OK"
}
}
index++
}
return authRsp {
code = AuthCode.NO_TICKET
msg = "Invalid ticket"
}
}
}

View File

@ -0,0 +1,7 @@
package moe.fuqiuluo.shamrock.config
object ActiveTicket: ConfigKey<String>() {
override fun name(): String = "active_ticket"
override fun default(): String = ""
}

View File

@ -10,3 +10,6 @@ abstract class ConfigKey<T> {
} }
} }
internal inline fun <reified Type, reified T: ConfigKey<Type>> T.get(): Type {
return ShamrockConfig[this]
}

View File

@ -1,6 +1,8 @@
package moe.fuqiuluo.shamrock.config package moe.fuqiuluo.shamrock.config
import android.content.Intent import android.content.Intent
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader.moduleLoader
import mqq.app.MobileQQ import mqq.app.MobileQQ
import java.util.Properties import java.util.Properties
@ -12,15 +14,28 @@ private val configFile = configDir.resolve("config.prop")
private val configKeys = setOf( private val configKeys = setOf(
ActiveRPC, ActiveRPC,
AntiJvmTrace,
ForceTablet, ForceTablet,
PassiveRPC, PassiveRPC,
ResourceGroup, ResourceGroup,
RPCAddress, RPCAddress,
RPCPort RPCPort,
) )
internal object ShamrockConfig: Properties() { internal object ShamrockConfig: Properties() {
init { init {
if (!configFile.exists()) {
moduleLoader.getResourceAsStream("assets/config.properties")?.use {
configDir.resolve("default.prop").outputStream().use { output ->
it.copyTo(output)
}
}
moduleLoader.getResourceAsStream("assets/config.properties")?.use {
configFile.outputStream().use { output ->
it.copyTo(output)
}
}
}
if (configFile.exists()) configFile.inputStream().use { if (configFile.exists()) configFile.inputStream().use {
load(it) load(it)
} }
@ -39,13 +54,34 @@ internal object ShamrockConfig: Properties() {
fun updateConfig(intent: Intent? = null) { fun updateConfig(intent: Intent? = null) {
intent?.let { intent?.let {
for (key in configKeys) { for (key in configKeys) {
when (key.default()) {
is String -> {
val value = intent.getStringExtra(key.name()) val value = intent.getStringExtra(key.name())
if (value != null) setProperty(key.name(), value) if (value != null) setProperty(key.name(), value)
} }
is Boolean -> {
val value = intent.getBooleanExtra(key.name(), key.default() as Boolean)
setProperty(key.name(), value.toString())
}
is Int -> {
val value = intent.getIntExtra(key.name(), key.default() as Int)
setProperty(key.name(), value.toString())
}
is Long -> {
val value = intent.getLongExtra(key.name(), key.default() as Long)
setProperty(key.name(), value.toString())
}
}
}
if (getProperty(ActiveTicket.name()).isNullOrEmpty()) {
setProperty(ActiveTicket.name(), "") // 初始化ticket
}
setProperty(IsInit.name(), "true") setProperty(IsInit.name(), "true")
} }
configFile.outputStream().use { configFile.outputStream().use {
store(it, "Shamrock Config ${System.currentTimeMillis()}") store(it, "Shamrock Config")
} }
} }

View File

@ -10,6 +10,7 @@ import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.hookMethod import moe.fuqiuluo.shamrock.tools.hookMethod
import moe.fuqiuluo.shamrock.utils.PlatformUtils import moe.fuqiuluo.shamrock.utils.PlatformUtils
import qq.service.internals.AioListener
import qq.service.internals.msgService import qq.service.internals.msgService
internal object NTServiceFetcher { internal object NTServiceFetcher {
@ -58,7 +59,7 @@ internal object NTServiceFetcher {
try { try {
LogCenter.log("Register MSG listener successfully.") LogCenter.log("Register MSG listener successfully.")
//msgService.addMsgListener(AioListener) msgService.addMsgListener(AioListener)
// 接口缺失 暂不使用 // 接口缺失 暂不使用
//groupService.addKernelGroupListener(GroupEventListener) //groupService.addKernelGroupListener(GroupEventListener)

View File

@ -4,12 +4,38 @@ package moe.fuqiuluo.shamrock.xposed.actions
import android.content.Context import android.content.Context
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kritor.server.KritorServer
import moe.fuqiuluo.shamrock.config.ActiveRPC
import moe.fuqiuluo.shamrock.config.RPCPort
import moe.fuqiuluo.shamrock.config.ShamrockConfig
import moe.fuqiuluo.shamrock.config.get
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.symbols.Process import moe.fuqiuluo.symbols.Process
import moe.fuqiuluo.symbols.XposedHook import moe.fuqiuluo.symbols.XposedHook
private lateinit var server: KritorServer
@XposedHook(Process.MAIN, priority = 10) @XposedHook(Process.MAIN, priority = 10)
internal class InitRemoteService : IAction { internal class InitRemoteService : IAction {
override fun invoke(ctx: Context) { override fun invoke(ctx: Context) {
GlobalScope.launch {
runCatching {
if (ActiveRPC.get()) {
if (!::server.isInitialized) {
server = KritorServer(RPCPort.get())
server.start()
}
} else {
LogCenter.log("ActiveRPC is disabled, KritorServer will not be started.")
}
}.onFailure {
LogCenter.log("Start RPC failed: ${it.message}", Level.ERROR)
}
}
} }
} }

View File

@ -34,8 +34,6 @@ internal object NativeLoader {
XposedBridge.log("[Shamrock] 反射检测到 Android x86") XposedBridge.log("[Shamrock] 反射检测到 Android x86")
true true
} else false } else false
}.onFailure {
XposedBridge.log("[Shamrock] ${it.stackTraceToString()}")
}.getOrElse { false } }.getOrElse { false }
private fun getLibFilePath(name: String): String { private fun getLibFilePath(name: String): String {

View File

@ -0,0 +1,314 @@
package qq.service.internals
import com.tencent.qqnt.kernel.nativeinterface.BroadcastHelperTransNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.Contact
import com.tencent.qqnt.kernel.nativeinterface.ContactMsgBoxInfo
import com.tencent.qqnt.kernel.nativeinterface.CustomWithdrawConfig
import com.tencent.qqnt.kernel.nativeinterface.DevInfo
import com.tencent.qqnt.kernel.nativeinterface.DownloadRelateEmojiResultInfo
import com.tencent.qqnt.kernel.nativeinterface.EmojiNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.EmojiResourceInfo
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.FirstViewDirectMsgNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.FirstViewGroupGuildInfo
import com.tencent.qqnt.kernel.nativeinterface.FreqLimitInfo
import com.tencent.qqnt.kernel.nativeinterface.GroupFileListResult
import com.tencent.qqnt.kernel.nativeinterface.GroupGuildNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.GroupItem
import com.tencent.qqnt.kernel.nativeinterface.GuildInteractiveNotificationItem
import com.tencent.qqnt.kernel.nativeinterface.GuildMsgAbFlag
import com.tencent.qqnt.kernel.nativeinterface.GuildNotificationAbstractInfo
import com.tencent.qqnt.kernel.nativeinterface.HitRelatedEmojiWordsResult
import com.tencent.qqnt.kernel.nativeinterface.IKernelMsgListener
import com.tencent.qqnt.kernel.nativeinterface.ImportOldDbMsgNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.InputStatusInfo
import com.tencent.qqnt.kernel.nativeinterface.KickedInfo
import com.tencent.qqnt.kernel.nativeinterface.MsgAbstract
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
import com.tencent.qqnt.kernel.nativeinterface.MsgSetting
import com.tencent.qqnt.kernel.nativeinterface.RecvdOrder
import com.tencent.qqnt.kernel.nativeinterface.RelatedWordEmojiInfo
import com.tencent.qqnt.kernel.nativeinterface.SearchGroupFileResult
import com.tencent.qqnt.kernel.nativeinterface.TabStatusInfo
import com.tencent.qqnt.kernel.nativeinterface.TempChatInfo
import com.tencent.qqnt.kernel.nativeinterface.UnreadCntInfo
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
object AioListener: IKernelMsgListener {
override fun onRecvMsg(arrayList: ArrayList<MsgRecord>?) {
}
override fun onMsgRecall(chatType: Int, peerId: String, msgId: Long) {
LogCenter.log("onMsgRecall($chatType, $peerId, $msgId)")
}
override fun onAddSendMsg(record: MsgRecord) {
}
override fun onMsgInfoListUpdate(msgList: ArrayList<MsgRecord>?) {
}
override fun onTempChatInfoUpdate(tempChatInfo: TempChatInfo) {
}
override fun onMsgAbstractUpdate(arrayList: ArrayList<MsgAbstract>?) {
//arrayList?.forEach {
// LogCenter.log("onMsgAbstractUpdate($it)", Level.WARN)
//}
}
override fun onRecvMsgSvrRspTransInfo(
j2: Long,
contact: Contact?,
i2: Int,
i3: Int,
str: String?,
bArr: ByteArray?
) {
LogCenter.log("onRecvMsgSvrRspTransInfo($j2, $contact, $i2, $i3, $str)", Level.DEBUG)
}
override fun onRecvS2CMsg(arrayList: ArrayList<Byte>?) {
LogCenter.log("onRecvS2CMsg(${arrayList.toString()})", Level.DEBUG)
}
override fun onRecvSysMsg(arrayList: ArrayList<Byte>?) {
LogCenter.log("onRecvSysMsg(${arrayList.toString()})", Level.DEBUG)
}
override fun onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: BroadcastHelperTransNotifyInfo?) {}
override fun onBroadcastHelperProgerssUpdate(broadcastHelperTransNotifyInfo: BroadcastHelperTransNotifyInfo?) {}
override fun onChannelFreqLimitInfoUpdate(
contact: Contact?,
z: Boolean,
freqLimitInfo: FreqLimitInfo?
) {
}
override fun onContactUnreadCntUpdate(unreadMap: HashMap<Int, HashMap<String, UnreadCntInfo>>) {
// 推送未读消息数量
}
override fun onCustomWithdrawConfigUpdate(customWithdrawConfig: CustomWithdrawConfig?) {
LogCenter.log("onCustomWithdrawConfigUpdate: " + customWithdrawConfig.toString(), Level.DEBUG)
}
override fun onDraftUpdate(contact: Contact?, arrayList: ArrayList<MsgElement>?, j2: Long) {
LogCenter.log("onDraftUpdate: " + contact.toString() + "|" + arrayList + "|" + j2.toString(), Level.DEBUG)
}
override fun onEmojiDownloadComplete(emojiNotifyInfo: EmojiNotifyInfo?) {
}
override fun onEmojiResourceUpdate(emojiResourceInfo: EmojiResourceInfo?) {
}
override fun onFeedEventUpdate(firstViewDirectMsgNotifyInfo: FirstViewDirectMsgNotifyInfo?) {
}
override fun onFileMsgCome(arrayList: ArrayList<MsgRecord>?) {
}
override fun onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: FirstViewDirectMsgNotifyInfo?) {
}
override fun onFirstViewGroupGuildMapping(arrayList: ArrayList<FirstViewGroupGuildInfo>?) {
}
override fun onGrabPasswordRedBag(
i2: Int,
str: String?,
i3: Int,
recvdOrder: RecvdOrder?,
msgRecord: MsgRecord?
) {
}
override fun onKickedOffLine(kickedInfo: KickedInfo?) {
LogCenter.log("onKickedOffLine($kickedInfo)")
}
override fun onRichMediaUploadComplete(notifyInfo: FileTransNotifyInfo) {
LogCenter.log({ "[BDH] 资源上传完成(${notifyInfo.trasferStatus}, ${notifyInfo.fileId}, ${notifyInfo.msgId}, ${notifyInfo.commonFileInfo})" }, Level.DEBUG)
}
override fun onRecvOnlineFileMsg(arrayList: ArrayList<MsgRecord>?) {
LogCenter.log(("onRecvOnlineFileMsg" + arrayList?.joinToString { ", " }), Level.DEBUG)
}
override fun onRichMediaDownloadComplete(fileTransNotifyInfo: FileTransNotifyInfo) {
}
override fun onRichMediaProgerssUpdate(fileTransNotifyInfo: FileTransNotifyInfo) {
}
override fun onSearchGroupFileInfoUpdate(searchGroupFileResult: SearchGroupFileResult?) {
LogCenter.log("onSearchGroupFileInfoUpdate($searchGroupFileResult)", Level.DEBUG)
}
override fun onGroupFileInfoAdd(groupItem: GroupItem?) {
LogCenter.log("onGroupFileInfoAdd: " + groupItem.toString(), Level.DEBUG)
}
override fun onGroupFileInfoUpdate(groupFileListResult: GroupFileListResult?) {
LogCenter.log("onGroupFileInfoUpdate: " + groupFileListResult.toString(), Level.DEBUG)
}
override fun onGroupGuildUpdate(groupGuildNotifyInfo: GroupGuildNotifyInfo?) {
LogCenter.log("onGroupGuildUpdate: " + groupGuildNotifyInfo.toString(), Level.DEBUG)
}
override fun onGroupTransferInfoAdd(groupItem: GroupItem?) {
LogCenter.log("onGroupTransferInfoAdd: " + groupItem.toString(), Level.DEBUG)
}
override fun onGroupTransferInfoUpdate(groupFileListResult: GroupFileListResult?) {
LogCenter.log("onGroupTransferInfoUpdate: " + groupFileListResult.toString(), Level.DEBUG)
}
override fun onGuildInteractiveUpdate(guildInteractiveNotificationItem: GuildInteractiveNotificationItem?) {
}
override fun onGuildMsgAbFlagChanged(guildMsgAbFlag: GuildMsgAbFlag?) {
}
override fun onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: GuildNotificationAbstractInfo?) {
}
override fun onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: DownloadRelateEmojiResultInfo?) {
}
override fun onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: HitRelatedEmojiWordsResult?) {
}
override fun onHitRelatedEmojiResult(relatedWordEmojiInfo: RelatedWordEmojiInfo?) {
}
override fun onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: ImportOldDbMsgNotifyInfo?) {
}
override fun onInputStatusPush(inputStatusInfo: InputStatusInfo?) {
}
override fun onLineDev(devList: ArrayList<DevInfo>?) {
//LogCenter.log("onLineDev($arrayList)")
}
override fun onLogLevelChanged(newLevel: Long) {
}
override fun onMsgBoxChanged(arrayList: ArrayList<ContactMsgBoxInfo>?) {
}
override fun onMsgDelete(contact: Contact?, arrayList: ArrayList<Long>?) {
}
override fun onMsgEventListUpdate(hashMap: HashMap<String, ArrayList<Long>>?) {
}
override fun onMsgInfoListAdd(arrayList: ArrayList<MsgRecord>?) {
}
override fun onMsgQRCodeStatusChanged(i2: Int) {
}
override fun onMsgSecurityNotify(msgRecord: MsgRecord?) {
LogCenter.log("onMsgSecurityNotify($msgRecord)")
}
override fun onMsgSettingUpdate(msgSetting: MsgSetting?) {
}
override fun onNtFirstViewMsgSyncEnd() {
}
override fun onNtMsgSyncEnd() {
LogCenter.log("NTKernel同步消息完成", Level.DEBUG)
}
override fun onNtMsgSyncStart() {
LogCenter.log("NTKernel同步消息开始", Level.DEBUG)
}
override fun onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: FirstViewDirectMsgNotifyInfo?) {
}
override fun onRecvGroupGuildFlag(i2: Int) {
}
override fun onRecvUDCFlag(i2: Int) {
LogCenter.log("onRecvUDCFlag($i2)", Level.DEBUG)
}
override fun onSendMsgError(j2: Long, contact: Contact?, i2: Int, str: String?) {
LogCenter.log("onSendMsgError($j2, $contact, $j2, $str)", Level.DEBUG)
}
override fun onSysMsgNotification(i2: Int, j2: Long, j3: Long, arrayList: ArrayList<Byte>?) {
LogCenter.log("onSysMsgNotification($i2, $j2, $j3, $arrayList)", Level.DEBUG)
}
override fun onUnreadCntAfterFirstView(hashMap: HashMap<Int, ArrayList<UnreadCntInfo>>?) {
}
override fun onUnreadCntUpdate(hashMap: HashMap<Int, ArrayList<UnreadCntInfo>>?) {
}
override fun onUserChannelTabStatusChanged(z: Boolean) {
}
override fun onUserOnlineStatusChanged(z: Boolean) {
}
override fun onUserTabStatusChanged(arrayList: ArrayList<TabStatusInfo>?) {
LogCenter.log("onUserTabStatusChanged($arrayList)", Level.DEBUG)
}
override fun onlineStatusBigIconDownloadPush(i2: Int, j2: Long, str: String?) {
}
override fun onlineStatusSmallIconDownloadPush(i2: Int, j2: Long, str: String?) {
}
}

View File

@ -4,6 +4,8 @@ import com.tencent.qphone.base.remote.FromServiceMsg
import com.tencent.qphone.base.remote.ToServiceMsg import com.tencent.qphone.base.remote.ToServiceMsg
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
typealias MsfPush = (FromServiceMsg) -> Unit typealias MsfPush = (FromServiceMsg) -> Unit
typealias MsfResp = (ToServiceMsg, FromServiceMsg) -> Unit typealias MsfResp = (ToServiceMsg, FromServiceMsg) -> Unit
@ -45,8 +47,13 @@ internal object MSFHandler {
} }
fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) { fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) {
val cmd = toServiceMsg.getAttribute("respkey") as Int runCatching {
val cmd = toServiceMsg.getAttribute("shamrock_uid") as? Int?
?: return@runCatching
val resp = mRespHandler[cmd] val resp = mRespHandler[cmd]
resp?.invoke(toServiceMsg, fromServiceMsg) resp?.invoke(toServiceMsg, fromServiceMsg)
}.onFailure {
LogCenter.log("MSF.onResp failed: ${it.message}", Level.ERROR)
}
} }
} }