From fb4a46b151139c79ab38ce737d28b7ad92bc8ebd Mon Sep 17 00:00:00 2001 From: klxiaoniu Date: Sun, 16 Jul 2023 21:33:34 +0800 Subject: [PATCH] fix: BaseBubbleBuilderHook for QQNT --- .../ioctl/hook/msg/MultiForwardAvatarHook.kt | 4 ++ .../ketal/dispacher/BaseBubbleBuilderHook.kt | 41 +++++++++++++++++++ .../java/me/ketal/hook/ChatItemShowQQUin.kt | 6 +++ app/src/main/java/me/ketal/hook/ShowMsgAt.kt | 17 ++++++++ .../java/xyz/nextalone/hook/HideTroopLevel.kt | 6 +++ 5 files changed, 74 insertions(+) diff --git a/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt b/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt index 9019201710..30a5fa7d65 100644 --- a/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt +++ b/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt @@ -188,6 +188,10 @@ object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils)), On headIconView.setOnClickListener(baseBubbleBuilderOnClick) } + override fun onGetViewNt(rootView: ViewGroup, chatMessage: MsgRecord, param: MethodHookParam) { + // 此处无需实现 + } + private var mLeftCheckBoxVisible: Field? = null /** diff --git a/app/src/main/java/me/ketal/dispacher/BaseBubbleBuilderHook.kt b/app/src/main/java/me/ketal/dispacher/BaseBubbleBuilderHook.kt index e9bf5867fd..6be8ec01a2 100644 --- a/app/src/main/java/me/ketal/dispacher/BaseBubbleBuilderHook.kt +++ b/app/src/main/java/me/ketal/dispacher/BaseBubbleBuilderHook.kt @@ -25,15 +25,22 @@ package me.ketal.dispacher import android.view.View import android.view.ViewGroup import cc.ioctl.hook.msg.MultiForwardAvatarHook +import cc.ioctl.util.HostInfo +import com.github.kyuubiran.ezxhelper.utils.hookBefore +import com.github.kyuubiran.ezxhelper.utils.paramCount +import com.tencent.qqnt.kernel.nativeinterface.MsgRecord import de.robv.android.xposed.XC_MethodHook import io.github.qauxv.base.annotation.FunctionHookEntry import io.github.qauxv.hook.BasePersistBackgroundHook import io.github.qauxv.util.Initiator +import io.github.qauxv.util.QQVersion import me.ketal.hook.ChatItemShowQQUin import me.ketal.hook.ShowMsgAt import me.singleneuron.data.MsgRecordData import xyz.nextalone.hook.HideTroopLevel import xyz.nextalone.util.hookAfter +import xyz.nextalone.util.invoke +import xyz.nextalone.util.method import java.lang.reflect.Method import java.lang.reflect.Modifier @@ -52,6 +59,33 @@ object BaseBubbleBuilderHook : BasePersistBackgroundHook() { @Throws(Exception::class) override fun initOnce(): Boolean { + if (HostInfo.requireMinQQVersion(QQVersion.QQ_8_9_63)) { + val kBaseContentComponent = Initiator.loadClass("com.tencent.mobileqq.aio.msglist.holder.component.BaseContentComponent") + val getView = kBaseContentComponent.declaredMethods.singleOrNull { it.name == "onCreateView" }!! + getView.hookAfter(this) {param-> +// Log.d("BaseContentComponent.onCreateView") + if (param.result == null) return@hookAfter + val rootView = param.result as ViewGroup + var clz = param.thisObject.javaClass.superclass + while (clz != kBaseContentComponent) { + clz = clz.superclass + } + // onCreateView时AIOMsgItem还没被设置 + clz.method { it.paramCount == 1 && it.parameterTypes[0].name == "com.tencent.mobileqq.aio.msg.AIOMsgItem" }!!.hookBefore { + val item = it.args[0] + val msg = item.invoke("getMsgRecord")!! as MsgRecord +// Log.i("get!!!!!!") + for (decorator in decorators) { + try { + decorator.onGetViewNt(rootView, msg, it) + } catch (e: Exception) { + traceError(e) + } + } + } + } + return true + } val kBaseBubbleBuilder = Initiator.loadClass("com.tencent.mobileqq.activity.aio.BaseBubbleBuilder") val getView: Method? = kBaseBubbleBuilder.declaredMethods.singleOrNull { m -> if (m.parameterTypes.size == 6 && m.returnType == View::class.java && m.modifiers == Modifier.PUBLIC) { @@ -83,4 +117,11 @@ interface OnBubbleBuilder { chatMessage: MsgRecordData, param: XC_MethodHook.MethodHookParam ) + + @Throws(Exception::class) + fun onGetViewNt( + rootView: ViewGroup, + chatMessage: MsgRecord, + param: XC_MethodHook.MethodHookParam + ) } diff --git a/app/src/main/java/me/ketal/hook/ChatItemShowQQUin.kt b/app/src/main/java/me/ketal/hook/ChatItemShowQQUin.kt index 3ab914864e..06e642ff32 100644 --- a/app/src/main/java/me/ketal/hook/ChatItemShowQQUin.kt +++ b/app/src/main/java/me/ketal/hook/ChatItemShowQQUin.kt @@ -43,6 +43,7 @@ import cc.ioctl.hook.msg.FlashPicHook import cc.ioctl.util.LayoutHelper import cc.ioctl.util.Reflex import cc.ioctl.util.ui.FaultyDialog +import com.tencent.qqnt.kernel.nativeinterface.MsgRecord import de.robv.android.xposed.XC_MethodHook import io.github.qauxv.R import io.github.qauxv.base.IUiItemAgent @@ -284,6 +285,11 @@ object ChatItemShowQQUin : CommonConfigFunctionHook(), OnBubbleBuilder { pfnSetTailMessage.invoke(rootView, true, text, if (mEnableDetailInfo) mOnTailMessageClickListener else null) } + override fun onGetViewNt(rootView: ViewGroup, chatMessage: MsgRecord, param: XC_MethodHook.MethodHookParam) { + if (!isEnabled) return + + } + private fun isFlashPic(chatMessage: MsgRecordData): Boolean { val msgtype = chatMessage.msgType return (msgtype == -2000 || msgtype == -2006) && diff --git a/app/src/main/java/me/ketal/hook/ShowMsgAt.kt b/app/src/main/java/me/ketal/hook/ShowMsgAt.kt index 9747268bad..ce292863e7 100644 --- a/app/src/main/java/me/ketal/hook/ShowMsgAt.kt +++ b/app/src/main/java/me/ketal/hook/ShowMsgAt.kt @@ -31,6 +31,7 @@ import android.view.ViewGroup import android.widget.TextView import androidx.core.view.forEach import cc.ioctl.hook.profile.OpenProfileCard +import com.tencent.qqnt.kernel.nativeinterface.MsgRecord import de.robv.android.xposed.XC_MethodHook import io.github.qauxv.base.annotation.UiItemAgentEntry import io.github.qauxv.dsl.FunctionEntryRouter @@ -89,6 +90,22 @@ object ShowMsgAt : CommonSwitchFunctionHook(), OnBubbleBuilder { } } + override fun onGetViewNt(rootView: ViewGroup, chatMessage: MsgRecord, param: XC_MethodHook.MethodHookParam) { + if (!isEnabled) return + + Log.i("----------------onGetViewNt") + Log.i(chatMessage.toString()) + //if (!isEnabled || 1 != chatMessage.chatType) return + val elements = chatMessage.elements ?: return + elements.forEach { + if (it.textElement != null && it.textElement.atType != 0) { + Log.i(it.textElement.content) + } + } + val tv = rootView.findHostView("ex1") + //tv?.text = "12345" + } + private fun copeAtInfo(textView: TextView, atList: List<*>) { val spannableString = SpannableString(textView.text) atList.forEach { diff --git a/app/src/main/java/xyz/nextalone/hook/HideTroopLevel.kt b/app/src/main/java/xyz/nextalone/hook/HideTroopLevel.kt index ec60a1c3f1..cd19083e07 100644 --- a/app/src/main/java/xyz/nextalone/hook/HideTroopLevel.kt +++ b/app/src/main/java/xyz/nextalone/hook/HideTroopLevel.kt @@ -23,6 +23,7 @@ package xyz.nextalone.hook import android.view.ViewGroup import androidx.core.view.isVisible +import com.tencent.qqnt.kernel.nativeinterface.MsgRecord import de.robv.android.xposed.XC_MethodHook import io.github.qauxv.base.annotation.UiItemAgentEntry import io.github.qauxv.dsl.FunctionEntryRouter @@ -66,4 +67,9 @@ object HideTroopLevel : CommonSwitchFunctionHook(), OnBubbleBuilder { val isAdmin = admin?.contains(sendUin) == true || ownerUin == sendUin levelView?.isVisible = isAdmin } + + override fun onGetViewNt(rootView: ViewGroup, chatMessage: MsgRecord, param: XC_MethodHook.MethodHookParam) { + if (!isEnabled) return + + } }