Skip to content

Commit 73a003a

Browse files
committed
Refactor FMessageWpp and related classes to improve key handling and message retrieval logic
1 parent bd32b8f commit 73a003a

File tree

9 files changed

+95
-77
lines changed

9 files changed

+95
-77
lines changed

app/src/main/java/com/wmods/wppenhacer/xposed/core/WppCore.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,13 @@ public class WppCore {
6868
private static Object mWaJidMapRepository;
6969
private static Method convertJidToLid;
7070
private static Class actionUser;
71+
private static Method cachedMessageStoreKey;
7172

7273

7374
public static void Initialize(ClassLoader loader, XSharedPreferences pref) throws Exception {
7475
privPrefs = Utils.getApplication().getSharedPreferences("WaGlobal", Context.MODE_PRIVATE);
7576
// init UserJID
76-
var mSendReadClass = Unobfuscator.findFirstClassUsingName(loader, StringMatchType.EndsWith,"SendReadReceiptJob");
77+
var mSendReadClass = Unobfuscator.findFirstClassUsingName(loader, StringMatchType.EndsWith, "SendReadReceiptJob");
7778
var subClass = ReflectionUtils.findConstructorUsingFilter(mSendReadClass, (constructor) -> constructor.getParameterCount() == 8).getParameterTypes()[0];
7879
mGenJidClass = ReflectionUtils.findFieldUsingFilter(subClass, (field) -> Modifier.isStatic(field.getModifiers())).getType();
7980
mGenJidMethod = ReflectionUtils.findMethodUsingFilter(mGenJidClass, (method) -> method.getParameterCount() == 1 && !Modifier.isStatic(method.getModifiers()));
@@ -106,8 +107,8 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
106107
});
107108

