@neelegirl/baileys 1.5.2 → 1.5.3

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 (193) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +195 -187
  3. package/WAProto/WAProto.proto +537 -236
  4. package/WAProto/index.d.ts +5971 -2388
  5. package/WAProto/index.js +17298 -6513
  6. package/lib/Defaults/baileys-version.json +3 -3
  7. package/lib/Defaults/index.d.ts +77 -67
  8. package/lib/Defaults/index.js +148 -136
  9. package/lib/Defaults/phonenumber-mcc.json +223 -223
  10. package/lib/Signal/WASignalGroup/GroupProtocol.js +1908 -1908
  11. package/lib/Signal/WASignalGroup/ciphertext-message.d.ts +9 -0
  12. package/lib/Signal/WASignalGroup/ciphertext-message.js +19 -0
  13. package/lib/Signal/WASignalGroup/ciphertext_message.js +15 -15
  14. package/lib/Signal/WASignalGroup/group-session-builder.d.ts +17 -0
  15. package/lib/Signal/WASignalGroup/group-session-builder.js +72 -0
  16. package/lib/Signal/WASignalGroup/group.proto +41 -41
  17. package/lib/Signal/WASignalGroup/group_cipher.d.ts +19 -0
  18. package/lib/Signal/WASignalGroup/group_cipher.js +101 -110
  19. package/lib/Signal/WASignalGroup/group_session_builder.js +45 -45
  20. package/lib/Signal/WASignalGroup/index.d.ts +11 -0
  21. package/lib/Signal/WASignalGroup/index.js +61 -6
  22. package/lib/Signal/WASignalGroup/keyhelper.d.ts +16 -0
  23. package/lib/Signal/WASignalGroup/keyhelper.js +58 -13
  24. package/lib/Signal/WASignalGroup/protobufs.js +2 -2
  25. package/lib/Signal/WASignalGroup/queue_job.js +68 -68
  26. package/lib/Signal/WASignalGroup/readme.md +5 -5
  27. package/lib/Signal/WASignalGroup/sender-chain-key.d.ts +14 -0
  28. package/lib/Signal/WASignalGroup/sender-chain-key.js +47 -0
  29. package/lib/Signal/WASignalGroup/sender-key-distribution-message.d.ts +17 -0
  30. package/lib/Signal/WASignalGroup/sender-key-distribution-message.js +71 -0
  31. package/lib/Signal/WASignalGroup/sender-key-message.d.ts +19 -0
  32. package/lib/Signal/WASignalGroup/sender-key-message.js +73 -0
  33. package/lib/Signal/WASignalGroup/sender-key-name.d.ts +19 -0
  34. package/lib/Signal/WASignalGroup/sender-key-name.js +59 -0
  35. package/lib/Signal/WASignalGroup/sender-key-record.d.ts +32 -0
  36. package/lib/Signal/WASignalGroup/sender-key-record.js +58 -0
  37. package/lib/Signal/WASignalGroup/sender-key-state.d.ts +44 -0
  38. package/lib/Signal/WASignalGroup/sender-key-state.js +147 -0
  39. package/lib/Signal/WASignalGroup/sender-message-key.d.ts +11 -0
  40. package/lib/Signal/WASignalGroup/sender-message-key.js +33 -0
  41. package/lib/Signal/WASignalGroup/sender_chain_key.js +49 -49
  42. package/lib/Signal/WASignalGroup/sender_key_distribution_message.js +77 -77
  43. package/lib/Signal/WASignalGroup/sender_key_message.js +91 -91
  44. package/lib/Signal/WASignalGroup/sender_key_name.js +69 -69
  45. package/lib/Signal/WASignalGroup/sender_key_record.js +55 -55
  46. package/lib/Signal/WASignalGroup/sender_key_state.js +128 -128
  47. package/lib/Signal/WASignalGroup/sender_message_key.js +38 -38
  48. package/lib/Signal/libsignal.d.ts +5 -1
  49. package/lib/Signal/libsignal.js +390 -161
  50. package/lib/Signal/lid-mapping.d.ts +28 -0
  51. package/lib/Signal/lid-mapping.js +184 -0
  52. package/lib/Socket/Client/abstract-socket-client.d.ts +15 -15
  53. package/lib/Socket/Client/abstract-socket-client.js +13 -13
  54. package/lib/Socket/Client/index.d.ts +2 -2
  55. package/lib/Socket/Client/mobile-socket-client.d.ts +12 -12
  56. package/lib/Socket/Client/mobile-socket-client.js +65 -65
  57. package/lib/Socket/Client/types.d.ts +1 -1
  58. package/lib/Socket/Client/websocket.d.ts +1 -1
  59. package/lib/Socket/business.d.ts +6 -6
  60. package/lib/Socket/business.js +152 -5
  61. package/lib/Socket/chats.d.ts +3 -4
  62. package/lib/Socket/chats.js +31 -26
  63. package/lib/Socket/communities.d.ts +223 -223
  64. package/lib/Socket/communities.js +432 -432
  65. package/lib/Socket/groups.d.ts +2 -4
  66. package/lib/Socket/groups.js +22 -14
  67. package/lib/Socket/index.d.ts +69 -69
  68. package/lib/Socket/index.js +3 -2
  69. package/lib/Socket/messages-recv.d.ts +3 -6
  70. package/lib/Socket/messages-recv.js +1449 -1707
  71. package/lib/Socket/messages-send.d.ts +2 -4
  72. package/lib/Socket/messages-send.js +617 -126
  73. package/lib/Socket/mex.d.ts +2 -2
  74. package/lib/Socket/mex.js +46 -46
  75. package/lib/Socket/newsletter.d.ts +2 -4
  76. package/lib/Socket/newsletter.js +294 -285
  77. package/lib/Socket/socket.js +318 -132
  78. package/lib/Socket/usync.js +3 -3
  79. package/lib/Store/index.d.ts +4 -4
  80. package/lib/Store/index.js +23 -23
  81. package/lib/Store/make-cache-manager-store.d.ts +13 -13
  82. package/lib/Store/make-cache-manager-store.js +89 -89
  83. package/lib/Store/make-in-memory-store.d.ts +122 -122
  84. package/lib/Store/make-in-memory-store.js +428 -428
  85. package/lib/Store/make-ordered-dictionary.d.ts +11 -11
  86. package/lib/Store/make-ordered-dictionary.js +85 -85
  87. package/lib/Store/object-repository.d.ts +9 -9
  88. package/lib/Store/object-repository.js +30 -30
  89. package/lib/Types/Auth.d.ts +5 -4
  90. package/lib/Types/Bussines.js +3 -0
  91. package/lib/Types/Bussiness.d.ts +28 -0
  92. package/lib/Types/Chat.d.ts +13 -8
  93. package/lib/Types/Contact.d.ts +4 -1
  94. package/lib/Types/Events.d.ts +13 -16
  95. package/lib/Types/GroupMetadata.d.ts +1 -1
  96. package/lib/Types/Message.d.ts +18 -7
  97. package/lib/Types/Message.js +7 -1
  98. package/lib/Types/MexUpdates.d.ts +8 -8
  99. package/lib/Types/MexUpdates.js +17 -17
  100. package/lib/Types/Newsletter.d.ts +1 -1
  101. package/lib/Types/Product.d.ts +1 -1
  102. package/lib/Types/Signal.d.ts +31 -1
  103. package/lib/Types/Socket.d.ts +34 -13
  104. package/lib/Types/State.d.ts +1 -1
  105. package/lib/Types/USync.d.ts +2 -2
  106. package/lib/Types/index.d.ts +16 -15
  107. package/lib/Types/index.js +4 -2
  108. package/lib/Utils/auth-utils.d.ts +20 -20
  109. package/lib/Utils/auth-utils.js +527 -204
  110. package/lib/Utils/baileys-event-stream.d.ts +17 -17
  111. package/lib/Utils/baileys-event-stream.js +69 -69
  112. package/lib/Utils/business.d.ts +28 -28
  113. package/lib/Utils/business.js +254 -254
  114. package/lib/Utils/chat-utils.d.ts +81 -81
  115. package/lib/Utils/chat-utils.js +808 -780
  116. package/lib/Utils/crypto.d.ts +55 -55
  117. package/lib/Utils/crypto.js +188 -178
  118. package/lib/Utils/decode-wa-message.d.ts +52 -40
  119. package/lib/Utils/decode-wa-message.js +322 -252
  120. package/lib/Utils/event-buffer.d.ts +38 -38
  121. package/lib/Utils/event-buffer.js +594 -564
  122. package/lib/Utils/generics.d.ts +131 -129
  123. package/lib/Utils/generics.js +629 -623
  124. package/lib/Utils/history.d.ts +22 -22
  125. package/lib/Utils/history.js +103 -109
  126. package/lib/Utils/index.d.ts +20 -19
  127. package/lib/Utils/index.js +39 -38
  128. package/lib/Utils/link-preview.d.ts +22 -22
  129. package/lib/Utils/link-preview.js +119 -119
  130. package/lib/Utils/logger.d.ts +13 -13
  131. package/lib/Utils/logger.js +7 -7
  132. package/lib/Utils/lt-hash.d.ts +13 -13
  133. package/lib/Utils/lt-hash.js +57 -57
  134. package/lib/Utils/make-mutex.d.ts +8 -8
  135. package/lib/Utils/make-mutex.js +48 -48
  136. package/lib/Utils/message-retry-manager.d.ts +88 -0
  137. package/lib/Utils/message-retry-manager.js +160 -0
  138. package/lib/Utils/messages-media.d.ts +134 -128
  139. package/lib/Utils/messages-media.js +868 -805
  140. package/lib/Utils/messages.d.ts +104 -102
  141. package/lib/Utils/messages.js +1744 -1578
  142. package/lib/Utils/noise-handler.d.ts +20 -19
  143. package/lib/Utils/noise-handler.js +164 -154
  144. package/lib/Utils/process-message.d.ts +48 -48
  145. package/lib/Utils/process-message.js +427 -428
  146. package/lib/Utils/signal.d.ts +41 -41
  147. package/lib/Utils/signal.js +165 -165
  148. package/lib/Utils/use-mongo-file-auth-state.d.ts +5 -5
  149. package/lib/Utils/use-mongo-file-auth-state.js +83 -83
  150. package/lib/Utils/use-multi-file-auth-state.d.ts +17 -17
  151. package/lib/Utils/use-multi-file-auth-state.js +237 -237
  152. package/lib/Utils/use-single-file-auth-state.d.ts +12 -12
  153. package/lib/Utils/use-single-file-auth-state.js +79 -79
  154. package/lib/Utils/validate-connection.d.ts +12 -12
  155. package/lib/Utils/validate-connection.js +219 -186
  156. package/lib/WABinary/constants.d.ts +29 -29
  157. package/lib/WABinary/constants.js +1315 -1315
  158. package/lib/WABinary/decode.d.ts +8 -8
  159. package/lib/WABinary/decode.js +287 -287
  160. package/lib/WABinary/encode.d.ts +2 -2
  161. package/lib/WABinary/encode.js +264 -264
  162. package/lib/WABinary/generic-utils.d.ts +27 -27
  163. package/lib/WABinary/generic-utils.js +141 -141
  164. package/lib/WABinary/index.d.ts +5 -5
  165. package/lib/WABinary/index.js +24 -24
  166. package/lib/WABinary/jid-utils.d.ts +58 -53
  167. package/lib/WABinary/jid-utils.js +103 -91
  168. package/lib/WABinary/types.d.ts +21 -21
  169. package/lib/WABinary/types.js +2 -2
  170. package/lib/WAM/BinaryInfo.d.ts +15 -15
  171. package/lib/WAM/BinaryInfo.js +16 -16
  172. package/lib/WAM/constants.d.ts +46 -46
  173. package/lib/WAM/constants.js +15370 -15370
  174. package/lib/WAM/encode.d.ts +2 -2
  175. package/lib/WAM/encode.js +163 -164
  176. package/lib/WAM/index.d.ts +3 -3
  177. package/lib/WAM/index.js +22 -22
  178. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +27 -27
  179. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +68 -68
  180. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +3 -3
  181. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -2
  182. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -2
  183. package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +9 -8
  184. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +37 -29
  185. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -2
  186. package/lib/WAUSync/Protocols/index.d.ts +6 -6
  187. package/lib/WAUSync/USyncQuery.d.ts +3 -3
  188. package/lib/WAUSync/index.d.ts +3 -3
  189. package/lib/index.d.ts +13 -13
  190. package/lib/index.js +33 -33
  191. package/package.json +96 -94
  192. package/lib/Socket/registration.d.ts +0 -266
  193. package/lib/Socket/registration.js +0 -166
