@badzz88/baileys 8.5.3 → 8.5.4

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 (110) hide show
  1. package/README.md +1 -1
  2. package/WAProto/WAProto.proto +1256 -75
  3. package/WAProto/index.d.ts +36042 -19649
  4. package/WAProto/index.js +181990 -135645
  5. package/engine-requirements.js +7 -15
  6. package/lib/Defaults/index.js +22 -17
  7. package/lib/Signal/Group/group_cipher.js +5 -5
  8. package/lib/Signal/Group/keyhelper.js +4 -4
  9. package/lib/Signal/Group/sender-chain-key.js +2 -2
  10. package/lib/Signal/Group/sender-key-distribution-message.js +1 -1
  11. package/lib/Signal/Group/sender-key-message.js +3 -3
  12. package/lib/Signal/Group/sender-key-record.js +1 -1
  13. package/lib/Signal/Group/sender-message-key.js +5 -5
  14. package/lib/Signal/libsignal.js +39 -59
  15. package/lib/Signal/lid-mapping.js +28 -10
  16. package/lib/Socket/aigroups.js +5 -5
  17. package/lib/Socket/business.js +3 -11
  18. package/lib/Socket/chats.js +668 -319
  19. package/lib/Socket/communities.js +85 -89
  20. package/lib/Socket/graphql.js +435 -228
  21. package/lib/Socket/groups.js +132 -211
  22. package/lib/Socket/index.js +9 -7
  23. package/lib/Socket/interactive-handler.js +117 -60
  24. package/lib/Socket/interop.js +56 -175
  25. package/lib/Socket/managed-account.js +79 -48
  26. package/lib/Socket/messages-recv.js +898 -340
  27. package/lib/Socket/messages-send.js +462 -160
  28. package/lib/Socket/mex.js +40 -53
  29. package/lib/Socket/newsletter.js +291 -295
  30. package/lib/Socket/privacy.js +77 -265
  31. package/lib/Socket/registration.js +164 -157
  32. package/lib/Socket/socket.js +181 -199
  33. package/lib/Socket/username.js +144 -227
  34. package/lib/Store/make-cache-manager-store.js +2 -2
  35. package/lib/Store/make-in-memory-store.js +25 -141
  36. package/lib/Types/Auth.js +3 -3
  37. package/lib/Types/Label.js +1 -1
  38. package/lib/Types/LabelAssociation.js +1 -1
  39. package/lib/Types/Newsletter.js +96 -65
  40. package/lib/Types/State.js +4 -4
  41. package/lib/Types/index.js +1 -1
  42. package/lib/Utils/auth-utils.js +52 -57
  43. package/lib/Utils/browser-utils.js +1 -1
  44. package/lib/Utils/business.js +2 -6
  45. package/lib/Utils/chat-utils.js +102 -38
  46. package/lib/Utils/crypto.js +54 -84
  47. package/lib/Utils/decode-wa-message.js +316 -83
  48. package/lib/Utils/event-buffer.js +37 -61
  49. package/lib/Utils/generics.js +157 -103
  50. package/lib/Utils/group-history.js +3 -12
  51. package/lib/Utils/history.js +15 -15
  52. package/lib/Utils/index.js +1 -5
  53. package/lib/Utils/link-preview.js +3 -8
  54. package/lib/Utils/lt-hash.js +2 -35
  55. package/lib/Utils/make-mutex.js +1 -1
  56. package/lib/Utils/message-inspect.js +393 -0
  57. package/lib/Utils/message-retry-manager.js +27 -92
  58. package/lib/Utils/messages-media.js +159 -130
  59. package/lib/Utils/messages.js +144 -566
  60. package/lib/Utils/meta-ai-msmsg.js +62 -202
  61. package/lib/Utils/noise-handler.js +19 -21
  62. package/lib/Utils/offline-node-processor.js +3 -8
  63. package/lib/Utils/pre-key-manager.js +13 -23
  64. package/lib/Utils/process-message.js +197 -106
  65. package/lib/Utils/reporting-utils.js +2 -2
  66. package/lib/Utils/signal.js +28 -63
  67. package/lib/Utils/stanza-ack.js +39 -12
  68. package/lib/Utils/sync-action-utils.js +4 -7
  69. package/lib/Utils/tc-token-utils.js +20 -25
  70. package/lib/Utils/use-multi-file-auth-state.js +30 -14
  71. package/lib/Utils/validate-connection.js +59 -19
  72. package/lib/WABinary/decode.js +50 -16
  73. package/lib/WABinary/encode.js +54 -224
  74. package/lib/WABinary/generic-utils.js +7 -97
  75. package/lib/WABinary/jid-utils.js +27 -14
  76. package/lib/WAM/encode.js +7 -7
  77. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +58 -1
  78. package/lib/WAUSync/Protocols/USyncContactProtocol.js +7 -1
  79. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +13 -5
  80. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -4
  81. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +20 -7
  82. package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +865 -0
  83. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +1 -1
  84. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +2 -2
  85. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +7 -2
  86. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +1 -1
  87. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +2 -1
  88. package/lib/WAUSync/Protocols/index.js +1 -0
  89. package/lib/WAUSync/USyncBackoff.js +26 -0
  90. package/lib/WAUSync/USyncQuery.js +77 -6
  91. package/lib/WAUSync/USyncUser.js +16 -8
  92. package/lib/WAUSync/index.js +1 -0
  93. package/lib/antiban.js +608 -854
  94. package/lib/index.js +1 -1
  95. package/package.json +16 -20
  96. package/lib/Socket/luxu.js +0 -387
  97. package/lib/Socket/text-router.js +0 -83
  98. package/lib/Store/keyed-db.js +0 -108
  99. package/lib/Types/Mex.js +0 -112
  100. package/lib/Utils/command-loader.d.ts +0 -31
  101. package/lib/Utils/command-loader.js +0 -100
  102. package/lib/Utils/companion-reg-client-utils.js +0 -42
  103. package/lib/Utils/curve25519-js.js +0 -275
  104. package/lib/Utils/native-bridge.js +0 -82
  105. package/lib/Utils/session-pool.d.ts +0 -16
  106. package/lib/Utils/session-pool.js +0 -94
  107. package/lib/Utils/sticker.d.ts +0 -17
  108. package/lib/Utils/sticker.js +0 -145
  109. package/lib/Utils/view-once-cache.d.ts +0 -9
  110. package/lib/Utils/view-once-cache.js +0 -79