108109
// CachedMessageStore
109-
var cachedMessageStore = Unobfuscator.loadCachedMessageStore(loader);
110-
XposedBridge.hookAllConstructors(cachedMessageStore, new XC_MethodHook() {
110+
cachedMessageStoreKey = Unobfuscator.loadCachedMessageStoreKey(loader);
111+
XposedBridge.hookAllConstructors(cachedMessageStoreKey.getDeclaringClass(), new XC_MethodHook() {
111112
@Override
112113
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
113114
mCachedMessageStore = param.thisObject;
@@ -401,8 +402,11 @@ public static String getWppContactName(FMessageWpp.UserJid userJid) {
401402
public static Object getFMessageFromKey(Object messageKey) {
402403
if (messageKey == null) return null;
403404
try {
404-
var methodResult = ReflectionUtils.findMethodUsingFilter(mCachedMessageStore.getClass(), (method) -> method.getParameterCount() == 1 && FMessageWpp.Key.TYPE.isAssignableFrom(method.getParameterTypes()[0]) && method.getReturnType() == FMessageWpp.TYPE);
405-
return ReflectionUtils.callMethod(methodResult, mCachedMessageStore, messageKey);
405+
if (mCachedMessageStore == null) {
406+
XposedBridge.log("CachedMessageStore is null");
407+
return null;
408+
}
409+
return cachedMessageStoreKey.invoke(mCachedMessageStore, messageKey);
406410
} catch (Exception e) {
407411
XposedBridge.log(e);
408412
return null;

app/src/main/java/com/wmods/wppenhacer/xposed/core/components/FMessageWpp.java

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public long getRowId() {
105105
public Key getKey() {
106106
try {
107107
if (this.key == null)
108-
this.key = new Key(keyMessage.get(fmessage));
108+
this.key = new Key(keyMessage.get(fmessage), this);
109109
return key;
110110
} catch (Exception e) {
111111
XposedBridge.log(e);
@@ -115,7 +115,7 @@ public Key getKey() {
115115

116116
public Key getOriginalKey() {
117117
try {
118-
return new Key(getOriginalMessageKey.invoke(fmessage));
118+
return new Key(getOriginalMessageKey.invoke(fmessage), this);
119119
} catch (Exception e) {
120120
XposedBridge.log(e);
121121
}
@@ -211,6 +211,11 @@ public static class Key {
211211
* The class type of the key object.
212212
*/
213213
public static Class<?> TYPE;
214+
215+
/**
216+
* The wrapped FMessageWpp instance associated with this key.
217+
*/
218+
private FMessageWpp fmessage;
214219
/**
215220
* The underlying key object from WhatsApp's code.
216221
*/
@@ -238,8 +243,42 @@ public Key(Object key) {
238243
this.messageID = (String) XposedHelpers.getObjectField(key, "A01");
239244
this.isFromMe = XposedHelpers.getBooleanField(key, "A02");
240245
this.remoteJid = new UserJid(XposedHelpers.getObjectField(key, "A00"));
246+
var fmessage = WppCore.getFMessageFromKey(key);
247+
if (fmessage != null) {
248+
this.fmessage = new FMessageWpp(fmessage);
249+
}
250+
}
251+
252+
public Key(Object key, FMessageWpp fmessage) {
253+
this.thisObject = key;
254+
this.messageID = (String) XposedHelpers.getObjectField(key, "A01");
255+
this.isFromMe = XposedHelpers.getBooleanField(key, "A02");
256+
this.remoteJid = new UserJid(XposedHelpers.getObjectField(key, "A00"));
257+
this.fmessage = fmessage;
258+
}
259+
260+
public Key(String messageID, UserJid remoteJid, boolean isFromMe) {
261+
this.messageID = messageID;
262+
this.isFromMe = isFromMe;
263+
this.remoteJid = remoteJid;
264+
var key = XposedHelpers.newInstance(FMessageWpp.Key.TYPE, remoteJid.userJid, messageID, false);
265+
var fmessage = WppCore.getFMessageFromKey(key);
266+
if (fmessage != null) {
267+
this.thisObject = key;
268+
this.fmessage = new FMessageWpp(fmessage);
269+
} else {
270+
key = XposedHelpers.newInstance(FMessageWpp.Key.TYPE, remoteJid.phoneJid, messageID, false);
271+
fmessage = WppCore.getFMessageFromKey(key);
272+
if (fmessage != null) {
273+
this.thisObject = key;
274+
this.fmessage = new FMessageWpp(fmessage);
275+
}
276+
}
241277
}
242278

279+
public FMessageWpp getFMessage() {
280+
return fmessage;
281+
}
243282
}
244283

245284
public static class UserJid {

app/src/main/java/com/wmods/wppenhacer/xposed/core/db/MessageHistory.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,10 @@ public static class MessageSeenItem {
242242
public FMessageWpp getFMessage() {
243243
if (fMessageWpp == null) {
244244
try {
245-
var userJid = WppCore.getUserJidFromPhoneJid(WppCore.createUserJid(jid));
246-
if (userJid == null) return null;
247-
var key = XposedHelpers.newInstance(FMessageWpp.Key.TYPE, userJid, message, false);
248-
var fmessageObj = WppCore.getFMessageFromKey(key);
249-
fMessageWpp = new FMessageWpp(fmessageObj);
245+
var userJid = new FMessageWpp.UserJid(jid);
246+
if (userJid.isNull()) return null;
247+
fMessageWpp = new FMessageWpp.Key(message, userJid, false).getFMessage();
250248
} catch (Exception ignored) {
251-
252249
}
253250
}
254251
return fMessageWpp;

app/src/main/java/com/wmods/wppenhacer/xposed/core/devkit/Unobfuscator.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import android.graphics.drawable.Drawable;
88
import android.hardware.SensorEventListener;
99
import android.net.Uri;
10-
import android.util.Log;
11-
import android.view.ContextMenu;
1210
import android.view.LayoutInflater;
1311
import android.view.Menu;
1412
import android.view.MenuInflater;
@@ -47,7 +45,6 @@
4745
import java.util.ArrayList;
4846
import java.util.Arrays;
4947
import java.util.Calendar;
50-
import java.util.Collection;
5148
import java.util.Collections;
5249
import java.util.Date;
5350
import java.util.HashMap;
@@ -1838,12 +1835,12 @@ public static synchronized Method loadStateChangeMethod(ClassLoader classLoader)
18381835
return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> findFirstMethodUsingStrings(classLoader, StringMatchType.Contains, "presencestatemanager/startTransitionToUnavailable/new-state"));
18391836
}
18401837

1841-
public static synchronized Class loadCachedMessageStore(ClassLoader loader) throws Exception {
1842-
return UnobfuscatorCache.getInstance().getClass(loader, () -> {
1843-
var cacheMsClass = findFirstClassUsingStrings(loader, StringMatchType.Contains, "CachedMessageStore/getMessage/key");
1844-
if (cacheMsClass == null)
1838+
public static synchronized Method loadCachedMessageStoreKey(ClassLoader loader) throws Exception {
1839+
return UnobfuscatorCache.getInstance().getMethod(loader, () -> {
1840+
var method = findFirstMethodUsingStrings(loader, StringMatchType.Contains, "CachedMessageStore/getAvailableMessage/key");
1841+
if (method == null)
18451842
throw new RuntimeException("CachedMessageStore class not found");
1846-
return cacheMsClass;
1843+
return method;
18471844
});
18481845
}
18491846

app/src/main/java/com/wmods/wppenhacer/xposed/features/general/SeenTick.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void doHook() throws Throwable {
8989

9090
WaJobManagerMethod = Unobfuscator.loadBlueOnReplayWaJobManagerMethod(classLoader);
9191

92-
mSendReadClass = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith,"SendReadReceiptJob");
92+
mSendReadClass = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "SendReadReceiptJob");
9393

9494
// hook instance of WaJobManager;
9595

@@ -339,9 +339,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
339339
var keyClass = FMessageWpp.Key.TYPE;
340340
var fieldType = ReflectionUtils.getFieldByType(param.thisObject.getClass(), keyClass);
341341
var keyMessage = ReflectionUtils.getObjectField(fieldType, param.thisObject);
342-
var fMessageObj = WppCore.getFMessageFromKey(keyMessage);
343-
if (fMessageObj == null) return;
344-
var fMessage = new FMessageWpp(fMessageObj);
342+
var fMessage = new FMessageWpp.Key(keyMessage).getFMessage();
345343
var rawJid = fMessage.getKey().remoteJid.getPhoneRawString();
346344
var messageID = fMessage.getKey().messageID;
347345
MessageHistory.getInstance().updateViewedMessage(rawJid, messageID, MessageHistory.MessageType.VIEW_ONCE_TYPE, true);
@@ -362,7 +360,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
362360

363361
private void hookOnSendMessages() throws Exception {
364362
var messageJobMethod = Unobfuscator.loadBlueOnReplayMessageJobMethod(classLoader);
365-
var messageSendClass = Unobfuscator.findFirstClassUsingName(classLoader,StringMatchType.Contains,"SendE2EMessageJob");
363+
var messageSendClass = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.Contains, "SendE2EMessageJob");
366364

367365
XposedBridge.hookMethod(messageJobMethod, new XC_MethodHook() {
368366
@Override
@@ -434,8 +432,6 @@ private void sendBlueTickMsg(FMessageWpp.UserJid userJid, ArrayList<FMessageWpp>
434432

435433
WppCore.setPrivBoolean(messageIds[0] + "_rpass", true);
436434

437-
logDebug(userJid);
438-
439435
Object sendJob = XposedHelpers.newInstance(
440436
mSendReadClass, userJid.userJid, participant, null, null, messageIds, -1, 1L, false
441437
);
@@ -472,7 +468,7 @@ private void sendBlueTickMedia(FMessageWpp fMessage) {
472468
if (userJid.isGroup()) {
473469
participant = fMessage.getUserJid().userJid;
474470
}
475-
var sendPlayerClass = Unobfuscator.findFirstClassUsingName(classLoader,StringMatchType.Contains,"SendPlayedReceiptJob");
471+
var sendPlayerClass = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.Contains, "SendPlayedReceiptJob");
476472
var constructor = sendPlayerClass.getDeclaredConstructors()[0];
477473
var classParticipantInfo = constructor.getParameterTypes()[0];
478474
var rowsId = new Long[]{fMessage.getRowId()};

app/src/main/java/com/wmods/wppenhacer/xposed/features/general/Tasker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public void hookReceiveMessage() throws Throwable {
6969
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
7070
if (param.args[4] == "sender" || param.args[1] == null || param.args[3] == null)
7171
return;
72-
var fMessage = new FMessageWpp(WppCore.getFMessageFromKey(param.args[3]));
72+
var fMessage = new FMessageWpp.Key(param.args[3]).getFMessage();
7373
var userJid = fMessage.getKey().remoteJid;
7474
var name = WppCore.getContactName(userJid);
7575
var number = userJid.getPhoneNumber();

app/src/main/java/com/wmods/wppenhacer/xposed/features/media/DownloadViewOnce.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
100100
var keyClass = FMessageWpp.Key.TYPE;
101101
var fieldType = ReflectionUtils.getFieldByType(param.thisObject.getClass(), keyClass);
102102
var keyMessageObj = ReflectionUtils.getObjectField(fieldType, param.thisObject);
103-
var fmessageObj = WppCore.getFMessageFromKey(keyMessageObj);
104-
var fmessage = new FMessageWpp(fmessageObj);
103+
var fmessage = new FMessageWpp.Key(keyMessageObj).getFMessage();
105104
var file = fmessage.getMediaFile();
106105
if (file == null) {
107106
Utils.showToast(Utils.getApplication().getString(ResId.string.download_not_available), 1);

app/src/main/java/com/wmods/wppenhacer/xposed/features/privacy/HideReceipt.java

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.wmods.wppenhacer.xposed.core.db.MessageHistory;
99
import com.wmods.wppenhacer.xposed.core.devkit.Unobfuscator;
1010
import com.wmods.wppenhacer.xposed.features.customization.HideSeenView;
11+
import com.wmods.wppenhacer.xposed.utils.DebugUtils;
1112
import com.wmods.wppenhacer.xposed.utils.ReflectionUtils;
1213

1314
import java.lang.reflect.Method;
@@ -27,40 +28,32 @@ public void doHook() throws Exception {
2728
var ghostmode = WppCore.getPrivBoolean("ghostmode", false);
2829
var hideread = prefs.getBoolean("hideread", false);
2930

31+
logDebug("hideReceipt: " + hideReceipt + ", ghostmode: " + ghostmode + ", hideread: " + hideread);
32+
3033
var method = Unobfuscator.loadReceiptMethod(classLoader);
3134
logDebug("hook method:" + Unobfuscator.getMethodDescriptor(method));
32-
var method2 = Unobfuscator.loadReceiptOutsideChat(classLoader);
33-
logDebug("Outside Chat: " + Unobfuscator.getMethodDescriptor(method2));
34-
var mInChat = Unobfuscator.loadReceiptInChat(classLoader);
35-
logDebug("In Chat: " + Unobfuscator.getMethodDescriptor(mInChat));
3635

3736
XposedBridge.hookMethod(method, new XC_MethodHook() {
3837
@Override
3938
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
40-
if (!ReflectionUtils.isCalledFromMethod(method2) && !ReflectionUtils.isCalledFromMethod(mInChat))
41-
return;
39+
var userJid = ReflectionUtils.getArg(param.args, classLoader.loadClass("com.whatsapp.jid.Jid"), 0);
40+
var currentUserJid = new FMessageWpp.UserJid(userJid);
4241
var key = ReflectionUtils.getArg(param.args, FMessageWpp.Key.TYPE, 0);
43-
var messageKey = new FMessageWpp.Key(key);
44-
var userJid = messageKey.remoteJid;
45-
var privacy = CustomPrivacy.getJSON(userJid.getPhoneNumber());
42+
var fmessage = new FMessageWpp.Key(key).getFMessage();
43+
currentUserJid = fmessage.getKey().remoteJid;
44+
if (MessageHistory.getInstance().getHideSeenMessage(fmessage.getKey().remoteJid.getPhoneRawString(), fmessage.getKey().messageID, fmessage.isViewOnce() ? MessageHistory.MessageType.VIEW_ONCE_TYPE : MessageHistory.MessageType.MESSAGE_TYPE) != null) {
45+
return;
46+
}
47+
var privacy = CustomPrivacy.getJSON(currentUserJid.getPhoneNumber());
4648
var customHideReceipt = privacy.optBoolean("HideReceipt", hideReceipt);
47-
var customHideRead = privacy.optBoolean("HideSeen", hideread);
4849
var msgTypeIdx = ReflectionUtils.findIndexOfType(((Method) param.method).getParameterTypes(), String.class);
50+
var customHideRead = privacy.optBoolean("HideSeen", hideread);
4951
if (param.args[msgTypeIdx] != "sender" && (customHideReceipt || ghostmode)) {
50-
if (!ReflectionUtils.isCalledFromMethod(method2) && ReflectionUtils.isCalledFromMethod(mInChat) && !customHideRead) {
51-
return;
52-
}
53-
param.args[msgTypeIdx] = "inactive";
52+
if (WppCore.getCurrentConversation() == null || customHideRead)
53+
param.args[msgTypeIdx] = "inactive";
5454
}
5555
if (param.args[msgTypeIdx] == "inactive") {
56-
Object fmessageObj = WppCore.getFMessageFromKey(key);
57-
if (fmessageObj == null) return;
58-
var fmessage = new FMessageWpp(fmessageObj);
59-
var messageId = fmessage.getKey().messageID;
60-
MessageHistory.getInstance().insertHideSeenMessage(userJid.getPhoneRawString(), messageId, MessageHistory.MessageType.MESSAGE_TYPE, false);
61-
if (fmessage.isViewOnce()) {
62-
MessageHistory.getInstance().insertHideSeenMessage(userJid.getPhoneRawString(), messageId, MessageHistory.MessageType.VIEW_ONCE_TYPE, false);
63-
}
56+
MessageHistory.getInstance().insertHideSeenMessage(currentUserJid.getPhoneRawString(), fmessage.getKey().messageID, fmessage.isViewOnce() ? MessageHistory.MessageType.VIEW_ONCE_TYPE : MessageHistory.MessageType.MESSAGE_TYPE, false);
6457
HideSeenView.updateAllBubbleViews();
6558
}
6659
}

0 commit comments

Comments
 (0)