diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 81a0a17..b30bbac 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -36,13 +36,6 @@ jobs: run: | ./gradlew assembleRelease - - name: Upload artifacts - uses: actions/upload-artifact@v4 - id: upload - with: - name: app-release - path: app/build/outputs/apk/release/app-release.apk - - name: Setup NodeJs uses: actions/setup-node@v4.1.0 with: @@ -65,3 +58,10 @@ jobs: - name: Run Node.js script run: node index.js + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + id: upload + with: + name: app-release + path: app/build/outputs/apk/release/app-release.apk \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2b3144d..095e51d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,7 +13,7 @@ android { //noinspection OldTargetApi targetSdk = 34 versionCode = 1 - versionName = "0.0.5" + versionName = "0.0.6" } signingConfigs { diff --git a/app/src/main/java/its/madruga/warevamp/core/Utils.java b/app/src/main/java/its/madruga/warevamp/core/Utils.java index b0d95a9..e22abba 100644 --- a/app/src/main/java/its/madruga/warevamp/core/Utils.java +++ b/app/src/main/java/its/madruga/warevamp/core/Utils.java @@ -1,10 +1,6 @@ package its.madruga.warevamp.core; -import static its.madruga.warevamp.module.hooks.core.HooksLoader.mApp; - -import android.util.Log; - import its.madruga.warevamp.App; public class Utils { @@ -19,12 +15,4 @@ public static boolean isInstalled(String packageWpp) { } return false; } - - public static int getResourceId(String name, String type) { - int id = App.getInstance().getResources().getIdentifier(name, type, App.getInstance().getPackageName()); - if (id == 0) { - Log.e("WaRevamp", "Resource not found: " + name); - } - return id; - } } diff --git a/app/src/main/java/its/madruga/warevamp/module/core/FMessageInfo.java b/app/src/main/java/its/madruga/warevamp/module/core/FMessageInfo.java index 87b57ef..15a5435 100644 --- a/app/src/main/java/its/madruga/warevamp/module/core/FMessageInfo.java +++ b/app/src/main/java/its/madruga/warevamp/module/core/FMessageInfo.java @@ -65,19 +65,25 @@ public boolean isMediaFile() { try { return mediaMessageClass.isInstance(messageObject); } catch (Exception e) { + XposedBridge.log(e.getMessage() + " | " + (mediaMessageClass == null ? "MediaMessageClass" : "MessageObject")); return false; } } public File getMediaFile() { try { - if (!isMediaFile()) return null; + if (!isMediaFile()) { + XposedBridge.log("Not Media file"); + return null; + } for (var field : mediaMessageClass.getDeclaredFields()) { if (field.getType().isPrimitive()) continue; var fileField = ReferencesUtils.getFieldByType(field.getType(), File.class); if (fileField != null) { var mediaFile = ReferencesUtils.getObjectField(field, messageObject); return (File) fileField.get(mediaFile); + } else { + XposedBridge.log("File field is null!!"); } } } catch (Exception e) { diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/core/HooksLoader.java b/app/src/main/java/its/madruga/warevamp/module/hooks/core/HooksLoader.java index b97c7e9..6015641 100644 --- a/app/src/main/java/its/madruga/warevamp/module/hooks/core/HooksLoader.java +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/core/HooksLoader.java @@ -26,8 +26,10 @@ import its.madruga.warevamp.module.hooks.customization.SeparateGroupsHook; import its.madruga.warevamp.module.hooks.others.MenuHook; import its.madruga.warevamp.module.hooks.privacy.DndModeHook; +import its.madruga.warevamp.module.hooks.privacy.FreezeLastSeenHook; import its.madruga.warevamp.module.hooks.privacy.HideReadHook; import its.madruga.warevamp.module.hooks.privacy.HideReceiptHook; +import its.madruga.warevamp.module.hooks.privacy.HideTypingRecordingHook; import its.madruga.warevamp.module.references.References; import its.madruga.warevamp.module.hooks.media.MediaQualityHook; import its.madruga.warevamp.module.hooks.others.OthersHook; @@ -92,7 +94,9 @@ private static void plugins(@NonNull ClassLoader loader, @NonNull XSharedPrefere HideReadHook.class, HideArchivedChatsHook.class, DownloadStatusHook.class, - DownloadViewOnceHook.class + DownloadViewOnceHook.class, + HideTypingRecordingHook.class, + FreezeLastSeenHook.class }; for (var c : classes) { diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/media/DownloadStatusHook.java b/app/src/main/java/its/madruga/warevamp/module/hooks/media/DownloadStatusHook.java index 1982737..a7f7876 100644 --- a/app/src/main/java/its/madruga/warevamp/module/hooks/media/DownloadStatusHook.java +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/media/DownloadStatusHook.java @@ -4,7 +4,6 @@ import static its.madruga.warevamp.module.references.ModuleResources.string.download_status; import static its.madruga.warevamp.module.references.References.menuManagerClass; import static its.madruga.warevamp.module.references.References.menuStatusClickMethod; -import static its.madruga.warevamp.module.references.References.setPageActiveMethod; import android.media.MediaScannerConnection; import android.os.Environment; diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/media/MediaQualityHook.java b/app/src/main/java/its/madruga/warevamp/module/hooks/media/MediaQualityHook.java index 9166bad..90d8cf5 100644 --- a/app/src/main/java/its/madruga/warevamp/module/hooks/media/MediaQualityHook.java +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/media/MediaQualityHook.java @@ -37,7 +37,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.hookMethod(videoBitrateMethod(loader), new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { - param.setResult(40000); + param.setResult(1600000); } }); XposedBridge.hookMethod(videoGifBitrateMethod(loader), new XC_MethodReplacement() { diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/others/OthersHook.java b/app/src/main/java/its/madruga/warevamp/module/hooks/others/OthersHook.java index 30f2940..4a7e754 100644 --- a/app/src/main/java/its/madruga/warevamp/module/hooks/others/OthersHook.java +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/others/OthersHook.java @@ -8,18 +8,13 @@ import org.jetbrains.annotations.NotNull; import java.lang.reflect.Method; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; -import java.util.Locale; -import java.util.Objects; import static its.madruga.warevamp.module.references.References.expirationTimeClass; import static its.madruga.warevamp.module.references.References.propsMethod; import static its.madruga.warevamp.module.references.ReferencesUtils.findMethodUsingFilter; -import android.util.Log; - public class OthersHook extends HooksBase { HashMap propList; @@ -35,12 +30,10 @@ public void doHook() throws Exception { propList = new HashMap<>(); - propList.put(4524, prefs.getBoolean("novoTema", false)); - -// // Transcrição -// propList.put(8632, true); -// propList.put(2890, true); -// propList.put(9215, true); + // Transcrição + propList.put(8632, true); + propList.put(2890, true); + propList.put(9215, true); // Novo menu propList.put(2889, prefs.getBoolean("novoMenu", false)); diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/DndModeHook.java b/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/DndModeHook.java index 6f3f492..aeee383 100644 --- a/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/DndModeHook.java +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/DndModeHook.java @@ -24,10 +24,16 @@ public DndModeHook(@NonNull @NotNull ClassLoader loader, @NonNull @NotNull XShar @Override public void doHook() throws Exception { super.doHook(); - boolean dndMode = prefs.getBoolean("dnd_Mode", false); + boolean dndMode = prefs.getBoolean("dndMode", false); - if(!dndMode) return; + if(dndMode) { + XposedBridge.hookMethod(dndModeMethod(loader), new XC_MethodReplacement() { + @Override + protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { + return null; + } + }); + } - XposedBridge.hookMethod(dndModeMethod(loader), XC_MethodReplacement.DO_NOTHING); } } diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/FreezeLastSeenHook.java b/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/FreezeLastSeenHook.java new file mode 100644 index 0000000..6cbe5de --- /dev/null +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/FreezeLastSeenHook.java @@ -0,0 +1,33 @@ +package its.madruga.warevamp.module.hooks.privacy; + +import static its.madruga.warevamp.module.references.References.freezeLastSeenMethod; + +import androidx.annotation.NonNull; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XSharedPreferences; +import de.robv.android.xposed.XposedBridge; +import its.madruga.warevamp.module.hooks.core.HooksBase; + +public class FreezeLastSeenHook extends HooksBase { + public FreezeLastSeenHook(@NonNull ClassLoader loader, @NonNull XSharedPreferences preferences) { + super(loader, preferences); + } + + @Override + public void doHook() throws Exception { + super.doHook(); + + boolean freeze = prefs.getBoolean("freeze_last_seen", false); + + if (!freeze) return; + + XposedBridge.hookMethod(freezeLastSeenMethod(loader), new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (freeze) param.setResult(null); + else super.beforeHookedMethod(param); + } + }); + } +} diff --git a/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/HideTypingRecordingHook.java b/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/HideTypingRecordingHook.java new file mode 100644 index 0000000..2b7e661 --- /dev/null +++ b/app/src/main/java/its/madruga/warevamp/module/hooks/privacy/HideTypingRecordingHook.java @@ -0,0 +1,42 @@ +package its.madruga.warevamp.module.hooks.privacy; + +import static its.madruga.warevamp.module.references.References.typingAndRecordingMethod; + +import androidx.annotation.NonNull; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XSharedPreferences; +import de.robv.android.xposed.XposedBridge; +import its.madruga.warevamp.module.hooks.core.HooksBase; + +public class HideTypingRecordingHook extends HooksBase { + public HideTypingRecordingHook(@NonNull ClassLoader loader, @NonNull XSharedPreferences preferences) { + super(loader, preferences); + } + + @Override + public void doHook() throws Exception { + super.doHook(); + + boolean hide_typing = prefs.getBoolean("hide_typing", false); + boolean hide_recording = prefs.getBoolean("hide_recording", false); + + if (!hide_typing && !hide_recording) return; + + XposedBridge.hookMethod(typingAndRecordingMethod(loader), new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + var p1 = (int) param.args[2]; + if (p1 == 1 && hide_recording) { + param.setResult(null); + return; + } + if (p1 == 0 && hide_typing) { + param.setResult(null); + return; + } + super.beforeHookedMethod(param); + } + }); + } +} diff --git a/app/src/main/java/its/madruga/warevamp/module/references/References.java b/app/src/main/java/its/madruga/warevamp/module/references/References.java index 2fca30b..4cf9483 100644 --- a/app/src/main/java/its/madruga/warevamp/module/references/References.java +++ b/app/src/main/java/its/madruga/warevamp/module/references/References.java @@ -170,7 +170,13 @@ public synchronized static Method newMessageMethod(ClassLoader loader) throws Ex .matcher(new MethodMatcher() .addUsingString("\n") .returnType(String.class))); - if (methodDataList.isEmpty()) throw new Exception("FMessage method not found"); + if (methodDataList.isEmpty()) { + methodDataList = fMessageData.findMethod(new FindMethod() + .matcher(new MethodMatcher() + .paramCount(0) + .returnType(String.class))); + if (methodDataList.isEmpty()) throw new Exception("FMessage method not found"); + } result = methodDataList.get(0).getMethodInstance(loader); saveMethodPath(result, "newMessageMethod"); return result; @@ -180,12 +186,17 @@ public synchronized static Method newMessageWithMediaMethod(ClassLoader loader) Method result = getMethod("newMessageWithMediaMethod"); if (result != null) return result; ClassData fMessageData = dexKitBridge.getClassData(FMessageClass(loader)); - MethodDataList methodDataList = fMessageData.findMethod(new FindMethod() + MethodDataList methodDataList = dexKitBridge.findMethod(new FindMethod() .matcher(new MethodMatcher() - .addUsingNumber(0x200000) - .returnType(String.class))); - if (methodDataList.isEmpty()) throw new Exception("FMessage method not found"); - result = methodDataList.get(0).getMethodInstance(loader); + .addUsingString("Quoted message chatJid is not specified, parentJid is not a UserJid.", StringMatchType.Contains) + )); + for (MethodData m : methodDataList) { + MethodDataList m2 = m.getInvokes(); + for (MethodData n : m2) { + if(n.getClassName().equals(fMessageData.getName()) && n.getReturnType().getName().equals(String.class.getName())) result = n.getMethodInstance(loader); + } + } + if (result == null) throw new Exception("newMessageWithMediaMethod not found"); saveMethodPath(result, "newMessageWithMediaMethod"); return result; } @@ -591,7 +602,7 @@ public synchronized static Method pinnedChatsMethod(ClassLoader loader) throws E public synchronized static Method pinnedHashSetMethod(ClassLoader loader) throws Exception { Method result = getMethod("pinnedHashSetMethod"); if (result != null) return result; - Class cls = getIns().findClassByString(StringMatchType.Contains, loader, "SELECT jid, pinned_time FROM settings"); + Class cls = getIns().findClassByString(StringMatchType.Contains, loader, "getPinnedJids/QUERY"); if (cls == null) throw new Exception("pinnedClassList not found"); result = Arrays.stream(cls.getDeclaredMethods()).filter(m -> m.getReturnType().equals(Set.class)).findFirst().orElse(null); if (result == null) throw new Exception("pinnedHashSetMethod not found"); @@ -699,7 +710,7 @@ public synchronized static Method setPageActiveMethod(ClassLoader loader) throws public synchronized static Method menuStatusClickMethod(ClassLoader loader) throws Exception { Method result = getMethod("menuStatusClickMethod"); if (result != null) return result; - result = getIns().findMethodByString(StringMatchType.Contains, loader, "chatSettingsStore", "systemFeatures"); + result = getIns().findMethodByString(StringMatchType.Contains, loader, "biz_block_header_chat", "Required value was null."); if (result == null) throw new Exception("menuStatusClickMethod not found"); saveMethodPath(result, "menuStatusClickMethod"); return result; @@ -738,6 +749,28 @@ public synchronized static Field menuStyleField(ClassLoader loader) throws Excep return result; } + // Hide Typing and Recording + + public synchronized static Method typingAndRecordingMethod(ClassLoader loader) throws Exception { + Method result = getMethod("typingAndRecordingMethod"); + if (result != null) return result; + result = getIns().findMethodByString(StringMatchType.Contains, loader, "HandleMeComposing/sendComposing; toJid="); + if (result == null) throw new Exception("typingAndRecordingMethod not found"); + saveMethodPath(result, "typingAndRecordingMethod"); + return result; + } + + // Freeze Last Seen + + public synchronized static Method freezeLastSeenMethod(ClassLoader loader) throws Exception { + Method result = getMethod("freezeLastSeenMethod"); + if (result != null) return result; + result = getIns().findMethodByString(StringMatchType.Contains, loader, "presencestatemanager/setAvailable/new-state:"); + if (result == null) throw new Exception("freezeLastSeenMethod not found"); + saveMethodPath(result, "freezeLastSeenMethod"); + return result; + } + public static void start() { ins = new References(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b7e9def..38a04cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ Click for more information. Update Message Deleted + Privacy Features Customization Home Screen • Chat Screen General @@ -73,4 +74,10 @@ Create a view once download button. Remove FLAG_SECURE from Window This function removes the FLAG_SECURE from app windows, allowing unrestricted screenshot and screen recording capabilities. + Hide Recording Audio + When active, the person cannot see that you are recording audio. + Hide Typing + When active, the person cannot see that you are typing. + Freeze last seen + When it\'is enabled, you\'ll don\'t see any presence updates from other users, like typing, recording, online. \ No newline at end of file diff --git a/app/src/main/res/xml/perso_general_fragment.xml b/app/src/main/res/xml/perso_general_fragment.xml index 88db3bf..cdc043f 100644 --- a/app/src/main/res/xml/perso_general_fragment.xml +++ b/app/src/main/res/xml/perso_general_fragment.xml @@ -1,9 +1,5 @@ - + android:title="@string/privacy_features" > + + + \ No newline at end of file diff --git a/change_log.txt b/change_log.txt index 2fb1f51..b4ca14b 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,5 +1,13 @@ | ADDED | -- Download Status Button -- Download View Once Button -- Disable Secure Flags Button \ No newline at end of file +- Hide Typing and Recording +- Freeze last seen + +| FIXED | + +- Download View Once and Status +- Others minor errors + +| NOTICE | + +Until the moment of this update, the module was able to support version 2.25.1.14 of WhatsApp without presenting errors, any problem report in our group \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4ee6081..493114f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ appcompatVersion = "1.6.1" rikkaXMaterial = "2.7.2" rikkaXPreference = "2.0.0" -agp = "8.7.2" +agp = "8.7.3" appcompat = "1.7.0" [libraries]