diff --git a/app/src/main/java/com/wmods/wppenhacer/xposed/core/MainFeatures.java b/app/src/main/java/com/wmods/wppenhacer/xposed/core/MainFeatures.java
index 887f6f15..8755fa49 100644
--- a/app/src/main/java/com/wmods/wppenhacer/xposed/core/MainFeatures.java
+++ b/app/src/main/java/com/wmods/wppenhacer/xposed/core/MainFeatures.java
@@ -43,6 +43,7 @@
import com.wmods.wppenhacer.xposed.features.general.ShareLimit;
import com.wmods.wppenhacer.xposed.features.general.ShowEditMessage;
import com.wmods.wppenhacer.xposed.features.general.StatusDownload;
+import com.wmods.wppenhacer.xposed.features.general.Tasker;
import com.wmods.wppenhacer.xposed.features.general.ViewOnce;
import com.wmods.wppenhacer.xposed.features.privacy.FreezeLastSeen;
import com.wmods.wppenhacer.xposed.features.privacy.GhostMode;
@@ -211,7 +212,8 @@ private static void plugins(@NonNull ClassLoader loader, @NonNull XSharedPrefere
ViewOnce.class,
CallType.class,
MediaPreview.class,
- FilterGroups.class
+ FilterGroups.class,
+ Tasker.class
};
for (var classe : classes) {
diff --git a/app/src/main/java/com/wmods/wppenhacer/xposed/core/Unobfuscator.java b/app/src/main/java/com/wmods/wppenhacer/xposed/core/Unobfuscator.java
index 29564d5d..e353a720 100644
--- a/app/src/main/java/com/wmods/wppenhacer/xposed/core/Unobfuscator.java
+++ b/app/src/main/java/com/wmods/wppenhacer/xposed/core/Unobfuscator.java
@@ -1528,4 +1528,13 @@ public static Class getFilterView(ClassLoader loader) throws Exception {
return results.get(0).getInstance(loader);
});
}
+
+ public static Class loadActionUser(ClassLoader loader) throws Exception {
+ return UnobfuscatorCache.getInstance().getClass(loader, () -> {
+ var results = dexkit.findClass(new FindClass().matcher(new ClassMatcher().addUsingString("UserActions/reportIfBadTime: time=")));
+ if (results.isEmpty()) throw new RuntimeException("ActionUser class not found");
+ return results.get(0).getInstance(loader);
+ });
+ }
+
}
diff --git a/app/src/main/java/com/wmods/wppenhacer/xposed/core/WppCore.java b/app/src/main/java/com/wmods/wppenhacer/xposed/core/WppCore.java
index 564000d5..e72dd058 100644
--- a/app/src/main/java/com/wmods/wppenhacer/xposed/core/WppCore.java
+++ b/app/src/main/java/com/wmods/wppenhacer/xposed/core/WppCore.java
@@ -7,6 +7,7 @@
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.view.Menu;
+import android.widget.Toast;
import androidx.annotation.Nullable;
@@ -18,6 +19,7 @@
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -43,6 +45,7 @@ public class WppCore {
private static Object mContactManager;
private static SharedPreferences privPrefs;
private static Object mStartUpConfig;
+ private static Object mActionUser;
public static void addMenuItemClass(Class> aClass, OnMenuCreate listener) {
var list = listenerMenu.computeIfAbsent(aClass, k -> new ArrayList<>());
@@ -56,6 +59,37 @@ public static void addMenuItemString(String className, OnMenuCreate listener) {
list.add(listener);
}
+ public static Object getConversation() {
+ return mConversation;
+ }
+
+ public static void sendMessage(String number, String message) {
+ try {
+ var senderMethod = ReflectionUtils.findMethodUsingFilterIfExists(mActionUser.getClass(), (method) -> List.class.isAssignableFrom(method.getReturnType()) && ReflectionUtils.findIndexOfType(method.getParameterTypes(), String.class) != -1);
+ if (senderMethod != null) {
+ var userJid = createUserJid(number + "@s.whatsapp.net");
+ if (userJid == null) {
+ Utils.showToast("UserJID not found", Toast.LENGTH_SHORT);
+ return;
+ }
+ var newObject = new Object[senderMethod.getParameterCount()];
+ var index = ReflectionUtils.findIndexOfType(senderMethod.getParameterTypes(), String.class);
+ newObject[index - 1] = 0;
+ newObject[index] = message;
+ newObject[newObject.length - 1] = false;
+ newObject[newObject.length - 2] = false;
+ newObject[newObject.length - 3] = false;
+ var index2 = ReflectionUtils.findIndexOfType(senderMethod.getParameterTypes(), List.class);
+ newObject[index2] = Collections.singletonList(userJid);
+ senderMethod.invoke(mActionUser, newObject);
+ Utils.showToast("Message sent to " + number, Toast.LENGTH_SHORT);
+ }
+ } catch (Exception e) {
+ Utils.showToast("Error in sending message:" + e.getMessage(), Toast.LENGTH_SHORT);
+ XposedBridge.log(e);
+ }
+ }
+
public interface ObjectOnChangeListener {
void onChange(Object object, String type);
@@ -63,95 +97,106 @@ public interface ObjectOnChangeListener {
}
public static void Initialize(ClassLoader loader) throws Exception {
- privPrefs = Utils.getApplication().getSharedPreferences("WaGlobal", Context.MODE_PRIVATE);
+ privPrefs = Utils.getApplication().getSharedPreferences("WaGlobal", Context.MODE_PRIVATE);
- // init Main activity
- XposedBridge.hookAllMethods(XposedHelpers.findClass("com.whatsapp.HomeActivity", loader), "onCreate", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- mainActivity = param.thisObject;
- }
- });
+ // init Main activity
+ XposedBridge.hookAllMethods(XposedHelpers.findClass("com.whatsapp.HomeActivity", loader), "onCreate", new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ mainActivity = param.thisObject;
+ }
+ });
- XposedBridge.hookAllMethods(XposedHelpers.findClass("com.whatsapp.HomeActivity", loader), "onResume", new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- mainActivity = param.thisObject;
- }
- });
-
- XposedHelpers.findAndHookMethod(Activity.class, "onCreateOptionsMenu", Menu.class, new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- for (Class> aClass : listenerMenu.keySet()) {
- if (!aClass.isInstance(param.thisObject)) return;
- for (OnMenuCreate listener : listenerMenu.get(aClass)) {
- listener.onBeforeCreate((Activity) param.thisObject, (Menu) param.args[0]);
- }
+ XposedBridge.hookAllMethods(XposedHelpers.findClass("com.whatsapp.HomeActivity", loader), "onResume", new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ mainActivity = param.thisObject;
+ }
+ });
+
+ XposedHelpers.findAndHookMethod(Activity.class, "onCreateOptionsMenu", Menu.class, new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ for (Class> aClass : listenerMenu.keySet()) {
+ if (!aClass.isInstance(param.thisObject)) return;
+ for (OnMenuCreate listener : listenerMenu.get(aClass)) {
+ listener.onBeforeCreate((Activity) param.thisObject, (Menu) param.args[0]);
}
}
+ }
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- for (Class> aClass : listenerMenu.keySet()) {
- if (!aClass.isInstance(param.thisObject)) return;
- for (OnMenuCreate listener : listenerMenu.get(aClass)) {
- listener.onAfterCreate((Activity) param.thisObject, (Menu) param.args[0]);
- }
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ for (Class> aClass : listenerMenu.keySet()) {
+ if (!aClass.isInstance(param.thisObject)) return;
+ for (OnMenuCreate listener : listenerMenu.get(aClass)) {
+ listener.onAfterCreate((Activity) param.thisObject, (Menu) param.args[0]);
}
}
- });
-
- // init ContactManager
- getContactMethod = Unobfuscator.loadGetContactInfoMethod(loader);
- XposedBridge.hookAllConstructors(getContactMethod.getDeclaringClass(), new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) throws Throwable {
- mContactManager = param.thisObject;
- }
- });
-
- // init UserJID
- var mSendReadClass = XposedHelpers.findClass("com.whatsapp.jobqueue.job.SendReadReceiptJob", loader);
- var subClass = Arrays.stream(mSendReadClass.getConstructors()).filter(c -> c.getParameterTypes().length == 8).findFirst().orElse(null).getParameterTypes()[0];
- mGenJidClass = Arrays.stream(subClass.getFields()).filter(field -> Modifier.isStatic(field.getModifiers())).findFirst().orElse(null).getType();
- mGenJidMethod = Arrays.stream(mGenJidClass.getMethods()).filter(m -> m.getParameterCount() == 1 && !Modifier.isStatic(m.getModifiers())).findFirst().orElse(null);
- // Bottom Dialog
- bottomDialog = Unobfuscator.loadDialogViewClass(loader);
-
- // Conversation
- var onStartMethod = Unobfuscator.loadAntiRevokeOnStartMethod(loader);
- var onResumeMethod = Unobfuscator.loadAntiRevokeOnResumeMethod(loader);
- convChatField = Unobfuscator.loadAntiRevokeConvChatField(loader);
- chatJidField = Unobfuscator.loadAntiRevokeChatJidField(loader);
- XposedBridge.hookMethod(onStartMethod, new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) {
- mConversation = (Activity) param.thisObject;
- for (ObjectOnChangeListener listener : listenerChat) {
- listener.onChange(mConversation, "onStartConversation");
- }
- }
- });
-
- XposedBridge.hookMethod(onResumeMethod, new XC_MethodHook() {
- @Override
- protected void afterHookedMethod(MethodHookParam param) {
- mConversation = (Activity) param.thisObject;
- for (ObjectOnChangeListener listener : listenerChat) {
- listener.onChange(mConversation, "onResumeConversation");
- }
+ }
+ });
+
+ // init ContactManager
+ getContactMethod = Unobfuscator.loadGetContactInfoMethod(loader);
+ XposedBridge.hookAllConstructors(getContactMethod.getDeclaringClass(), new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ mContactManager = param.thisObject;
+ }
+ });
+
+ // init UserJID
+ var mSendReadClass = XposedHelpers.findClass("com.whatsapp.jobqueue.job.SendReadReceiptJob", loader);
+ var subClass = Arrays.stream(mSendReadClass.getConstructors()).filter(c -> c.getParameterTypes().length == 8).findFirst().orElse(null).getParameterTypes()[0];
+ mGenJidClass = Arrays.stream(subClass.getFields()).filter(field -> Modifier.isStatic(field.getModifiers())).findFirst().orElse(null).getType();
+ mGenJidMethod = Arrays.stream(mGenJidClass.getMethods()).filter(m -> m.getParameterCount() == 1 && !Modifier.isStatic(m.getModifiers())).findFirst().orElse(null);
+ // Bottom Dialog
+ bottomDialog = Unobfuscator.loadDialogViewClass(loader);
+
+ // Conversation
+ var onStartMethod = Unobfuscator.loadAntiRevokeOnStartMethod(loader);
+ var onResumeMethod = Unobfuscator.loadAntiRevokeOnResumeMethod(loader);
+ convChatField = Unobfuscator.loadAntiRevokeConvChatField(loader);
+ chatJidField = Unobfuscator.loadAntiRevokeChatJidField(loader);
+ XposedBridge.hookMethod(onStartMethod, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) {
+ mConversation = (Activity) param.thisObject;
+ for (ObjectOnChangeListener listener : listenerChat) {
+ listener.onChange(mConversation, "onStartConversation");
}
- });
-
- // StartUpPrefs
- var startPrefsConfig = Unobfuscator.loadStartPrefsConfig(loader);
- XposedBridge.hookMethod(startPrefsConfig, new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- mStartUpConfig = param.thisObject;
+ }
+ });
+
+ XposedBridge.hookMethod(onResumeMethod, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) {
+ mConversation = (Activity) param.thisObject;
+ for (ObjectOnChangeListener listener : listenerChat) {
+ listener.onChange(mConversation, "onResumeConversation");
}
- });
+ }
+ });
+
+ // StartUpPrefs
+ var startPrefsConfig = Unobfuscator.loadStartPrefsConfig(loader);
+ XposedBridge.hookMethod(startPrefsConfig, new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ mStartUpConfig = param.thisObject;
+ }
+ });
+
+ var actionUser = Unobfuscator.loadActionUser(loader);
+ XposedBridge.hookAllConstructors(actionUser, new XC_MethodHook() {
+ @Override
+ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
+ mActionUser = param.thisObject;
+ XposedBridge.log("mActionUser: " + mActionUser);
+ }
+ });
+
+
}
public static int getDefaultTheme() {
diff --git a/app/src/main/java/com/wmods/wppenhacer/xposed/features/general/Tasker.java b/app/src/main/java/com/wmods/wppenhacer/xposed/features/general/Tasker.java
new file mode 100644
index 00000000..fb459495
--- /dev/null
+++ b/app/src/main/java/com/wmods/wppenhacer/xposed/features/general/Tasker.java
@@ -0,0 +1,94 @@
+package com.wmods.wppenhacer.xposed.features.general;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+
+import com.wmods.wppenhacer.xposed.core.Feature;
+import com.wmods.wppenhacer.xposed.core.Unobfuscator;
+import com.wmods.wppenhacer.xposed.core.Utils;
+import com.wmods.wppenhacer.xposed.core.WppCore;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XSharedPreferences;
+import de.robv.android.xposed.XposedBridge;
+import de.robv.android.xposed.XposedHelpers;
+
+public class Tasker extends Feature {
+ private static Object fMessage;
+
+ public Tasker(@NonNull ClassLoader classLoader, @NonNull XSharedPreferences preferences) {
+ super(classLoader, preferences);
+ }
+
+ @Override
+ public void doHook() throws Throwable {
+ if (!prefs.getBoolean("tasker", false)) return;
+ hookReceiveMessage();
+ registerSenderMessage();
+ }
+
+ @NonNull
+ @Override
+ public String getPluginName() {
+ return "Tasker";
+ }
+
+ private void registerSenderMessage() {
+ IntentFilter filter = new IntentFilter("com.wmods.wppenhacer.MESSAGE_SENT");
+ ContextCompat.registerReceiver(Utils.getApplication(), new SenderMessageBroadcastReceiver(), filter, ContextCompat.RECEIVER_EXPORTED);
+ }
+
+ public void hookReceiveMessage() throws Throwable {
+ var method = Unobfuscator.loadReceiptMethod(classLoader);
+ var method2 = Unobfuscator.loadReceiptOutsideChat(classLoader);
+ var newMessageMethod = Unobfuscator.loadNewMessageMethod(classLoader);
+ var fieldMessageKey = Unobfuscator.loadMessageKeyField(classLoader);
+
+ XposedBridge.hookMethod(method2, new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ fMessage = param.args[0];
+ }
+ });
+
+ XposedBridge.hookMethod(method, new XC_MethodHook() {
+ @Override
+ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+ if (param.args[4] == "sender" || param.args[1] == null) return;
+ var messageKey = fieldMessageKey.get(fMessage);
+ var userJid = XposedHelpers.getObjectField(messageKey, "A00");
+ var rawJid = WppCore.getRawString(userJid);
+ var number = WppCore.stripJID(rawJid);
+ var msg = (String) newMessageMethod.invoke(fMessage);
+ new Handler(Utils.getApplication().getMainLooper()).post(() -> {
+ Intent intent = new Intent("com.wmods.wppenhacer.MESSAGE_RECEIVED");
+ intent.putExtra("number", number);
+ intent.putExtra("message", msg);
+ Utils.getApplication().sendBroadcast(intent);
+ });
+ }
+ });
+
+ }
+
+ public static class SenderMessageBroadcastReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ XposedBridge.log("Message sent");
+ var number = intent.getStringExtra("number");
+ var message = intent.getStringExtra("message");
+ if (number == null || message == null) return;
+ number = number.replaceAll("\\D", "");
+ WppCore.sendMessage(number, message);
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/com/wmods/wppenhacer/xposed/utils/ReflectionUtils.java b/app/src/main/java/com/wmods/wppenhacer/xposed/utils/ReflectionUtils.java
index 81d01a5e..f04a7fd6 100644
--- a/app/src/main/java/com/wmods/wppenhacer/xposed/utils/ReflectionUtils.java
+++ b/app/src/main/java/com/wmods/wppenhacer/xposed/utils/ReflectionUtils.java
@@ -86,7 +86,12 @@ public static Object getField(Field loadProfileInfoField, Object thisObject) {
public static int findIndexOfType(Object[] args, Class> type) {
for (int i = 0; i < args.length; i++) {
- if (args[i] != null && type.isAssignableFrom(args[i].getClass())) return i;
+ if (args[i] == null) continue;
+ if (args[i] instanceof Class) {
+ if (type.isAssignableFrom((Class) args[i])) return i;
+ continue;
+ }
+ if (type.isAssignableFrom(args[i].getClass())) return i;
}
return -1;
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bc173e79..28c7605b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -249,4 +249,6 @@
Call declined
Unable to receive WhatsApp calls
Not answered
+ Enable Tasker Automation
+ Enables the possibility of using intent to receive and send messages in Tasker
diff --git a/app/src/main/res/xml/fragment_general.xml b/app/src/main/res/xml/fragment_general.xml
index b07fe19b..cd2972aa 100644
--- a/app/src/main/res/xml/fragment_general.xml
+++ b/app/src/main/res/xml/fragment_general.xml
@@ -29,6 +29,12 @@
app:iconSpaceReserved="false"
app:key="secondstotime"
app:title="@string/textonahora" />
+
+
+