@periskope/baileys 7.0.0-beta-1 → 7.0.0-beta-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/lib/Defaults/index.d.ts +0 -5
  2. package/lib/Defaults/index.d.ts.map +1 -1
  3. package/lib/Defaults/index.js +2 -8
  4. package/lib/Defaults/index.js.map +1 -1
  5. package/lib/Signal/Group/queue-job.d.ts +0 -1
  6. package/lib/Signal/Group/queue-job.d.ts.map +1 -1
  7. package/lib/Signal/Group/queue-job.js +0 -3
  8. package/lib/Signal/Group/queue-job.js.map +1 -1
  9. package/lib/Signal/Group/sender-key-state.d.ts.map +1 -1
  10. package/lib/Signal/Group/sender-key-state.js +1 -6
  11. package/lib/Signal/Group/sender-key-state.js.map +1 -1
  12. package/lib/Signal/libsignal.d.ts.map +1 -1
  13. package/lib/Signal/libsignal.js +9 -147
  14. package/lib/Signal/libsignal.js.map +1 -1
  15. package/lib/Socket/business.d.ts +7 -18
  16. package/lib/Socket/business.d.ts.map +1 -1
  17. package/lib/Socket/business.js +1 -122
  18. package/lib/Socket/business.js.map +1 -1
  19. package/lib/Socket/chats.d.ts +2 -8
  20. package/lib/Socket/chats.d.ts.map +1 -1
  21. package/lib/Socket/chats.js +1 -38
  22. package/lib/Socket/chats.js.map +1 -1
  23. package/lib/Socket/communities.d.ts +4 -17
  24. package/lib/Socket/communities.d.ts.map +1 -1
  25. package/lib/Socket/communities.js +0 -44
  26. package/lib/Socket/communities.js.map +1 -1
  27. package/lib/Socket/groups.d.ts +2 -7
  28. package/lib/Socket/groups.d.ts.map +1 -1
  29. package/lib/Socket/index.d.ts +4 -17
  30. package/lib/Socket/index.d.ts.map +1 -1
  31. package/lib/Socket/messages-recv.d.ts +4 -11
  32. package/lib/Socket/messages-recv.d.ts.map +1 -1
  33. package/lib/Socket/messages-recv.js +7 -70
  34. package/lib/Socket/messages-recv.js.map +1 -1
  35. package/lib/Socket/messages-send.d.ts +4 -11
  36. package/lib/Socket/messages-send.d.ts.map +1 -1
  37. package/lib/Socket/messages-send.js +55 -443
  38. package/lib/Socket/messages-send.js.map +1 -1
  39. package/lib/Socket/newsletter.d.ts +2 -7
  40. package/lib/Socket/newsletter.d.ts.map +1 -1
  41. package/lib/Socket/socket.d.ts +2 -2
  42. package/lib/Socket/socket.d.ts.map +1 -1
  43. package/lib/Socket/socket.js +24 -146
  44. package/lib/Socket/socket.js.map +1 -1
  45. package/lib/Socket/usync.d.ts +2 -2
  46. package/lib/Types/Auth.d.ts +0 -1
  47. package/lib/Types/Auth.d.ts.map +1 -1
  48. package/lib/Types/Chat.d.ts +0 -3
  49. package/lib/Types/Chat.d.ts.map +1 -1
  50. package/lib/Types/Chat.js.map +1 -1
  51. package/lib/Types/Message.d.ts +1 -21
  52. package/lib/Types/Message.d.ts.map +1 -1
  53. package/lib/Types/Signal.d.ts +0 -20
  54. package/lib/Types/Signal.d.ts.map +1 -1
  55. package/lib/Utils/chat-utils.d.ts.map +1 -1
  56. package/lib/Utils/chat-utils.js +0 -17
  57. package/lib/Utils/chat-utils.js.map +1 -1
  58. package/lib/Utils/decode-wa-message.d.ts +0 -5
  59. package/lib/Utils/decode-wa-message.d.ts.map +1 -1
  60. package/lib/Utils/decode-wa-message.js +3 -51
  61. package/lib/Utils/decode-wa-message.js.map +1 -1
  62. package/lib/Utils/messages-media.d.ts.map +1 -1
  63. package/lib/Utils/messages-media.js +1 -4
  64. package/lib/Utils/messages-media.js.map +1 -1
  65. package/lib/Utils/messages.d.ts.map +1 -1
  66. package/lib/Utils/messages.js +1 -21
  67. package/lib/Utils/messages.js.map +1 -1
  68. package/package.json +2 -4