@@ -17,9 +17,10 @@ const WABinary_1 = require("../WABinary")
17
17
  const WAUSync_1 = require("../WAUSync")
18
18
  const newsletter_1 = require("./newsletter")
19
19
  const link_preview_1 = require("../Utils/link-preview")
20
+ const make_keyed_mutex_1 = require("../Utils/make-mutex")
20
21
 
21
22
  const makeMessagesSocket = (config) => {
22
- const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata, } = config
23
+ const { logger, maxMsgRetryCount, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache } = config
23
24
  const baron = newsletter_1.makeNewsletterSocket(config)
24
25
  const { ev, authState, processingMutex, signalRepository, upsertMessage, createCallLink, query, fetchPrivacySettings, sendNode, groupQuery, groupMetadata, groupToggleEphemeral, newsletterWMexQuery, executeUSyncQuery } = baron
25
26
 
@@ -27,6 +28,12 @@ const makeMessagesSocket = (config) => {
27
28
  stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
28
29
  useClones: false
29
30
  })
31
+
32
+ // Initialize message retry manager if enabled
33
+ const messageRetryManager = enableRecentMessageCache ? new Utils_1.MessageRetryManager(logger, maxMsgRetryCount) : null
34
+
35
+ // Prevent race conditions in Signal session encryption by user
36
+ const encryptionMutex = make_keyed_mutex_1.makeKeyedMutex()
30
37
 
