Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 12 additions & 19 deletions app/src/main/java/moe/ono/hooks/base/api/QQMessageViewListener.kt
Original file line number Diff line number Diff line change
@@ -1,34 +1,19 @@
package moe.ono.hooks.base.api

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.View
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
import de.robv.android.xposed.XposedBridge
import moe.ono.bridge.kernelcompat.ContactCompat
import moe.ono.config.ConfigManager
import moe.ono.config.ONOConf
import moe.ono.constants.Constants
import moe.ono.hooks._base.ApiHookItem
import moe.ono.hooks._base.BaseHookItem
import moe.ono.hooks._base.BaseSwitchFunctionHookItem
import moe.ono.hooks._core.annotation.HookItem
import moe.ono.hooks._core.factory.ExceptionFactory
import moe.ono.hooks._core.factory.HookItemFactory
import moe.ono.hooks.item.chat.SelfMessageReactor
import moe.ono.hooks.protocol.buildMessage
import moe.ono.hooks.protocol.sendPacket
import moe.ono.hostInfo
import moe.ono.reflex.ClassUtils
import moe.ono.reflex.FieldUtils
import moe.ono.reflex.Ignore
import moe.ono.reflex.MethodUtils
import moe.ono.service.QQInterfaces
import moe.ono.util.Initiator.loadClass
import moe.ono.util.Logger
import moe.ono.util.QAppUtils
import java.lang.ref.WeakReference
import java.lang.reflect.Method