@@ -4,7 +4,6 @@ import { proto } from '../../WAProto/index.js';
4
4
  import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
5
5
  import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
6
6
  import { getUrlInfo } from '../Utils/link-preview.js';
7
- import { makeKeyedMutex } from '../Utils/make-mutex.js';
8
7
  import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, isJidUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
9
8
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
10
9
  import { makeGroupsSocket } from './groups.js';
@@ -18,8 +17,6 @@ export const makeMessagesSocket = (config) => {
18
17
  stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
19
18
  useClones: false
20
19
  });
21
- // Prevent race conditions in Signal session encryption by user
22
- const encryptionMutex = makeKeyedMutex();
23
20
  let mediaConn;
24
21
  const refreshMediaConn = async (forceGet = false) => {
25
22
  const media = await mediaConn;
@@ -111,34 +108,6 @@ export const makeMessagesSocket = (config) => {
111
108
  const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self';
112
109
  await sendReceipts(keys, readType);
113
110
  };
114
- /**
115
- * Deduplicate JIDs when both LID and PN versions exist for same user
116
- * Prefers LID over PN to maintain single encryption layer
117
- */
118
- const deduplicateLidPnJids = (jids) => {
119
- const lidUsers = new Set();
120
- const filteredJids = [];
121
- // Collect all LID users
122
- for (const jid of jids) {
123
- if (jid.includes('@lid')) {
124
- const user = jidDecode(jid)?.user;
125
- if (user)
126
- lidUsers.add(user);
127
- }
128
- }
129
- // Filter out PN versions when LID exists
130
- for (const jid of jids) {
131
- if (jid.includes('@s.whatsapp.net')) {
132
- const user = jidDecode(jid)?.user;
133
- if (user && lidUsers.has(user)) {
134
- logger.debug({ jid }, 'Skipping PN - LID version exists');
135
- continue;
136
- }
137
- }
138
- filteredJids.push(jid);
139
- }
140
- return filteredJids;
141
- };
142
111
  /** Fetch all the devices we've to send a message to */
143
112
  const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
144
113
  const deviceResults = [];
@@ -146,33 +115,14 @@ export const makeMessagesSocket = (config) => {
146
115
  logger.debug('not using cache for devices');
147
116
  }
148
117
  const toFetch = [];
149
- // Deduplicate and normalize JIDs
150
- jids = deduplicateLidPnJids(Array.from(new Set(jids)));
118
+ jids = Array.from(new Set(jids));
151
119
  for (let jid of jids) {
152
- const decoded = jidDecode(jid);
153
- const user = decoded?.user;
154
- const device = decoded?.device;
155
- const isExplicitDevice = typeof device === 'number' && device >= 0;
156
- // Handle explicit device JIDs directly
157
- if (isExplicitDevice && user) {
158
- deviceResults.push({
159
- user,
160
- device,
161
- wireJid: jid // Preserve exact JID format for wire protocol
162
- });
163
- continue;
164
- }
165
- // For user JIDs, normalize and prepare for device enumeration
120
+ const user = jidDecode(jid)?.user;
166
121
  jid = jidNormalizedUser(jid);
167
122
  if (useCache) {
168
123
  const devices = userDevicesCache.get(user);
169
124
  if (devices) {
170
- const isLidJid = jid.includes('@lid');
171
- const devicesWithWire = devices.map(d => ({
172
- ...d,
173
- wireJid: isLidJid ? jidEncode(d.user, 'lid', d.device) : jidEncode(d.user, 's.whatsapp.net', d.device)
174
- }));
175
- deviceResults.push(...devicesWithWire);
125
+ deviceResults.push(...devices);
176
126
  logger.trace({ user }, 'using cache for devices');
177
127
  }
178
128
  else {
@@ -186,14 +136,6 @@ export const makeMessagesSocket = (config) => {
186
136
  if (!toFetch.length) {
187
137
  return deviceResults;
188
138
  }
189
- const requestedLidUsers = new Set();
190
- for (const jid of toFetch) {
191
- if (jid.includes('@lid')) {
192
- const user = jidDecode(jid)?.user;
193
- if (user)
194
- requestedLidUsers.add(user);
195
- }
196
- }
197
139
  const query = new USyncQuery().withContext('message').withDeviceProtocol();
198
140
  for (const jid of toFetch) {
199
141
  query.withUser(new USyncUser().withId(jid));
@@ -205,26 +147,7 @@ export const makeMessagesSocket = (config) => {
205
147
  for (const item of extracted) {
206
148
  deviceMap[item.user] = deviceMap[item.user] || [];
207
149
  deviceMap[item.user]?.push(item);
208
- }
209
- // Process each user's devices as a group for bulk LID migration
210
- for (const [user, userDevices] of Object.entries(deviceMap)) {
211
- const isLidUser = requestedLidUsers.has(user);
212
- // Process all devices for this user
213
- for (const item of userDevices) {
214
- const finalWireJid = isLidUser
215
- ? jidEncode(user, 'lid', item.device)
216
- : jidEncode(item.user, 's.whatsapp.net', item.device);
217
- deviceResults.push({
218
- ...item,
219
- wireJid: finalWireJid
220
- });
221
- logger.debug({
222
- user: item.user,
223
- device: item.device,
224
- finalWireJid,
225
- usedLid: isLidUser
226
- }, 'Processed device with LID priority');
227
- }
150
+ deviceResults.push(item);
228
151
  }
229
152
  for (const key in deviceMap) {
230
153
  userDevicesCache.set(key, deviceMap[key]);
@@ -232,179 +155,24 @@ export const makeMessagesSocket = (config) => {
232
155
  }
233
156
  return deviceResults;
234
157
  };
235
- // Helper to check if JID has migrated LID session
236
- const checkForMigratedLidSession = async (jid) => {
237
- if (!jid.includes('@s.whatsapp.net'))
238
- return false;
239
- const lidMapping = signalRepository.getLIDMappingStore();
240
- const lidForPN = await lidMapping.getLIDForPN(jid);
241
- if (!lidForPN?.includes('@lid'))
242
- return false;
243
- const lidSignalId = signalRepository.jidToSignalProtocolAddress(lidForPN);
244
- const lidSessions = await authState.keys.get('session', [lidSignalId]);
245
- return !!lidSessions[lidSignalId];
246
- };
247
158
  const assertSessions = async (jids, force) => {
248
159
  let didFetchNewSession = false;
249
- const jidsRequiringFetch = [];
250
- // Apply same deduplication as in getUSyncDevices
251
- jids = deduplicateLidPnJids(jids);
160
+ let jidsRequiringFetch = [];
252
161
  if (force) {
253
- // Check which sessions are missing (with LID migration check)
254
- const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid));
255
- const sessions = await authState.keys.get('session', addrs);
256
- // Helper to check session for a JID
257
- const checkJidSession = async (jid) => {
258
- const signalId = signalRepository.jidToSignalProtocolAddress(jid);
259
- let hasSession = !!sessions[signalId];
260
- // Check for migrated LID session if PN session missing
261
- if (!hasSession) {
262
- hasSession = await checkForMigratedLidSession(jid);
263
- if (hasSession) {
264
- logger.debug({ jid }, 'Found migrated LID session during force assert, skipping PN fetch');
265
- }
266
- }
267
- // Add to fetch list if no session exists
268
- if (!hasSession) {
269
- if (jid.includes('@lid')) {
270
- logger.debug({ jid }, 'No LID session found, will create new LID session');
271
- }
272
- jidsRequiringFetch.push(jid);
273
- }
274
- };
275
- // Process all JIDs
276
- for (const jid of jids) {
277
- await checkJidSession(jid);
278
- }
162
+ jidsRequiringFetch = jids;
279
163
  }
280
164
  else {
281
- const lidMapping = signalRepository.getLIDMappingStore();
282
165
  const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid));
283
166
  const sessions = await authState.keys.get('session', addrs);
284
- // Group JIDs by user for bulk migration
285
- const userGroups = new Map();
286
167
  for (const jid of jids) {
287
- const user = jidNormalizedUser(jid);
288
- if (!userGroups.has(user)) {
289
- userGroups.set(user, []);
290
- }
291
- userGroups.get(user).push(jid);
292
- }
293
- // Helper to check LID mapping for a user
294
- const checkUserLidMapping = async (user, userJids) => {
295
- if (!userJids.some(jid => jid.includes('@s.whatsapp.net'))) {
296
- return { shouldMigrate: false, lidForPN: undefined };
297
- }
298
- try {
299
- const mapping = await lidMapping.getLIDForPN(user);
300
- if (mapping?.includes('@lid')) {
301
- logger.debug({ user, lidForPN: mapping, deviceCount: userJids.length }, 'User has LID mapping - preparing bulk migration');
302
- return { shouldMigrate: true, lidForPN: mapping };
303
- }
304
- }
305
- catch (error) {
306
- logger.debug({ user, error }, 'Failed to check LID mapping for user');
307
- }
308
- return { shouldMigrate: false, lidForPN: undefined };
309
- };
310
- // Helper to migrate a single device
311
- const migrateDeviceToLid = async (jid, lidForPN) => {
312
- if (!jid.includes('@s.whatsapp.net'))
313
- return;
314
- try {
315
- const jidDecoded = jidDecode(jid);
316
- const deviceId = jidDecoded?.device || 0;
317
- const lidDecoded = jidDecode(lidForPN);
318
- const lidWithDevice = jidEncode(lidDecoded?.user, 'lid', deviceId);
319
- await signalRepository.migrateSession(jid, lidWithDevice);
320
- logger.debug({ fromJid: jid, toJid: lidWithDevice }, 'Migrated device session to LID');
321
- // Delete PN session after successful migration
322
- try {
323
- await signalRepository.deleteSession(jid);
324
- logger.debug({ deletedPNSession: jid }, 'Deleted PN session after migration');
325
- }
326
- catch (deleteError) {
327
- logger.warn({ jid, error: deleteError }, 'Failed to delete PN session');
328
- }
329
- }
330
- catch (migrationError) {
331
- logger.warn({ jid, error: migrationError }, 'Failed to migrate device session');
332
- }
333
- };
334
- // Process each user group for potential bulk LID migration
335
- for (const [user, userJids] of userGroups) {
336
- const mappingResult = await checkUserLidMapping(user, userJids);
337
- const shouldMigrateUser = mappingResult.shouldMigrate;
338
- const lidForPN = mappingResult.lidForPN;
339
- // Migrate all devices for this user if LID mapping exists
340
- if (shouldMigrateUser && lidForPN) {
341
- // Migrate each device individually
342
- for (const jid of userJids) {
343
- await migrateDeviceToLid(jid, lidForPN);
344
- }
345
- logger.info({
346
- user,
347
- lidMapping: lidForPN,
348
- deviceCount: userJids.length
349
- }, 'Completed migration attempt for user devices');
350
- }
351
- // Helper to check session for migrated user
352
- const checkMigratedSession = async (jid) => {
353
- const signalId = signalRepository.jidToSignalProtocolAddress(jid);
354
- let hasSession = !!sessions[signalId];
355
- let jidToFetch = jid;
356
- // Check if we should use migrated LID session instead
357
- if (shouldMigrateUser && lidForPN && jid.includes('@s.whatsapp.net')) {
358
- const originalDecoded = jidDecode(jid);
359
- const deviceId = originalDecoded?.device || 0;
360
- const lidDecoded = jidDecode(lidForPN);
361
- const lidWithDevice = jidEncode(lidDecoded?.user, 'lid', deviceId);
362
- // Check if LID session exists
363
- const lidSignalId = signalRepository.jidToSignalProtocolAddress(lidWithDevice);
364
- const lidSessions = await authState.keys.get('session', [lidSignalId]);
365
- hasSession = !!lidSessions[lidSignalId];
366
- jidToFetch = lidWithDevice;
367
- if (hasSession) {
368
- logger.debug({ originalJid: jid, lidJid: lidWithDevice }, '✅ Found bulk-migrated LID session');
369
- }
370
- }
371
- // Add to fetch list if no session exists
372
- if (!hasSession) {
373
- jidsRequiringFetch.push(jidToFetch);
374
- logger.debug({ jid: jidToFetch, originalJid: jid !== jidToFetch ? jid : undefined }, 'Adding to session fetch list');
375
- }
376
- };
377
- // Now check which sessions need to be fetched for this user
378
- for (const jid of userJids) {
379
- await checkMigratedSession(jid);
168
+ const signalId = signalRepository.jidToSignalProtocolAddress(jid);
169
+ if (!sessions[signalId]) {
170
+ jidsRequiringFetch.push(jid);
380
171
  }
381
172
  }
382
173
  }
383
174
  if (jidsRequiringFetch.length) {
384
175
  logger.debug({ jidsRequiringFetch }, 'fetching sessions');
385
- // DEBUG: Check if there are PN versions of LID users being fetched
386
- const lidUsersBeingFetched = new Set();
387
- const pnUsersBeingFetched = new Set();
388
- for (const jid of jidsRequiringFetch) {
389
- const user = jidDecode(jid)?.user;
390
- if (user) {
391
- if (jid.includes('@lid')) {
392
- lidUsersBeingFetched.add(user);
393
- }
394
- else if (jid.includes('@s.whatsapp.net')) {
395
- pnUsersBeingFetched.add(user);
396
- }
397
- }
398
- }
399
- // Find overlaps
400
- const overlapping = Array.from(pnUsersBeingFetched).filter(user => lidUsersBeingFetched.has(user));
401
- if (overlapping.length > 0) {
402
- logger.warn({
403
- overlapping,
404
- lidUsersBeingFetched: Array.from(lidUsersBeingFetched),
405
- pnUsersBeingFetched: Array.from(pnUsersBeingFetched)
406
- }, 'Fetching both LID and PN sessions for same users');
407
- }
408
176
  const result = await query({
409
177
  tag: 'iq',
410
178
  attrs: {
@@ -448,132 +216,43 @@ export const makeMessagesSocket = (config) => {
448
216
  });
449
217
  return msgId;
450
218
  };
451
- const createParticipantNodes = async (jids, message, extraAttrs, dsmMessage) => {
219
+ const createParticipantNodes = async (jids, message, extraAttrs) => {
452
220
  let patched = await patchMessageBeforeSending(message, jids);
453
221
  if (!Array.isArray(patched)) {
454
222
  patched = jids ? jids.map(jid => ({ recipientJid: jid, ...patched })) : [patched];
455
223
  }
456
224
  let shouldIncludeDeviceIdentity = false;
457
- const meId = authState.creds.me.id;
458
- const meLid = authState.creds.me?.lid;
459
- const meLidUser = meLid ? jidDecode(meLid)?.user : null;
460
- const devicesByUser = new Map();
461
- for (const patchedMessageWithJid of patched) {
462
- const { recipientJid: wireJid, ...patchedMessage } = patchedMessageWithJid;
463
- if (!wireJid)
464
- continue;
465
- // Extract user from JID for grouping
466
- const decoded = jidDecode(wireJid);
467
- const user = decoded?.user;
468
- if (!user)
469
- continue;
470
- if (!devicesByUser.has(user)) {
471
- devicesByUser.set(user, []);
472
- }
473
- devicesByUser.get(user).push({ recipientJid: wireJid, patchedMessage });
474
- }
475
- // Process each user's devices sequentially, but different users in parallel
476
- const userEncryptionPromises = Array.from(devicesByUser.entries()).map(([user, userDevices]) => encryptionMutex.mutex(user, async () => {
477
- logger.debug({ user, deviceCount: userDevices.length }, 'Acquiring encryption lock for user devices');
478
- const userNodes = [];
479
- // Helper to get encryption JID with LID migration
480
- const getEncryptionJid = async (wireJid) => {
481
- if (!wireJid.includes('@s.whatsapp.net'))
482
- return wireJid;
483
- try {
484
- const lidMapping = signalRepository.getLIDMappingStore();
485
- const lidForPN = await lidMapping.getLIDForPN(wireJid);
486
- if (!lidForPN?.includes('@lid'))
487
- return wireJid;
488
- // Preserve device ID from original wire JID
489
- const wireDecoded = jidDecode(wireJid);
490
- const deviceId = wireDecoded?.device || 0;
491
- const lidDecoded = jidDecode(lidForPN);
492
- const lidWithDevice = jidEncode(lidDecoded?.user, 'lid', deviceId);
493
- // Migrate session to LID for unified encryption layer
494
- try {
495
- await signalRepository.migrateSession(wireJid, lidWithDevice);
496
- const recipientUser = jidNormalizedUser(wireJid);
497
- const ownPnUser = jidNormalizedUser(meId);
498
- const isOwnDevice = recipientUser === ownPnUser;
499
- logger.info({ wireJid, lidWithDevice, isOwnDevice }, 'Migrated to LID encryption');
500
- // Delete PN session after successful migration
501
- try {
502
- await signalRepository.deleteSession(wireJid);
503
- logger.debug({ deletedPNSession: wireJid }, 'Deleted PN session');
504
- }
505
- catch (deleteError) {
506
- logger.warn({ wireJid, error: deleteError }, 'Failed to delete PN session');
507
- }
508
- return lidWithDevice;
509
- }
510
- catch (migrationError) {
511
- logger.warn({ wireJid, error: migrationError }, 'Failed to migrate session');
512
- return wireJid;
225
+ const nodes = await Promise.all(patched.map(async (patchedMessageWithJid) => {
226
+ const { recipientJid: jid, ...patchedMessage } = patchedMessageWithJid;
227
+ if (!jid) {
228
+ return {};
229
+ }
230
+ const bytes = encodeWAMessage(patchedMessage);
231
+ const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes });
232
+ if (type === 'pkmsg') {
233
+ shouldIncludeDeviceIdentity = true;
234
+ }
235
+ const node = {
236
+ tag: 'to',
237
+ attrs: { jid },
238
+ content: [
239
+ {
240
+ tag: 'enc',
241
+ attrs: {
242
+ v: '2',
243
+ type,
244
+ ...(extraAttrs || {})
245
+ },
246
+ content: ciphertext
513
247
  }
514
- }
515
- catch (error) {
516
- logger.debug({ wireJid, error }, 'Failed to check LID mapping');
517
- return wireJid;
518
- }
248
+ ]
519
249
  };
520
- // Encrypt to this user's devices sequentially to prevent session corruption
521
- for (const { recipientJid: wireJid, patchedMessage } of userDevices) {
522
- // DSM logic: Use DSM for own other devices (following whatsmeow implementation)
523
- let messageToEncrypt = patchedMessage;
524
- if (dsmMessage) {
525
- const { user: targetUser } = jidDecode(wireJid);
526
- const { user: ownPnUser } = jidDecode(meId);
527
- const ownLidUser = meLidUser;
528
- // Check if this is our device (same user, different device)
529
- const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
530
- // Exclude exact sender device (whatsmeow: if jid == ownJID || jid == ownLID { continue })
531
- const isExactSenderDevice = wireJid === meId || (authState.creds.me?.lid && wireJid === authState.creds.me.lid);
532
- if (isOwnUser && !isExactSenderDevice) {
533
- messageToEncrypt = dsmMessage;
534
- logger.debug({ wireJid, targetUser }, 'Using DSM for own device');
535
- }
536
- }
537
- const bytes = encodeWAMessage(messageToEncrypt);
538
- // Get encryption JID with LID migration
539
- const encryptionJid = await getEncryptionJid(wireJid);
540
- // ENCRYPT: Use the determined encryption identity (prefers migrated LID)
541
- const { type, ciphertext } = await signalRepository.encryptMessage({
542
- jid: encryptionJid, // Unified encryption layer (LID when available)
543
- data: bytes
544
- });
545
- if (type === 'pkmsg') {
546
- shouldIncludeDeviceIdentity = true;
547
- }
548
- const node = {
549
- tag: 'to',
550
- attrs: { jid: wireJid }, // Always use original wire identity in envelope
551
- content: [
552
- {
553
- tag: 'enc',
554
- attrs: {
555
- v: '2',
556
- type,
557
- ...(extraAttrs || {})
558
- },
559
- content: ciphertext
560
- }
561
- ]
562
- };
563
- userNodes.push(node);
564
- }
565
- logger.debug({ user, nodesCreated: userNodes.length }, 'Releasing encryption lock for user devices');
566
- return userNodes;
250
+ return node;
567
251
  }));
568
- // Wait for all users to complete (users are processed in parallel)
569
- const userNodesArrays = await Promise.all(userEncryptionPromises);
570
- const nodes = userNodesArrays.flat();
571
252
  return { nodes, shouldIncludeDeviceIdentity };
572
253
  };
573
254
  const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
574
255
  const meId = authState.creds.me.id;
575
- const meLid = authState.creds.me?.lid;
576
- // ADDRESSING CONSISTENCY: Keep envelope addressing as user provided, handle LID migration in encryption
577
256
  let shouldIncludeDeviceIdentity = false;
578
257
  const { user, server } = jidDecode(jid);
579
258
  const statusJid = 'status@broadcast';
@@ -581,22 +260,11 @@ export const makeMessagesSocket = (config) => {
581
260
  const isStatus = jid === statusJid;
582
261
  const isLid = server === 'lid';
583
262
  const isNewsletter = server === 'newsletter';
584
- // Keep user's original JID choice for envelope addressing
585
- const finalJid = jid;
586
- // ADDRESSING CONSISTENCY: Match own identity to conversation context
587
- let ownId = meId;
588
- if (isLid && meLid) {
589
- ownId = meLid;
590
- logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
591
- }
592
- else {
593
- logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
594
- }
595
263
  msgId = msgId || generateMessageIDV2(sock.user?.id);
596
264
  useUserDevicesCache = useUserDevicesCache !== false;
597
265
  useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
598
266
  const participants = [];
599
- const destinationJid = !isStatus ? finalJid : statusJid;
267
+ const destinationJid = !isStatus ? jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : 's.whatsapp.net') : statusJid;
600
268
  const binaryNodeContent = [];
601
269
  const devices = [];
602
270
  const meMsg = {
@@ -615,11 +283,7 @@ export const makeMessagesSocket = (config) => {
615
283
  additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
616
284
  }
617
285
  const { user, device } = jidDecode(participant.jid);
618
- devices.push({
619
- user,
620
- device,
621
- wireJid: participant.jid // Use the participant JID as wire JID
622
- });
286
+ devices.push({ user, device });
623
287
  }
624
288
  await authState.keys.transaction(async () => {
625
289
  const mediaType = getMediaType(message);
@@ -678,10 +342,9 @@ export const makeMessagesSocket = (config) => {
678
342
  participantsList.push(...statusJidList);
679
343
  }
680
344
  if (!isStatus) {
681
- const groupAddressingMode = groupData?.addressingMode || (isLid ? 'lid' : 'pn');
682
345
  additionalAttributes = {
683
346
  ...additionalAttributes,
684
- addressing_mode: groupAddressingMode
347
+ addressing_mode: groupData?.addressingMode || 'pn'
685
348
  };
686
349
  }
687
350
  const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
@@ -692,24 +355,19 @@ export const makeMessagesSocket = (config) => {
692
355
  throw new Boom('Per-jid patching is not supported in groups');
693
356
  }
694
357
  const bytes = encodeWAMessage(patched);
695
- // This should match the group's addressing mode and conversation context
696
- const groupAddressingMode = groupData?.addressingMode || (isLid ? 'lid' : 'pn');
697
- const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
698
358
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
699
359
  group: destinationJid,
700
360
  data: bytes,
701
- meId: groupSenderIdentity
361
+ meId
702
362
  });
703
363
  const senderKeyJids = [];
704
364
  // ensure a connection is established with every device
705
- for (const device of devices) {
706
- // This preserves the LID migration results from getUSyncDevices
707
- const deviceJid = device.wireJid;
708
- const hasKey = !!senderKeyMap[deviceJid];
709
- if (!hasKey || !!participant) {
710
- senderKeyJids.push(deviceJid);
365
+ for (const { user, device } of devices) {
366
+ const jid = jidEncode(user, groupData?.addressingMode === 'lid' ? 'lid' : 's.whatsapp.net', device);
367
+ if (!senderKeyMap[jid] || !!participant) {
368
+ senderKeyJids.push(jid);
711
369
  // store that this person has had the sender keys sent to them
712
- senderKeyMap[deviceJid] = true;
370
+ senderKeyMap[jid] = true;
713
371
  }
714
372
  }
715
373
  // if there are some participants with whom the session has not been established
@@ -735,54 +393,23 @@ export const makeMessagesSocket = (config) => {
735
393
  await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
736
394
  }
737
395
  else {
738
- const { user: ownUser } = jidDecode(ownId);
396
+ const { user: meUser } = jidDecode(meId);
739
397
  if (!participant) {
740
- const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
741
- devices.push({
742
- user,
743
- device: 0,
744
- wireJid: jidEncode(user, targetUserServer, 0)
745
- });
746
- // Own user matches conversation addressing mode
747
- if (user !== ownUser) {
748
- const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
749
- const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
750
- devices.push({
751
- user: ownUserForAddressing,
752
- device: 0,
753
- wireJid: jidEncode(ownUserForAddressing, ownUserServer, 0)
754
- });
398
+ devices.push({ user });
399
+ if (user !== meUser) {
400
+ devices.push({ user: meUser });
755
401
  }
756
402
  if (additionalAttributes?.['category'] !== 'peer') {
757
- // Clear placeholders and enumerate actual devices
758
- devices.length = 0;
759
- // Use conversation-appropriate sender identity
760
- const senderIdentity = isLid && meLid
761
- ? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
762
- : jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
763
- // Enumerate devices for sender and target with consistent addressing
764
- const sessionDevices = await getUSyncDevices([senderIdentity, jid], false, false);
765
- devices.push(...sessionDevices);
766
- logger.debug({
767
- deviceCount: devices.length,
768
- devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.wireJid)?.server}`)
769
- }, 'Device enumeration complete with unified addressing');
403
+ const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true);
404
+ devices.push(...additionalDevices);
770
405
  }
771
406
  }
772
407
  const allJids = [];
773
408
  const meJids = [];
774
409
  const otherJids = [];
775
- const { user: mePnUser } = jidDecode(meId);
776
- const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
777
- for (const { user, wireJid } of devices) {
778
- const isExactSenderDevice = wireJid === meId || (meLid && wireJid === meLid);
779
- if (isExactSenderDevice) {
780
- logger.debug({ wireJid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
781
- continue;
782
- }
783
- // Check if this is our device (could match either PN or LID user)
784
- const isMe = user === mePnUser || (meLidUser && user === meLidUser);
785
- const jid = wireJid;
410
+ for (const { user, device } of devices) {
411
+ const isMe = user === meUser;
412
+ const jid = jidEncode(isMe && isLid ? authState.creds?.me?.lid.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device);
786
413
  if (isMe) {
787
414
  meJids.push(jid);
788
415
  }
@@ -791,11 +418,10 @@ export const makeMessagesSocket = (config) => {
791
418
  }
792
419
  allJids.push(jid);
793
420
  }
794
- await assertSessions([...otherJids, ...meJids], false);
421
+ await assertSessions(allJids, false);
795
422
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
796
- // For own devices: use DSM if available (1:1 chats only)
797
- createParticipantNodes(meJids, meMsg || message, extraAttrs),
798
- createParticipantNodes(otherJids, message, extraAttrs, meMsg)
423
+ createParticipantNodes(meJids, meMsg, extraAttrs),
424
+ createParticipantNodes(otherJids, message, extraAttrs)
799
425
  ]);
800
426
  participants.push(...meNodes);
801
427
  participants.push(...otherNodes);
@@ -820,7 +446,6 @@ export const makeMessagesSocket = (config) => {
820
446
  tag: 'message',
821
447
  attrs: {
822
448
  id: msgId,
823
- to: destinationJid,
824
449
  type: getMessageType(message),
825
450
  ...(additionalAttributes || {})
826
451
  },
@@ -867,9 +492,6 @@ export const makeMessagesSocket = (config) => {
867
492
  if (message.pollCreationMessage || message.pollCreationMessageV2 || message.pollCreationMessageV3) {
868
493
  return 'poll';
869
494
  }
870
- if (message.eventMessage) {
871
- return 'event';
872
- }
873
495
  return 'text';
874
496
  };
875
497
  const getMediaType = (message) => {
@@ -1032,14 +654,12 @@ export const makeMessagesSocket = (config) => {
1032
654
  }),
1033
655
  //TODO: CACHE
1034
656
  getProfilePicUrl: sock.profilePictureUrl,
1035
- getCallLink: sock.createCallLink,
1036
657
  upload: waUploadToServer,
1037
658
  mediaCache: config.mediaCache,
1038
659
  options: config.options,
1039
660
  messageId: generateMessageIDV2(sock.user?.id),
1040
661
  ...options
1041
662
  });
1042
- const isEventMsg = 'event' in content && !!content.event;
1043
663
  const isDeleteMsg = 'delete' in content && !!content.delete;
1044
664
  const isEditMsg = 'edit' in content && !!content.edit;
1045
665
  const isPinMsg = 'pin' in content && !!content.pin;
@@ -1070,14 +690,6 @@ export const makeMessagesSocket = (config) => {
1070
690
  }
1071
691
  });
1072
692
  }
1073
- else if (isEventMsg) {
1074
- additionalNodes.push({
1075
- tag: 'meta',
1076
- attrs: {
1077
- event_type: 'creation'
1078
- }
1079
- });
1080
- }
1081
693
  if ('cachedGroupMetadata' in options) {
1082
694
  console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
1083
695
  }