31
38
  let mediaConn
32
39
 
@@ -139,6 +146,37 @@ const makeMessagesSocket = (config) => {
139
146
 
140
147
  await sendReceipts(keys, readType)
141
148
  }
149
+
150
+ /**
151
+ * Deduplicate JIDs when both LID and PN versions exist for same user
152
+ * Prefers LID over PN to maintain single encryption layer
153
+ */
154
+ const deduplicateLidPnJids = (jids) => {
155
+ const lidUsers = new Set()
156
+ const filteredJids = []
157
+
158
+ // Collect all LID users
159
+ for (const jid of jids) {
160
+ if (WABinary_1.isLidUser(jid)) {
161
+ const user = WABinary_1.jidDecode(jid)?.user
162
+ if (user)
163
+ lidUsers.add(user)
164
+ }
165
+ }
166
+
167
+ // Filter out PN versions when LID exists
168
+ for (const jid of jids) {
169
+ if (WABinary_1.isJidUser(jid)) {
170
+ const user = WABinary_1.jidDecode(jid)?.user
171
+ if (user && lidUsers.has(user)) {
172
+ logger.debug({ jid }, 'Skipping PN - LID version exists')
173
+ continue
174
+ }
175
+ }
176
+ filteredJids.push(jid)
177
+ }
178
+ return filteredJids
179
+ }
142
180
 
143
181
  /** Fetch image for groups, user, and newsletter **/
144
182
  const profilePictureUrl = async (jid) => {
@@ -190,103 +228,293 @@ const makeMessagesSocket = (config) => {
190
228
  /** Fetch all the devices we've to send a message to */
191
229
  const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
192
230
  const deviceResults = []
193
-
231
+
194
232
  if (!useCache) {
195
233
  logger.debug('not using cache for devices')
196
234
  }
197
-
235
+
198
236
  const toFetch = []
199
-
200
- jids = Array.from(new Set(jids))
201
-
202
- for (let jid of jids) {
203
- const user = WABinary_1.jidDecode(jid)?.user
204
-
237
+
238
+ jids = deduplicateLidPnJids(Array.from(new Set(jids)))
239
+ const jidsWithUser = jids
240
+ .map(jid => {
241
+ const decoded = WABinary_1.jidDecode(jid)
242
+ const user = decoded?.user
243
+ const device = decoded?.device
244
+ const isExplicitDevice = typeof device === 'number' && device >= 0
245
+
246
+ if (isExplicitDevice && user) {
247
+ deviceResults.push({
248
+ user,
249
+ device,
250
+ wireJid: jid // again this makes no sense
251
+ });
252
+ return null
253
+ }
254
+
205
255
  jid = WABinary_1.jidNormalizedUser(jid)
206
-
256
+ return { jid, user }
257
+ })
258
+ .filter(jid => jid !== null)
259
+
260
+ let mgetDevices
261
+
262
+ if (useCache && userDevicesCache.mget) {
263
+ const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean)
264
+ mgetDevices = await userDevicesCache.mget(usersToFetch)
265
+ }
266
+
267
+ for (const { jid, user } of jidsWithUser) {
207
268
  if (useCache) {
208
- const devices = userDevicesCache.get(user)
209
-
269
+ const devices = mgetDevices?.[user] ||
270
+ (userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)))
271
+
210
272
  if (devices) {
211
- deviceResults.push(...devices)
273
+ const isLidJid = WABinary_1.isLidUser(jid)
274
+ const devicesWithWire = devices.map(d => ({
275
+ ...d,
276
+ wireJid: isLidJid ? WABinary_1.jidEncode(d.user, 'lid', d.device) : WABinary_1.jidEncode(d.user, 's.whatsapp.net', d.device)
277
+ }))
278
+
279
+ deviceResults.push(...devicesWithWire)
212
280
  logger.trace({ user }, 'using cache for devices')
213
281
  }
214
-
215
282
  else {
216
283
  toFetch.push(jid)
217
284
  }
218
285
  }
219
-
220
286
  else {
221
287
  toFetch.push(jid)
222
288
  }
223
289
  }
224
-
290
+
225
291
  if (!toFetch.length) {
226
292
  return deviceResults
227
293
  }
228
-
229
- const query = new WAUSync_1.USyncQuery()
230
- .withContext('message')
231
- .withDeviceProtocol()
232
-
294
+
295
+ const requestedLidUsers = new Set()
296
+ for (const jid of toFetch) {
297
+ if (WABinary_1.isLidUser(jid)) {
298
+ const user = WABinary_1.jidDecode(jid)?.user
299
+ if (user)
300
+ requestedLidUsers.add(user)
301
+ }
302
+ }
303
+
304
+ const query = new WAUSync_1.USyncQuery().withContext('message').withDeviceProtocol()
233
305
  for (const jid of toFetch) {
234
306
  query.withUser(new WAUSync_1.USyncUser().withId(jid))
235
307
  }
236
-
308
+
237
309
  const result = await executeUSyncQuery(query)
