amiudmodz 4.0.6 → 5.0.0
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 +130 -0
- package/lib/Defaults/index.js +9 -4
- package/lib/Socket/Client/web-socket-client.js +13 -5
- package/lib/Socket/chats.js +50 -77
- package/lib/Socket/groupStatus.js +51 -41
- package/lib/Socket/groups.js +8 -5
- package/lib/Socket/messages-recv.js +26 -10
- package/lib/Socket/messages-send.js +38 -42
- package/lib/Socket/newsletter.js +1 -1
- package/lib/Socket/socket.js +18 -6
- package/lib/Utils/auth-utils.js +9 -1
- package/lib/Utils/crypto.js +10 -2
- package/lib/Utils/event-buffer.js +14 -17
- package/lib/Utils/make-mutex.js +20 -16
- package/lib/Utils/messages-media.js +15 -10
- package/lib/Utils/messages.js +6 -2
- package/lib/Utils/noise-handler.js +27 -13
- package/lib/Utils/process-message.js +30 -22
- package/lib/Utils/use-multi-file-auth-state.js +10 -5
- package/lib/WABinary/decode.js +21 -11
- package/lib/WABinary/encode.js +8 -8
- package/package.json +11 -1
package/lib/Socket/groups.js
CHANGED
|
@@ -114,7 +114,7 @@ const makeGroupsSocket = (config) => {
|
|
|
114
114
|
}
|
|
115
115
|
]);
|
|
116
116
|
const node = (0, WABinary_1.getBinaryNodeChild)(result, 'membership_approval_requests');
|
|
117
|
-
const participants = (0, WABinary_1.getBinaryNodeChildren)(node, 'membership_approval_request');
|
|
117
|
+
const participants = node ? (0, WABinary_1.getBinaryNodeChildren)(node, 'membership_approval_request') : [];
|
|
118
118
|
return participants.map(v => v.attrs);
|
|
119
119
|
},
|
|
120
120
|
groupRequestParticipantsUpdate: async (jid, participants, action) => {
|
|
@@ -133,8 +133,8 @@ const makeGroupsSocket = (config) => {
|
|
|
133
133
|
]
|
|
134
134
|
}]);
|
|
135
135
|
const node = (0, WABinary_1.getBinaryNodeChild)(result, 'membership_requests_action');
|
|
136
|
-
const nodeAction = (0, WABinary_1.getBinaryNodeChild)(node, action);
|
|
137
|
-
const participantsAffected = (0, WABinary_1.getBinaryNodeChildren)(nodeAction, 'participant');
|
|
136
|
+
const nodeAction = node ? (0, WABinary_1.getBinaryNodeChild)(node, action) : undefined;
|
|
137
|
+
const participantsAffected = nodeAction ? (0, WABinary_1.getBinaryNodeChildren)(nodeAction, 'participant') : [];
|
|
138
138
|
return participantsAffected.map(p => {
|
|
139
139
|
return { status: p.attrs.error || '200', jid: p.attrs.jid };
|
|
140
140
|
});
|
|
@@ -263,8 +263,11 @@ const makeGroupsSocket = (config) => {
|
|
|
263
263
|
exports.makeGroupsSocket = makeGroupsSocket;
|
|
264
264
|
const extractGroupMetadata = (result) => {
|
|
265
265
|
var _a, _b;
|
|
266
|
-
const group = WABinary_1.getBinaryNodeChild(result, 'group');
|
|
267
|
-
|
|
266
|
+
const group = (0, WABinary_1.getBinaryNodeChild)(result, 'group');
|
|
267
|
+
if (!group) {
|
|
268
|
+
throw new boom_1.Boom('Invalid group metadata', { statusCode: 400 });
|
|
269
|
+
}
|
|
270
|
+
const descChild = (0, WABinary_1.getBinaryNodeChild)(group, 'description');
|
|
268
271
|
let desc;
|
|
269
272
|
let descId;
|
|
270
273
|
let descOwner;
|
|
@@ -388,7 +388,6 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
388
388
|
msg.messageStubType = Types_1.WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
|
389
389
|
msg.messageStubParameters = [participantJid, isDenied ? 'revoked' : 'rejected'];
|
|
390
390
|
break;
|
|
391
|
-
break;
|
|
392
391
|
default:
|
|
393
392
|
|
|
394
393
|
}
|
|
@@ -396,7 +395,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
396
395
|
const handleNewsletterNotification = (id, node) => {
|
|
397
396
|
const messages = (0, WABinary_1.getBinaryNodeChild)(node, 'messages');
|
|
398
397
|
const message = (0, WABinary_1.getBinaryNodeChild)(messages, 'message');
|
|
399
|
-
|
|
398
|
+
if (!message) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const serverId = message.attrs?.server_id;
|
|
400
402
|
const reactionsList = (0, WABinary_1.getBinaryNodeChild)(message, 'reactions');
|
|
401
403
|
const viewsList = (0, WABinary_1.getBinaryNodeChildren)(message, 'views_count');
|
|
402
404
|
if (reactionsList) {
|
|
@@ -417,8 +419,17 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
417
419
|
};
|
|
418
420
|
const handleMexNewsletterNotification = (id, node) => {
|
|
419
421
|
var _a;
|
|
420
|
-
const operation = node
|
|
421
|
-
const
|
|
422
|
+
const operation = node?.attrs?.op_name;
|
|
423
|
+
const rawContent = (_a = node?.content) === null || _a === void 0 ? void 0 : _a.toString();
|
|
424
|
+
if (!rawContent) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
let content;
|
|
428
|
+
try {
|
|
429
|
+
content = JSON.parse(rawContent);
|
|
430
|
+
} catch (e) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
422
433
|
let contentPath;
|
|
423
434
|
if (operation === Types_1.MexOperations.PROMOTE || operation === Types_1.MexOperations.DEMOTE) {
|
|
424
435
|
let action;
|
|
@@ -812,7 +823,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
812
823
|
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) {
|
|
813
824
|
return sendMessageAck(node, Utils_1.NACK_REASONS.ParsingError);
|
|
814
825
|
}
|
|
815
|
-
retryMutex.mutex(async () => {
|
|
826
|
+
await retryMutex.mutex(async () => {
|
|
816
827
|
if (ws.isOpen) {
|
|
817
828
|
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable')) {
|
|
818
829
|
return;
|
|
@@ -1001,11 +1012,11 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1001
1012
|
|
|
1002
1013
|
const processNodeWithBuffer = async (node, identifier, exec) => {
|
|
1003
1014
|
ev.buffer();
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
function execTask() {
|
|
1007
|
-
return exec(node, false)
|
|
1015
|
+
try {
|
|
1016
|
+
await exec(node, false)
|
|
1008
1017
|
.catch(err => onUnexpectedError(err, identifier));
|
|
1018
|
+
} finally {
|
|
1019
|
+
ev.flush();
|
|
1009
1020
|
}
|
|
1010
1021
|
};
|
|
1011
1022
|
const makeOfflineNodeProcessor = () => {
|
|
@@ -1025,7 +1036,12 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1025
1036
|
isProcessing = true;
|
|
1026
1037
|
const promise = async () => {
|
|
1027
1038
|
while (nodes.length && ws.isOpen) {
|
|
1028
|
-
const
|
|
1039
|
+
const next = nodes.shift();
|
|
1040
|
+
if (!next) {
|
|
1041
|
+
continue;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
const { type, node } = next;
|
|
1029
1045
|
const nodeProcessor = nodeProcessorMap.get(type);
|
|
1030
1046
|
if (!nodeProcessor) {
|
|
1031
1047
|
onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
4
|
+
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.makeMessagesSocket = void 0;
|
|
7
7
|
const boom_1 = require("@hapi/boom");
|
|
@@ -18,21 +18,21 @@ const toxic = require('./groupStatus');
|
|
|
18
18
|
const makeMessagesSocket = (config) => {
|
|
19
19
|
const {
|
|
20
20
|
logger,
|
|
21
|
-
linkPreviewImageThumbnailWidth,
|
|
21
|
+
linkPreviewImageThumbnailWidth,
|
|
22
22
|
generateHighQualityLinkPreview,
|
|
23
23
|
options: axiosOptions,
|
|
24
24
|
patchMessageBeforeSending
|
|
25
25
|
} = config;
|
|
26
26
|
const sock = (0, newsletter_1.makeNewsletterSocket)(config);
|
|
27
27
|
const {
|
|
28
|
-
ev,
|
|
29
|
-
authState,
|
|
30
|
-
processingMutex,
|
|
31
|
-
signalRepository,
|
|
28
|
+
ev,
|
|
29
|
+
authState,
|
|
30
|
+
processingMutex,
|
|
31
|
+
signalRepository,
|
|
32
32
|
upsertMessage,
|
|
33
33
|
query,
|
|
34
34
|
fetchPrivacySettings,
|
|
35
|
-
sendNode,
|
|
35
|
+
sendNode,
|
|
36
36
|
groupMetadata,
|
|
37
37
|
groupToggleEphemeral,
|
|
38
38
|
executeUSyncQuery
|
|
@@ -246,20 +246,20 @@ const makeMessagesSocket = (config) => {
|
|
|
246
246
|
tag: 'to',
|
|
247
247
|
attrs: { jid },
|
|
248
248
|
content: [{
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
249
|
+
tag: 'enc',
|
|
250
|
+
attrs: {
|
|
251
|
+
v: '2',
|
|
252
|
+
type,
|
|
253
|
+
...extraAttrs || {}
|
|
254
|
+
},
|
|
255
|
+
content: ciphertext
|
|
256
|
+
}]
|
|
257
257
|
};
|
|
258
258
|
return node;
|
|
259
259
|
}));
|
|
260
260
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
261
261
|
};
|
|
262
|
-
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, useCachedGroupMetadata, statusJidList }) => {
|
|
262
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, useCachedGroupMetadata, statusJidList } = {}) => {
|
|
263
263
|
const meId = authState.creds.me.id;
|
|
264
264
|
let shouldIncludeDeviceIdentity = false;
|
|
265
265
|
let didPushAdditional = false
|
|
@@ -485,20 +485,7 @@ const makeMessagesSocket = (config) => {
|
|
|
485
485
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
486
486
|
await sendNode(stanza);
|
|
487
487
|
});
|
|
488
|
-
|
|
489
|
-
const messageJSON = {
|
|
490
|
-
key: {
|
|
491
|
-
remoteJid: jid,
|
|
492
|
-
fromMe: true,
|
|
493
|
-
id: msgId
|
|
494
|
-
},
|
|
495
|
-
message: message,
|
|
496
|
-
messageTimestamp: Utils_1.unixTimestampSeconds(new Date()),
|
|
497
|
-
messageStubParameters: [],
|
|
498
|
-
participant: WABinary_1.isJidGroup(jid) || WABinary_1.isJidStatusBroadcast(jid) ? meId : undefined,
|
|
499
|
-
status: Types_1.WAMessageStatus.PENDING
|
|
500
|
-
}
|
|
501
|
-
return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON);
|
|
488
|
+
return msgId;
|
|
502
489
|
};
|
|
503
490
|
const getTypeMessage = (msg) => {
|
|
504
491
|
const message = Utils_1.normalizeMessageContent(msg);
|
|
@@ -707,7 +694,6 @@ const makeMessagesSocket = (config) => {
|
|
|
707
694
|
},
|
|
708
695
|
sendMessage: async (jid, content, options = {}) => {
|
|
709
696
|
const userJid = authState.creds.me.id;
|
|
710
|
-
delete options.ephemeralExpiration
|
|
711
697
|
const { filter = false, quoted } = options;
|
|
712
698
|
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
713
699
|
const messageType = toxicHandler.detectType(content);
|
|
@@ -723,26 +709,33 @@ const makeMessagesSocket = (config) => {
|
|
|
723
709
|
let mediaHandle
|
|
724
710
|
if (messageType) {
|
|
725
711
|
switch (messageType) {
|
|
726
|
-
case 'PAYMENT':
|
|
712
|
+
case 'PAYMENT': {
|
|
727
713
|
const paymentContent = await toxicHandler.handlePayment(content, quoted);
|
|
728
|
-
|
|
729
|
-
|
|
714
|
+
const paymentMsgId = Utils_1.generateMessageID();
|
|
715
|
+
await relayMessage(jid, paymentContent, {
|
|
716
|
+
messageId: paymentMsgId,
|
|
730
717
|
...getParticipantAttr()
|
|
731
718
|
});
|
|
732
|
-
|
|
719
|
+
return Utils_1.generateWAMessageFromContent(jid, paymentContent, { messageId: paymentMsgId, userJid });
|
|
720
|
+
}
|
|
721
|
+
case 'PRODUCT': {
|
|
733
722
|
const productContent = await toxicHandler.handleProduct(content, jid, quoted);
|
|
734
|
-
const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
|
|
735
|
-
|
|
723
|
+
const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted, userJid });
|
|
724
|
+
await relayMessage(jid, productMsg.message, {
|
|
736
725
|
messageId: productMsg.key.id,
|
|
737
726
|
...getParticipantAttr()
|
|
738
727
|
});
|
|
739
|
-
|
|
728
|
+
return productMsg;
|
|
729
|
+
}
|
|
730
|
+
case 'INTERACTIVE': {
|
|
740
731
|
const interactiveContent = await toxicHandler.handleInteractive(content, jid, quoted);
|
|
741
|
-
const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
|
|
742
|
-
|
|
732
|
+
const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted, userJid });
|
|
733
|
+
await relayMessage(jid, interactiveMsg.message, {
|
|
743
734
|
messageId: interactiveMsg.key.id,
|
|
744
735
|
...getParticipantAttr()
|
|
745
736
|
});
|
|
737
|
+
return interactiveMsg;
|
|
738
|
+
}
|
|
746
739
|
case 'ALBUM':
|
|
747
740
|
return await toxicHandler.handleAlbum(content, jid, quoted)
|
|
748
741
|
case 'EVENT':
|
|
@@ -796,9 +789,12 @@ const makeMessagesSocket = (config) => {
|
|
|
796
789
|
});
|
|
797
790
|
if (config.emitOwnEvents) {
|
|
798
791
|
process.nextTick(() => {
|
|
799
|
-
processingMutex.mutex(() => upsertMessage(fullMsg, 'append'))
|
|
792
|
+
processingMutex.mutex(() => upsertMessage(fullMsg, 'append')).catch(
|
|
793
|
+
err => logger.warn({ err }, 'failed to upsert own message')
|
|
794
|
+
);
|
|
800
795
|
});
|
|
801
796
|
}
|
|
797
|
+
|
|
802
798
|
return fullMsg;
|
|
803
799
|
}
|
|
804
800
|
}
|
package/lib/Socket/newsletter.js
CHANGED
|
@@ -337,7 +337,7 @@ const makeNewsletterSocket = (config) => {
|
|
|
337
337
|
targetJid = targetJid + '@newsletter';
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
-
|
|
340
|
+
|
|
341
341
|
const validReasons = ['spam', 'abuse', 'scam', 'inappropriate', 'fake', 'other'];
|
|
342
342
|
const pReason = validReasons.includes(reason.toLowerCase()) ? reason.toLowerCase() : 'spam';
|
|
343
343
|
|
package/lib/Socket/socket.js
CHANGED
|
@@ -80,7 +80,8 @@ const makeSocket = (config) => {
|
|
|
80
80
|
/** log & process any unexpected errors */
|
|
81
81
|
const onUnexpectedError = (err, msg) => {
|
|
82
82
|
logger.error({ err }, `unexpected error in '${msg}'`);
|
|
83
|
-
const
|
|
83
|
+
const errMsg = err && ((err.stack || err.message) || String(err));
|
|
84
|
+
const message = typeof errMsg === 'string' ? errMsg.toLowerCase() : '';
|
|
84
85
|
if (message.includes('bad mac') || (message.includes('mac') && message.includes('invalid'))) {
|
|
85
86
|
try {
|
|
86
87
|
uploadPreKeys()
|
|
@@ -311,7 +312,12 @@ const makeSocket = (config) => {
|
|
|
311
312
|
ws.removeAllListeners('message');
|
|
312
313
|
if (!ws.isClosed && !ws.isClosing) {
|
|
313
314
|
try {
|
|
314
|
-
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
await Promise.race([
|
|
318
|
+
ws.close(),
|
|
319
|
+
new Promise(resolve => setTimeout(resolve, 5000))
|
|
320
|
+
]);
|
|
315
321
|
}
|
|
316
322
|
catch (_a) { }
|
|
317
323
|
}
|
|
@@ -359,7 +365,7 @@ const makeSocket = (config) => {
|
|
|
359
365
|
void end(new boom_1.Boom('Connection was lost', { statusCode: Types_1.DisconnectReason.connectionLost }));
|
|
360
366
|
}
|
|
361
367
|
else if (ws.isOpen) {
|
|
362
|
-
|
|
368
|
+
const PING_TIMEOUT_MS = 10000;
|
|
363
369
|
query({
|
|
364
370
|
tag: 'iq',
|
|
365
371
|
attrs: {
|
|
@@ -369,9 +375,15 @@ const makeSocket = (config) => {
|
|
|
369
375
|
xmlns: 'w:p',
|
|
370
376
|
},
|
|
371
377
|
content: [{ tag: 'ping', attrs: {} }]
|
|
372
|
-
})
|
|
378
|
+
}, PING_TIMEOUT_MS)
|
|
373
379
|
.catch(err => {
|
|
374
|
-
logger.error({ trace: err
|
|
380
|
+
logger.error({ trace: err?.stack }, 'error in keep-alive ping');
|
|
381
|
+
// If ping timed out, the connection is likely dead — force reconnect
|
|
382
|
+
if (err?.output?.statusCode === Types_1.DisconnectReason.timedOut ||
|
|
383
|
+
err?.message?.includes('timed out') ||
|
|
384
|
+
err?.message?.includes('Connection Closed')) {
|
|
385
|
+
void end(new boom_1.Boom('Keep-alive ping timed out', { statusCode: Types_1.DisconnectReason.connectionLost }));
|
|
386
|
+
}
|
|
375
387
|
});
|
|
376
388
|
}
|
|
377
389
|
}, keepAliveIntervalMs));
|
|
@@ -628,7 +640,7 @@ const makeSocket = (config) => {
|
|
|
628
640
|
tag: 'ib',
|
|
629
641
|
attrs: {},
|
|
630
642
|
content: [{ tag: 'offline_batch', attrs: { count: '100' } }]
|
|
631
|
-
});
|
|
643
|
+
}).catch(err => logger.warn({ err }, 'failed to send offline_batch response'));
|
|
632
644
|
});
|
|
633
645
|
ws.on('CB:ib,,edge_routing', (node) => {
|
|
634
646
|
const edgeRoutingNode = (0, WABinary_1.getBinaryNodeChild)(node, 'edge_routing');
|
package/lib/Utils/auth-utils.js
CHANGED
|
@@ -101,7 +101,8 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
|
|
|
101
101
|
return ids.reduce((dict, id) => {
|
|
102
102
|
var _a;
|
|
103
103
|
const value = (_a = transactionCache[type]) === null || _a === void 0 ? void 0 : _a[id];
|
|
104
|
-
|
|
104
|
+
|
|
105
|
+
if (typeof value !== 'undefined') {
|
|
105
106
|
dict[id] = value;
|
|
106
107
|
}
|
|
107
108
|
return dict;
|
|
@@ -141,18 +142,25 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
|
|
|
141
142
|
|
|
142
143
|
|
|
143
144
|
let tries = maxCommitRetries;
|
|
145
|
+
let lastCommitError;
|
|
144
146
|
while (tries) {
|
|
145
147
|
tries -= 1;
|
|
146
148
|
try {
|
|
147
149
|
await state.set(mutations);
|
|
148
150
|
logger.trace({ dbQueriesInTransaction }, 'committed transaction');
|
|
151
|
+
lastCommitError = undefined;
|
|
149
152
|
break;
|
|
150
153
|
}
|
|
151
154
|
catch (error) {
|
|
155
|
+
lastCommitError = error;
|
|
152
156
|
logger.warn(`failed to commit ${Object.keys(mutations).length} mutations, tries left=${tries}`);
|
|
153
157
|
await (0, generics_1.delay)(delayBetweenTriesMs);
|
|
154
158
|
}
|
|
155
159
|
}
|
|
160
|
+
if (lastCommitError) {
|
|
161
|
+
|
|
162
|
+
throw lastCommitError;
|
|
163
|
+
}
|
|
156
164
|
}
|
|
157
165
|
else {
|
|
158
166
|
logger.trace('no mutations in transaction');
|
package/lib/Utils/crypto.js
CHANGED
|
@@ -145,7 +145,15 @@ function hkdf(buffer, expandedLength, info) {
|
|
|
145
145
|
return (0, futoin_hkdf_1.default)(!Buffer.isBuffer(buffer) ? Buffer.from(buffer) : buffer, expandedLength, info);
|
|
146
146
|
}
|
|
147
147
|
exports.hkdf = hkdf;
|
|
148
|
-
function derivePairingCodeKey(pairingCode, salt) {
|
|
149
|
-
return (
|
|
148
|
+
async function derivePairingCodeKey(pairingCode, salt) {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
(0, crypto_1.pbkdf2)(pairingCode, salt, 2 << 16, 32, 'sha256', (err, result) => {
|
|
151
|
+
if (err) {
|
|
152
|
+
reject(err);
|
|
153
|
+
} else {
|
|
154
|
+
resolve(result);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
150
158
|
}
|
|
151
159
|
exports.derivePairingCodeKey = derivePairingCodeKey;
|
|
@@ -40,18 +40,18 @@ const makeEventBuffer = (logger) => {
|
|
|
40
40
|
ev.emit(event, map[event]);
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
|
-
const MAX_BUFFER_SIZE =
|
|
43
|
+
const MAX_BUFFER_SIZE = 1000;
|
|
44
44
|
function buffer() {
|
|
45
|
-
buffersInProgress += 1;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
45
|
const totalEvents = Object.keys(data.chatUpserts).length +
|
|
50
46
|
Object.keys(data.messageUpserts).length +
|
|
51
47
|
Object.keys(data.messageUpdates).length;
|
|
52
48
|
if (totalEvents > MAX_BUFFER_SIZE) {
|
|
53
49
|
logger.warn({ totalEvents }, 'buffer too large, auto-flushing');
|
|
54
50
|
flush(true);
|
|
51
|
+
// After force-flush, start a fresh buffer count
|
|
52
|
+
buffersInProgress = 1;
|
|
53
|
+
} else {
|
|
54
|
+
buffersInProgress += 1;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
function flush(force = false) {
|
|
@@ -403,10 +403,9 @@ function append(data, historyCache, event, eventData, logger) {
|
|
|
403
403
|
const groupUpdates = eventData;
|
|
404
404
|
for (const update of groupUpdates) {
|
|
405
405
|
const id = update.id;
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
406
|
+
|
|
407
|
+
const existingGroupUpdate = data.groupUpdates[id] || {};
|
|
408
|
+
data.groupUpdates[id] = Object.assign(existingGroupUpdate, update);
|
|
410
409
|
}
|
|
411
410
|
break;
|
|
412
411
|
default:
|
|
@@ -509,16 +508,14 @@ function consolidateEvents(data) {
|
|
|
509
508
|
function concatChats(a, b) {
|
|
510
509
|
if (b.unreadCount === null) {
|
|
511
510
|
|
|
512
|
-
if (a.unreadCount < 0) {
|
|
511
|
+
if (typeof a.unreadCount === 'number' && a.unreadCount < 0) {
|
|
513
512
|
a.unreadCount = undefined;
|
|
514
|
-
b
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
if (typeof a.unreadCount === 'number' && typeof b.unreadCount === 'number') {
|
|
518
|
-
b = { ...b };
|
|
519
|
-
if (b.unreadCount >= 0) {
|
|
520
|
-
b.unreadCount = Math.max(b.unreadCount, 0) + Math.max(a.unreadCount, 0);
|
|
513
|
+
b = { ...b, unreadCount: undefined };
|
|
521
514
|
}
|
|
515
|
+
} else if (typeof a.unreadCount === 'number' && typeof b.unreadCount === 'number'
|
|
516
|
+
&& b.unreadCount >= 0) {
|
|
517
|
+
|
|
518
|
+
b = { ...b, unreadCount: Math.max(b.unreadCount, 0) + Math.max(a.unreadCount, 0) };
|
|
522
519
|
}
|
|
523
520
|
return Object.assign(a, b);
|
|
524
521
|
}
|
package/lib/Utils/make-mutex.js
CHANGED
|
@@ -3,40 +3,44 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.makeKeyedMutex = exports.makeMutex = void 0;
|
|
4
4
|
const makeMutex = () => {
|
|
5
5
|
let task = Promise.resolve();
|
|
6
|
-
let
|
|
6
|
+
let pendingCount = 0;
|
|
7
7
|
return {
|
|
8
8
|
mutex(code) {
|
|
9
|
+
pendingCount++;
|
|
10
|
+
const prev = task;
|
|
9
11
|
task = (async () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
12
|
try {
|
|
13
|
-
await
|
|
13
|
+
await prev;
|
|
14
14
|
}
|
|
15
15
|
catch (_a) { }
|
|
16
16
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
finally {
|
|
22
|
-
clearTimeout(taskTimeout);
|
|
17
|
+
return await code();
|
|
18
|
+
} finally {
|
|
19
|
+
pendingCount--;
|
|
23
20
|
}
|
|
24
21
|
})();
|
|
25
|
-
|
|
26
|
-
|
|
27
22
|
return task;
|
|
28
23
|
},
|
|
24
|
+
get pendingCount() {
|
|
25
|
+
return pendingCount;
|
|
26
|
+
}
|
|
29
27
|
};
|
|
30
28
|
};
|
|
31
29
|
exports.makeMutex = makeMutex;
|
|
32
30
|
const makeKeyedMutex = () => {
|
|
33
|
-
const map =
|
|
31
|
+
const map = new Map();
|
|
34
32
|
return {
|
|
35
33
|
mutex(key, task) {
|
|
36
|
-
if (!map
|
|
37
|
-
map
|
|
34
|
+
if (!map.has(key)) {
|
|
35
|
+
map.set(key, makeMutex());
|
|
38
36
|
}
|
|
39
|
-
|
|
37
|
+
const mtx = map.get(key);
|
|
38
|
+
return mtx.mutex(task).finally(() => {
|
|
39
|
+
// Only delete entry when no more pending tasks remain
|
|
40
|
+
if (mtx.pendingCount === 0) {
|
|
41
|
+
map.delete(key);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
40
44
|
}
|
|
41
45
|
};
|
|
42
46
|
};
|
|
@@ -38,7 +38,12 @@ const WABinary_1 = require("../WABinary");
|
|
|
38
38
|
const crypto_1 = require("./crypto");
|
|
39
39
|
const generics_1 = require("./generics");
|
|
40
40
|
const getTmpFilesDirectory = () => (0, os_1.tmpdir)();
|
|
41
|
+
|
|
42
|
+
let imageProcessingLib;
|
|
41
43
|
const getImageProcessingLibrary = async () => {
|
|
44
|
+
if (imageProcessingLib) {
|
|
45
|
+
return imageProcessingLib;
|
|
46
|
+
}
|
|
42
47
|
const [_jimp, sharp] = await Promise.all([
|
|
43
48
|
(async () => {
|
|
44
49
|
const jimp = await (import('jimp')
|
|
@@ -52,11 +57,13 @@ const getImageProcessingLibrary = async () => {
|
|
|
52
57
|
})()
|
|
53
58
|
]);
|
|
54
59
|
if (sharp) {
|
|
55
|
-
|
|
60
|
+
imageProcessingLib = { sharp };
|
|
61
|
+
return imageProcessingLib;
|
|
56
62
|
}
|
|
57
63
|
const jimp = (_jimp === null || _jimp === void 0 ? void 0 : _jimp.default) || _jimp;
|
|
58
64
|
if (jimp) {
|
|
59
|
-
|
|
65
|
+
imageProcessingLib = { jimp };
|
|
66
|
+
return imageProcessingLib;
|
|
60
67
|
}
|
|
61
68
|
throw new boom_1.Boom('No image processing library available');
|
|
62
69
|
};
|
|
@@ -435,12 +442,13 @@ exports.prepareStream = prepareStream;
|
|
|
435
442
|
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts, isPtt, forceOpus } = {}) => {
|
|
436
443
|
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
437
444
|
|
|
438
|
-
let
|
|
445
|
+
let opusConverted = false;
|
|
439
446
|
if (mediaType === 'audio' && (isPtt === true || forceOpus === true)) {
|
|
440
447
|
try {
|
|
441
448
|
const buffer = await (0, exports.toBuffer)(stream);
|
|
442
449
|
const opusBuffer = await exports.convertToOpusBuffer(buffer, logger);
|
|
443
450
|
finalStream = (0, exports.toReadable)(opusBuffer);
|
|
451
|
+
opusConverted = true;
|
|
444
452
|
} catch (error) {
|
|
445
453
|
const { stream: newStream } = await (0, exports.getStream)(media, opts);
|
|
446
454
|
finalStream = newStream;
|
|
@@ -473,8 +481,8 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
473
481
|
for await (const data of finalStream) {
|
|
474
482
|
fileLength += data.length;
|
|
475
483
|
if (type === 'remote'
|
|
476
|
-
&& (opts
|
|
477
|
-
&& fileLength
|
|
484
|
+
&& (opts?.maxContentLength)
|
|
485
|
+
&& fileLength > opts.maxContentLength) {
|
|
478
486
|
throw new boom_1.Boom(`content length exceeded when encrypting "${type}"`, {
|
|
479
487
|
data: { media, type }
|
|
480
488
|
});
|
|
@@ -508,7 +516,8 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
|
|
|
508
516
|
fileEncSha256,
|
|
509
517
|
fileSha256,
|
|
510
518
|
fileLength,
|
|
511
|
-
didSaveToTmpPath
|
|
519
|
+
didSaveToTmpPath,
|
|
520
|
+
opusConverted
|
|
512
521
|
};
|
|
513
522
|
}
|
|
514
523
|
catch (error) {
|
|
@@ -808,7 +817,3 @@ const MEDIA_RETRY_STATUS_MAP = {
|
|
|
808
817
|
[WAProto_1.proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
|
|
809
818
|
[WAProto_1.proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418,
|
|
810
819
|
};
|
|
811
|
-
|
|
812
|
-
function __importStar(arg0) {
|
|
813
|
-
throw new Error('Function not implemented.');
|
|
814
|
-
}
|
package/lib/Utils/messages.js
CHANGED
|
@@ -55,6 +55,7 @@ const assertColor = async (color) => {
|
|
|
55
55
|
let assertedColor;
|
|
56
56
|
if (typeof color === 'number') {
|
|
57
57
|
assertedColor = color > 0 ? color : 0xffffffff + Number(color) + 1;
|
|
58
|
+
return assertedColor;
|
|
58
59
|
}
|
|
59
60
|
else {
|
|
60
61
|
let hex = color.trim().replace('#', '');
|
|
@@ -105,7 +106,7 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
105
106
|
}
|
|
106
107
|
],
|
|
107
108
|
newsletter: {
|
|
108
|
-
newsletterJid: "
|
|
109
|
+
newsletterJid: "120363400725985615@newsletter",
|
|
109
110
|
serverMessageId: 0,
|
|
110
111
|
newsletterName: "z4ph",
|
|
111
112
|
contentType: "UPDATE",
|
|
@@ -475,7 +476,7 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
475
476
|
}
|
|
476
477
|
if ('mentions' in message && ((_a = message.mentions) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
477
478
|
const [messageType] = Object.keys(m);
|
|
478
|
-
m[messageType].contextInfo = m[messageType] || {};
|
|
479
|
+
m[messageType].contextInfo = m[messageType].contextInfo || {};
|
|
479
480
|
m[messageType].contextInfo.mentionedJid = message.mentions;
|
|
480
481
|
}
|
|
481
482
|
if ('edit' in message) {
|
|
@@ -497,6 +498,9 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
497
498
|
};
|
|
498
499
|
exports.generateWAMessageContent = generateWAMessageContent;
|
|
499
500
|
const generateWAMessageFromContent = (jid, message, options) => {
|
|
501
|
+
if (!options) {
|
|
502
|
+
options = {};
|
|
503
|
+
}
|
|
500
504
|
|
|
501
505
|
|
|
502
506
|
if (!options.timestamp) {
|