@@ -88,37 +88,28 @@ private void saveOne(Context context, Object msg) throws Exception {
8888 if (msg == null ) return ;
8989 Class <?> msgClass = msg .getClass ();
9090
91- // 1. Find Key Field (Scan for first NON-NULL field of Key type)
91+ // 1. Find Key Field
9292 Object key = null ;
9393 if (FMessageWpp .Key .TYPE != null ) {
9494 key = getFirstNonNullFieldByType (msg , FMessageWpp .Key .TYPE );
9595 }
96-
97- // Fallback: search by name "key" if type search failed or key type unknown
9896 if (key == null ) {
9997 Field keyField = findField (msgClass , "key" );
10098 if (keyField != null ) key = keyField .get (msg );
10199 }
102-
103100 if (key == null ) return ;
104101
105- // 2. Extract Message ID
106- String msgId = getStr (key , "id" );
107- if (msgId == null ) msgId = getStr (key , "A01" ); // Obfuscated ID
108- if (msgId == null ) {
109- XposedBridge .log ("WAE: msgId not found on Key " + key .getClass ().getName ());
110- return ;
111- }
102+ // 2. Extract Message ID (Key ID)
103+ String keyId = getStr (key , "id" );
104+ if (keyId == null ) keyId = getStr (key , "A01" );
105+ if (keyId == null ) return ;
112106
113107 // 3. Extract RemoteJid / ChatJid
114108 String chatJid = null ;
115109 Object jidObj = getObj (key , "remoteJid" );
116110 if (jidObj == null ) jidObj = getObj (key , "chatJid" );
117- if (jidObj == null ) jidObj = getObj (key , "A00" ); // Obfuscated RemoteJid
118-
111+ if (jidObj == null ) jidObj = getObj (key , "A00" );
119112 if (jidObj != null ) chatJid = jidObj .toString ();
120-
121- // Fix: Ensure JID isn't "false" or "true" due to bad reflection
122113 if (chatJid != null && (chatJid .equalsIgnoreCase ("false" ) || chatJid .equalsIgnoreCase ("true" ))) {
123114 chatJid = null ;
124115 }
@@ -127,20 +118,18 @@ private void saveOne(Context context, Object msg) throws Exception {
127118 boolean fromMe = false ;
128119 Field fmField = findField (key .getClass (), "fromMe" );
129120 if (fmField == null ) fmField = findField (key .getClass (), "isFromMe" );
130- if (fmField == null ) fmField = findField (key .getClass (), "A02" ); // Obfuscated fromMe
131-
121+ if (fmField == null ) fmField = findField (key .getClass (), "A02" );
132122 if (fmField != null ) {
133123 Object v = fmField .get (key );
134124 if (v instanceof Boolean ) fromMe = (Boolean ) v ;
135125 }
136126
137127 // 5. Extract Text Body
138- String text = getStr (msg , "text" );
139- if (text == null ) text = getStr (msg , "body" );
140- if (text == null ) text = getStr (msg , "A0Q" );
128+ String textContent = getStr (msg , "text" );
129+ if (textContent == null ) textContent = getStr (msg , "body" );
130+ if (textContent == null ) textContent = getStr (msg , "A0Q" );
141131
142- // Scan for all strings to find the text
143- if (text == null ) {
132+ if (textContent == null ) {
144133 String bestCandidate = null ;
145134 Class <?> cls = msgClass ;
146135 while (cls != null && cls != Object .class ) {
@@ -159,9 +148,7 @@ private void saveOne(Context context, Object msg) throws Exception {
159148 }
160149 cls = cls .getSuperclass ();
161150 }
162- if (bestCandidate != null ) {
163- text = bestCandidate ;
164- }
151+ if (bestCandidate != null ) textContent = bestCandidate ;
165152 }
166153
167154 // 6. Media Type
@@ -171,78 +158,42 @@ private void saveOne(Context context, Object msg) throws Exception {
171158 if (mtf != null ) {
172159 try { mediaType = mtf .getInt (msg ); } catch (Exception ignored ) {}
173160 }
174-
161+
162+ // 7. Sender JID
175163 String senderJid = fromMe ? "Me" : chatJid ;
176164 Object participant = getObj (msg , "participant" );
177165 if (participant == null ) participant = getObj (msg , "senderJid" );
178166 if (participant == null ) participant = getObj (msg , "A0b" );
179-
180167 if (participant != null ) {
181168 String val = participant .toString ();
182169 if (!val .equalsIgnoreCase ("false" ) && !val .equalsIgnoreCase ("true" )) {
183170 senderJid = val ;
184171 }
185172 }
186173
187- // 5. Extract Text Content
188- String textContent = null ;
189- if (msgObj != null ) {
190- textContent = findLongestString (msgObj );
191- }
192-
193- // 6. Extract Media (if any)
194- int mediaType = -1 ;
195- String mediaCaption = null ;
174+ // 8. Media Details
196175 String mediaPath = null ;
197-
198- // Original media extraction logic
199- Field mtf = findField (msgClass , "mediaType" );
200- if (mtf == null ) mtf = findField (msgClass , "media_wa_type" );
201- if (mtf != null ) {
202- try { mediaType = mtf .getInt (msgObj ); } catch (Exception ignored ) {}
203- }
204-
205- Object mf = getObj (msgObj , "mediaData" );
206- if (mf == null ) mf = getObj (msgObj , "mediaFile" );
176+ Object mf = getObj (msg , "mediaData" );
177+ if (mf == null ) mf = getObj (msg , "mediaFile" );
207178 if (mf instanceof File && ((File ) mf ).exists ()) {
208179 mediaPath = ((File ) mf ).getAbsolutePath ();
209180 }
210181
211- String caption = getStr (msgObj , "caption" );
212- if (caption == null ) caption = getStr (msgObj , "mediaCaption" );
213- if (caption == null ) caption = getStr (msgObj , "A03" );
214- mediaCaption = caption ; // Assign to mediaCaption
182+ String mediaCaption = getStr (msg , "caption" );
183+ if (mediaCaption == null ) mediaCaption = getStr (msg , "mediaCaption" );
184+ if (mediaCaption == null ) mediaCaption = getStr (msg , "A03" );
215185
216- long timestamp = System .currentTimeMillis (); // Assuming current time for deleted message
186+ long timestamp = System .currentTimeMillis ();
217187
218- // --- NEW: Contact Name Resolution ---
188+ // 9. Contact Name Resolution
219189 String contactName = null ;
220190 try {
221- if (chatJid != null ) {
222- if (chatJid .contains ("@g.us" )) {
223- // Group Chat: Try to get Subject
224- // We can try to find the "subject" or "name" field in the chat object if available,
225- // or use a utility if we can find one.
226- // For now, let's try a common trick: query the Contacts database for the Group JID (WaEnhancer often syncs groups)
227- // OR better: use the same ContactHelper logic but inside the hook context
228- contactName = getContactName (context , chatJid );
229- } else {
230- // Individual Chat: Resolve from ContactsContract
231- contactName = getContactName (context , chatJid );
232- }
233- }
234- if (contactName == null && senderJid != null && chatJid .contains ("@g.us" )) {
235- // If in group and sender is known, maybe we want sender name?
236- // But UI wants Title to be Group Name.
237- // We will leave contactName as null if Group Name not found,
238- // and let UI handle Sender Name for the bubble separately (or we can save sender name too?)
239- // For now, let's stick to Chat Title.
240- }
191+ contactName = resolveWaContactName (context , msg , chatJid );
241192 } catch (Throwable t ) {
242193 t .printStackTrace ();
243194 }
244195
245- // Save to Database
196+ // Create and Save
246197 DeletedMessage deletedMessage = new DeletedMessage (
247198 0 , keyId , chatJid , senderJid , timestamp , mediaType , textContent , mediaPath , mediaCaption , fromMe , contactName
248199 );
@@ -366,6 +317,28 @@ private String getStr(Object obj, String name) {
366317 return v instanceof String ? (String ) v : null ;
367318 } catch (Exception e ) { return null ; }
368319 }
320+
321+ // New utility: Get string by scanning all fields
322+ private String findLongestString (Object obj ) {
323+ if (obj == null ) return null ;
324+ String best = null ;
325+ Class <?> cls = obj .getClass ();
326+ while (cls != null && cls != Object .class ) {
327+ for (Field f : cls .getDeclaredFields ()) {
328+ if (f .getType () == String .class ) {
329+ f .setAccessible (true );
330+ try {
331+ String s = (String ) f .get (obj );
332+ if (s != null && s .length () > 0 ) {
333+ if (best == null || s .length () > best .length ()) best = s ;
334+ }
335+ } catch (Exception e ) {}
336+ }
337+ }
338+ cls = cls .getSuperclass ();
339+ }
340+ return best ;
341+ }
369342
370343 private Object getObj (Object obj , String name ) {
371344 try {
@@ -374,6 +347,55 @@ private Object getObj(Object obj, String name) {
374347 return f .get (obj );
375348 } catch (Exception e ) { return null ; }
376349 }
350+
351+ // Internal WA Contact Resolution Helper
352+ private String resolveWaContactName (Context context , Object msgObj , String chatJid ) {
353+ try {
354+ // Strategy 1: Look for a "name" or "subject" field directly in a Chat/Contact object attached to msg
355+ // Often msg has a field 'A0J' or similar that is the Contact/ChatInfo
356+
357+ // Scan fields of msgObj for objects that might be "Contact" or "Chat"
358+ Class <?> msgClass = msgObj .getClass ();
359+ while (msgClass != null && msgClass != Object .class ) {
360+ for (Field f : msgClass .getDeclaredFields ()) {
361+ f .setAccessible (true );
362+ Object fieldVal = f .get (msgObj );
363+ if (fieldVal != null && !f .getType ().isPrimitive () && !f .getType ().getName ().startsWith ("java.lang" )) {
364+ // Check this object for a "name" or "subject" string
365+ String possibleName = getPrivString (fieldVal , "name" );
366+ if (possibleName == null ) possibleName = getPrivString (fieldVal , "subject" );
367+ if (possibleName == null ) possibleName = getPrivString (fieldVal , "A0X" ); // Obfuscated name?
368+ if (possibleName == null ) possibleName = getPrivString (fieldVal , "A0W" );
369+
370+ // Validation: Names usually don't have @ or are not JIDs
371+ if (possibleName != null && !possibleName .contains ("@" ) && possibleName .length () > 0 ) {
372+ XposedBridge .log ("WAE: Potentially found name via reflection: " + possibleName );
373+ return possibleName ;
374+ }
375+ }
376+ }
377+ msgClass = msgClass .getSuperclass ();
378+ }
379+
380+ // Strategy 2: If we failed to find it in msg, fall back to ContactsContract (for individuals)
381+ // But strict cleaning of JID
382+ if (chatJid != null && !chatJid .contains ("@g.us" )) {
383+ return getContactName (context , chatJid );
384+ }
385+
386+ } catch (Exception e ) {
387+ XposedBridge .log ("WAE: ResolveWaContactName Error: " + e .getMessage ());
388+ }
389+ return null ;
390+ }
391+
392+ private String getPrivString (Object obj , String name ) {
393+ try {
394+ Field f = findField (obj .getClass (), name );
395+ if (f != null ) return (String ) f .get (obj );
396+ } catch (Exception e ) {}
397+ return null ;
398+ }
377399
378400 @ Override
379401 public String getPluginName () {
0 commit comments