238
-
310
+
239
311
  if (result) {
240
312
  const extracted = Utils_1.extractDeviceJids(result?.list, authState.creds.me.id, ignoreZeroDevices)
241
313
  const deviceMap = {}
242
-
314
+
243
315
  for (const item of extracted) {
244
316
  deviceMap[item.user] = deviceMap[item.user] || []
245
- deviceMap[item.user].push(item)
246
- deviceResults.push(item)
317
+ deviceMap[item.user]?.push(item)
247
318
  }
248
-
249
- for (const key in deviceMap) {
250
- userDevicesCache.set(key, deviceMap[key])
319
+
320
+ // Process each user's devices as a group for bulk LID migration
321
+ for (const [user, userDevices] of Object.entries(deviceMap)) {
322
+ const isLidUser = requestedLidUsers.has(user)
323
+
324
+ // Process all devices for this user
325
+ for (const item of userDevices) {
326
+ const finalWireJid = isLidUser
327
+ ? WABinary_1.jidEncode(user, 'lid', item.device)
328
+ : WABinary_1.jidEncode(item.user, 's.whatsapp.net', item.device)
329
+ deviceResults.push({
330
+ ...item,
331
+ wireJid: finalWireJid
332
+ });
333
+
334
+ logger.debug({
335
+ user: item.user,
336
+ device: item.device,
337
+ finalWireJid,
338
+ usedLid: isLidUser
339
+ }, 'Processed device with LID priority')
340
+ }
341
+ }
342
+
343
+ if (userDevicesCache.mset) {
344
+ // if the cache supports mset, we can set all devices in one go
345
+ await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })))
251
346
  }
347
+
348
+ else {
349
+ for (const key in deviceMap) {
350
+ if (deviceMap[key])
351
+ await userDevicesCache.set(key, deviceMap[key])
352
+ }
353
+ }
354
+
252
355
  }
253
-
254
356
  return deviceResults
255
357
  }
256
358
 
257
- /** Assert Sessions */
258
359
  const assertSessions = async (jids, force) => {
259
360
  let didFetchNewSession = false
260
- let jidsRequiringFetch = []
261
-
361
+ const jidsRequiringFetch = []
362
+
363
+ // Apply same deduplication as in getUSyncDevices
364
+ jids = deduplicateLidPnJids(jids)
365
+
262
366
  if (force) {
263
- jidsRequiringFetch = jids
367
+ // Check which sessions are missing (with LID migration check)
368
+ const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid))
369
+ const sessions = await authState.keys.get('session', addrs)
370
+
371
+ const checkJidSession = (jid) => {
372
+ const signalId = signalRepository.jidToSignalProtocolAddress(jid)
373
+ const hasSession = !!sessions[signalId]
374
+
375
+ // Add to fetch list if no session exists
376
+ // Session type selection (LID vs PN) is handled in encryptMessage
377
+ if (!hasSession) {
378
+ if (jid.includes('@lid')) {
379
+ logger.debug({ jid }, 'No LID session found, will create new LID session')
380
+ }
381
+ jidsRequiringFetch.push(jid)
382
+ }
383
+ }
384
+
385
+ // Process all JIDs
386
+ for (const jid of jids) {
387
+ checkJidSession(jid)
388
+ }
264
389
  }