@@ -41,11 +41,9 @@ exports.bindWaitForEvent = bindWaitForEvent
41
41
  exports.trimUndefined = trimUndefined
42
42
  exports.bytesToCrockford = bytesToCrockford
43
43
  exports.encodeNewsletterMessage = encodeNewsletterMessage
44
- exports.generateIOSMessageID = void 0
45
- exports.generateAndroMessageID = void 0
46
44
  const boom_1 = require('@hapi/boom')
47
45
  const crypto_1 = require('crypto')
48
- const Crypto_1 = require('./crypto')
46
+ const rb = require('whatsapp-rust-bridge')
49
47
  const DEFAULTS_1 = require('../Defaults')
50
48
  const index_js_1 = require('../../WAProto/index.js')
51
49
  const baileysVersion = DEFAULTS_1.VERSION
@@ -53,14 +51,14 @@ const Types_1 = require('../Types')
53
51
  const WABinary_1 = require('../WABinary')
54
52
  const crypto_2 = require('./crypto')
55
53
  exports.BufferJSON = {
56
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+
57
55
  replacer: (k, value) => {
58
56
  if (Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') {
59
57
  return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') }
60
58
  }
61
59
  return value
62
60
  },
63
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+
64
62
  reviver: (_, value) => {
65
63
  if (typeof value === 'object' && value !== null && value.type === 'Buffer' && typeof value.data === 'string') {
66
64
  return Buffer.from(value.data, 'base64')
@@ -81,7 +79,7 @@ const getKeyAuthor = (key, meId = 'me') =>
81
79
  (key?.fromMe ? meId : key?.participantAlt || key?.remoteJidAlt || key?.participant || key?.remoteJid) || ''
82
80
  exports.getKeyAuthor = getKeyAuthor
83
81
  const isStringNullOrEmpty = value =>
84
- // eslint-disable-next-line eqeqeq
82
+
85
83
  value == null || value === ''
86
84
  exports.isStringNullOrEmpty = isStringNullOrEmpty
87
85
  const writeRandomPadMax16 = msg => {
@@ -102,7 +100,7 @@ const unpadRandomMax16 = e => {
102
100
  return new Uint8Array(t.buffer, t.byteOffset, t.length - r)
103
101
  }
104
102
  exports.unpadRandomMax16 = unpadRandomMax16
105
- // code is inspired by whatsmeow
103
+
106
104
  const generateParticipantHashV2 = participants => {
107
105
  participants.sort()
108
106
  const sha256Hash = (0, crypto_2.sha256)(Buffer.from(participants.join(''))).toString('base64')
@@ -127,7 +125,7 @@ const encodeBigEndian = (e, t = 4) => {
127
125
  exports.encodeBigEndian = encodeBigEndian
128
126
  const toNumber = t => (typeof t === 'object' && t ? ('toNumber' in t ? t.toNumber() : t.low) : t || 0)
129
127
  exports.toNumber = toNumber
130
- /** unix timestamp of a date in seconds */
128
+
131
129
  const unixTimestampSeconds = (date = new Date()) => Math.floor(date.getTime() / 1000)
132
130
  exports.unixTimestampSeconds = unixTimestampSeconds
133
131
  const debouncedTimeout = (intervalMs = 1000, task) => {
@@ -177,7 +175,7 @@ async function promiseTimeout(ms, promise) {
177
175
  return new Promise(promise)
178
176
  }
179
177
  const stack = new Error().stack
180
- // Create a promise that rejects in <ms> milliseconds
178
+
181
179
  const { delay, cancel } = (0, exports.delayCancellable)(ms)
182
180
  const p = new Promise((resolve, reject) => {
183
181
  delay
@@ -196,38 +194,26 @@ async function promiseTimeout(ms, promise) {
196
194
  }).finally(cancel)
197
195
  return p
198
196
  }
199
- // inspired from whatsmeow code
200
- // https://github.com/tulir/whatsmeow/blob/64bc969fbe78d31ae0dd443b8d4c80a5d026d07a/send.go#L42
201
- const generateMessageIDV2 = (userId) => {
202
- const data = Buffer.alloc(8 + 20 + 16);
203
- data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
204
- if (userId) {
205
- const id = (0, WABinary_1.jidDecode)(userId);
206
- if (id?.user) {
207
- data.write(id.user, 8);
208
- data.write('@c.us', 8 + id.user.length);
209
- }
210
- }
211
- const random = (0, crypto_1.randomBytes)(16);
212
- random.copy(data, 28);
213
- const hash = (0, crypto_1.createHash)('sha256').update(data).digest();
214
- return 'XZCYYX-' + hash.toString('hex').toUpperCase().substring(0, 18);
215
- };
197
+
198
+
199
+ const generateMessageIDV2 = userId => {
200
+ const data = Buffer.alloc(8 + 20 + 16)
201
+ data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)))
202
+ if (userId) {
203
+ const id = (0, WABinary_1.jidDecode)(userId)
204
+ if (id?.user) {
205
+ data.write(id.user, 8)
206
+ data.write('@c.us', 8 + id.user.length)
207
+ }
208
+ }
209
+ const random = (0, crypto_1.randomBytes)(16)
210
+ random.copy(data, 28)
211
+ const hash = Buffer.from(rb.sha256(data))
212
+ return '3EB0' + hash.toString('hex').toUpperCase().substring(0, 18)
213
+ }
216
214
  exports.generateMessageIDV2 = generateMessageIDV2
217
- const generateIOSMessageID = () => {
218
- const prefix = '3A';
219
- const random = (0, crypto_1.randomBytes)(9.5); // 19 hex chars = 9.5 bytes
220
- return (prefix + random.toString('hex')).toUpperCase().substring(0, 21);
221
- };
222
- exports.generateIOSMessageID = generateIOSMessageID
223
- const generateAndroMessageID = () => {
224
- const prefix = '3A';
225
- const random = (0, crypto_1.randomBytes)(16); // 32 hex chars = 16 bytes
226
- return (random.toString('hex')).toUpperCase().substring(0, 21);
227
- };
228
- exports.generateAndroMessageID = generateAndroMessageID
229
- // generate a random ID to attach to a message
230
- const generateMessageID = () => 'XZCYYX-' + (0, crypto_1.randomBytes)(18).toString('hex').toUpperCase()
215
+
216
+ const generateMessageID = () => '3EB0' + (0, crypto_1.randomBytes)(18).toString('hex').toUpperCase()
231
217
  exports.generateMessageID = generateMessageID
232
218
  function bindWaitForEvent(ev, event) {
233
219
  return async (check, timeoutMs) => {
@@ -257,30 +243,33 @@ function bindWaitForEvent(ev, event) {
257
243
  }
258
244
  const bindWaitForConnectionUpdate = ev => bindWaitForEvent(ev, 'connection.update')
259
245
  exports.bindWaitForConnectionUpdate = bindWaitForConnectionUpdate
260
- /**
261
- * utility that fetches latest baileys version from the master branch.
262
- * Use to ensure your WA connection is always on the latest version
263
- */
246
+
264
247
  const fetchLatestBaileysVersion = async (options = {}) => {
265
248
  const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/index.ts'
266
249
  try {
250
+
251
+
252
+ const controller = new AbortController()
253
+ const timer = setTimeout(() => controller.abort(), options.timeout ?? 5000)
267
254
  const response = await fetch(URL, {
268
255
  dispatcher: options.dispatcher,
269
256
  method: 'GET',
270
- headers: options.headers
257
+ headers: options.headers,
258
+ signal: controller.signal
271
259
  })
260
+ clearTimeout(timer)
272
261
  if (!response.ok) {
273
262
  throw new boom_1.Boom(`Failed to fetch latest Baileys version: ${response.statusText}`, {
274
263
  statusCode: response.status
275
264
  })
276
265
  }
277
266
  const text = await response.text()
278
- // Extract version from line 7 (const version = [...])
267
+
279
268
  const lines = text.split('\n')
280
- const versionLine = lines[6] // Line 7 (0-indexed)
269
+ const versionLine = lines[6]
281
270
  const versionMatch = versionLine.match(/const version = \[(\d+),\s*(\d+),\s*(\d+)\]/)
282
271
  if (versionMatch) {
283
- const version = [parseInt(versionMatch[1]), parseInt(versionMatch[2]), parseInt(versionMatch[3])]
272
+ const version = [parseInt(versionMatch[1], 10), parseInt(versionMatch[2], 10), parseInt(versionMatch[3], 10)]
284
273
  return {
285
274
  version,
286
275
  isLatest: true
@@ -297,24 +286,25 @@ const fetchLatestBaileysVersion = async (options = {}) => {
297
286
  }
298
287
  }
299
288
  exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion
300
- /**
301
- * A utility that fetches the latest web version of whatsapp.
302
- * Use to ensure your WA connection is always on the latest version
303
- */
289
+
304
290
  const fetchLatestWaWebVersion = async (options = {}) => {
305
291
  try {
306
- // Absolute minimal headers required to bypass anti-bot detection
292
+
307
293
  const defaultHeaders = {
308
294
  'sec-fetch-site': 'none',
309
295
  'user-agent':
310
296
  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
311
297
  }
312
298
  const headers = { ...defaultHeaders, ...options.headers }
299
+ const controller = new AbortController()
300
+ const timer = setTimeout(() => controller.abort(), options.timeout ?? 5000)
313
301
  const response = await fetch('https://web.whatsapp.com/sw.js', {
314
302
  ...options,
315
303
  method: 'GET',
316
- headers
304
+ headers,
305
+ signal: controller.signal
317
306
  })
307
+ clearTimeout(timer)
318
308
  if (!response.ok) {
319
309
  throw new boom_1.Boom(`Failed to fetch sw.js: ${response.statusText}`, { statusCode: response.status })
320
310
  }
@@ -344,7 +334,7 @@ const fetchLatestWaWebVersion = async (options = {}) => {
344
334
  }
345
335
  }
346
336
  exports.fetchLatestWaWebVersion = fetchLatestWaWebVersion
347
- /** unique message tag prefix for MD clients */
337
+
348
338
  const generateMdTagPrefix = () => {
349
339
  const bytes = (0, crypto_1.randomBytes)(4)
350
340
  return `${bytes.readUInt16BE()}.${bytes.readUInt16BE(2)}-`
@@ -353,13 +343,11 @@ exports.generateMdTagPrefix = generateMdTagPrefix
353
343
  const STATUS_MAP = {
354
344
  sender: index_js_1.proto.WebMessageInfo.Status.SERVER_ACK,
355
345
  played: index_js_1.proto.WebMessageInfo.Status.PLAYED,
346
+ 'played-self': index_js_1.proto.WebMessageInfo.Status.PLAYED,
356
347
  read: index_js_1.proto.WebMessageInfo.Status.READ,
357
348
  'read-self': index_js_1.proto.WebMessageInfo.Status.READ
358
349
  }
359
- /**
360
- * Given a type of receipt, returns what the new status of the message should be
361
- * @param type type from receipt
362
- */
350
+
363
351
  const getStatusFromReceiptType = type => {
364
352
  const status = STATUS_MAP[type]
365
353
  if (typeof type === 'undefined') {
@@ -371,10 +359,7 @@ exports.getStatusFromReceiptType = getStatusFromReceiptType
371
359
  const CODE_MAP = {
372
360
  conflict: Types_1.DisconnectReason.connectionReplaced
373
361
  }
374
- /**
375
- * Stream errors generally provide a reason, map that to a baileys DisconnectReason
376
- * @param reason the string reason given, eg. "conflict"
377
- */
362
+
378
363
  const getErrorCodeFromStreamError = node => {
379
364
  const [reasonNode] = (0, WABinary_1.getAllBinaryNodeChildren)(node)
380
365
  let reason = reasonNode?.tag || 'unknown'
@@ -396,11 +381,31 @@ const getCallStatusFromNode = ({ tag, attrs }) => {
396
381
  status = 'offer'
397
382
  break
398
383
  case 'terminate':
399
- if (attrs.reason === 'timeout') {
400
- status = 'timeout'
401
- } else {
402
- //fired when accepted/rejected/timeout/caller hangs up
403
- status = 'terminate'
384
+
385
+ switch (attrs.reason) {
386
+ case 'timeout':
387
+ case 'Timeout':
388
+ status = 'timeout'
389
+ break
390
+ case 'RejectDoNotDisturb':
391
+ status = 'reject_do_not_disturb'
392
+ break
393
+ case 'MicPermissionDenied':
394
+ status = 'mic_permission_denied'
395
+ break
396
+ case 'CameraPermissionDenied':
397
+ status = 'camera_permission_denied'
398
+ break
399
+ case 'RemoteBusy':
400
+ status = 'remote_busy'
401
+ break
402
+ case 'RemoteOffline':
403
+ status = 'remote_offline'
404
+ break
405
+ default:
406
+
407
+ status = 'terminate'
408
+ break
404
409
  }
405
410
  break
406
411
  case 'reject':
@@ -409,6 +414,76 @@ const getCallStatusFromNode = ({ tag, attrs }) => {
409
414
  case 'accept':
410
415
  status = 'accept'
411
416
  break
417
+ case 'preaccept':
418
+ status = 'preaccept'
419
+ break
420
+ case 'accept_ack':
421
+ status = 'accept_ack'
422
+ break
423
+ case 'enc-rekey':
424
+ case 'enc_rekey':
425
+ status = 'enc_rekey'
426
+ break
427
+ case 'peer_state':
428
+ status = 'peer_state'
429
+ break
430
+ case 'group_info':
431
+ status = 'group_info'
432
+ break
433
+ case 'video_state':
434
+ status = 'video_state'
435
+ break
436
+ case 'video_state_ack':
437
+ status = 'video_state_ack'
438
+ break
439
+ case 'flow_control':
440
+ status = 'flow_control'
441
+ break
442
+ case 'relaylatency':
443
+ status = 'relaylatency'
444
+ break
445
+ case 'mute_v2':
446
+ status = 'mute'
447
+ break
448
+ case 'waiting_room_request':
449
+ status = 'waiting_room_request'
450
+ break
451
+ case 'signal':
452
+
453
+ switch (attrs.type) {
454
+ case '13':
455
+ status = 'preaccept'
456
+ break
457
+ case '15':
458
+ status = 'video_state'
459
+ break
460
+ case '17':
461
+ status = 'group_info'
462
+ break
463
+ case '20':
464
+ status = 'video_state_ack'
465
+ break
466
+ case '21':
467
+ status = 'flow_control'
468
+ break
469
+ case '23':
470
+ status = 'accept_ack'
471
+ break
472
+ case '1002':
473
+ case '1007':
474
+ status = 'peer_state'
475
+ break
476
+ case '1008':
477
+ status = 'enc_rekey'
478
+ break
479
+ case '12':
480
+ status = 'mute'
481
+ break
482
+ default:
483
+ status = 'ringing'
484
+ break
485
+ }
486
+ break
412
487
  default:
413
488
  status = 'ringing'
414
489
  break
@@ -425,25 +500,22 @@ const getCodeFromWSError = error => {
425
500
  statusCode = code
426
501
  }
427
502
  } else if (
428
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
503
+
429
504
  error?.code?.startsWith('E') ||
430
505
  error?.message?.includes('timed out')
431
506
  ) {
432
- // handle ETIMEOUT, ENOTFOUND etc
507
+
433
508
  statusCode = 408
434
509
  }
435
510
  return statusCode
436
511
  }
437
512
  exports.getCodeFromWSError = getCodeFromWSError
438
- /**
439
- * Is the given platform WA business
440
- * @param platform AuthenticationCreds.platform
441
- */
513
+
442
514
  const isWABusinessPlatform = platform => {
443
515
  return platform === 'smbi' || platform === 'smba'
444
516
  }
445
517
  exports.isWABusinessPlatform = isWABusinessPlatform
446
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
518
+
447
519
  function trimUndefined(obj) {
448
520
  for (const key in obj) {
449
521
  if (typeof obj[key] === 'undefined') {
@@ -474,51 +546,40 @@ function encodeNewsletterMessage(message) {
474
546
  return index_js_1.proto.Message.encode(message).finish()
475
547
  }
476
548
 
477
- /**
478
- * Add human-like jitter to a base delay
479
- * @param baseMs base delay in milliseconds
480
- * @param varianceFraction fraction of baseMs to use as variance (0–1), default 0.3
481
- */
549
+
482
550
  const jitterDelay = (baseMs, varianceFraction = 0.3) => {
483
551
  const variance = baseMs * varianceFraction
484
552
  return baseMs + (Math.random() * 2 - 1) * variance
485
553
  }
486
554
  exports.jitterDelay = jitterDelay
487
555
 
488
- /**
489
- * Compute exponential backoff delay for a given attempt number (0-based)
490
- * @param attempt attempt index (0 = first retry)
491
- * @param baseMs starting delay in ms (default 500)
492
- * @param maxMs maximum delay cap in ms (default 30000)
493
- */
556
+
494
557
  const exponentialBackoff = (attempt, baseMs = 500, maxMs = 30000) => {
495
558
  return Math.min(baseMs * Math.pow(2, attempt), maxMs)
496
559
  }
497
560
  exports.exponentialBackoff = exponentialBackoff
498
561
 
499
- /** Convert buffer/Uint8Array to hex string */
562
+
500
563
  const bytesToHex = buf => Buffer.from(buf).toString('hex')
501
564
  exports.bytesToHex = bytesToHex
502
565
 
503
- /** Convert hex string to Buffer */
566
+
504
567
  const hexToBytes = hex => Buffer.from(hex, 'hex')
505
568
  exports.hexToBytes = hexToBytes
506
569
 
507
- /** Convert buffer to base64url string */
570
+
508
571
  const bytesToBase64Url = buf => Buffer.from(buf).toString('base64url')
509
572
  exports.bytesToBase64Url = bytesToBase64Url
510
573
 
511
- /** Compute SHA-256 hex digest of data */
574
+
512
575
  const sha256Hex = data => (0, crypto_1.createHash)('sha256').update(data).digest('hex')
513
576
  exports.sha256Hex = sha256Hex
514
577
 
515
- /** Compute HMAC-SHA-256 of data with key, returns Buffer */
578
+
516
579
  const hmacSha256 = (data, key) => (0, crypto_1.createHmac)('sha256', key).update(data).digest()
517
580
  exports.hmacSha256 = hmacSha256
518
581
 
519
- /**
520
- * Normalize and deduplicate an array of JIDs
521
- */
582
+
522
583
  const normalizeJidBatch = (jids, normalizer) => {
523
584
  const seen = new Set()
524
585
  const result = []
@@ -534,18 +595,11 @@ const normalizeJidBatch = (jids, normalizer) => {
534
595
  }
535
596
  exports.normalizeJidBatch = normalizeJidBatch
536
597
 
537
- /**
538
- * Sleep for a given number of milliseconds, returns a cancellable promise
539
- */
598
+
540
599
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
541
600
  exports.sleep = sleep
542
601
 
543
- /**
544
- * Run an async function with retry using exponential backoff
545
- * @param fn async function to retry
546
- * @param maxAttempts maximum number of attempts
547
- * @param baseDelayMs base delay between retries
548
- */
602
+
549
603
  const withRetry = async (fn, maxAttempts = 3, baseDelayMs = 500) => {
550
604
  let lastErr
551
605
  for (let i = 0; i < maxAttempts; i++) {
@@ -4,13 +4,7 @@ exports.processGroupHistory = exports.decodeGroupHistory = void 0
4
4
  const zlib_1 = require('zlib')
5
5
  const index_js_1 = require('../../WAProto/index.js')
6
6
 
7
- /**
8
- * Decode a GroupHistory protobuf blob (community/group history container).
9
- * @param buffer raw bytes, optionally zlib-compressed
10
- * @param options.inflate try zlib.inflateSync first, falling back to raw bytes (default true)
11
- * @param options.withMessageBytes decode the GroupHistoryWithMessageBytes variant,
12
- * expanding each entry's messageBytes into a WebMessageInfo (default false)
13
- */
7
+
14
8
  const decodeGroupHistory = (buffer, options = {}) => {
15
9
  const { inflate = true, withMessageBytes = false } = options
16
10
  if (!Buffer.isBuffer(buffer) && !(buffer instanceof Uint8Array)) {
@@ -21,7 +15,7 @@ const decodeGroupHistory = (buffer, options = {}) => {
21
15
  try {
22
16
  data = zlib_1.inflateSync(data)
23
17
  } catch {
24
- // not zlib-compressed — use raw bytes
18
+
25
19
  }
26
20
  }
27
21
  if (withMessageBytes) {
@@ -44,10 +38,7 @@ const decodeGroupHistory = (buffer, options = {}) => {
44
38
  }
45
39
  exports.decodeGroupHistory = decodeGroupHistory
46
40
 
47
- /**
48
- * Normalize a decoded GroupHistory into stable message buckets.
49
- * @param groupHistory a decoded proto.GroupHistory (or the withMessageBytes shape)
50
- */
41
+
51
42
  const processGroupHistory = groupHistory => {
52
43
  const gh = groupHistory || {}
53
44
  return {
@@ -17,8 +17,8 @@ const inflatePromise = (0, util_1.promisify)(zlib_1.inflate)
17
17
  const extractPnFromMessages = messages => {
18
18
  for (const msgItem of messages) {
19
19
  const message = msgItem.message
20
- // Only extract from outgoing messages (fromMe: true) in 1:1 chats
21
- // because userReceipt.userJid is the recipient's JID
20
+
21
+
22
22
  if (!message?.key?.fromMe || !message.userReceipt?.length) {
23
23
  continue
24
24
  }
@@ -36,7 +36,7 @@ const downloadHistory = async (msg, options) => {
36
36
  bufferArray.push(chunk)
37
37
  }
38
38
  let buffer = Buffer.concat(bufferArray)
39
- // decompress buffer
39
+
40
40
  buffer = await inflatePromise(buffer)
41
41
  const syncData = index_js_1.proto.HistorySync.decode(buffer)
42
42
  return syncData
@@ -53,13 +53,13 @@ const processHistoryMessage = (item, logger) => {
53
53
  let globalSettings = undefined
54
54
  let statusV3Messages = undefined
55
55
  logger?.trace({ progress: item.progress }, 'processing history of type ' + item.syncType?.toString())
56
- // Extract LID-PN mappings for all sync types
56
+
57
57
  for (const m of item.phoneNumberToLidMappings || []) {
58
58
  if (m.lidJid && m.pnJid) {
59
59
  lidPnMappings.push({ lid: m.lidJid, pn: m.pnJid })
60
60
  }
61
61
  }
62
- // Extract inline contacts (LID-PN mappings with names)
62
+
63
63
  for (const c of item.inlineContacts || []) {
64
64
  if (c.lidJid && c.pnJid) {
65
65
  lidPnMappings.push({ lid: c.lidJid, pn: c.pnJid })
@@ -77,7 +77,7 @@ const processHistoryMessage = (item, logger) => {
77
77
  })
78
78
  }
79
79
  }
80
- // Extract call log records with richer metadata
80
+
81
81
  for (const rec of item.callLogRecords || []) {
82
82
  callLogRecords.push({
83
83
  ...rec,
@@ -89,7 +89,7 @@ const processHistoryMessage = (item, logger) => {
89
89
  timestamp: rec.startTime ? (0, generics_1.toNumber)(rec.startTime) : undefined
90
90
  })
91
91
  }
92
- // Extract recent stickers with metadata, deduped by key
92
+
93
93
  const stickerKeys = new Set()
94
94
  for (const s of item.recentStickers || []) {
95
95
  const stickerKey = s.fileSha256 ? Buffer.from(s.fileSha256).toString('base64') : undefined
@@ -103,12 +103,12 @@ const processHistoryMessage = (item, logger) => {
103
103
  case index_js_1.proto.HistorySync.HistorySyncType.RECENT:
104
104
  case index_js_1.proto.HistorySync.HistorySyncType.FULL:
105
105
  case index_js_1.proto.HistorySync.HistorySyncType.ON_DEMAND:
106
- // Extract global client settings with full field parsing
106
+
107
107
  if (item.globalSettings) {
108
108
  const gs = item.globalSettings
109
109
  globalSettings = {
110
110
  ...gs,
111
- // Parsed convenience fields
111
+
112
112
  autoDownloadSettings: {
113
113
  photos: gs.autoDownloadPhotos,
114
114
  audio: gs.autoDownloadAudio,
@@ -139,7 +139,7 @@ const processHistoryMessage = (item, logger) => {
139
139
  : undefined
140
140
  }
141
141
  }
142
- // Extract status V3 messages with expiry tracking
142
+
143
143
  if (item.statusV3Messages?.length) {
144
144
  const now = Math.floor(Date.now() / 1000)
145
145
  statusV3Messages = item.statusV3Messages.filter(s => {
@@ -165,7 +165,7 @@ const processHistoryMessage = (item, logger) => {
165
165
  } else if (isPn && chat.lidJid) {
166
166
  lidPnMappings.push({ lid: chat.lidJid, pn: chatId })
167
167
  } else if (isLid && !chat.pnJid) {
168
- // Fallback: extract PN from userReceipt in messages when pnJid is missing
168
+
169
169
  const pnFromReceipt = extractPnFromMessages(chat.messages || [])
170
170
  if (pnFromReceipt) {
171
171
  lidPnMappings.push({ lid: chatId, pn: pnFromReceipt })
@@ -177,7 +177,7 @@ const processHistoryMessage = (item, logger) => {
177
177
  const message = item.message
178
178
  messages.push(message)
179
179
  if (!chat.messages?.length) {
180
- // keep only the most recent message in the chat array
180
+
181
181
  chat.messages = [{ message }]
182
182
  }
183
183
  if (!message.key.fromMe && !chat.lastMessageRecvTimestamp) {
@@ -194,13 +194,13 @@ const processHistoryMessage = (item, logger) => {
194
194
  })
195
195
  }
196
196
  }
197
- // Extract past participants metadata
197
+
198
198
  if (chat.id && (0, WABinary_1.isJidGroup)(chat.id)) {
199
- // Chat-level past participants info is available via PastParticipants messages
199
+
200
200
  }
201
201
  chats.push({ ...chat })
202
202
  }
203
- // Extract past participants from dedicated field
203
+
204
204
  for (const pp of item.pastParticipants || []) {
205
205
  pastParticipants.push(pp)
206
206
  }
@@ -28,6 +28,7 @@ var __exportStar =
28
28
  Object.defineProperty(exports, '__esModule', { value: true })
29
29
  __exportStar(require('./generics'), exports)
30
30
  __exportStar(require('./decode-wa-message'), exports)
31
+ __exportStar(require('./message-inspect'), exports)
31
32
  __exportStar(require('./messages'), exports)
32
33
  __exportStar(require('./messages-media'), exports)
33
34
  __exportStar(require('./validate-connection'), exports)
@@ -50,8 +51,3 @@ __exportStar(require('./message-composer'), exports)
50
51
  __exportStar(require('./group-history'), exports)
51
52
  __exportStar(require('./consumer-application'), exports)
52
53
  __exportStar(require('./voip-rekey'), exports)
53
- __exportStar(require('./companion-reg-client-utils'), exports)
54
- __exportStar(require('./view-once-cache'), exports)
55
- __exportStar(require('./sticker'), exports)
56
- __exportStar(require('./command-loader'), exports)
57
- __exportStar(require('./session-pool'), exports)
@@ -55,18 +55,13 @@ exports.getUrlInfo = void 0
55
55
  const messages_1 = require('./messages')
56
56
  const messages_media_1 = require('./messages-media')
57
57
  const THUMBNAIL_WIDTH_PX = 192
58
- /** Fetches an image and generates a thumbnail for it */
58
+
59
59
  const getCompressedJpegThumbnail = async (url, { thumbnailWidth, fetchOpts }) => {
60
60
  const stream = await (0, messages_media_1.getHttpStream)(url, fetchOpts)
61
61
  const result = await (0, messages_media_1.extractImageThumb)(stream, thumbnailWidth)
62
62
  return result
63
63
  }
64
- /**
65
- * Given a piece of text, checks for any URL present, generates link preview for the same and returns it
66
- * Return undefined if the fetch failed or no URL was found
67
- * @param text first matched URL in text
68
- * @returns the URL info required to generate link preview
69
- */
64
+
70
65
  const getUrlInfo = async (
71
66
  text,
72
67
  opts = {
@@ -75,7 +70,7 @@ const getUrlInfo = async (
75
70
  }
76
71
  ) => {
77
72
  try {
78
- // retries
73
+
79
74
  const retries = 0
80
75
  const maxRetry = 5
81
76
  const { getLinkPreview } = await Promise.resolve().then(() => __importStar(require('link-preview-js')))
@@ -1,39 +1,6 @@
1
1
  'use strict'
2
2
  Object.defineProperty(exports, '__esModule', { value: true })
3
3
  exports.LT_HASH_ANTI_TAMPERING = void 0
4
- const crypto_1 = require('./crypto')
4
+ const whatsapp_rust_bridge_1 = require('whatsapp-rust-bridge')
5
5
 
6
- /**
7
- * LT Hash ("lthash16") is a summation-based homomorphic hash algorithm that
8
- * maintains the integrity of a piece of data over a series of mutations. You
9
- * can add/remove mutations and it'll return a hash equal to if the same
10
- * series of mutations was made sequentially.
11
- *
12
- * WhatsApp expands each element to 128 bytes via HKDF (info = "WhatsApp Patch
13
- * Integrity"), treats that as 64 little-endian uint16 lanes, and combines
14
- * elements by adding/subtracting lane-wise mod 2^16 -- this is a pure HKDF +
15
- * integer-arithmetic algorithm, no elliptic-curve math involved. Pure-JS,
16
- * built on the already-validated `hkdf` implementation.
17
- */
18
- const LTHASH_INFO = 'WhatsApp Patch Integrity'
19
- const LTHASH_SIZE = 128 // bytes = 64 uint16 lanes
20
-
21
- const expand = element => (0, crypto_1.hkdf)(element, LTHASH_SIZE, { info: LTHASH_INFO })
22
-
23
- const applyDelta = (result, element, sign) => {
24
- const expanded = expand(element)
25
- for (let i = 0; i < LTHASH_SIZE; i += 2) {
26
- const lane = result.readUInt16LE(i)
27
- const delta = expanded.readUInt16LE(i)
28
- result.writeUInt16LE((lane + sign * delta) & 0xffff, i)
29
- }
30
- }
31
-
32
- exports.LT_HASH_ANTI_TAMPERING = {
33
- subtractThenAdd: (base, subtract = [], add = []) => {
34
- const result = Buffer.from(base)
35
- for (const element of subtract) applyDelta(result, element, -1)
36
- for (const element of add) applyDelta(result, element, 1)
37
- return result
38
- }
39
- }
6
+ exports.LT_HASH_ANTI_TAMPERING = new whatsapp_rust_bridge_1.LTHashAntiTampering()