diff --git a/app/src/main/java/cc/ioctl/hook/chat/GagInfoDisclosure.kt b/app/src/main/java/cc/ioctl/hook/chat/GagInfoDisclosure.kt
index 5a1cf1333f..4a215a46f7 100644
--- a/app/src/main/java/cc/ioctl/hook/chat/GagInfoDisclosure.kt
+++ b/app/src/main/java/cc/ioctl/hook/chat/GagInfoDisclosure.kt
@@ -1,190 +1,256 @@
/*
* QAuxiliary - An Xposed module for QQ/TIM
- * Copyright (C) 2019-2022 qwq233@qwq2333.top
+ * Copyright (C) 2019-2024 QAuxiliary developers
* https://github.com/cinit/QAuxiliary
*
- * This software is non-free but opensource software: you can redistribute it
- * and/or modify it under the terms of the GNU Affero General Public License
+ * This software is an opensource software: you can redistribute it
+ * and/or modify it under the terms of the General Public License
* as published by the Free Software Foundation; either
- * version 3 of the License, or any later version and our eula as published
+ * version 3 of the License, or any later version as published
* by QAuxiliary contributors.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Affero General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the General Public License for more details.
*
- * You should have received a copy of the GNU Affero General Public License
- * and eula along with this software. If not, see
- *
+ * You should have received a copy of the General Public License
+ * along with this software.
+ * If not, see
* .
*/
-package cc.ioctl.hook.chat;
-import static cc.ioctl.util.Reflex.findMethodByTypes_1;
-import static io.github.qauxv.bridge.GreyTipBuilder.MSG_TYPE_TROOP_GAP_GRAY_TIPS;
+package cc.ioctl.hook.chat
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import cc.ioctl.util.HookUtils;
-import de.robv.android.xposed.XC_MethodHook;
-import de.robv.android.xposed.XposedBridge;
-import io.github.qauxv.base.annotation.FunctionHookEntry;
-import io.github.qauxv.base.annotation.UiItemAgentEntry;
-import io.github.qauxv.bridge.AppRuntimeHelper;
-import io.github.qauxv.bridge.ContactUtils;
-import io.github.qauxv.bridge.GreyTipBuilder;
-import io.github.qauxv.bridge.QQMessageFacade;
-import io.github.qauxv.dsl.FunctionEntryRouter.Locations.Auxiliary;
-import io.github.qauxv.hook.CommonSwitchFunctionHook;
-import io.github.qauxv.util.Initiator;
-import io.github.qauxv.util.LicenseStatus;
-import io.github.qauxv.util.SyncUtils;
-import io.github.qauxv.util.dexkit.CMessageRecordFactory;
-import io.github.qauxv.util.dexkit.DexKitTarget;
-import io.github.qauxv.util.dexkit.NContactUtils_getBuddyName;
-import io.github.qauxv.util.dexkit.NContactUtils_getDiscussionMemberShowName;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
+import cc.hicore.QApp.QAppUtils
+import cc.ioctl.util.hookBeforeIfEnabled
+import io.github.qauxv.base.annotation.FunctionHookEntry
+import io.github.qauxv.base.annotation.UiItemAgentEntry
+import io.github.qauxv.bridge.AppRuntimeHelper
+import io.github.qauxv.bridge.ContactUtils
+import io.github.qauxv.bridge.GreyTipBuilder
+import io.github.qauxv.bridge.QQMessageFacade
+import io.github.qauxv.bridge.kernelcompat.ContactCompat
+import io.github.qauxv.bridge.ntapi.ChatTypeConstants
+import io.github.qauxv.bridge.ntapi.NtGrayTipHelper
+import io.github.qauxv.dsl.FunctionEntryRouter
+import io.github.qauxv.hook.CommonSwitchFunctionHook
+import io.github.qauxv.util.Initiator
+import io.github.qauxv.util.Log
+import io.github.qauxv.util.QQVersion
+import io.github.qauxv.util.SyncUtils
+import io.github.qauxv.util.dexkit.CMessageRecordFactory
+import io.github.qauxv.util.dexkit.NContactUtils_getBuddyName
+import io.github.qauxv.util.dexkit.NContactUtils_getDiscussionMemberShowName
+import io.github.qauxv.util.requireMinQQVersion
@FunctionHookEntry
@UiItemAgentEntry
-public class GagInfoDisclosure extends CommonSwitchFunctionHook {
+object GagInfoDisclosure : CommonSwitchFunctionHook(
+ // TODO: 2020/6/12 Figure out whether MSF is really needed
+ targetProc = SyncUtils.PROC_MAIN or SyncUtils.PROC_MSF,
+ targets = arrayOf(
+ CMessageRecordFactory,
+ NContactUtils_getDiscussionMemberShowName,
+ NContactUtils_getBuddyName,
+ )
+) {
- public static final GagInfoDisclosure INSTANCE = new GagInfoDisclosure();
+ override val name = "显示设置禁言的管理"
+ override val description = "总是显示哪个管理员设置了禁言"
+ override val uiItemLocation = FunctionEntryRouter.Locations.Auxiliary.CHAT_CATEGORY
- private GagInfoDisclosure() {
- // TODO: 2020/6/12 Figure out whether MSF is really needed
- super(SyncUtils.PROC_MAIN | SyncUtils.PROC_MSF, new DexKitTarget[]{
- CMessageRecordFactory.INSTANCE,
- NContactUtils_getDiscussionMemberShowName.INSTANCE,
- NContactUtils_getBuddyName.INSTANCE,
- });
+ private fun getSecStr(sec: Long): String {
+ val (min, hour, day) = Triple("分", "时", "天")
+ val d = sec / 86400
+ val h = (sec % 86400) / 3600
+ val m = ((sec % 86400) % 3600) / 60
+ val ret = StringBuilder()
+ if (d > 0) ret.append(d).append(day)
+ if (h > 0) ret.append(h).append(hour)
+ if (m > 0) ret.append(m).append(min)
+ return ret.toString()
}
- public static String getGagTimeString(long sec) {
- String _min = "分钟";
- String _hour = "小时";
- String _day = "天";
- if (sec < 60) {
- return 1 + _min;
- }
- long fsec = 59 + sec;
- long d = fsec / 86400;
- long h = (fsec - (86400 * d)) / 3600;
- long m = ((fsec - (86400 * d)) - (3600 * h)) / 60;
- String ret = "";
- if (d > 0) {
- ret = ret + d + _day;
- }
- if (h > 0) {
- ret = ret + h + _hour;
- }
- if (m > 0) {
- return ret + m + _min;
+ private fun addTroopGrayTipMsg(troopUin: String, jsonStr: String) {
+ NtGrayTipHelper.addLocalJsonGrayTipMsg(
+ AppRuntimeHelper.getAppRuntime()!!,
+ ContactCompat(ChatTypeConstants.GROUP, troopUin, ""),
+ NtGrayTipHelper.createLocalJsonElement(NtGrayTipHelper.AIO_AV_GROUP_NOTICE.toLong(), jsonStr, ""),
+ true,
+ true
+ ) { result, uin ->
+ if (result != 0) {
+ Log.e("GagInfoDisclosure error: addLocalJsonGrayTipMsg failed, result=$result, uin=$uin")
+ }
}
- return ret;
}
- @Override
- public boolean initOnce() throws Exception {
- Class> clzGagMgr = Initiator._TroopGagMgr();
- Method m1 = findMethodByTypes_1(clzGagMgr, void.class, String.class, long.class,
- long.class, int.class, String.class, String.class, boolean.class);
- XposedBridge.hookMethod(m1, new XC_MethodHook(48) {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- if (LicenseStatus.sDisableCommonHooks) {
- return;
- }
- if (!isEnabled()) {
- return;
- }
- String selfUin = AppRuntimeHelper.getAccount() + "";
- String troopUin = (String) param.args[0];
- long time = (long) param.args[1];
- long interval = (long) param.args[2];
- int msgseq = (int) param.args[3];
- String opUin = (String) param.args[4];
- String victimUin = (String) param.args[5];
- String opName = ContactUtils.getTroopMemberNick(troopUin, opUin);
- String victimName = ContactUtils.getTroopMemberNick(troopUin, victimUin);
- GreyTipBuilder builder = GreyTipBuilder.create(MSG_TYPE_TROOP_GAP_GRAY_TIPS);
- if (selfUin.endsWith(victimUin)) {
- builder.append("你");
- } else {
- builder.append(' ').appendTroopMember(victimUin, victimName).append(' ');
- }
- builder.append("被");
- if (selfUin.endsWith(opUin)) {
- builder.append("你");
- } else {
- builder.append(' ').appendTroopMember(opUin, opName).append(' ');
- }
- if (interval == 0) {
- builder.append("解除禁言");
+ override fun initOnce(): Boolean {
+ val clzGagMgr = Initiator._TroopGagMgr()
+ if (requireMinQQVersion(QQVersion.QQ_9_0_25)) {
+ val method = clzGagMgr.declaredMethods.single { method ->
+ val params = method.parameterTypes; params.size == 5
+ && params[0] == Int::class.java
+ && params[1] == Long::class.java
+ && params[2] == Long::class.java
+ && params[3] == Long::class.java
+ && params[4] == ArrayList::class.java
+ && method.returnType == Void.TYPE
+ }
+ hookBeforeIfEnabled(method) { param ->
+ val selfUin = AppRuntimeHelper.getAccount()
+ val troopUin = param.args[1] as Long
+ val opUin = param.args[2] as Long
+ val opName = ContactUtils.getDiscussionMemberShowName(AppRuntimeHelper.getAppRuntime()!!, troopUin.toString(), opUin.toString())
+ val builder = NtGrayTipHelper.NtGrayTipJsonBuilder()
+ builder.appendText("操作者: ")
+ if (opUin.toString() == selfUin) {
+ builder.appendText("你")
} else {
- builder.append("禁言").append(getGagTimeString(interval));
+ builder.appendText("$opName[$opUin]")
}
- Object msg = builder.build(troopUin, 1, opUin, time, msgseq);
- List