@HookItem(path = "API/监听QQMsgView更新")
Expand All @@ -37,15 +22,15 @@ class QQMessageViewListener : ApiHookItem() {

companion object {

private val ON_AIO_CHAT_VIEW_UPDATE_LISTENER_MAP: HashMap<BaseSwitchFunctionHookItem, OnChatViewUpdateListener> =
private val ON_AIO_CHAT_VIEW_UPDATE_LISTENER_MAP: HashMap<BaseHookItem, OnChatViewUpdateListener> =
HashMap()

/**
* 添加消息监听器 责任链模式
*/
@JvmStatic
fun addMessageViewUpdateListener(
hookItem: BaseSwitchFunctionHookItem,
hookItem: BaseHookItem,
onMsgViewUpdateListener: OnChatViewUpdateListener
) {
ON_AIO_CHAT_VIEW_UPDATE_LISTENER_MAP[hookItem] = onMsgViewUpdateListener
Expand Down Expand Up @@ -85,7 +70,15 @@ class QQMessageViewListener : ApiHookItem() {


for ((switchFunctionHookItem, listener) in ON_AIO_CHAT_VIEW_UPDATE_LISTENER_MAP.entries) {
if (switchFunctionHookItem.isEnabled) {
if (switchFunctionHookItem is BaseSwitchFunctionHookItem) {
if (switchFunctionHookItem.isEnabled) {
try {
listener.onViewUpdateAfter(msgView, msgRecord)
} catch (e: Throwable) {
ExceptionFactory.add(switchFunctionHookItem, e)
}
}
} else {
try {
listener.onViewUpdateAfter(msgView, msgRecord)
} catch (e: Throwable) {
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/moe/ono/hooks/base/api/QQSendMsgListener.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package moe.ono.hooks.base.api

import android.text.TextUtils
import com.tencent.qqnt.kernel.nativeinterface.MsgAttributeInfo
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import de.robv.android.xposed.XC_MethodHook
import moe.ono.config.ONOConf
Expand All @@ -18,11 +19,20 @@ class QQSendMsgListener : ApiHookItem() {

hookBefore(sendMsgMethod) { param ->
val elements = param.args[2] as ArrayList<MsgElement>
val attributeInfos = param.args[3] as java.util.HashMap<Integer, MsgAttributeInfo>

for (listener in listeners) {
listener(param, elements)
}

for (attributeInfoListener in attributeInfoListeners) {
attributeInfoListener(param, attributeInfos)
}

for (allListener in allListeners) {
allListener(param, elements, attributeInfos)
}

if (ONOConf.getBoolean("global", "sticker_panel_set_ch_change_title", false)) {
val text: String =
ONOConf.getString("global", "sticker_panel_set_ed_change_title", "")
Expand All @@ -40,5 +50,7 @@ class QQSendMsgListener : ApiHookItem() {

companion object {
val listeners = mutableListOf<(param: XC_MethodHook.MethodHookParam, elems: ArrayList<MsgElement>) -> Unit>()
val attributeInfoListeners = mutableListOf<(param: XC_MethodHook.MethodHookParam, attributeInfos: HashMap<Integer, MsgAttributeInfo>) -> Unit>()
val allListeners = mutableListOf<(param: XC_MethodHook.MethodHookParam, elems: ArrayList<MsgElement>, attributeInfos: HashMap<Integer, MsgAttributeInfo>) -> Unit>()
}
}
136 changes: 136 additions & 0 deletions app/src/main/java/moe/ono/hooks/base/api/TagIcon.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package moe.ono.hooks.base.api

import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.view.children
import moe.ono.R
import moe.ono.hooks._base.ApiHookItem
import moe.ono.hooks._core.annotation.HookItem
import moe.ono.reflex.FieldUtils
import moe.ono.util.AppRuntimeHelper
import moe.ono.util.Logger

@HookItem(path = "API/胎记")
class TagIcon : ApiHookItem() {
override fun entry(classLoader: ClassLoader) {
QQSendMsgListener.attributeInfoListeners.add { _, attributeInfos ->
attributeInfos[0 as Integer]?.let {
it.vasMsgInfo?.bubbleInfo?.bubbleDiyTextId = 114515
attributeInfos[0 as Integer] = it
}
}

QQMessageViewListener.addMessageViewUpdateListener(
this,
object : QQMessageViewListener.OnChatViewUpdateListener {
override fun onViewUpdateAfter(
msgItemView: View,
msgRecord: Any
) {
try {
val msgAttrs: HashMap<Integer, Any> = FieldUtils.create(msgRecord)
.fieldName("msgAttrs")
.fieldType(HashMap::class.java)
.firstValue(msgRecord)

val msgAttr = msgAttrs[0 as Integer] ?: return

val vasMsgInfo: Any = FieldUtils.create(msgAttr)
.fieldName("vasMsgInfo")
.firstValue(msgAttr)

val bubbleInfo: Any = FieldUtils.create(vasMsgInfo)
.fieldName("bubbleInfo")
.firstValue(vasMsgInfo)

val bubbleDiyTextId: Integer? = FieldUtils.create(bubbleInfo)
.fieldName("bubbleDiyTextId")
.fieldType(Integer::class.java)
.firstValue(bubbleInfo)

val senderUin: Long = FieldUtils.create(msgRecord)
.fieldName("senderUin")
.fieldType(Long::class.java)
.firstValue(msgRecord)

val rootView = msgItemView as ViewGroup
if (!QQMsgViewAdapter.hasContentMessage(rootView)) return

val targetLayout = rootView.children.find {
if (it is FrameLayout) {
if (it.childCount == 1 && it.getChildAt(0) is LinearLayout) {
val linearLayout = it.getChildAt(0) as LinearLayout
if (
(linearLayout.childCount == 2 &&
linearLayout.children.find { it1 -> it1.tag == 114514 } != null) ||
(linearLayout.childCount == 1 &&
linearLayout.getChildAt(0) is LinearLayout)
) {
return@find true
}
}
}
false
}

if (targetLayout is FrameLayout) {
val target = targetLayout.getChildAt(0) as? ViewGroup ?: return

if (target.children.find { it.tag == 114514 } != null) {
if (bubbleDiyTextId != 114515 as Integer) {
target.children.toList().forEach {
if (it.tag == 114514) {
target.removeView(it)
}
}
}
return
}

val size =
(16 * target.context.resources.displayMetrics.density).toInt()
val margin =
(4 * target.context.resources.displayMetrics.density).toInt()

fun dp(context: Context, value: Float): Float {
return value * context.resources.displayMetrics.density
}

val icon = ImageView(target.context).apply {
setImageResource(R.drawable.ic_ouo)
scaleType = ImageView.ScaleType.FIT_CENTER
adjustViewBounds = true
layoutParams = ViewGroup.MarginLayoutParams(size, size).apply {
leftMargin = margin
rightMargin = margin
}
tag = 114514
clipToOutline = true
outlineProvider = ViewOutlineProvider.BACKGROUND
background = GradientDrawable().apply {
cornerRadius = dp(context, 3f)
}
}

if (bubbleDiyTextId == 114515 as Integer) {
if (senderUin == AppRuntimeHelper.getLongAccountUin()) {
target.addView(icon)
} else {
target.addView(icon, 0)
}
}
}
} catch (e: Exception) {
Logger.e(e)
}
}
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@ class BottomShortcutMenu : BaseClickableFunctionHookItem() {
val bigForward = ConfigManager.getDefaultConfig().getBooleanOrFalse(Constants.PrekXXX + getItem(
BigForward::class.java).path)

val hintBlackShellUser = ConfigManager.getDefaultConfig().getBooleanOrFalse(Constants.PrekXXX + getItem(
HintBlackShellUser::class.java).path)


// 定义菜单分组结构
data class MenuItem(val label: String, val action: () -> Unit)
data class MenuGroup(val groupName: String, val items: List<MenuItem>)
Expand Down Expand Up @@ -264,10 +260,6 @@ class BottomShortcutMenu : BaseClickableFunctionHookItem() {
val item = getItem(FakeLocationShare::class.java)
if (item is IShortcutMenu) item.clickHandle(view.context)
})
if (hintBlackShellUser) msgItems.add(MenuItem("自定义黑色壳子用户底部 Tag") {
val item = getItem(HintBlackShellUser::class.java)
if (item is IShortcutMenu) item.clickHandle(view.context)
})
msgItems.add(MenuItem("匿名化"){
autoMosaicNameNT()
})
Expand Down
Loading
Loading