@queenanya/baileys 7.4.14 → 7.5.11

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 (88) hide show
  1. package/README.md +26 -26
  2. package/WAProto/index.js +66875 -96112
  3. package/lib/Defaults/baileys-version.json +1 -1
  4. package/lib/Defaults/index.d.ts +1 -231
  5. package/lib/Defaults/index.js +11 -23
  6. package/lib/Socket/Client/index.d.ts +2 -3
  7. package/lib/Socket/Client/index.js +2 -3
  8. package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +1 -1
  9. package/lib/Socket/Client/{web-socket-client.js → websocket.js} +2 -2
  10. package/lib/Socket/business.d.ts +29 -22
  11. package/lib/Socket/chats.d.ts +14 -3
  12. package/lib/Socket/chats.js +76 -48
  13. package/lib/Socket/groups.d.ts +21 -4
  14. package/lib/Socket/groups.js +12 -1
  15. package/lib/Socket/index.d.ts +37 -32
  16. package/lib/Socket/index.js +2 -2
  17. package/lib/Socket/messages-recv.d.ts +28 -22
  18. package/lib/Socket/messages-recv.js +291 -180
  19. package/lib/Socket/messages-send.d.ts +23 -13
  20. package/lib/Socket/messages-send.js +110 -76
  21. package/lib/Socket/newsletter.d.ts +17 -7
  22. package/lib/Socket/newsletter.js +67 -54
  23. package/lib/Socket/socket.d.ts +3 -1
  24. package/lib/Socket/socket.js +15 -17
  25. package/lib/Store/make-cache-manager-store.d.ts +2 -1
  26. package/lib/Store/make-in-memory-store.js +13 -11
  27. package/lib/Store/make-ordered-dictionary.js +2 -2
  28. package/lib/Types/Auth.d.ts +1 -6
  29. package/lib/Types/Call.d.ts +1 -1
  30. package/lib/Types/Chat.d.ts +12 -7
  31. package/lib/Types/Contact.d.ts +1 -1
  32. package/lib/Types/Events.d.ts +44 -2
  33. package/lib/Types/GroupMetadata.d.ts +3 -1
  34. package/lib/Types/Label.d.ts +11 -0
  35. package/lib/Types/Message.d.ts +37 -30
  36. package/lib/Types/Newsletter.d.ts +0 -13
  37. package/lib/Types/Newsletter.js +1 -15
  38. package/lib/Types/Socket.d.ts +10 -3
  39. package/lib/Types/index.d.ts +8 -0
  40. package/lib/Utils/auth-utils.js +1 -7
  41. package/lib/Utils/chat-utils.d.ts +5 -4
  42. package/lib/Utils/chat-utils.js +41 -20
  43. package/lib/Utils/crypto.d.ts +2 -1
  44. package/lib/Utils/crypto.js +4 -2
  45. package/lib/Utils/decode-wa-message.d.ts +1 -0
  46. package/lib/Utils/decode-wa-message.js +34 -14
  47. package/lib/Utils/event-buffer.js +14 -8
  48. package/lib/Utils/generics.d.ts +37 -13
  49. package/lib/Utils/generics.js +102 -18
  50. package/lib/Utils/history.d.ts +6 -2
  51. package/lib/Utils/history.js +3 -0
  52. package/lib/Utils/index.d.ts +1 -0
  53. package/lib/Utils/index.js +1 -0
  54. package/lib/Utils/link-preview.js +24 -1
  55. package/lib/Utils/logger.d.ts +1 -3
  56. package/lib/Utils/make-mutex.js +1 -0
  57. package/lib/Utils/messages-media.d.ts +3 -2
  58. package/lib/Utils/messages-media.js +17 -32
  59. package/lib/Utils/messages.d.ts +1 -0
  60. package/lib/Utils/messages.js +67 -72
  61. package/lib/Utils/noise-handler.d.ts +3 -3
  62. package/lib/Utils/noise-handler.js +7 -12
  63. package/lib/Utils/process-message.d.ts +3 -2
  64. package/lib/Utils/process-message.js +55 -21
  65. package/lib/Utils/signal.js +23 -16
  66. package/lib/Utils/use-multi-file-auth-state.js +17 -3
  67. package/lib/Utils/validate-connection.d.ts +0 -1
  68. package/lib/Utils/validate-connection.js +10 -44
  69. package/lib/WABinary/constants.js +5 -5
  70. package/lib/WABinary/decode.d.ts +3 -2
  71. package/lib/WABinary/decode.js +6 -4
  72. package/lib/WABinary/encode.d.ts +1 -2
  73. package/lib/WABinary/encode.js +8 -6
  74. package/lib/WABinary/generic-utils.d.ts +1 -0
  75. package/lib/WABinary/jid-utils.d.ts +3 -3
  76. package/lib/WABinary/jid-utils.js +5 -5
  77. package/lib/WAM/BinaryInfo.d.ts +3 -2
  78. package/lib/WAM/constants.d.ts +3 -2
  79. package/lib/WAM/encode.d.ts +1 -0
  80. package/lib/WAM/encode.js +2 -2
  81. package/package.json +37 -35
  82. package/lib/Defaults/phonenumber-mcc.json +0 -223
  83. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  84. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  85. package/lib/Socket/registration.d.ts +0 -267
  86. package/lib/Socket/registration.js +0 -166
  87. /package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +0 -0
  88. /package/lib/Socket/Client/{abstract-socket-client.js → types.js} +0 -0