265
-
266
390
  else {
267
- const addrs = jids.map(jid => (signalRepository.jidToSignalProtocolAddress(jid)))
268
-
391
+ const addrs = jids.map(jid => signalRepository.jidToSignalProtocolAddress(jid))
269
392
  const sessions = await authState.keys.get('session', addrs)
270
-
393
+
394
+ // Group JIDs by user for bulk migration
395
+ const userGroups = new Map()
271
396
  for (const jid of jids) {
272
- const signalId = signalRepository
273
- .jidToSignalProtocolAddress(jid)
274
-
275
- if (!sessions[signalId]) {
276
- jidsRequiringFetch.push(jid)
397
+ const user = WABinary_1.jidNormalizedUser(jid)
398
+ if (!userGroups.has(user)) {
399
+ userGroups.set(user, [])
277
400
  }
401
+ userGroups.get(user).push(jid)
402
+ }
403
+
404
+ // Helper to check LID mapping for a user
405
+ const checkUserLidMapping = async (user, userJids) => {
406
+ if (!userJids.some(jid => WABinary_1.isJidUser(jid))) {
407
+ return { shouldMigrate: false, lidForPN: undefined }
408
+ }
409
+
410
+ try {
411
+ // Convert user to proper PN JID format for getLIDForPN
412
+ const pnJid = `${user}@s.whatsapp.net`
413
+ const mapping = await signalRepository.lidMapping.getLIDForPN(pnJid)
414
+
415
+ if (mapping?.includes('@lid')) {
416
+ logger.debug({ user, lidForPN: mapping, deviceCount: userJids.length }, 'User has LID mapping - preparing bulk migration')
417
+ return { shouldMigrate: true, lidForPN: mapping }
418
+ }
419
+ }
420
+ catch (error) {
421
+ logger.debug({ user, error }, 'Failed to check LID mapping for user')
422
+ }
423
+
424
+ return { shouldMigrate: false, lidForPN: undefined }
425
+ }
426
+
427
+ // Process each user group for potential bulk LID migration
428
+ for (const [user, userJids] of userGroups) {
429
+ const mappingResult = await checkUserLidMapping(user, userJids)
430
+ const shouldMigrateUser = mappingResult.shouldMigrate
431
+ const lidForPN = mappingResult.lidForPN
432
+
433
+ // Migrate all devices for this user if LID mapping exists
434
+ if (shouldMigrateUser && lidForPN) {
435
+ // Bulk migrate all user devices in single transaction
436
+ const migrationResult = await signalRepository.migrateSession(userJids, lidForPN)
437
+
438
+ if (migrationResult.migrated > 0) {
439
+ logger.info({
440
+ user,
441
+ lidMapping: lidForPN,
442
+ migrated: migrationResult.migrated,
443
+ skipped: migrationResult.skipped,
444
+ total: migrationResult.total
445
+ }, 'Completed bulk migration for user devices');
446
+ }
447
+ else {
448
+ logger.debug({
449
+ user,
450
+ lidMapping: lidForPN,
451
+ skipped: migrationResult.skipped,
452
+ total: migrationResult.total
453
+ }, 'All user device sessions already migrated');
454
+ }
455
+ }
456
+
457
+ // Direct bulk session check with LID single source of truth
458
+ const addMissingSessionsToFetchList = (jid) => {
459
+ const signalId = signalRepository.jidToSignalProtocolAddress(jid)
460
+
461
+ if (sessions[signalId]) return
462
+
463
+ // Determine correct JID to fetch (LID if mapping exists, otherwise original)
464
+ if (jid.includes('@s.whatsapp.net') && shouldMigrateUser && lidForPN) {
465
+ const decoded = WABinary_1.jidDecode(jid)
466
+ const lidDeviceJid = decoded.device !== undefined ? `${WABinary_1.jidDecode(lidForPN).user}:${decoded.device}@lid` : lidForPN
467
+
468
+ jidsRequiringFetch.push(lidDeviceJid)
469
+ logger.debug({ pnJid: jid, lidJid: lidDeviceJid }, 'Adding LID JID to fetch list (conversion)')
470
+ }
471
+
472
+ else {
473
+ jidsRequiringFetch.push(jid)
474
+ logger.debug({ jid }, 'Adding JID to fetch list')
475
+ }
476
+ }
477
+
478
+ userJids.forEach(addMissingSessionsToFetchList)
278
479
  }
279
480
  }
280
-
481
+
281
482
  if (jidsRequiringFetch.length) {
282
483
  logger.debug({ jidsRequiringFetch }, 'fetching sessions')
283
-
484
+
485
+ // DEBUG: Check if there are PN versions of LID users being fetched
486
+ const lidUsersBeingFetched = new Set()
487
+ const pnUsersBeingFetched = new Set()
488
+
489
+ for (const jid of jidsRequiringFetch) {
490
+ const user = WABinary_1.jidDecode(jid)?.user
491
+
492
+ if (user) {
493
+ if (WABinary_1.isLidUser(jid)) {
494
+ lidUsersBeingFetched.add(user)
495
+ }
496
+ else if (WABinary_1.isJidUser(jid)) {
497
+ pnUsersBeingFetched.add(user)
498
+ }
499
+ }
500
+ }
501
+
502
+ // Find overlaps
503
+ const overlapping = Array.from(pnUsersBeingFetched).filter(user => lidUsersBeingFetched.has(user))
504
+ if (overlapping.length > 0) {
505
+ logger.warn({
506
+ overlapping,
507
+ lidUsersBeingFetched: Array.from(lidUsersBeingFetched),
508
+ pnUsersBeingFetched: Array.from(pnUsersBeingFetched)
509
+ }, 'Fetching both LID and PN sessions for same users')
510
+ }
511
+
284
512
  const result = await query({
285
513
  tag: 'iq',
286
514
  attrs: {
287
515
  xmlns: 'encrypt',
288
516
  type: 'get',
289
- to: WABinary_1.S_WHATSAPP_NET,
517
+ to: WABinary_1.S_WHATSAPP_NET
290
518
  },
291
519
  content: [
292
520
  {
@@ -294,17 +522,15 @@ const makeMessagesSocket = (config) => {
294
522
  attrs: {},
295
523
  content: jidsRequiringFetch.map(jid => ({
296
524
  tag: 'user',
297
- attrs: { jid },
525
+ attrs: { jid }
298
526
  }))
299
527
  }
300
528
  ]
301
529
  })
302
-
530
+
303
531
  await Utils_1.parseAndInjectE2ESessions(result, signalRepository)
304
-
305
532
  didFetchNewSession = true
306
533
  }
307
-
308
534
  return didFetchNewSession
309
535
  }
310
536
 
@@ -335,44 +561,159 @@ const makeMessagesSocket = (config) => {
335
561
  return msgId
336
562
  }
337
563
 
338
- const createParticipantNodes = async (jids, message, extraAttrs) => {
339
- const patched = await patchMessageBeforeSending(message, jids)
340
- const bytes = Utils_1.encodeWAMessage(patched)
341
-
564
+ const createParticipantNodes = async (jids, message, extraAttrs, dsmMessage) => {
565
+ let patched = await patchMessageBeforeSending(message, jids)
566
+
567
+ if (!Array.isArray(patched)) {
568
+ patched = jids ? jids.map(jid => ({ recipientJid: jid, ...patched })) : [patched]
569
+ }
570
+
342
571
  let shouldIncludeDeviceIdentity = false
343
-
344
- const nodes = await Promise.all(jids.map(async (jid) => {
345
- const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes })
346
-
347
- if (type === 'pkmsg') {
348
- shouldIncludeDeviceIdentity = true
572
+
573
+ const meId = authState.creds.me.id
574
+ const meLid = authState.creds.me?.lid
575
+ const meLidUser = meLid ? WABinary_1.jidDecode(meLid)?.user : null
576
+ const devicesByUser = new Map()
577
+
578
+ for (const patchedMessageWithJid of patched) {
579
+ const { recipientJid: wireJid, ...patchedMessage } = patchedMessageWithJid
580
+ if (!wireJid)
581
+ continue
582
+
583
+ // Extract user from JID for grouping
584
+ const decoded = WABinary_1.jidDecode(wireJid)
585
+ const user = decoded?.user
586
+
587
+ if (!user)
588
+ continue
589
+
590
+ if (!devicesByUser.has(user)) {
591
+ devicesByUser.set(user, []);
349
592
  }
350
-
351
- const node = {
352
- tag: 'to',
353
- attrs: { jid },
354
- content: [{
355
- tag: 'enc',
356
- attrs: {
357
- v: '2',
358
- type,
359
- ...extraAttrs || {}
360
- },
361
- content: ciphertext
362
- }]
593
+
594
+ devicesByUser.get(user).push({ recipientJid: wireJid, patchedMessage })
595
+ }
596
+
597
+ // Process each user's devices sequentially, but different users in parallel
598
+ const userEncryptionPromises = Array.from(devicesByUser.entries()).map(([user, userDevices]) => encryptionMutex.mutex(user, async () => {
599
+ logger.debug({ user, deviceCount: userDevices.length }, 'Acquiring encryption lock for user devices');
600
+ const userNodes = []
601
+
602
+ // Helper to get encryption JID with LID migration
603
+ const getEncryptionJid = async (wireJid) => {
604
+ if (!WABinary_1.isJidUser(wireJid))
605
+ return wireJid
606
+
607
+ try {
608
+ const lidForPN = await signalRepository.lidMapping.getLIDForPN(wireJid)
609
+
610
+ if (!lidForPN?.includes('@lid'))
611
+ return wireJid
612
+
613
+ // Preserve device ID from original wire JID
614
+ const wireDecoded = WABinary_1.jidDecode(wireJid)
615
+ const deviceId = wireDecoded?.device || 0
616
+ const lidDecoded = WABinary_1.jidDecode(lidForPN)
617
+ const lidWithDevice = WABinary_1.jidEncode(lidDecoded?.user, 'lid', deviceId)
618
+
619
+ // Migrate session to LID for unified encryption layer
620
+ try {
621
+ const migrationResult = await signalRepository.migrateSession([wireJid], lidWithDevice)
622
+ const recipientUser = WABinary_1.jidNormalizedUser(wireJid)
623
+ const ownPnUser = WABinary_1.jidNormalizedUser(meId)
624
+ const isOwnDevice = recipientUser === ownPnUser
625
+ logger.info({ wireJid, lidWithDevice, isOwnDevice }, 'Migrated to LID encryption')
626
+
627
+ // Delete PN session after successful migration
628
+ try {
629
+ if (migrationResult.migrated) {
630
+ await signalRepository.deleteSession([wireJid])
631
+ logger.debug({ deletedPNSession: wireJid }, 'Deleted PN session')
632
+ }
633
+ }
634
+ catch (deleteError) {
635
+ logger.warn({ wireJid, error: deleteError }, 'Failed to delete PN session')
636
+ }
637
+ return lidWithDevice
638
+ }
639
+ catch (migrationError) {
640
+ logger.warn({ wireJid, error: migrationError }, 'Failed to migrate session')
641
+ return wireJid
642
+ }
643
+ }
644
+ catch (error) {
645
+ logger.debug({ wireJid, error }, 'Failed to check LID mapping')
646
+ return wireJid
647
+ }
363
648
  }
364
-
365
- return node
649
+
650
+ // Encrypt to this user's devices sequentially to prevent session corruption
651
+ for (const { recipientJid: wireJid, patchedMessage } of userDevices) {
652
+ // DSM logic: Use DSM for own other devices (following whatsmeow implementation)
653
+ let messageToEncrypt = patchedMessage
654
+
655
+ if (dsmMessage) {
656
+ const { user: targetUser } = WABinary_1.jidDecode(wireJid)
657
+ const { user: ownPnUser } = WABinary_1.jidDecode(meId)
658
+ const ownLidUser = meLidUser
659
+
660
+ // Check if this is our device (same user, different device)
661
+ const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser)
662
+
663
+ // Exclude exact sender device (whatsmeow: if jid == ownJID || jid == ownLID { continue })
664
+ const isExactSenderDevice = wireJid === meId || (authState.creds.me?.lid && wireJid === authState.creds.me.lid)
665
+
666
+ if (isOwnUser && !isExactSenderDevice) {
667
+ messageToEncrypt = dsmMessage
668
+ logger.debug({ wireJid, targetUser }, 'Using DSM for own device')
669
+ }
670
+ }
671
+
672
+ const bytes = Utils_1.encodeWAMessage(messageToEncrypt)
673
+
674
+ // Get encryption JID with LID migration
675
+ const encryptionJid = await getEncryptionJid(wireJid)
676
+
677
+ // ENCRYPT: Use the determined encryption identity (prefers migrated LID)
678
+ const { type, ciphertext } = await signalRepository.encryptMessage({
679
+ jid: encryptionJid, // Unified encryption layer (LID when available)
680
+ data: bytes
681
+ })
682
+
683
+ if (type === 'pkmsg') {
684
+ shouldIncludeDeviceIdentity = true
685
+ }
686
+
687
+ const node = {
688
+ tag: 'to',
689
+ attrs: { jid: wireJid }, // Always use original wire identity in envelope
690
+ content: [
691
+ {
692
+ tag: 'enc',
693
+ attrs: {
694
+ v: '2',
695
+ type,
696
+ ...(extraAttrs || {})
697
+ },
698
+ content: ciphertext
699
+ }
700
+ ]
701
+ }
702
+ userNodes.push(node)
703
+ }
704
+ logger.debug({ user, nodesCreated: userNodes.length }, 'Releasing encryption lock for user devices');
705
+ return userNodes
366
706
  }))
367
-
368
- return {
369
- nodes,
370
- shouldIncludeDeviceIdentity
371
- }
707
+
708
+ // Wait for all users to complete (users are processed in parallel)
709
+ const userNodesArrays = await Promise.all(userEncryptionPromises)
710
+ const nodes = userNodesArrays.flat()
711
+ return { nodes, shouldIncludeDeviceIdentity }
372
712
  }
373
713
 
374
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, additionalNodes, AI = true }) => {
714
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, useCachedGroupMetadata, statusJidList, additionalNodes, AI = false, isSecret = 0 }) => {
375
715
  const meId = authState.creds.me.id
716
+ const meLid = authState.creds.me?.lid
376
717
 
377
718
  let didPushAdditional = false
378
719
  let shouldIncludeDeviceIdentity = false
@@ -385,13 +726,27 @@ const makeMessagesSocket = (config) => {
385
726
  const isNewsletter = server == 'newsletter'
386
727
  const isStatus = jid === statusJid
387
728
  const isLid = server === 'lid'
729
+
730
+ // Keep user's original JID choice for envelope addressing
731
+ const finalJid = jid
732
+
733
+ // ADDRESSING CONSISTENCY: Match own identity to conversation context
734
+ let ownId = meId
735
+
736
+ if (isLid && meLid) {
737
+ ownId = meLid
738
+ logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation')
739
+ }
740
+ else {
741
+ logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation')
742
+ }
388
743
 
389
744
  msgId = msgId || Utils_1.generateMessageID(authState.creds.me.id)
390
745
  useUserDevicesCache = useUserDevicesCache !== false
391
746
  useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus
392
747
 
393
748
  const participants = []
394
- const destinationJid = (!isStatus) ? WABinary_1.jidEncode(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid
749
+ const destinationJid = !isStatus ? finalJid : statusJid
395
750
  const binaryNodeContent = []
396
751
  const devices = []
397
752
 
@@ -423,7 +778,11 @@ const makeMessagesSocket = (config) => {
423
778
 
424
779
  const { user, device } = WABinary_1.jidDecode(participant.jid)
425
780
 
426
- devices.push({ user, device })
781
+ devices.push({
782
+ user,
783
+ device,
784
+ wireJid: participant.jid // Use the participant JID as wire JID
785
+ })
427
786
  }
428
787
 
429
788
  await authState.keys.transaction(async () => {
@@ -476,9 +835,10 @@ const makeMessagesSocket = (config) => {
476
835
  }
477
836
 
478
837
  if (!isStatus) {
479
- additionalAttributes = {
480
- ...additionalAttributes,
481
- addressing_mode: groupData.addressingMode
838
+ const groupAddressingMode = groupData?.addressingMode || (isLid ? Types_1.WAMessageAddressingMode.LID : Types_1.WAMessageAddressingMode.PN)
839
+ additionalAttributes = {
840
+ ...additionalAttributes,
841
+ addressing_mode: groupAddressingMode
482
842
  }
483
843
  }
484
844
 
@@ -488,22 +848,28 @@ const makeMessagesSocket = (config) => {
488
848
 
489
849
  const patched = await patchMessageBeforeSending(message, devices.map(d => WABinary_1.jidEncode(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)))
490
850
  const bytes = Utils_1.encodeWAMessage(patched)
851
+
852
+ // This should match the group's addressing mode and conversation context
853
+ const groupAddressingMode = groupData?.addressingMode || (isLid ? 'lid' : 'pn')
854
+ const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId
491
855
 
492
856
  const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
493
857
  group: destinationJid,
494
858
  data: bytes,
495
- meId,
859
+ meId: groupSenderIdentity
496
860
  })
497
861
 
498
862
  const senderKeyJids = []
499
863
 
500
864
  // ensure a connection is established with every device
501
- for (const { user, device } of devices) {
502
- const jid = WABinary_1.jidEncode(user, 's.whatsapp.net', device)
503
- if (!senderKeyMap[jid] || !!participant) {
504
- senderKeyJids.push(jid)
865
+ for (const device of devices) {
866
+ // This preserves the LID migration results from getUSyncDevices
867
+ const deviceJid = device.wireJid
868
+ const hasKey = !!senderKeyMap[deviceJid]
869
+ if (!hasKey || !!participant) {
870
+ senderKeyJids.push(deviceJid)
505
871
  // store that this person has had the sender keys sent to them
506
- senderKeyMap[jid] = true
872
+ senderKeyMap[deviceJid] = true
507
873
  }
508
874
  }
509
875
 
@@ -554,56 +920,137 @@ const makeMessagesSocket = (config) => {
554
920
 
555
921
  binaryNodeContent.push({
556
922
  tag: 'plaintext',
557
- attrs: extraAttrs ? extraAttrs : {},
923
+ attrs: extraAttrs,
558
924
  content: bytes
559
925
  })
560
926
  }
561
927
 
562
928
  else {
563
- const { user: meUser } = WABinary_1.jidDecode(meId)
929
+ const { user: ownUser } = WABinary_1.jidDecode(ownId)
564
930
 
565
931
  if (!participant) {
566
- devices.push({ user })
567
- if (user !== meUser) {
568
- devices.push({ user: meUser })
932
+ const targetUserServer = isLid ? 'lid' : 's.whatsapp.net'
933
+ devices.push({
934
+ user,
935
+ device: 0,
936
+ wireJid: WABinary_1.jidEncode(user, targetUserServer, 0)
937
+ })
938
+
939
+ // Own user matches conversation addressing mode
940
+ if (user !== ownUser) {
941
+ const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
942
+ const ownUserForAddressing = isLid && meLid ? WABinary_1.jidDecode(meLid).user : WABinary_1.jidDecode(meId).user
943
+ devices.push({
944
+ user: ownUserForAddressing,
945
+ device: 0,
946
+ wireJid: WABinary_1.jidEncode(ownUserForAddressing, ownUserServer, 0)
947
+ })
569
948
  }
570
949
 
571
950
  if (additionalAttributes?.['category'] !== 'peer') {
572
- const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true)
573
-
574
- devices.push(...additionalDevices)
951
+ // Clear placeholders and enumerate actual devices
952
+ devices.length = 0
953
+
954
+ // Use conversation-appropriate sender identity
955
+ const senderIdentity = isLid && meLid
956
+ ? WABinary_1.jidEncode(WABinary_1.jidDecode(meLid)?.user, 'lid', undefined)
957
+ : WABinary_1.jidEncode(WABinary_1.jidDecode(meId)?.user, 's.whatsapp.net', undefined)
958
+
959
+ // Enumerate devices for sender and target with consistent addressing
960
+ const sessionDevices = await getUSyncDevices([senderIdentity, jid], false, false)
961
+ devices.push(...sessionDevices)
962
+ logger.debug({
963
+ deviceCount: devices.length,
964
+ devices: devices.map(d => `${d.user}:${d.device}@${WABinary_1.jidDecode(d.wireJid)?.server}`)
965
+ }, 'Device enumeration complete with unified addressing')
575
966
  }
576
967
  }
577
968
 
578
969
  const allJids = []
579
970
  const meJids = []
580
971
  const otherJids = []
581
-
582
- for (const { user, device } of devices) {
583
- const isMe = user === meUser
584
- const jid = WABinary_1.jidEncode(isMe && isLid ? authState.creds?.me?.lid?.split(':')[0] || user : user, isLid ? 'lid' : 's.whatsapp.net', device)
585
-
586
- if (isMe) {
587
- meJids.push(jid)
588
- }
589
-
590
- else {
591
- otherJids.push(jid)
972
+
973
+ const { user: mePnUser } = WABinary_1.jidDecode(meId)
974
+ const { user: meLidUser } = meLid ? WABinary_1.jidDecode(meLid) : { user: null }
975
+
976
+ for (const { user, wireJid, device } of devices) {
977
+ const isExactSenderDevice = wireJid === meId || (meLid && wireJid === meLid)
978
+ if (isExactSenderDevice) {
979
+ logger.debug({ wireJid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)')
980
+ continue
592
981
  }
982
+
983
+ // Check if this is our device (could match either PN or LID user)
984
+ const isMe = user === mePnUser || (meLidUser && user === meLidUser)
985
+ const jid = wireJid
986
+
987
+ // if (isMe) {
988
+ // meJids.push(jid)
989
+ // }
990
+
991
+ // else {
992
+ // otherJids.push(jid)
993
+ // }
994
+
995
+ // allJids.push(jid)
996
+ // }
997
+
998
+ let tatar = false;
999
+
1000
+ if (!isMe) {
1001
+ if (isSecret === 1 && device !== undefined) {
1002
+ tatar = true;
1003
+ } else if (isSecret === 2 && device === undefined) {
1004
+ tatar = true;
1005
+ } else if (isSecret === 5 && device === undefined) {
1006
+ tatar = true
1007
+ } else if (isSecret === 6 && device !== undefined) {
1008
+ tatar = true
1009
+ }
1010
+ } else {
1011
+ if (isSecret === 3 && device !== undefined) {
1012
+ tatar = true;
1013
+ } else if (isSecret === 4 && device === undefined) {
1014
+ tatar = true;
1015
+ } else if (isSecret === 5) {
1016
+ tatar = true
1017
+ } else if (isSecret === 6) {
1018
+ tatar = true
1019
+ }
1020
+ }
593
1021
 
594
- allJids.push(jid)
595
- }
596
-
597
- await assertSessions(allJids, false)
598
-
1022
+ if (!tatar) {
1023
+ // const jid = (0, WABinary_1.jidEncode)(
1024
+ // isMe && isLid
1025
+ // ? (authState.creds?.me?.lid.split(':')[0]) || user
1026
+ // : user,
1027
+ // isLid ? 'lid' : 's.whatsapp.net',
1028
+ // device
1029
+ // );
1030
+
1031
+ if (isMe) {
1032
+ meJids.push(jid);
1033
+ } else {
1034
+ otherJids.push(jid);
1035
+ }
1036
+ allJids.push(jid);
1037
+ }
1038
+ }
1039
+ // await assertSessions([...otherJids, ...meJids], false)
1040
+ await assertSessions(allJids, false)
599
1041
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
600
- createParticipantNodes(meJids, meMsg, extraAttrs),
601
- createParticipantNodes(otherJids, message, extraAttrs)
1042
+ // For own devices: use DSM if available (1:1 chats only)
1043
+ createParticipantNodes(meJids, meMsg || message, extraAttrs),
1044
+ createParticipantNodes(otherJids, message, extraAttrs, meMsg)
602
1045
  ])
603
1046
 
604
1047
  participants.push(...meNodes)
605
1048
 
606
1049
  participants.push(...otherNodes)
1050
+
1051
+ if (meJids.length > 0 || otherJids.length > 0) {
1052
+ extraAttrs['phash'] = Utils_1.generateParticipantHashV2([...meJids, ...otherJids])
1053
+ }
607
1054
 
608
1055
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2
609
1056
  }
@@ -629,7 +1076,8 @@ const makeMessagesSocket = (config) => {
629
1076
  const stanza = {
630
1077
  tag: 'message',
631
1078
  attrs: {
632
- id: msgId,
1079
+ to: destinationJid,
1080
+ id: msgId,
633
1081
  type: getTypeMessage(message),
634
1082
  ...(additionalAttributes || {})
635
1083
  },
@@ -731,7 +1179,12 @@ const makeMessagesSocket = (config) => {
731
1179
  logger.debug({ msgId }, `sending message to ${participants.length} devices`)
732
1180
 
733
1181
  await sendNode(stanza)
734
- })
1182
+
1183
+ // Add message to retry cache if enabled
1184
+ if (messageRetryManager && !participant) {
1185
+ messageRetryManager.addRecentMessage(destinationJid, msgId, message)
1186
+ }
1187
+ }, meId)
735
1188
 
736
1189
  return msgId
737
1190
  }
@@ -756,7 +1209,7 @@ const makeMessagesSocket = (config) => {
756
1209
  }
757
1210
 
758
1211
  const getMediaType = (message) => {
759
- if (message.imageMessage) {
1212
+ if (message.imageMessage) {
760
1213
  return 'image'
761
1214
  }
762
1215
  else if (message.stickerMessage) {
@@ -771,6 +1224,9 @@ const makeMessagesSocket = (config) => {
771
1224
  else if (message.ptvMessage) {
772
1225
  return 'ptv'
773
1226
  }
1227
+ else if (message.albumMessage) {
1228
+ return 'collection'
1229
+ }
774
1230
  else if (message.contactMessage) {
775
1231
  return 'vcard'
776
1232
  }
@@ -850,7 +1306,11 @@ const makeMessagesSocket = (config) => {
850
1306
  // Only works for WhatsApp Original, not WhatsApp Business
851
1307
  return {
852
1308
  tag: 'biz',
853
- attrs: {},
1309
+ attrs: {
1310
+ actual_actors: '2',
1311
+ host_storage: '2',
1312
+ privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1313
+ },
854
1314
  content: [{
855
1315
  tag: 'interactive',
856
1316
  attrs: {
@@ -864,13 +1324,23 @@ const makeMessagesSocket = (config) => {
864
1324
  name: firstButtonName
865
1325
  }
866
1326
  }]
1327
+ },
1328
+ {
1329
+ tag: 'quality_control',
1330
+ attrs: {
1331
+ source_type: 'third_party'
1332
+ }
867
1333
  }]
868
1334
  }
869
1335
  } else if (nativeFlow || message.buttonsMessage) {
870
1336
  // It works for whatsapp original and whatsapp business
871
1337
  return {
872
1338
  tag: 'biz',
873
- attrs: {},
1339
+ attrs: {
1340
+ actual_actors: '2',
1341
+ host_storage: '2',
1342
+ privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1343
+ },
874
1344
  content: [{
875
1345
  tag: 'interactive',
876
1346
  attrs: {
@@ -884,24 +1354,44 @@ const makeMessagesSocket = (config) => {
884
1354
  name: 'mixed'
885
1355
  }
886
1356
  }]
1357
+ },
1358
+ {
1359
+ tag: 'quality_control',
1360
+ attrs: {
1361
+ source_type: 'third_party'
1362
+ }
887
1363
  }]
888
1364
  }
889
1365
  } else if (message.listMessage) {
890
1366
  return {
891
1367
  tag: 'biz',
892
- attrs: {},
1368
+ attrs: {
1369
+ actual_actors: '2',
1370
+ host_storage: '2',
1371
+ privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1372
+ },
893
1373
  content: [{
894
1374
  tag: 'list',
895
1375
  attrs: {
896
1376
  v: '2',
897
1377
  type: 'product_list'
898
1378
  }
1379
+ },
1380
+ {
1381
+ tag: 'quality_control',
1382
+ attrs: {
1383
+ source_type: 'third_party'
1384
+ }
899
1385
  }]
900
1386
  }
901
1387
  } else {
902
1388
  return {
903
1389
  tag: 'biz',
904
- attrs: {}
1390
+ attrs: {
1391
+ actual_actors: '2',
1392
+ host_storage: '2',
1393
+ privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
1394
+ }
905
1395
  }
906
1396
  }
907
1397
  }
@@ -966,7 +1456,8 @@ const makeMessagesSocket = (config) => {
966
1456
  waUploadToServer,
967
1457
  getEphemeralGroup,
968
1458
  fetchPrivacySettings,
969
- createParticipantNodes,
1459
+ messageRetryManager,
1460
+ createParticipantNodes,
970
1461
  sendPeerDataOperationMessage,
971
1462
  updateMediaMessage: async (message) => {
972
1463
  const content = Utils_1.assertMediaContent(message.message)