diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/utils/PlatformUtils.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/utils/PlatformUtils.kt index cb8af55..83f7d15 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/utils/PlatformUtils.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/utils/PlatformUtils.kt @@ -6,15 +6,18 @@ import android.content.Context import android.content.Context.BATTERY_SERVICE import android.content.Intent import android.content.IntentFilter +import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.os.BatteryManager import android.os.Build import android.os.Process import android.provider.Settings import kotlinx.serialization.Serializable +import moe.fuqiuluo.shamrock.tools.ShamrockVersion import mqq.app.MobileQQ import kotlin.random.Random + internal object PlatformUtils { const val QQ_9_0_8_VER = 5540 @@ -69,6 +72,15 @@ internal object PlatformUtils { return MobileQQ.getMobileQQ().qqProcessName == "com.tencent.tim" } + fun isApkInDebug(context: Context): Boolean { + try { + val info = context.applicationInfo + return (info.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0 + } catch (e: Exception) { + return false + } + } + fun killProcess(context: Context, processName: String) { for (processInfo in (context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).runningAppProcesses) { if (processInfo.processName == processName) { diff --git a/xposed/src/main/java/qq/service/file/GroupFileHelper.kt b/xposed/src/main/java/qq/service/file/GroupFileHelper.kt index 5f5642e..2e5db18 100644 --- a/xposed/src/main/java/qq/service/file/GroupFileHelper.kt +++ b/xposed/src/main/java/qq/service/file/GroupFileHelper.kt @@ -10,6 +10,7 @@ import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY import moe.fuqiuluo.shamrock.tools.slice +import moe.fuqiuluo.shamrock.tools.toHexString import moe.fuqiuluo.shamrock.utils.DeflateTools import qq.service.QQInterfaces import tencent.im.oidb.cmd0x6d8.oidb_0x6d8 @@ -31,12 +32,19 @@ internal object GroupFileHelper: QQInterfaces() { val fileCnt: Int val limitCnt: Int if (fromServiceMsg.wupBuffer != null) { - oidb_0x6d8.RspBody().mergeFrom( - oidb_sso.OIDBSSOPkg() - .mergeFrom(fromServiceMsg.wupBuffer.slice(4)) - .bytes_bodybuffer.get() - .toByteArray() - ).group_file_cnt_rsp.apply { + val oidb1 = kotlin.runCatching { + oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg.wupBuffer.slice(4).let { + if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it + }) + }.onFailure { + LogCenter.log("unable to parse oidb response: ${fromServiceMsg.wupBuffer.toHexString()}", Level.ERROR) + }.getOrElse { + oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg.wupBuffer.let { + if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it + }) + } + + oidb_0x6d8.RspBody().mergeFrom(oidb1.bytes_bodybuffer.get().toByteArray()).group_file_cnt_rsp.apply { fileCnt = uint32_all_file_count.get() limitCnt = uint32_limit_count.get() } @@ -53,11 +61,19 @@ internal object GroupFileHelper: QQInterfaces() { val totalSpace: Long val usedSpace: Long if (fromServiceMsg2.isSuccess && fromServiceMsg2.wupBuffer != null) { - oidb_0x6d8.RspBody().mergeFrom( - oidb_sso.OIDBSSOPkg() - .mergeFrom(fromServiceMsg2.wupBuffer.slice(4)) - .bytes_bodybuffer.get() - .toByteArray()).group_space_rsp.apply { + val oidb2 = kotlin.runCatching { + oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg2.wupBuffer.slice(4).let { + if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it + }) + }.onFailure { + LogCenter.log("unable to parse oidb response: ${fromServiceMsg2.wupBuffer.toHexString()}", Level.ERROR) + }.getOrElse { + oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg2.wupBuffer.let { + if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it + }) + } + + oidb_0x6d8.RspBody().mergeFrom(oidb2.bytes_bodybuffer.get().toByteArray()).group_space_rsp.apply { totalSpace = uint64_total_space.get() usedSpace = uint64_used_space.get() } @@ -95,16 +111,24 @@ internal object GroupFileHelper: QQInterfaces() { uint32_show_onlinedoc_folder.set(0) }) - }.toByteArray(), timeout = 15.seconds) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request")) + }.toByteArray(), timeout = 30.seconds) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request")) if (fromServiceMsg.wupBuffer == null) { throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed")) } val files = arrayListOf() val folders = arrayListOf() if (fromServiceMsg.wupBuffer != null) { - val oidb = oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg.wupBuffer.slice(4).let { - if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it - }) + val oidb = kotlin.runCatching { + oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg.wupBuffer.slice(4).let { + if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it + }) + }.onFailure { + LogCenter.log("unable to parse oidb response: ${fromServiceMsg.wupBuffer.toHexString()}", Level.ERROR) + }.getOrElse { + oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg.wupBuffer.let { + if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it + }) + } oidb_0x6d8.RspBody().mergeFrom(oidb.bytes_bodybuffer.get().toByteArray()) .file_list_info_rsp.apply { diff --git a/xposed/src/main/java/qq/service/internals/AioListener.kt b/xposed/src/main/java/qq/service/internals/AioListener.kt index 96118fa..9defeb2 100644 --- a/xposed/src/main/java/qq/service/internals/AioListener.kt +++ b/xposed/src/main/java/qq/service/internals/AioListener.kt @@ -9,14 +9,15 @@ import com.tencent.qqnt.kernel.nativeinterface.TextElement import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import kotlinx.serialization.json.JsonNull.content import moe.fuqiuluo.shamrock.config.AliveReply -import moe.fuqiuluo.shamrock.config.ConfigKey import moe.fuqiuluo.shamrock.config.get import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter +import moe.fuqiuluo.shamrock.utils.PlatformUtils import qq.service.bdh.RichProtoSvc +import qq.service.file.GroupFileHelper +import qq.service.group.GroupHelper import qq.service.kernel.SimpleKernelMsgListener import qq.service.msg.MessageHelper @@ -35,7 +36,6 @@ object AioListener : SimpleKernelMsgListener() { private suspend fun onMsg(record: MsgRecord) { if (AliveReply.get()) { - //LogCenter.log("自回复测试功能打开!") val texts = record.elements.filter { it.elementType == MsgConstant.KELEMTYPETEXT } val text = texts.joinToString { it.textElement.content } if (texts.isNotEmpty() && text == "ping") { @@ -50,6 +50,33 @@ object AioListener : SimpleKernelMsgListener() { ), 3, MessageHelper.generateMsgId(record.chatType)) return } + + if (record.chatType == MsgConstant.KCHATTYPEGROUP && text == ".shamrock.members") { + val contact = MessageHelper.generateContact(record) + GroupHelper.getGroupMemberList(record.peerUin, true).onSuccess { + MessageHelper.sendMessage(contact, arrayListOf( + MsgElement().apply { + elementType = MsgConstant.KELEMTYPETEXT + textElement = TextElement().apply { + content = "memberCount: ${it.size}" + } + } + ), 3, MessageHelper.generateMsgId(record.chatType)) + }.onFailure { + LogCenter.log("获取群成员列表失败: $it", Level.ERROR) + } + } else if (record.chatType == MsgConstant.KCHATTYPEGROUP && text == ".shamrock.root_files") { + val contact = MessageHelper.generateContact(record) + val files = GroupFileHelper.getGroupFiles(record.peerUin) + MessageHelper.sendMessage(contact, arrayListOf( + MsgElement().apply { + elementType = MsgConstant.KELEMTYPETEXT + textElement = TextElement().apply { + content = "foldersCount: ${files.foldersCount}\nfilesCount: ${files.filesCount}" + } + } + ), 3, MessageHelper.generateMsgId(record.chatType)) + } } when (record.chatType) { MsgConstant.KCHATTYPEGROUP -> {