@@ -17,9 +17,9 @@ const WABinary_1 = require("../WABinary");
17
17
  const groups_1 = require("./groups");
18
18
  const messages_send_1 = require("./messages-send");
19
19
  const makeMessagesRecvSocket = (config) => {
20
- const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid } = config;
20
+ const { logger, retryRequestDelayMs, maxMsgRetryCount, ignoreMsgLoading, getMessage, shouldIgnoreJid } = config;
21
21
  const sock = (0, messages_send_1.makeMessagesSocket)(config);
22
- const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, getUSyncDevices, createParticipantNodes } = sock;
22
+ const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, } = sock;
23
23
  /** this mutex ensures that each retryRequest will wait for the previous one to finish */
24
24
  const retryMutex = (0, make_mutex_1.makeMutex)();
25
25
  const msgRetryCache = config.msgRetryCounterCache || new node_cache_1.default({
@@ -30,6 +30,10 @@ const makeMessagesRecvSocket = (config) => {
30
30
  stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.CALL_OFFER,
31
31
  useClones: false
32
32
  });
33
+ const placeholderResendCache = config.placeholderResendCache || new node_cache_1.default({
34
+ stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY,
35
+ useClones: false
36
+ });
33
37
  let sendActiveReceipts = false;
34
38
  const sendMessageAck = async ({ tag, attrs, content }) => {
35
39
  const stanza = {
@@ -55,58 +59,6 @@ const makeMessagesRecvSocket = (config) => {
55
59
  logger.debug({ recv: { tag, attrs }, sent: stanza.attrs }, 'sent ack');
56
60
  await sendNode(stanza);
57
61
  };
58
- const offerCall = async (toJid, isVideo = false) => {
59
- const callId = (0, crypto_1.randomBytes)(16).toString('hex').toUpperCase().substring(0, 64);
60
- const offerContent = [];
61
- offerContent.push({ tag: 'audio', attrs: { enc: 'opus', rate: '16000' }, content: undefined });
62
- offerContent.push({ tag: 'audio', attrs: { enc: 'opus', rate: '8000' }, content: undefined });
63
- if (isVideo) {
64
- offerContent.push({
65
- tag: 'video',
66
- attrs: { enc: 'vp8', dec: 'vp8', orientation: '0', 'screen_width': '1920', 'screen_height': '1080', 'device_orientation': '0' },
67
- content: undefined
68
- });
69
- }
70
- offerContent.push({ tag: 'net', attrs: { medium: '3' }, content: undefined });
71
- offerContent.push({ tag: 'capability', attrs: { ver: '1' }, content: new Uint8Array([1, 4, 255, 131, 207, 4]) });
72
- offerContent.push({ tag: 'encopt', attrs: { keygen: '2' }, content: undefined });
73
- const encKey = (0, crypto_1.randomBytes)(32);
74
- const devices = (await getUSyncDevices([toJid], true, false)).map(({ user, device }) => (0, WABinary_1.jidEncode)(user, 's.whatsapp.net', device));
75
- await assertSessions(devices, true);
76
- const { nodes: destinations, shouldIncludeDeviceIdentity } = await createParticipantNodes(devices, {
77
- call: {
78
- callKey: new Uint8Array(encKey)
79
- }
80
- }, { count: '0' });
81
- offerContent.push({ tag: 'destination', attrs: {}, content: destinations });
82
- if (shouldIncludeDeviceIdentity) {
83
- offerContent.push({
84
- tag: 'device-identity',
85
- attrs: {},
86
- content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
87
- });
88
- }
89
- const stanza = ({
90
- tag: 'call',
91
- attrs: {
92
- id: (0, Utils_1.generateMessageIDV2)(),
93
- to: toJid,
94
- },
95
- content: [{
96
- tag: 'offer',
97
- attrs: {
98
- 'call-id': callId,
99
- 'call-creator': authState.creds.me.id,
100
- },
101
- content: offerContent,
102
- }],
103
- });
104
- await query(stanza);
105
- return {
106
- id: callId,
107
- to: toJid
108
- };
109
- };
110
62
  const rejectCall = async (callId, callFrom) => {
111
63
  const stanza = ({
112
64
  tag: 'call',
@@ -127,16 +79,24 @@ const makeMessagesRecvSocket = (config) => {
127
79
  await query(stanza);
128
80
  };
129
81
  const sendRetryRequest = async (node, forceIncludeKeys = false) => {
130
- const msgId = node.attrs.id;
131
- let retryCount = msgRetryCache.get(msgId) || 0;
82
+ const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
83
+ const { key: msgKey } = fullMessage;
84
+ const msgId = msgKey.id;
85
+ const key = `${msgId}:${msgKey === null || msgKey === void 0 ? void 0 : msgKey.participant}`;
86
+ let retryCount = msgRetryCache.get(key) || 0;
132
87
  if (retryCount >= maxMsgRetryCount) {
133
88
  logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
134
- msgRetryCache.del(msgId);
89
+ msgRetryCache.del(key);
135
90
  return;
136
91
  }
137
92
  retryCount += 1;
138
- msgRetryCache.set(msgId, retryCount);
93
+ msgRetryCache.set(key, retryCount);
139
94
  const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
95
+ if (retryCount === 1) {
96
+ //request a resend via phone
97
+ const msgId = await requestPlaceholderResend(msgKey);
98
+ logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
99
+ }
140
100
  const deviceIdentity = (0, Utils_1.encodeSignedDeviceIdentity)(account, true);
141
101
  await authState.keys.transaction(async () => {
142
102
  const receipt = {
@@ -215,6 +175,8 @@ const makeMessagesRecvSocket = (config) => {
215
175
  }
216
176
  };
217
177
  const handleGroupNotification = (participant, child, msg) => {
178
+ var _a, _b, _c, _d;
179
+ const participantJid = ((_b = (_a = (0, WABinary_1.getBinaryNodeChild)(child, 'participant')) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.jid) || participant;
218
180
  switch (child === null || child === void 0 ? void 0 : child.tag) {
219
181
  case 'create':
220
182
  const metadata = (0, groups_1.extractGroupMetadata)(child);
@@ -240,6 +202,11 @@ const makeMessagesRecvSocket = (config) => {
240
202
  }
241
203
  };
242
204
  break;
205
+ case 'modify':
206
+ const oldNumber = (0, WABinary_1.getBinaryNodeChildren)(child, 'participant').map(p => p.attrs.jid);
207
+ msg.messageStubParameters = oldNumber || [];
208
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
209
+ break;
243
210
  case 'promote':
244
211
  case 'demote':
245
212
  case 'remove':
@@ -261,6 +228,11 @@ const makeMessagesRecvSocket = (config) => {
261
228
  msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT;
262
229
  msg.messageStubParameters = [child.attrs.subject];
263
230
  break;
231
+ case 'description':
232
+ const description = (_d = (_c = (0, WABinary_1.getBinaryNodeChild)(child, 'body')) === null || _c === void 0 ? void 0 : _c.content) === null || _d === void 0 ? void 0 : _d.toString();
233
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
234
+ msg.messageStubParameters = description ? [description] : undefined;
235
+ break;
264
236
  case 'announcement':
265
237
  case 'not_announcement':
266
238
  msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
@@ -289,6 +261,59 @@ const makeMessagesRecvSocket = (config) => {
289
261
  msg.messageStubParameters = [approvalMode.attrs.state];
290
262
  }
291
263
  break;
264
+ case 'created_membership_requests':
265
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
266
+ msg.messageStubParameters = [participantJid, 'created', child.attrs.request_method];
267
+ break;
268
+ case 'revoked_membership_requests':
269
+ const isDenied = (0, WABinary_1.areJidsSameUser)(participantJid, participant);
270
+ msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
271
+ msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected'];
272
+ break;
273
+ }
274
+ };
275
+ const handleNewsletterNotification = (id, node) => {
276
+ const messages = (0, WABinary_1.getBinaryNodeChild)(node, 'messages');
277
+ const message = (0, WABinary_1.getBinaryNodeChild)(messages, 'message');
278
+ const server_id = message.attrs.server_id;
279
+ const reactionsList = (0, WABinary_1.getBinaryNodeChild)(message, 'reactions');
280
+ const viewsList = (0, WABinary_1.getBinaryNodeChildren)(message, 'views_count');
281
+ if (reactionsList) {
282
+ const reactions = (0, WABinary_1.getBinaryNodeChildren)(reactionsList, 'reaction');
283
+ if (reactions.length === 0) {
284
+ ev.emit('newsletter.reaction', { id, server_id, reaction: { removed: true } });
285
+ }
286
+ reactions.forEach(item => {
287
+ var _a, _b;
288
+ ev.emit('newsletter.reaction', { id, server_id, reaction: { code: (_a = item.attrs) === null || _a === void 0 ? void 0 : _a.code, count: +((_b = item.attrs) === null || _b === void 0 ? void 0 : _b.count) } });
289
+ });
290
+ }
291
+ if (viewsList.length) {
292
+ viewsList.forEach(item => {
293
+ ev.emit('newsletter.view', { id, server_id, count: +item.attrs.count });
294
+ });
295
+ }
296
+ };
297
+ const handleMexNewsletterNotification = (id, node) => {
298
+ var _a;
299
+ const operation = node === null || node === void 0 ? void 0 : node.attrs.op_name;
300
+ const content = JSON.parse((_a = node === null || node === void 0 ? void 0 : node.content) === null || _a === void 0 ? void 0 : _a.toString());
301
+ let contentPath;
302
+ if (operation === Types_1.MexOperations.PROMOTE || operation === Types_1.MexOperations.DEMOTE) {
303
+ let action;
304
+ if (operation === Types_1.MexOperations.PROMOTE) {
305
+ action = 'promote';
306
+ contentPath = content.data[Types_1.XWAPaths.PROMOTE];
307
+ }
308
+ if (operation === Types_1.MexOperations.DEMOTE) {
309
+ action = 'demote';
310
+ contentPath = content.data[Types_1.XWAPaths.DEMOTE];
311
+ }
312
+ ev.emit('newsletter-participants.update', { id, author: contentPath.actor.pn, user: contentPath.user.pn, new_role: contentPath.user_new_role, action });
313
+ }
314
+ if (operation === Types_1.MexOperations.UPDATE) {
315
+ contentPath = content.data[Types_1.XWAPaths.METADATA_UPDATE];
316
+ ev.emit('newsletter-settings.update', { id, update: contentPath.thread_metadata.settings });
292
317
  }
293
318
  };
294
319
  const processNotification = async (node) => {
@@ -311,6 +336,12 @@ const makeMessagesRecvSocket = (config) => {
311
336
  logger.debug({ jid }, 'got privacy token update');
312
337
  }
313
338
  break;
339
+ case 'newsletter':
340
+ handleNewsletterNotification(node.attrs.from, child);
341
+ break;
342
+ case 'mex':
343
+ handleMexNewsletterNotification(node.attrs.from, child);
344
+ break;
314
345
  case 'w:gp2':
315
346
  handleGroupNotification(node.attrs.participant, child, result);
316
347
  break;
@@ -342,7 +373,7 @@ const makeMessagesRecvSocket = (config) => {
342
373
  const setPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'set');
343
374
  const delPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'delete');
344
375
  ev.emit('contacts.update', [{
345
- id: (0, WABinary_1.jidNormalizedUser)((_a = node === null || node === void 0 ? void 0 : node.attrs) === null || _a === void 0 ? void 0 : _a.jid) || ((_c = (_b = (setPicture || delPicture)) === null || _b === void 0 ? void 0 : _b.attrs) === null || _c === void 0 ? void 0 : _c.hash) || '',
376
+ id: (0, WABinary_1.jidNormalizedUser)((_a = node === null || node === void 0 ? void 0 : node.attrs) === null || _a === void 0 ? void 0 : _a.from) || ((_c = (_b = (setPicture || delPicture)) === null || _b === void 0 ? void 0 : _b.attrs) === null || _c === void 0 ? void 0 : _c.hash) || '',
346
377
  imgUrl: setPicture ? 'changed' : 'removed'
347
378
  }]);
348
379
  if ((0, WABinary_1.isJidGroup)(from)) {
@@ -387,7 +418,7 @@ const makeMessagesRecvSocket = (config) => {
387
418
  const ref = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_ref'));
388
419
  const primaryIdentityPublicKey = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'primary_identity_pub'));
389
420
  const primaryEphemeralPublicKeyWrapped = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
390
- const codePairingPublicKey = decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
421
+ const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
391
422
  const companionSharedKey = Utils_1.Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
392
423
  const random = (0, crypto_1.randomBytes)(32);
393
424
  const linkCodeSalt = (0, crypto_1.randomBytes)(32);
@@ -444,10 +475,10 @@ const makeMessagesRecvSocket = (config) => {
444
475
  return result;
445
476
  }
446
477
  };
447
- function decipherLinkPublicKey(data) {
478
+ async function decipherLinkPublicKey(data) {
448
479
  const buffer = toRequiredBuffer(data);
449
480
  const salt = buffer.slice(0, 32);
450
- const secretKey = (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
481
+ const secretKey = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
451
482
  const iv = buffer.slice(32, 48);
452
483
  const payload = buffer.slice(48, 80);
453
484
  return (0, Utils_1.aesDecryptCTR)(payload, secretKey, iv);
@@ -482,8 +513,7 @@ const makeMessagesRecvSocket = (config) => {
482
513
  await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
483
514
  }
484
515
  logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
485
- for (let i = 0; i < msgs.length; i++) {
486
- const msg = msgs[i];
516
+ for (const [i, msg] of msgs.entries()) {
487
517
  if (msg) {
488
518
  updateSendMessageAgainCount(ids[i], participant);
489
519
  const msgRelayOpts = { messageId: ids[i] };
@@ -526,59 +556,63 @@ const makeMessagesRecvSocket = (config) => {
526
556
  const items = (0, WABinary_1.getBinaryNodeChildren)(content[0], 'item');
527
557
  ids.push(...items.map(i => i.attrs.id));
528
558
  }
529
- await Promise.all([
530
- processingMutex.mutex(async () => {
531
- const status = (0, Utils_1.getStatusFromReceiptType)(attrs.type);
532
- if (typeof status !== 'undefined' &&
533
- (
534
- // basically, we only want to know when a message from us has been delivered to/read by the other person
535
- // or another device of ours has read some messages
536
- status > WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ||
537
- !isNodeFromMe)) {
538
- if ((0, WABinary_1.isJidGroup)(remoteJid)) {
539
- if (attrs.participant) {
540
- const updateKey = status === WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
541
- ev.emit('message-receipt.update', ids.map(id => ({
559
+ try {
560
+ await Promise.all([
561
+ processingMutex.mutex(async () => {
562
+ const status = (0, Utils_1.getStatusFromReceiptType)(attrs.type);
563
+ if (typeof status !== 'undefined' &&
564
+ (
565
+ // basically, we only want to know when a message from us has been delivered to/read by the other person
566
+ // or another device of ours has read some messages
567
+ status > WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ||
568
+ !isNodeFromMe)) {
569
+ if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
570
+ if (attrs.participant) {
571
+ const updateKey = status === WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
572
+ ev.emit('message-receipt.update', ids.map(id => ({
573
+ key: { ...key, id },
574
+ receipt: {
575
+ userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
576
+ [updateKey]: +attrs.t
577
+ }
578
+ })));
579
+ }
580
+ }
581
+ else {
582
+ ev.emit('messages.update', ids.map(id => ({
542
583
  key: { ...key, id },
543
- receipt: {
544
- userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
545
- [updateKey]: +attrs.t
546
- }
584
+ update: { status }
547
585
  })));
548
586
  }
549
587
  }
550
- else {
551
- ev.emit('messages.update', ids.map(id => ({
552
- key: { ...key, id },
553
- update: { status }
554
- })));
555
- }
556
- }
557
- if (attrs.type === 'retry') {
558
- // correctly set who is asking for the retry
559
- key.participant = key.participant || attrs.from;
560
- const retryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'retry');
561
- if (willSendMessageAgain(ids[0], key.participant)) {
562
- if (key.fromMe) {
563
- try {
564
- logger.debug({ attrs, key }, 'recv retry request');
565
- await sendMessagesAgain(key, ids, retryNode);
588
+ if (attrs.type === 'retry') {
589
+ // correctly set who is asking for the retry
590
+ key.participant = key.participant || attrs.from;
591
+ const retryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'retry');
592
+ if (willSendMessageAgain(ids[0], key.participant)) {
593
+ if (key.fromMe) {
594
+ try {
595
+ logger.debug({ attrs, key }, 'recv retry request');
596
+ await sendMessagesAgain(key, ids, retryNode);
597
+ }
598
+ catch (error) {
599
+ logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
600
+ }
566
601
  }
567
- catch (error) {
568
- logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
602
+ else {
603
+ logger.info({ attrs, key }, 'recv retry for not fromMe message');
569
604
  }
570
605
  }
571
606
  else {
572
- logger.info({ attrs, key }, 'recv retry for not fromMe message');
607
+ logger.info({ attrs, key }, 'will not send message again, as sent too many times');
573
608
  }
574
609
  }
575
- else {
576
- logger.info({ attrs, key }, 'will not send message again, as sent too many times');
577
- }
578
- }
579
- }),
580
- sendMessageAck(node)
581
- ]);
610
+ })
611
+ ]);
612
+ }
613
+ finally {
614
+ await sendMessageAck(node);
615
+ }
582
616
  };
583
617
  const handleNotification = async (node) => {
584
618
  const remoteJid = node.attrs.from;
@@ -587,89 +621,164 @@ const makeMessagesRecvSocket = (config) => {
587
621
  await sendMessageAck(node);
588
622
  return;
589
623
  }
590
- await Promise.all([
591
- processingMutex.mutex(async () => {
592
- var _a;
593
- const msg = await processNotification(node);
594
- if (msg) {
595
- const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
596
- msg.key = {
597
- remoteJid,
598
- fromMe,
599
- participant: node.attrs.participant,
600
- id: node.attrs.id,
601
- ...(msg.key || {})
602
- };
603
- (_a = msg.participant) !== null && _a !== void 0 ? _a : (msg.participant = node.attrs.participant);
604
- msg.messageTimestamp = +node.attrs.t;
605
- const fullMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
606
- await upsertMessage(fullMsg, 'append');
607
- }
608
- }),
609
- sendMessageAck(node)
610
- ]);
624
+ try {
625
+ await Promise.all([
626
+ processingMutex.mutex(async () => {
627
+ var _a;
628
+ const msg = await processNotification(node);
629
+ if (msg) {
630
+ const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
631
+ msg.key = {
632
+ remoteJid,
633
+ fromMe,
634
+ participant: node.attrs.participant,
635
+ id: node.attrs.id,
636
+ ...(msg.key || {})
637
+ };
638
+ (_a = msg.participant) !== null && _a !== void 0 ? _a : (msg.participant = node.attrs.participant);
639
+ msg.messageTimestamp = +node.attrs.t;
640
+ const fullMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
641
+ await upsertMessage(fullMsg, 'append');
642
+ }
643
+ })
644
+ ]);
645
+ }
646
+ finally {
647
+ await sendMessageAck(node);
648
+ }
611
649
  };
612
650
  const handleMessage = async (node) => {
613
- var _a, _b;
651
+ var _a, _b, _c;
614
652
  if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
615
653
  logger.debug({ key: node.attrs.key }, 'ignored message');
616
654
  await sendMessageAck(node);
617
655
  return;
618
656
  }
619
- const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
620
- if (((_b = (_a = msg.message) === null || _a === void 0 ? void 0 : _a.protocolMessage) === null || _b === void 0 ? void 0 : _b.type) === WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER) {
621
- if (node.attrs.sender_pn) {
622
- ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
657
+ let response;
658
+ if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable') && !(0, WABinary_1.getBinaryNodeChild)(node, 'enc')) {
659
+ await sendMessageAck(node);
660
+ const { key } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
661
+ response = await requestPlaceholderResend(key);
662
+ if (response === 'RESOLVED') {
663
+ return;
623
664
  }
665
+ logger.debug('received unavailable message, acked and requested resend from phone');
624
666
  }
625
- await Promise.all([
626
- processingMutex.mutex(async () => {
627
- await decrypt();
628
- // message failed to decrypt
629
- if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
630
- retryMutex.mutex(async () => {
631
- if (ws.isOpen) {
632
- const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
633
- await sendRetryRequest(node, !encNode);
634
- if (retryRequestDelayMs) {
635
- await (0, Utils_1.delay)(retryRequestDelayMs);
667
+ else {
668
+ if (placeholderResendCache.get(node.attrs.id)) {
669
+ placeholderResendCache.del(node.attrs.id);
670
+ }
671
+ }
672
+ const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
673
+ if (response && ((_a = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) === Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT) {
674
+ msg.messageStubParameters = [Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT, response];
675
+ }
676
+ if (((_c = (_b = msg.message) === null || _b === void 0 ? void 0 : _b.protocolMessage) === null || _c === void 0 ? void 0 : _c.type) === WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER && node.attrs.sender_pn) {
677
+ ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
678
+ }
679
+ try {
680
+ await Promise.all([
681
+ processingMutex.mutex(async () => {
682
+ await decrypt();
683
+ // message failed to decrypt
684
+ if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
685
+ retryMutex.mutex(async () => {
686
+ if (ws.isOpen) {
687
+ if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable')) {
688
+ return;
689
+ }
690
+ const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
691
+ await sendRetryRequest(node, !encNode);
692
+ if (retryRequestDelayMs) {
693
+ await (0, Utils_1.delay)(retryRequestDelayMs);
694
+ }
695
+ }
696
+ else {
697
+ logger.debug({ node }, 'connection closed, ignoring retry req');
636
698
  }
699
+ });
700
+ }
701
+ else {
702
+ // no type in the receipt => message delivered
703
+ let type = undefined;
704
+ let participant = msg.key.participant;
705
+ if (category === 'peer') { // special peer message
706
+ type = 'peer_msg';
637
707
  }
638
- else {
639
- logger.debug({ node }, 'connection closed, ignoring retry req');
708
+ else if (msg.key.fromMe) { // message was sent by us from a different device
709
+ type = 'sender';
710
+ // need to specially handle this case
711
+ if ((0, WABinary_1.isJidUser)(msg.key.remoteJid)) {
712
+ participant = author;
713
+ }
640
714
  }
641
- });
642
- }
643
- else {
644
- // no type in the receipt => message delivered
645
- let type = undefined;
646
- let participant = msg.key.participant;
647
- if (category === 'peer') { // special peer message
648
- type = 'peer_msg';
649
- }
650
- else if (msg.key.fromMe) { // message was sent by us from a different device
651
- type = 'sender';
652
- // need to specially handle this case
653
- if ((0, WABinary_1.isJidUser)(msg.key.remoteJid)) {
654
- participant = author;
715
+ else if (!sendActiveReceipts) {
716
+ type = 'inactive';
717
+ }
718
+ await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
719
+ // send ack for history message
720
+ const isAnyHistoryMsg = (0, Utils_1.getHistoryMsg)(msg.message);
721
+ if (isAnyHistoryMsg) {
722
+ const jid = (0, WABinary_1.jidNormalizedUser)(msg.key.remoteJid);
723
+ await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
655
724
  }
656
725
  }
657
- else if (!sendActiveReceipts) {
658
- type = 'inactive';
659
- }
660
- await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
661
- // send ack for history message
662
- const isAnyHistoryMsg = (0, Utils_1.getHistoryMsg)(msg.message);
663
- if (isAnyHistoryMsg) {
664
- const jid = (0, WABinary_1.jidNormalizedUser)(msg.key.remoteJid);
665
- await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
666
- }
667
- }
668
- (0, Utils_2.cleanMessage)(msg, authState.creds.me.id);
669
- await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
670
- }),
671
- sendMessageAck(node)
672
- ]);
726
+ (0, Utils_2.cleanMessage)(msg, authState.creds.me.id);
727
+ await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
728
+ })
729
+ ]);
730
+ }
731
+ finally {
732
+ await sendMessageAck(node);
733
+ }
734
+ };
735
+ const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
736
+ var _a;
737
+ if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
738
+ throw new boom_1.Boom('Not authenticated');
739
+ }
740
+ const pdoMessage = {
741
+ historySyncOnDemandRequest: {
742
+ chatJid: oldestMsgKey.remoteJid,
743
+ oldestMsgFromMe: oldestMsgKey.fromMe,
744
+ oldestMsgId: oldestMsgKey.id,
745
+ oldestMsgTimestampMs: oldestMsgTimestamp,
746
+ onDemandMsgCount: count
747
+ },
748
+ peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
749
+ };
750
+ return sendPeerDataOperationMessage(pdoMessage);
751
+ };
752
+ const requestPlaceholderResend = async (messageKey) => {
753
+ var _a;
754
+ if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
755
+ throw new boom_1.Boom('Not authenticated');
756
+ }
757
+ if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
758
+ logger.debug('already requested resend', { messageKey });
759
+ return;
760
+ }
761
+ else {
762
+ placeholderResendCache.set(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id, true);
763
+ }
764
+ await (0, Utils_1.delay)(5000);
765
+ if (!placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
766
+ logger.debug('message received while resend requested', { messageKey });
767
+ return 'RESOLVED';
768
+ }
769
+ const pdoMessage = {
770
+ placeholderMessageResendRequest: [{
771
+ messageKey
772
+ }],
773
+ peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
774
+ };
775
+ setTimeout(() => {
776
+ if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
777
+ logger.debug('PDO message without response after 15 seconds. Phone possibly offline', { messageKey });
778
+ placeholderResendCache.del(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id);
779
+ }
780
+ }, 15000);
781
+ return sendPeerDataOperationMessage(pdoMessage);
673
782
  };
674
783
  const handleCall = async (node) => {
675
784
  const { attrs } = node;
@@ -698,14 +807,15 @@ const makeMessagesRecvSocket = (config) => {
698
807
  call.isGroup = existingCall.isGroup;
699
808
  }
700
809
  // delete data once call has ended
701
- if (status === 'reject' || status === 'accept' || status === 'timeout') {
810
+ if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
702
811
  callOfferCache.del(call.id);
703
812
  }
704
813
  ev.emit('call', [call]);
705
814
  await sendMessageAck(node);
706
815
  };
707
816
  const handleBadAck = async ({ attrs }) => {
708
- const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
817
+ // const key: WAMessageKey = { remoteJid: attrs.from, fromMe: true, id: attrs.id }
818
+ const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id, server_id: attrs === null || attrs === void 0 ? void 0 : attrs.server_id };
709
819
  // current hypothesis is that if pash is sent in the ack
710
820
  // it means -- the message hasn't reached all devices yet
711
821
  // we'll retry sending the message here
@@ -800,8 +910,9 @@ const makeMessagesRecvSocket = (config) => {
800
910
  ...sock,
801
911
  sendMessageAck,
802
912
  sendRetryRequest,
803
- offerCall,
804
- rejectCall
913
+ rejectCall,
914
+ fetchMessageHistory,
915
+ requestPlaceholderResend,
805
916
  };
806
917
  };
807
918
  exports.makeMessagesRecvSocket = makeMessagesRecvSocket;