@jkt48connect-corp/baileys 7.3.2 → 7.3.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.
- package/README.md +459 -143
- package/WAProto/WAProto.proto +227 -2
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.d.ts +9 -7
- package/lib/Defaults/index.js +6 -4
- package/lib/Socket/Client/index.d.ts +2 -3
- package/lib/Socket/Client/index.js +2 -3
- package/lib/Socket/Client/types.d.ts +17 -0
- package/lib/Socket/Client/types.js +13 -0
- package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +1 -1
- package/lib/Socket/Client/{web-socket-client.js → websocket.js} +2 -2
- package/lib/Socket/business.d.ts +8 -3
- package/lib/Socket/chats.d.ts +21 -19
- package/lib/Socket/chats.js +51 -48
- package/lib/Socket/groups.d.ts +28 -26
- package/lib/Socket/groups.js +2 -1
- package/lib/Socket/index.d.ts +6 -3
- package/lib/Socket/messages-recv.d.ts +8 -3
- package/lib/Socket/messages-recv.js +308 -149
- package/lib/Socket/messages-send.d.ts +23 -26
- package/lib/Socket/messages-send.js +193 -166
- package/lib/Socket/newsletter.d.ts +2 -2
- package/lib/Socket/newsletter.js +3 -3
- package/lib/Socket/registration.d.ts +8 -3
- package/lib/Socket/socket.d.ts +8 -6
- package/lib/Socket/socket.js +19 -14
- package/lib/Socket/usync.d.ts +37 -0
- package/lib/Socket/usync.js +70 -0
- package/lib/Store/make-cache-manager-store.d.ts +2 -2
- package/lib/Store/make-ordered-dictionary.d.ts +1 -1
- package/lib/Types/Call.d.ts +1 -1
- package/lib/Types/Chat.d.ts +12 -7
- package/lib/Types/Events.d.ts +17 -2
- package/lib/Types/GroupMetadata.d.ts +3 -1
- package/lib/Types/Label.d.ts +11 -0
- package/lib/Types/Message.d.ts +324 -328
- package/lib/Types/Socket.d.ts +7 -0
- package/lib/Types/USync.d.ts +25 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.d.ts +9 -0
- package/lib/Utils/chat-utils.d.ts +4 -4
- package/lib/Utils/chat-utils.js +41 -20
- package/lib/Utils/crypto.d.ts +1 -1
- package/lib/Utils/crypto.js +4 -2
- package/lib/Utils/decode-wa-message.d.ts +17 -0
- package/lib/Utils/decode-wa-message.js +42 -14
- package/lib/Utils/generics.d.ts +4 -10
- package/lib/Utils/generics.js +30 -14
- package/lib/Utils/history.d.ts +6 -2
- package/lib/Utils/history.js +3 -0
- package/lib/Utils/messages.d.ts +0 -1
- package/lib/Utils/messages.js +247 -39
- package/lib/Utils/signal.d.ts +2 -1
- package/lib/Utils/signal.js +11 -19
- package/lib/Utils/use-multi-file-auth-state.js +11 -3
- package/lib/Utils/validate-connection.d.ts +2 -2
- package/lib/Utils/validate-connection.js +1 -1
- package/lib/WABinary/encode.d.ts +1 -1
- package/lib/WABinary/encode.js +16 -10
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
- package/lib/WAUSync/Protocols/index.d.ts +4 -0
- package/lib/WAUSync/Protocols/index.js +20 -0
- package/lib/WAUSync/USyncQuery.d.ts +26 -0
- package/lib/WAUSync/USyncQuery.js +79 -0
- package/lib/WAUSync/USyncUser.d.ts +10 -0
- package/lib/WAUSync/USyncUser.js +22 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +19 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +23 -18
- package/LICENSE +0 -21
- package/lib/index.ts +0 -13
@@ -19,7 +19,7 @@ const messages_send_1 = require("./messages-send");
|
|
19
19
|
const makeMessagesRecvSocket = (config) => {
|
20
20
|
const { logger, retryRequestDelayMs, maxMsgRetryCount, 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, getUSyncDevices, sendPeerDataOperationMessage, createParticipantNodes } = 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,23 +30,30 @@ const makeMessagesRecvSocket = (config) => {
|
|
30
30
|
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
|
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, // 1 hour
|
35
|
+
useClones: false
|
36
|
+
});
|
33
37
|
let sendActiveReceipts = false;
|
34
|
-
const sendMessageAck = async ({ tag, attrs, content }) => {
|
38
|
+
const sendMessageAck = async ({ tag, attrs, content }, errorCode) => {
|
35
39
|
const stanza = {
|
36
40
|
tag: 'ack',
|
37
41
|
attrs: {
|
38
42
|
id: attrs.id,
|
39
43
|
to: attrs.from,
|
40
|
-
class: tag
|
44
|
+
class: tag
|
41
45
|
}
|
42
46
|
};
|
47
|
+
if (!!errorCode) {
|
48
|
+
stanza.attrs.error = errorCode.toString();
|
49
|
+
}
|
43
50
|
if (!!attrs.participant) {
|
44
51
|
stanza.attrs.participant = attrs.participant;
|
45
52
|
}
|
46
53
|
if (!!attrs.recipient) {
|
47
54
|
stanza.attrs.recipient = attrs.recipient;
|
48
55
|
}
|
49
|
-
if (!!attrs.type && (tag !== 'message' || (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable'))) {
|
56
|
+
if (!!attrs.type && (tag !== 'message' || (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable') || errorCode !== 0)) {
|
50
57
|
stanza.attrs.type = attrs.type;
|
51
58
|
}
|
52
59
|
if (tag === 'message' && (0, WABinary_1.getBinaryNodeChild)({ tag, attrs, content }, 'unavailable')) {
|
@@ -127,16 +134,24 @@ const makeMessagesRecvSocket = (config) => {
|
|
127
134
|
await query(stanza);
|
128
135
|
};
|
129
136
|
const sendRetryRequest = async (node, forceIncludeKeys = false) => {
|
130
|
-
const
|
131
|
-
|
137
|
+
const { fullMessage } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '');
|
138
|
+
const { key: msgKey } = fullMessage;
|
139
|
+
const msgId = msgKey.id;
|
140
|
+
const key = `${msgId}:${msgKey === null || msgKey === void 0 ? void 0 : msgKey.participant}`;
|
141
|
+
let retryCount = msgRetryCache.get(key) || 0;
|
132
142
|
if (retryCount >= maxMsgRetryCount) {
|
133
143
|
logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
|
134
|
-
msgRetryCache.del(
|
144
|
+
msgRetryCache.del(key);
|
135
145
|
return;
|
136
146
|
}
|
137
147
|
retryCount += 1;
|
138
|
-
msgRetryCache.set(
|
148
|
+
msgRetryCache.set(key, retryCount);
|
139
149
|
const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
|
150
|
+
if (retryCount === 1) {
|
151
|
+
//request a resend via phone
|
152
|
+
const msgId = await requestPlaceholderResend(msgKey);
|
153
|
+
logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
|
154
|
+
}
|
140
155
|
const deviceIdentity = (0, Utils_1.encodeSignedDeviceIdentity)(account, true);
|
141
156
|
await authState.keys.transaction(async () => {
|
142
157
|
const receipt = {
|
@@ -215,6 +230,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
215
230
|
}
|
216
231
|
};
|
217
232
|
const handleGroupNotification = (participant, child, msg) => {
|
233
|
+
var _a, _b, _c, _d;
|
234
|
+
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
235
|
switch (child === null || child === void 0 ? void 0 : child.tag) {
|
219
236
|
case 'create':
|
220
237
|
const metadata = (0, groups_1.extractGroupMetadata)(child);
|
@@ -240,6 +257,11 @@ const makeMessagesRecvSocket = (config) => {
|
|
240
257
|
}
|
241
258
|
};
|
242
259
|
break;
|
260
|
+
case 'modify':
|
261
|
+
const oldNumber = (0, WABinary_1.getBinaryNodeChildren)(child, 'participant').map(p => p.attrs.jid);
|
262
|
+
msg.messageStubParameters = oldNumber || [];
|
263
|
+
msg.messageStubType = Types_1.WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
|
264
|
+
break;
|
243
265
|
case 'promote':
|
244
266
|
case 'demote':
|
245
267
|
case 'remove':
|
@@ -261,6 +283,11 @@ const makeMessagesRecvSocket = (config) => {
|
|
261
283
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_SUBJECT;
|
262
284
|
msg.messageStubParameters = [child.attrs.subject];
|
263
285
|
break;
|
286
|
+
case 'description':
|
287
|
+
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();
|
288
|
+
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
|
289
|
+
msg.messageStubParameters = description ? [description] : undefined;
|
290
|
+
break;
|
264
291
|
case 'announcement':
|
265
292
|
case 'not_announcement':
|
266
293
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
|
@@ -289,6 +316,15 @@ const makeMessagesRecvSocket = (config) => {
|
|
289
316
|
msg.messageStubParameters = [approvalMode.attrs.state];
|
290
317
|
}
|
291
318
|
break;
|
319
|
+
case 'created_membership_requests':
|
320
|
+
msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
321
|
+
msg.messageStubParameters = [participantJid, 'created', child.attrs.request_method];
|
322
|
+
break;
|
323
|
+
case 'revoked_membership_requests':
|
324
|
+
const isDenied = (0, WABinary_1.areJidsSameUser)(participantJid, participant);
|
325
|
+
msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
326
|
+
msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected'];
|
327
|
+
break;
|
292
328
|
}
|
293
329
|
};
|
294
330
|
const processNotification = async (node) => {
|
@@ -321,9 +357,6 @@ const makeMessagesRecvSocket = (config) => {
|
|
321
357
|
case 'encrypt':
|
322
358
|
await handleEncryptNotification(node);
|
323
359
|
break;
|
324
|
-
case 'newsletter':
|
325
|
-
// TO DO
|
326
|
-
break;
|
327
360
|
case 'devices':
|
328
361
|
const devices = (0, WABinary_1.getBinaryNodeChildren)(child, 'device');
|
329
362
|
if ((0, WABinary_1.areJidsSameUser)(child.attrs.jid, authState.creds.me.id)) {
|
@@ -342,7 +375,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
342
375
|
const setPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'set');
|
343
376
|
const delPicture = (0, WABinary_1.getBinaryNodeChild)(node, 'delete');
|
344
377
|
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.
|
378
|
+
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
379
|
imgUrl: setPicture ? 'changed' : 'removed'
|
347
380
|
}]);
|
348
381
|
if ((0, WABinary_1.isJidGroup)(from)) {
|
@@ -387,7 +420,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
387
420
|
const ref = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_ref'));
|
388
421
|
const primaryIdentityPublicKey = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'primary_identity_pub'));
|
389
422
|
const primaryEphemeralPublicKeyWrapped = toRequiredBuffer((0, WABinary_1.getBinaryNodeChildBuffer)(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
|
390
|
-
const codePairingPublicKey = decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
|
423
|
+
const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
|
391
424
|
const companionSharedKey = Utils_1.Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
|
392
425
|
const random = (0, crypto_1.randomBytes)(32);
|
393
426
|
const linkCodeSalt = (0, crypto_1.randomBytes)(32);
|
@@ -444,10 +477,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
444
477
|
return result;
|
445
478
|
}
|
446
479
|
};
|
447
|
-
function decipherLinkPublicKey(data) {
|
480
|
+
async function decipherLinkPublicKey(data) {
|
448
481
|
const buffer = toRequiredBuffer(data);
|
449
482
|
const salt = buffer.slice(0, 32);
|
450
|
-
const secretKey = (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
|
483
|
+
const secretKey = await (0, Utils_1.derivePairingCodeKey)(authState.creds.pairingCode, salt);
|
451
484
|
const iv = buffer.slice(32, 48);
|
452
485
|
const payload = buffer.slice(48, 80);
|
453
486
|
return (0, Utils_1.aesDecryptCTR)(payload, secretKey, iv);
|
@@ -482,8 +515,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
482
515
|
await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
|
483
516
|
}
|
484
517
|
logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
|
485
|
-
for (
|
486
|
-
const msg = msgs[i];
|
518
|
+
for (const [i, msg] of msgs.entries()) {
|
487
519
|
if (msg) {
|
488
520
|
updateSendMessageAgainCount(ids[i], participant);
|
489
521
|
const msgRelayOpts = { messageId: ids[i] };
|
@@ -526,59 +558,63 @@ const makeMessagesRecvSocket = (config) => {
|
|
526
558
|
const items = (0, WABinary_1.getBinaryNodeChildren)(content[0], 'item');
|
527
559
|
ids.push(...items.map(i => i.attrs.id));
|
528
560
|
}
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
(
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
if (
|
540
|
-
|
541
|
-
|
561
|
+
try {
|
562
|
+
await Promise.all([
|
563
|
+
processingMutex.mutex(async () => {
|
564
|
+
const status = (0, Utils_1.getStatusFromReceiptType)(attrs.type);
|
565
|
+
if (typeof status !== 'undefined' &&
|
566
|
+
(
|
567
|
+
// basically, we only want to know when a message from us has been delivered to/read by the other person
|
568
|
+
// or another device of ours has read some messages
|
569
|
+
status > WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ||
|
570
|
+
!isNodeFromMe)) {
|
571
|
+
if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
|
572
|
+
if (attrs.participant) {
|
573
|
+
const updateKey = status === WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
|
574
|
+
ev.emit('message-receipt.update', ids.map(id => ({
|
575
|
+
key: { ...key, id },
|
576
|
+
receipt: {
|
577
|
+
userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
|
578
|
+
[updateKey]: +attrs.t
|
579
|
+
}
|
580
|
+
})));
|
581
|
+
}
|
582
|
+
}
|
583
|
+
else {
|
584
|
+
ev.emit('messages.update', ids.map(id => ({
|
542
585
|
key: { ...key, id },
|
543
|
-
|
544
|
-
userJid: (0, WABinary_1.jidNormalizedUser)(attrs.participant),
|
545
|
-
[updateKey]: +attrs.t
|
546
|
-
}
|
586
|
+
update: { status }
|
547
587
|
})));
|
548
588
|
}
|
549
589
|
}
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
try {
|
564
|
-
logger.debug({ attrs, key }, 'recv retry request');
|
565
|
-
await sendMessagesAgain(key, ids, retryNode);
|
590
|
+
if (attrs.type === 'retry') {
|
591
|
+
// correctly set who is asking for the retry
|
592
|
+
key.participant = key.participant || attrs.from;
|
593
|
+
const retryNode = (0, WABinary_1.getBinaryNodeChild)(node, 'retry');
|
594
|
+
if (willSendMessageAgain(ids[0], key.participant)) {
|
595
|
+
if (key.fromMe) {
|
596
|
+
try {
|
597
|
+
logger.debug({ attrs, key }, 'recv retry request');
|
598
|
+
await sendMessagesAgain(key, ids, retryNode);
|
599
|
+
}
|
600
|
+
catch (error) {
|
601
|
+
logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
|
602
|
+
}
|
566
603
|
}
|
567
|
-
|
568
|
-
logger.
|
604
|
+
else {
|
605
|
+
logger.info({ attrs, key }, 'recv retry for not fromMe message');
|
569
606
|
}
|
570
607
|
}
|
571
608
|
else {
|
572
|
-
logger.info({ attrs, key }, '
|
609
|
+
logger.info({ attrs, key }, 'will not send message again, as sent too many times');
|
573
610
|
}
|
574
611
|
}
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
]);
|
612
|
+
})
|
613
|
+
]);
|
614
|
+
}
|
615
|
+
finally {
|
616
|
+
await sendMessageAck(node);
|
617
|
+
}
|
582
618
|
};
|
583
619
|
const handleNotification = async (node) => {
|
584
620
|
const remoteJid = node.attrs.from;
|
@@ -587,89 +623,169 @@ const makeMessagesRecvSocket = (config) => {
|
|
587
623
|
await sendMessageAck(node);
|
588
624
|
return;
|
589
625
|
}
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
626
|
+
try {
|
627
|
+
await Promise.all([
|
628
|
+
processingMutex.mutex(async () => {
|
629
|
+
var _a;
|
630
|
+
const msg = await processNotification(node);
|
631
|
+
if (msg) {
|
632
|
+
const fromMe = (0, WABinary_1.areJidsSameUser)(node.attrs.participant || remoteJid, authState.creds.me.id);
|
633
|
+
msg.key = {
|
634
|
+
remoteJid,
|
635
|
+
fromMe,
|
636
|
+
participant: node.attrs.participant,
|
637
|
+
id: node.attrs.id,
|
638
|
+
...(msg.key || {})
|
639
|
+
};
|
640
|
+
(_a = msg.participant) !== null && _a !== void 0 ? _a : (msg.participant = node.attrs.participant);
|
641
|
+
msg.messageTimestamp = +node.attrs.t;
|
642
|
+
const fullMsg = WAProto_1.proto.WebMessageInfo.fromObject(msg);
|
643
|
+
await upsertMessage(fullMsg, 'append');
|
644
|
+
}
|
645
|
+
})
|
646
|
+
]);
|
647
|
+
}
|
648
|
+
finally {
|
649
|
+
await sendMessageAck(node);
|
650
|
+
}
|
611
651
|
};
|
612
652
|
const handleMessage = async (node) => {
|
613
|
-
var _a, _b;
|
653
|
+
var _a, _b, _c;
|
614
654
|
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
|
615
655
|
logger.debug({ key: node.attrs.key }, 'ignored message');
|
616
656
|
await sendMessageAck(node);
|
617
657
|
return;
|
618
658
|
}
|
619
|
-
|
620
|
-
if ((
|
621
|
-
|
622
|
-
|
659
|
+
let response;
|
660
|
+
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable') && !(0, WABinary_1.getBinaryNodeChild)(node, 'enc')) {
|
661
|
+
await sendMessageAck(node);
|
662
|
+
const { key } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
|
663
|
+
response = await requestPlaceholderResend(key);
|
664
|
+
if (response === 'RESOLVED') {
|
665
|
+
return;
|
666
|
+
}
|
667
|
+
logger.debug('received unavailable message, acked and requested resend from phone');
|
668
|
+
}
|
669
|
+
else {
|
670
|
+
if (placeholderResendCache.get(node.attrs.id)) {
|
671
|
+
placeholderResendCache.del(node.attrs.id);
|
623
672
|
}
|
624
673
|
}
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
674
|
+
const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
|
675
|
+
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) {
|
676
|
+
msg.messageStubParameters = [Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT, response];
|
677
|
+
}
|
678
|
+
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) {
|
679
|
+
ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
|
680
|
+
}
|
681
|
+
try {
|
682
|
+
await Promise.all([
|
683
|
+
processingMutex.mutex(async () => {
|
684
|
+
var _a;
|
685
|
+
await decrypt();
|
686
|
+
// message failed to decrypt
|
687
|
+
if (msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT) {
|
688
|
+
if (((_a = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) === Utils_1.MISSING_KEYS_ERROR_TEXT) {
|
689
|
+
return sendMessageAck(node, Utils_1.NACK_REASONS.ParsingError);
|
690
|
+
}
|
691
|
+
retryMutex.mutex(async () => {
|
692
|
+
if (ws.isOpen) {
|
693
|
+
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable')) {
|
694
|
+
return;
|
695
|
+
}
|
696
|
+
const encNode = (0, WABinary_1.getBinaryNodeChild)(node, 'enc');
|
697
|
+
await sendRetryRequest(node, !encNode);
|
698
|
+
if (retryRequestDelayMs) {
|
699
|
+
await (0, Utils_1.delay)(retryRequestDelayMs);
|
700
|
+
}
|
636
701
|
}
|
702
|
+
else {
|
703
|
+
logger.debug({ node }, 'connection closed, ignoring retry req');
|
704
|
+
}
|
705
|
+
});
|
706
|
+
}
|
707
|
+
else {
|
708
|
+
// no type in the receipt => message delivered
|
709
|
+
let type = undefined;
|
710
|
+
let participant = msg.key.participant;
|
711
|
+
if (category === 'peer') { // special peer message
|
712
|
+
type = 'peer_msg';
|
637
713
|
}
|
638
|
-
else {
|
639
|
-
|
714
|
+
else if (msg.key.fromMe) { // message was sent by us from a different device
|
715
|
+
type = 'sender';
|
716
|
+
// need to specially handle this case
|
717
|
+
if ((0, WABinary_1.isJidUser)(msg.key.remoteJid)) {
|
718
|
+
participant = author;
|
719
|
+
}
|
640
720
|
}
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
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;
|
721
|
+
else if (!sendActiveReceipts) {
|
722
|
+
type = 'inactive';
|
723
|
+
}
|
724
|
+
await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
|
725
|
+
// send ack for history message
|
726
|
+
const isAnyHistoryMsg = (0, Utils_1.getHistoryMsg)(msg.message);
|
727
|
+
if (isAnyHistoryMsg) {
|
728
|
+
const jid = (0, WABinary_1.jidNormalizedUser)(msg.key.remoteJid);
|
729
|
+
await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
|
655
730
|
}
|
656
731
|
}
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
732
|
+
(0, Utils_2.cleanMessage)(msg, authState.creds.me.id);
|
733
|
+
await sendMessageAck(node);
|
734
|
+
await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
|
735
|
+
})
|
736
|
+
]);
|
737
|
+
}
|
738
|
+
catch (error) {
|
739
|
+
logger.error({ error, node }, 'error in handling message');
|
740
|
+
}
|
741
|
+
};
|
742
|
+
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
743
|
+
var _a;
|
744
|
+
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
745
|
+
throw new boom_1.Boom('Not authenticated');
|
746
|
+
}
|
747
|
+
const pdoMessage = {
|
748
|
+
historySyncOnDemandRequest: {
|
749
|
+
chatJid: oldestMsgKey.remoteJid,
|
750
|
+
oldestMsgFromMe: oldestMsgKey.fromMe,
|
751
|
+
oldestMsgId: oldestMsgKey.id,
|
752
|
+
oldestMsgTimestampMs: oldestMsgTimestamp,
|
753
|
+
onDemandMsgCount: count
|
754
|
+
},
|
755
|
+
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
756
|
+
};
|
757
|
+
return sendPeerDataOperationMessage(pdoMessage);
|
758
|
+
};
|
759
|
+
const requestPlaceholderResend = async (messageKey) => {
|
760
|
+
var _a;
|
761
|
+
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
762
|
+
throw new boom_1.Boom('Not authenticated');
|
763
|
+
}
|
764
|
+
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
765
|
+
logger.debug('already requested resend', { messageKey });
|
766
|
+
return;
|
767
|
+
}
|
768
|
+
else {
|
769
|
+
placeholderResendCache.set(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id, true);
|
770
|
+
}
|
771
|
+
await (0, Utils_1.delay)(5000);
|
772
|
+
if (!placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
773
|
+
logger.debug('message received while resend requested', { messageKey });
|
774
|
+
return 'RESOLVED';
|
775
|
+
}
|
776
|
+
const pdoMessage = {
|
777
|
+
placeholderMessageResendRequest: [{
|
778
|
+
messageKey
|
779
|
+
}],
|
780
|
+
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
781
|
+
};
|
782
|
+
setTimeout(() => {
|
783
|
+
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
784
|
+
logger.debug('PDO message without response after 15 seconds. Phone possibly offline', { messageKey });
|
785
|
+
placeholderResendCache.del(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id);
|
786
|
+
}
|
787
|
+
}, 15000);
|
788
|
+
return sendPeerDataOperationMessage(pdoMessage);
|
673
789
|
};
|
674
790
|
const handleCall = async (node) => {
|
675
791
|
const { attrs } = node;
|
@@ -698,7 +814,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
698
814
|
call.isGroup = existingCall.isGroup;
|
699
815
|
}
|
700
816
|
// delete data once call has ended
|
701
|
-
if (status === 'reject' || status === 'accept' || status === 'timeout') {
|
817
|
+
if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
|
702
818
|
callOfferCache.del(call.id);
|
703
819
|
}
|
704
820
|
ev.emit('call', [call]);
|
@@ -706,19 +822,19 @@ const makeMessagesRecvSocket = (config) => {
|
|
706
822
|
};
|
707
823
|
const handleBadAck = async ({ attrs }) => {
|
708
824
|
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
|
709
|
-
//
|
710
|
-
//
|
711
|
-
//
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
}
|
825
|
+
// WARNING: REFRAIN FROM ENABLING THIS FOR NOW. IT WILL CAUSE A LOOP
|
826
|
+
// // current hypothesis is that if pash is sent in the ack
|
827
|
+
// // it means -- the message hasn't reached all devices yet
|
828
|
+
// // we'll retry sending the message here
|
829
|
+
// if(attrs.phash) {
|
830
|
+
// logger.info({ attrs }, 'received phash in ack, resending message...')
|
831
|
+
// const msg = await getMessage(key)
|
832
|
+
// if(msg) {
|
833
|
+
// await relayMessage(key.remoteJid!, msg, { messageId: key.id!, useUserDevicesCache: false })
|
834
|
+
// } else {
|
835
|
+
// logger.warn({ attrs }, 'could not send message again, as it was not found')
|
836
|
+
// }
|
837
|
+
// }
|
722
838
|
// error in acknowledgement,
|
723
839
|
// device could not display the message
|
724
840
|
if (attrs.error) {
|
@@ -743,22 +859,63 @@ const makeMessagesRecvSocket = (config) => {
|
|
743
859
|
await execTask();
|
744
860
|
ev.flush();
|
745
861
|
function execTask() {
|
746
|
-
return exec(node)
|
862
|
+
return exec(node, false)
|
747
863
|
.catch(err => onUnexpectedError(err, identifier));
|
748
864
|
}
|
749
865
|
};
|
866
|
+
const makeOfflineNodeProcessor = () => {
|
867
|
+
const nodeProcessorMap = new Map([
|
868
|
+
['message', handleMessage],
|
869
|
+
['call', handleCall],
|
870
|
+
['receipt', handleReceipt],
|
871
|
+
['notification', handleNotification]
|
872
|
+
]);
|
873
|
+
const nodes = [];
|
874
|
+
let isProcessing = false;
|
875
|
+
const enqueue = (type, node) => {
|
876
|
+
nodes.push({ type, node });
|
877
|
+
if (isProcessing) {
|
878
|
+
return;
|
879
|
+
}
|
880
|
+
isProcessing = true;
|
881
|
+
const promise = async () => {
|
882
|
+
while (nodes.length && ws.isOpen) {
|
883
|
+
const { type, node } = nodes.shift();
|
884
|
+
const nodeProcessor = nodeProcessorMap.get(type);
|
885
|
+
if (!nodeProcessor) {
|
886
|
+
onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
|
887
|
+
continue;
|
888
|
+
}
|
889
|
+
await nodeProcessor(node);
|
890
|
+
}
|
891
|
+
isProcessing = false;
|
892
|
+
};
|
893
|
+
promise().catch(error => onUnexpectedError(error, 'processing offline nodes'));
|
894
|
+
};
|
895
|
+
return { enqueue };
|
896
|
+
};
|
897
|
+
const offlineNodeProcessor = makeOfflineNodeProcessor();
|
898
|
+
const processNode = (type, node, identifier, exec) => {
|
899
|
+
const isOffline = !!node.attrs.offline;
|
900
|
+
if (isOffline) {
|
901
|
+
offlineNodeProcessor.enqueue(type, node);
|
902
|
+
}
|
903
|
+
else {
|
904
|
+
processNodeWithBuffer(node, identifier, exec);
|
905
|
+
}
|
906
|
+
};
|
750
907
|
// recv a message
|
751
908
|
ws.on('CB:message', (node) => {
|
752
|
-
|
909
|
+
processNode('message', node, 'processing message', handleMessage);
|
753
910
|
});
|
754
911
|
ws.on('CB:call', async (node) => {
|
755
|
-
|
912
|
+
processNode('call', node, 'handling call', handleCall);
|
756
913
|
});
|
757
914
|
ws.on('CB:receipt', node => {
|
758
|
-
|
915
|
+
processNode('receipt', node, 'handling receipt', handleReceipt);
|
759
916
|
});
|
760
917
|
ws.on('CB:notification', async (node) => {
|
761
|
-
|
918
|
+
processNode('notification', node, 'handling notification', handleNotification);
|
762
919
|
});
|
763
920
|
ws.on('CB:ack,class:message', (node) => {
|
764
921
|
handleBadAck(node)
|
@@ -801,7 +958,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
801
958
|
sendMessageAck,
|
802
959
|
sendRetryRequest,
|
803
960
|
offerCall,
|
804
|
-
rejectCall
|
961
|
+
rejectCall,
|
962
|
+
fetchMessageHistory,
|
963
|
+
requestPlaceholderResend,
|
805
964
|
};
|
806
965
|
};
|
807
966
|
exports.makeMessagesRecvSocket = makeMessagesRecvSocket;
|