@kelvdra/baileys 1.0.4 → 1.0.5
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/LICENSE +21 -0
- package/WAProto/index.js +65472 -137440
- package/lib/Defaults/index.d.ts +1 -1
- package/lib/Defaults/index.js +22 -3
- package/lib/Socket/chats.js +12 -13
- package/lib/Socket/groups.js +140 -7
- package/lib/Socket/hydra.js +44 -0
- package/lib/Socket/messages-recv.js +736 -324
- package/lib/Socket/messages-send.js +481 -110
- package/lib/Socket/mex.js +44 -6
- package/lib/Socket/newsletter.d.ts +16 -9
- package/lib/Socket/newsletter.js +259 -70
- package/lib/Types/Mex.d.ts +141 -0
- package/lib/Types/Mex.js +37 -0
- package/lib/Types/State.js +54 -1
- package/lib/Utils/auth-utils.js +12 -1
- package/lib/Utils/chat-utils.js +36 -2
- package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/decode-wa-message.js +23 -4
- package/lib/Utils/generics.js +4 -1
- package/lib/Utils/identity-change-handler.d.ts +44 -0
- package/lib/Utils/identity-change-handler.js +50 -0
- package/lib/Utils/index.js +1 -1
- package/lib/Utils/message-retry-manager.js +25 -1
- package/lib/Utils/messages-media.js +162 -43
- package/lib/Utils/messages.d.ts +1 -1
- package/lib/Utils/messages.js +230 -9
- package/lib/Utils/offline-node-processor.d.ts +17 -0
- package/lib/Utils/offline-node-processor.js +40 -0
- package/lib/Utils/reporting-utils.d.ts +11 -0
- package/lib/Utils/reporting-utils.js +258 -0
- package/lib/Utils/signal.js +45 -1
- package/lib/Utils/stanza-ack.d.ts +11 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/sync-action-utils.d.ts +19 -0
- package/lib/Utils/sync-action-utils.js +49 -0
- package/lib/Utils/tc-token-utils.d.ts +37 -0
- package/lib/Utils/tc-token-utils.js +163 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/package.json +3 -1
|
@@ -2,17 +2,20 @@ import NodeCache from '@cacheable/node-cache';
|
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { proto } from '../../WAProto/index.js';
|
|
4
4
|
import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
5
|
-
import
|
|
5
|
+
import * as Utils_1 from "../Utils/index.js"
|
|
6
|
+
import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
|
|
6
7
|
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
7
8
|
import { makeKeyedMutex } from '../Utils/make-mutex.js';
|
|
8
|
-
import
|
|
9
|
+
import * as WABinary_1 from "../WABinary/index.js"
|
|
9
10
|
import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidGroup, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
10
11
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
11
12
|
import { makeNewsletterSocket } from './newsletter.js';
|
|
13
|
+
import hydra from './hydra.js'
|
|
14
|
+
import { randomBytes } from "crypto"
|
|
12
15
|
export const makeMessagesSocket = (config) => {
|
|
13
16
|
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
|
|
14
17
|
const sock = makeNewsletterSocket(config);
|
|
15
|
-
const { ev, authState,
|
|
18
|
+
const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
|
|
16
19
|
const userDevicesCache = config.userDevicesCache ||
|
|
17
20
|
new NodeCache({
|
|
18
21
|
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
@@ -255,31 +258,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
255
258
|
}
|
|
256
259
|
return deviceResults;
|
|
257
260
|
};
|
|
258
|
-
/**
|
|
259
|
-
* Update Member Label
|
|
260
|
-
*/
|
|
261
|
-
const updateMemberLabel = (jid, memberLabel) => {
|
|
262
|
-
return relayMessage(jid, {
|
|
263
|
-
protocolMessage: {
|
|
264
|
-
type: proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
|
|
265
|
-
memberLabel: {
|
|
266
|
-
label: memberLabel?.slice(0, 30),
|
|
267
|
-
labelTimestamp: unixTimestampSeconds()
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}, {
|
|
271
|
-
additionalNodes: [
|
|
272
|
-
{
|
|
273
|
-
tag: 'meta',
|
|
274
|
-
attrs: {
|
|
275
|
-
tag_reason: 'user_update',
|
|
276
|
-
appdata: 'member_tag'
|
|
277
|
-
},
|
|
278
|
-
content: undefined
|
|
279
|
-
}
|
|
280
|
-
]
|
|
281
|
-
});
|
|
282
|
-
};
|
|
283
261
|
const assertSessions = async (jids, force) => {
|
|
284
262
|
let didFetchNewSession = false;
|
|
285
263
|
const uniqueJids = [...new Set(jids)]; // Deduplicate JIDs
|
|
@@ -376,59 +354,57 @@ export const makeMessagesSocket = (config) => {
|
|
|
376
354
|
? patched
|
|
377
355
|
: recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
|
|
378
356
|
let shouldIncludeDeviceIdentity = false;
|
|
379
|
-
const meId = authState.creds
|
|
357
|
+
const meId = assertMeId(authState.creds);
|
|
380
358
|
const meLid = authState.creds.me?.lid;
|
|
381
359
|
const meLidUser = meLid ? jidDecode(meLid)?.user : null;
|
|
382
360
|
const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
|
|
383
|
-
|
|
384
|
-
if (!jid)
|
|
385
|
-
return null;
|
|
386
|
-
let msgToEncrypt = patchedMessage;
|
|
387
|
-
if (dsmMessage) {
|
|
388
|
-
const { user: targetUser } = jidDecode(jid);
|
|
389
|
-
const { user: ownPnUser } = jidDecode(meId);
|
|
390
|
-
const ownLidUser = meLidUser;
|
|
391
|
-
const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
|
|
392
|
-
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
393
|
-
if (isOwnUser && !isExactSenderDevice) {
|
|
394
|
-
msgToEncrypt = dsmMessage;
|
|
395
|
-
logger.debug({ jid, targetUser }, 'Using DSM for own device');
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
const bytes = encodeWAMessage(msgToEncrypt);
|
|
399
|
-
const mutexKey = jid;
|
|
400
|
-
const node = await encryptionMutex.mutex(mutexKey, async () => {
|
|
401
|
-
const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes });
|
|
402
|
-
if (type === 'pkmsg') {
|
|
403
|
-
shouldIncludeDeviceIdentity = true;
|
|
404
|
-
}
|
|
405
|
-
return {
|
|
406
|
-
tag: 'to',
|
|
407
|
-
attrs: { jid },
|
|
408
|
-
content: [
|
|
409
|
-
{
|
|
410
|
-
tag: 'enc',
|
|
411
|
-
attrs: { v: '2', type, ...(extraAttrs || {}) },
|
|
412
|
-
content: ciphertext
|
|
413
|
-
}
|
|
414
|
-
]
|
|
415
|
-
};
|
|
416
|
-
});
|
|
417
|
-
return node;
|
|
418
|
-
}
|
|
419
|
-
catch (err) {
|
|
420
|
-
logger.error({ jid, err }, 'Failed to encrypt for recipient');
|
|
361
|
+
if (!jid)
|
|
421
362
|
return null;
|
|
363
|
+
let msgToEncrypt = patchedMessage;
|
|
364
|
+
if (dsmMessage) {
|
|
365
|
+
const { user: targetUser } = jidDecode(jid);
|
|
366
|
+
const { user: ownPnUser } = jidDecode(meId);
|
|
367
|
+
const ownLidUser = meLidUser;
|
|
368
|
+
const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
|
|
369
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
370
|
+
if (isOwnUser && !isExactSenderDevice) {
|
|
371
|
+
msgToEncrypt = dsmMessage;
|
|
372
|
+
logger.debug({ jid, targetUser }, 'Using DSM for own device');
|
|
373
|
+
}
|
|
422
374
|
}
|
|
375
|
+
const bytes = encodeWAMessage(msgToEncrypt);
|
|
376
|
+
const mutexKey = jid;
|
|
377
|
+
const node = await encryptionMutex.mutex(mutexKey, async () => {
|
|
378
|
+
const { type, ciphertext } = await signalRepository.encryptMessage({
|
|
379
|
+
jid,
|
|
380
|
+
data: bytes
|
|
381
|
+
});
|
|
382
|
+
if (type === 'pkmsg') {
|
|
383
|
+
shouldIncludeDeviceIdentity = true;
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
tag: 'to',
|
|
387
|
+
attrs: { jid },
|
|
388
|
+
content: [
|
|
389
|
+
{
|
|
390
|
+
tag: 'enc',
|
|
391
|
+
attrs: {
|
|
392
|
+
v: '2',
|
|
393
|
+
type,
|
|
394
|
+
...(extraAttrs || {})
|
|
395
|
+
},
|
|
396
|
+
content: ciphertext
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
};
|
|
400
|
+
});
|
|
401
|
+
return node;
|
|
423
402
|
});
|
|
424
403
|
const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
|
|
425
|
-
if (recipientJids.length > 0 && nodes.length === 0) {
|
|
426
|
-
throw new Boom('All encryptions failed', { statusCode: 500 });
|
|
427
|
-
}
|
|
428
404
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
429
405
|
};
|
|
430
|
-
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
|
|
431
|
-
const meId = authState.creds
|
|
406
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList } = {}) => {
|
|
407
|
+
const meId = assertMeId(authState.creds);
|
|
432
408
|
const meLid = authState.creds.me?.lid;
|
|
433
409
|
const isRetryResend = Boolean(participant?.jid);
|
|
434
410
|
let shouldIncludeDeviceIdentity = isRetryResend;
|
|
@@ -444,10 +420,12 @@ export const makeMessagesSocket = (config) => {
|
|
|
444
420
|
useUserDevicesCache = useUserDevicesCache !== false;
|
|
445
421
|
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
|
|
446
422
|
const participants = [];
|
|
423
|
+
let additionalAlready = false
|
|
447
424
|
const destinationJid = !isStatus ? finalJid : statusJid;
|
|
448
425
|
const binaryNodeContent = [];
|
|
449
426
|
const devices = [];
|
|
450
|
-
|
|
427
|
+
const messages = Utils_1.normalizeMessageContent(message)
|
|
428
|
+
const buttonType = getButtonType(messages)
|
|
451
429
|
const meMsg = {
|
|
452
430
|
deviceSentMessage: {
|
|
453
431
|
destinationJid,
|
|
@@ -542,7 +520,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
542
520
|
throw new Boom('Per-jid patching is not supported in groups');
|
|
543
521
|
}
|
|
544
522
|
const bytes = encodeWAMessage(patched);
|
|
545
|
-
reportingMessage = patched;
|
|
546
523
|
const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
|
|
547
524
|
const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
|
|
548
525
|
const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
|
|
@@ -597,12 +574,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
597
574
|
logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
|
|
598
575
|
}
|
|
599
576
|
const { user: ownUser } = jidDecode(ownId);
|
|
600
|
-
if (!participant) {
|
|
601
|
-
const patchedForReporting = await patchMessageBeforeSending(message, [jid]);
|
|
602
|
-
reportingMessage = Array.isArray(patchedForReporting)
|
|
603
|
-
? patchedForReporting.find(item => item.recipientJid === jid) || patchedForReporting[0]
|
|
604
|
-
: patchedForReporting;
|
|
605
|
-
}
|
|
606
577
|
if (!isRetryResend) {
|
|
607
578
|
const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
608
579
|
devices.push({
|
|
@@ -738,6 +709,16 @@ export const makeMessagesSocket = (config) => {
|
|
|
738
709
|
else {
|
|
739
710
|
stanza.attrs.to = destinationJid;
|
|
740
711
|
}
|
|
712
|
+
if (!isNewsletter && buttonType) {
|
|
713
|
+
const buttonsNode = getButtonArgs(messages)
|
|
714
|
+
const filteredButtons = WABinary_1.getBinaryFilteredButtons(additionalNodes ? additionalNodes : [])
|
|
715
|
+
if (filteredButtons) {
|
|
716
|
+
stanza.content.push(...additionalNodes)
|
|
717
|
+
additionalAlready = true
|
|
718
|
+
} else {
|
|
719
|
+
stanza.content.push(buttonsNode)
|
|
720
|
+
}
|
|
721
|
+
}
|
|
741
722
|
if (shouldIncludeDeviceIdentity) {
|
|
742
723
|
;
|
|
743
724
|
stanza.content.push({
|
|
@@ -747,29 +728,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
747
728
|
});
|
|
748
729
|
logger.debug({ jid }, 'adding device identity');
|
|
749
730
|
}
|
|
750
|
-
if (!isNewsletter &&
|
|
751
|
-
!isRetryResend &&
|
|
752
|
-
reportingMessage?.messageContextInfo?.messageSecret &&
|
|
753
|
-
shouldIncludeReportingToken(reportingMessage)) {
|
|
754
|
-
try {
|
|
755
|
-
const encoded = encodeWAMessage(reportingMessage);
|
|
756
|
-
const reportingKey = {
|
|
757
|
-
id: msgId,
|
|
758
|
-
fromMe: true,
|
|
759
|
-
remoteJid: destinationJid,
|
|
760
|
-
participant: participant?.jid
|
|
761
|
-
};
|
|
762
|
-
const reportingNode = await getMessageReportingToken(encoded, reportingMessage, reportingKey);
|
|
763
|
-
if (reportingNode) {
|
|
764
|
-
;
|
|
765
|
-
stanza.content.push(reportingNode);
|
|
766
|
-
logger.trace({ jid }, 'added reporting token to message');
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
catch (error) {
|
|
770
|
-
logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token');
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
731
|
const contactTcTokenData = !isGroup && !isRetryResend && !isStatus ? await authState.keys.get('tctoken', [destinationJid]) : {};
|
|
774
732
|
const tcTokenBuffer = contactTcTokenData[destinationJid]?.token;
|
|
775
733
|
if (tcTokenBuffer) {
|
|
@@ -780,7 +738,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
780
738
|
content: tcTokenBuffer
|
|
781
739
|
});
|
|
782
740
|
}
|
|
783
|
-
if (additionalNodes && additionalNodes.length > 0) {
|
|
741
|
+
if (!additionalAlready && additionalNodes && additionalNodes.length > 0) {
|
|
784
742
|
;
|
|
785
743
|
stanza.content.push(...additionalNodes);
|
|
786
744
|
}
|
|
@@ -794,9 +752,20 @@ export const makeMessagesSocket = (config) => {
|
|
|
794
752
|
return msgId;
|
|
795
753
|
};
|
|
796
754
|
const getMessageType = (message) => {
|
|
797
|
-
|
|
755
|
+
// stickerPackMessage/media must be sent as media, especially in groups.
|
|
756
|
+
const normalizedMessage = Utils_1.normalizeMessageContent(message) || message;
|
|
757
|
+
if (normalizedMessage?.reactionMessage || normalizedMessage?.encReactionMessage) {
|
|
758
|
+
return 'reaction';
|
|
759
|
+
}
|
|
760
|
+
if (normalizedMessage?.pollCreationMessage || normalizedMessage?.pollCreationMessageV2 || normalizedMessage?.pollCreationMessageV3 || normalizedMessage?.pollUpdateMessage) {
|
|
798
761
|
return 'poll';
|
|
799
762
|
}
|
|
763
|
+
if (normalizedMessage?.eventMessage) {
|
|
764
|
+
return 'event';
|
|
765
|
+
}
|
|
766
|
+
if (getMediaType(normalizedMessage) !== '') {
|
|
767
|
+
return 'media';
|
|
768
|
+
}
|
|
800
769
|
return 'text';
|
|
801
770
|
};
|
|
802
771
|
const getMediaType = (message) => {
|
|
@@ -824,6 +793,9 @@ export const makeMessagesSocket = (config) => {
|
|
|
824
793
|
else if (message.stickerMessage) {
|
|
825
794
|
return 'sticker';
|
|
826
795
|
}
|
|
796
|
+
else if (message.stickerPackMessage) {
|
|
797
|
+
return 'sticker_pack';
|
|
798
|
+
}
|
|
827
799
|
else if (message.listMessage) {
|
|
828
800
|
return 'list';
|
|
829
801
|
}
|
|
@@ -847,6 +819,114 @@ export const makeMessagesSocket = (config) => {
|
|
|
847
819
|
}
|
|
848
820
|
return '';
|
|
849
821
|
};
|
|
822
|
+
|
|
823
|
+
const getButtonType = (message) => {
|
|
824
|
+
if (message.listMessage) {
|
|
825
|
+
return 'list'
|
|
826
|
+
}
|
|
827
|
+
else if (message.buttonsMessage) {
|
|
828
|
+
return 'buttons'
|
|
829
|
+
}
|
|
830
|
+
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'review_and_pay') {
|
|
831
|
+
return 'review_and_pay'
|
|
832
|
+
}
|
|
833
|
+
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'review_order') {
|
|
834
|
+
return 'review_order'
|
|
835
|
+
}
|
|
836
|
+
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'payment_info') {
|
|
837
|
+
return 'payment_info'
|
|
838
|
+
}
|
|
839
|
+
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'payment_status') {
|
|
840
|
+
return 'payment_status'
|
|
841
|
+
}
|
|
842
|
+
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'payment_method') {
|
|
843
|
+
return 'payment_method'
|
|
844
|
+
}
|
|
845
|
+
else if (message.interactiveMessage && message.interactiveMessage?.nativeFlowMessage) {
|
|
846
|
+
return 'interactive'
|
|
847
|
+
}
|
|
848
|
+
else if (message.interactiveMessage?.nativeFlowMessage) {
|
|
849
|
+
return 'native_flow'
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
const getButtonArgs = (message) => {
|
|
854
|
+
const message_content = message.viewOnceMessage?.message || message;
|
|
855
|
+
const message_flow = message_content.interactiveMessage?.nativeFlowMessage;
|
|
856
|
+
const flow_buttons_first = message_flow?.buttons?.[0]?.name;
|
|
857
|
+
const flow_buttons_special = [ 'mpm', 'cta_catalog', 'send_location', 'call_permission_request', 'wa_payment_transaction_details', 'automated_greeting_message_view_catalog' ];
|
|
858
|
+
const baseArgs = {
|
|
859
|
+
tag: 'biz',
|
|
860
|
+
attrs: {
|
|
861
|
+
actual_actors: '2',
|
|
862
|
+
host_storage: '2',
|
|
863
|
+
privacy_mode_ts: Utils_1.unixTimestampSeconds().toString()
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
if (message_flow && (flow_buttons_first === 'review_and_pay' || flow_buttons_first === 'payment_info')) {
|
|
867
|
+
return {
|
|
868
|
+
tag: 'biz',
|
|
869
|
+
attrs: {
|
|
870
|
+
native_flow_name: flow_buttons_first === 'review_and_pay' ? 'order_details' : flow_buttons_first
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
if (message_flow && flow_buttons_special.includes(flow_buttons_first)) {
|
|
875
|
+
return {
|
|
876
|
+
...baseArgs,
|
|
877
|
+
content: [
|
|
878
|
+
{
|
|
879
|
+
tag: 'interactive',
|
|
880
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
881
|
+
content: [{
|
|
882
|
+
tag: 'native_flow',
|
|
883
|
+
attrs: { v: '2', name: flow_buttons_first }
|
|
884
|
+
}]
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
tag: 'quality_control',
|
|
888
|
+
attrs: { source_type: 'third_party' }
|
|
889
|
+
}
|
|
890
|
+
]
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
if (message_flow || message_content.buttonsMessage) {
|
|
894
|
+
return {
|
|
895
|
+
...baseArgs,
|
|
896
|
+
content: [
|
|
897
|
+
{
|
|
898
|
+
tag: 'interactive',
|
|
899
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
900
|
+
content: [{
|
|
901
|
+
tag: 'native_flow',
|
|
902
|
+
attrs: { v: '9', name: 'mixed' }
|
|
903
|
+
}]
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
tag: 'quality_control',
|
|
907
|
+
attrs: { source_type: 'third_party' }
|
|
908
|
+
}
|
|
909
|
+
]
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
if (message_content.listMessage) {
|
|
913
|
+
return {
|
|
914
|
+
...baseArgs,
|
|
915
|
+
content: [
|
|
916
|
+
{
|
|
917
|
+
tag: 'list',
|
|
918
|
+
attrs: { v: '2', type: 'product_list' }
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
tag: 'quality_control',
|
|
922
|
+
attrs: { source_type: 'third_party' }
|
|
923
|
+
}
|
|
924
|
+
]
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
return baseArgs;
|
|
928
|
+
};
|
|
929
|
+
|
|
850
930
|
const getPrivacyTokens = async (jids) => {
|
|
851
931
|
const t = unixTimestampSeconds().toString();
|
|
852
932
|
const result = await query({
|
|
@@ -873,7 +953,22 @@ export const makeMessagesSocket = (config) => {
|
|
|
873
953
|
});
|
|
874
954
|
return result;
|
|
875
955
|
};
|
|
956
|
+
|
|
957
|
+
const getEphemeralGroup = (jid) => {
|
|
958
|
+
if (!WABinary_1.isJidGroup(jid)) throw new TypeError("Jid should originate from a group!")
|
|
959
|
+
|
|
960
|
+
return groupQuery(jid, 'get', [{
|
|
961
|
+
tag: 'query',
|
|
962
|
+
attrs: {
|
|
963
|
+
request: 'interactive'
|
|
964
|
+
}
|
|
965
|
+
}])
|
|
966
|
+
.then((groups) => WABinary_1.getBinaryNodeChild(groups, 'group'))
|
|
967
|
+
.then((metadata) => WABinary_1.getBinaryNodeChild(metadata, 'ephemeral')?.attrs?.expiration || 0)
|
|
968
|
+
}
|
|
969
|
+
|
|
876
970
|
const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
|
|
971
|
+
const kelvdra = new hydra(Utils_1, waUploadToServer, relayMessage)
|
|
877
972
|
const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
|
|
878
973
|
return {
|
|
879
974
|
...sock,
|
|
@@ -885,17 +980,17 @@ export const makeMessagesSocket = (config) => {
|
|
|
885
980
|
readMessages,
|
|
886
981
|
refreshMediaConn,
|
|
887
982
|
waUploadToServer,
|
|
983
|
+
kelvdra,
|
|
888
984
|
fetchPrivacySettings,
|
|
889
985
|
sendPeerDataOperationMessage,
|
|
890
986
|
createParticipantNodes,
|
|
891
987
|
getUSyncDevices,
|
|
892
988
|
messageRetryManager,
|
|
893
|
-
updateMemberLabel,
|
|
894
989
|
updateMediaMessage: async (message) => {
|
|
895
990
|
const content = assertMediaContent(message.message);
|
|
896
991
|
const mediaKey = content.mediaKey;
|
|
897
|
-
const meId = authState.creds
|
|
898
|
-
const node = encryptMediaRetryRequest(message.key, mediaKey, meId);
|
|
992
|
+
const meId = assertMeId(authState.creds);
|
|
993
|
+
const node = await encryptMediaRetryRequest(message.key, mediaKey, meId);
|
|
899
994
|
let error = undefined;
|
|
900
995
|
await Promise.all([
|
|
901
996
|
sendNode(node),
|
|
@@ -907,7 +1002,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
907
1002
|
}
|
|
908
1003
|
else {
|
|
909
1004
|
try {
|
|
910
|
-
const media = decryptMediaRetryData(result.media, mediaKey, result.key.id);
|
|
1005
|
+
const media = await decryptMediaRetryData(result.media, mediaKey, result.key.id);
|
|
911
1006
|
if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
|
|
912
1007
|
const resultStr = proto.MediaRetryNotification.ResultType[media.result];
|
|
913
1008
|
throw new Boom(`Media re-upload failed by device (${resultStr})`, {
|
|
@@ -933,8 +1028,284 @@ export const makeMessagesSocket = (config) => {
|
|
|
933
1028
|
ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
|
|
934
1029
|
return message;
|
|
935
1030
|
},
|
|
1031
|
+
sendStatusMentions: async (content, jids = []) => {
|
|
1032
|
+
const userJid = WABinary_1.jidNormalizedUser(authState.creds.me.id)
|
|
1033
|
+
let allUsers = new Set()
|
|
1034
|
+
allUsers.add(userJid)
|
|
1035
|
+
|
|
1036
|
+
for (const id of jids) {
|
|
1037
|
+
const isGroup = WABinary_1.isJidGroup(id)
|
|
1038
|
+
const isPrivate = WABinary_1.isPnUser(id)
|
|
1039
|
+
|
|
1040
|
+
if (isGroup) {
|
|
1041
|
+
try {
|
|
1042
|
+
const metadata = await cachedGroupMetadata(id) || await global.groupMetadataCache(id)
|
|
1043
|
+
const participants = metadata.participants.map(p => WABinary_1.jidNormalizedUser(p.id))
|
|
1044
|
+
participants.forEach(jid => allUsers.add(jid))
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
logger.error(`Error getting metadata for group ${id}: ${error}`)
|
|
1047
|
+
}
|
|
1048
|
+
} else if (isPrivate) {
|
|
1049
|
+
allUsers.add(WABinary_1.jidNormalizedUser(id))
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const uniqueUsers = Array.from(allUsers)
|
|
1054
|
+
const getRandomHexColor = () => "#" + Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0")
|
|
1055
|
+
|
|
1056
|
+
const isMedia = content.image || content.video || content.audio
|
|
1057
|
+
const isAudio = !!content.audio
|
|
1058
|
+
|
|
1059
|
+
const messageContent = {
|
|
1060
|
+
...content
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
if (isMedia && !isAudio) {
|
|
1064
|
+
if (messageContent.text) {
|
|
1065
|
+
messageContent.caption = messageContent.text
|
|
1066
|
+
|
|
1067
|
+
delete messageContent.text
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
delete messageContent.ptt
|
|
1071
|
+
delete messageContent.font
|
|
1072
|
+
delete messageContent.backgroundColor
|
|
1073
|
+
delete messageContent.textColor
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
if (isAudio) {
|
|
1077
|
+
delete messageContent.text
|
|
1078
|
+
delete messageContent.caption
|
|
1079
|
+
delete messageContent.font
|
|
1080
|
+
delete messageContent.textColor
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
const font = !isMedia ? (content.font || Math.floor(Math.random() * 9)) : undefined
|
|
1084
|
+
const textColor = !isMedia ? (content.textColor || getRandomHexColor()) : undefined
|
|
1085
|
+
const backgroundColor = (!isMedia || isAudio) ? (content.backgroundColor || getRandomHexColor()) : undefined
|
|
1086
|
+
const ptt = isAudio ? (typeof content.ptt === 'boolean' ? content.ptt : true) : undefined
|
|
1087
|
+
|
|
1088
|
+
let msg
|
|
1089
|
+
let mediaHandle
|
|
1090
|
+
try {
|
|
1091
|
+
msg = await Utils_1.generateWAMessage(WABinary_1.STORIES_JID, messageContent, {
|
|
1092
|
+
logger,
|
|
1093
|
+
userJid,
|
|
1094
|
+
getUrlInfo: text => link_preview_1.getUrlInfo(text, {
|
|
1095
|
+
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1096
|
+
fetchOpts: {
|
|
1097
|
+
timeout: 3000,
|
|
1098
|
+
...axiosOptions || {}
|
|
1099
|
+
},
|
|
1100
|
+
logger,
|
|
1101
|
+
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1102
|
+
}),
|
|
1103
|
+
upload: async (encFilePath, opts) => {
|
|
1104
|
+
const up = await waUploadToServer(encFilePath, {
|
|
1105
|
+
...opts
|
|
1106
|
+
})
|
|
1107
|
+
mediaHandle = up.handle
|
|
1108
|
+
return up
|
|
1109
|
+
},
|
|
1110
|
+
mediaCache: config.mediaCache,
|
|
1111
|
+
options: config.options,
|
|
1112
|
+
font,
|
|
1113
|
+
textColor,
|
|
1114
|
+
backgroundColor,
|
|
1115
|
+
ptt
|
|
1116
|
+
})
|
|
1117
|
+
} catch (error) {
|
|
1118
|
+
logger.error(`Error generating message: ${error}`)
|
|
1119
|
+
throw error
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
await relayMessage(WABinary_1.STORIES_JID, msg.message, {
|
|
1123
|
+
messageId: msg.key.id,
|
|
1124
|
+
statusJidList: uniqueUsers,
|
|
1125
|
+
additionalNodes: [{
|
|
1126
|
+
tag: 'meta',
|
|
1127
|
+
attrs: {},
|
|
1128
|
+
content: [{
|
|
1129
|
+
tag: 'mentioned_users',
|
|
1130
|
+
attrs: {},
|
|
1131
|
+
content: jids.map(jid => ({
|
|
1132
|
+
tag: 'to',
|
|
1133
|
+
attrs: {
|
|
1134
|
+
jid: WABinary_1.jidNormalizedUser(jid)
|
|
1135
|
+
}
|
|
1136
|
+
}))
|
|
1137
|
+
}]
|
|
1138
|
+
}]
|
|
1139
|
+
})
|
|
1140
|
+
|
|
1141
|
+
for (const id of jids) {
|
|
1142
|
+
try {
|
|
1143
|
+
const normalizedId = WABinary_1.jidNormalizedUser(id)
|
|
1144
|
+
const isPrivate = WABinary_1.isJidUser(normalizedId)
|
|
1145
|
+
const type = isPrivate ? 'statusMentionMessage' : 'groupStatusMentionMessage'
|
|
1146
|
+
|
|
1147
|
+
const protocolMessage = {
|
|
1148
|
+
[type]: {
|
|
1149
|
+
message: {
|
|
1150
|
+
protocolMessage: {
|
|
1151
|
+
key: msg.key,
|
|
1152
|
+
type: 25
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
messageContextInfo: {
|
|
1157
|
+
messageSecret: randomBytes(32)
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
const statusMsg = await Utils_1.generateWAMessageFromContent(normalizedId,
|
|
1162
|
+
protocolMessage, {}
|
|
1163
|
+
)
|
|
1164
|
+
|
|
1165
|
+
await relayMessage(
|
|
1166
|
+
normalizedId,
|
|
1167
|
+
statusMsg.message, {
|
|
1168
|
+
additionalNodes: [{
|
|
1169
|
+
tag: 'meta',
|
|
1170
|
+
attrs: isPrivate ? {
|
|
1171
|
+
is_status_mention: 'true'
|
|
1172
|
+
} : {
|
|
1173
|
+
is_group_status_mention: 'true'
|
|
1174
|
+
}
|
|
1175
|
+
}]
|
|
1176
|
+
}
|
|
1177
|
+
)
|
|
1178
|
+
|
|
1179
|
+
await Utils_1.delay(2000)
|
|
1180
|
+
} catch (error) {
|
|
1181
|
+
logger.error(`Error sending to ${id}: ${error}`)
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
return msg
|
|
1186
|
+
},
|
|
1187
|
+
sendAlbumMessage: async (jid, medias, options = {}) => {
|
|
1188
|
+
const userJid = authState.creds.me.id
|
|
1189
|
+
for (const media of medias) {
|
|
1190
|
+
if (!media.image && !media.video) throw new TypeError(`medias[i] must have image or video property`)
|
|
1191
|
+
}
|
|
1192
|
+
if (medias.length < 2) throw new RangeError("Minimum 2 media")
|
|
1193
|
+
const time = options.delay || 500
|
|
1194
|
+
delete options.delay
|
|
1195
|
+
const album = await Utils_1.generateWAMessageFromContent(jid, {
|
|
1196
|
+
albumMessage: {
|
|
1197
|
+
expectedImageCount: medias.filter(media => media.image).length,
|
|
1198
|
+
expectedVideoCount: medias.filter(media => media.video).length,
|
|
1199
|
+
...options
|
|
1200
|
+
}
|
|
1201
|
+
}, {
|
|
1202
|
+
userJid,
|
|
1203
|
+
...options
|
|
1204
|
+
})
|
|
1205
|
+
await relayMessage(jid, album.message, {
|
|
1206
|
+
messageId: album.key.id
|
|
1207
|
+
})
|
|
1208
|
+
let mediaHandle
|
|
1209
|
+
let msg
|
|
1210
|
+
for (const i in medias) {
|
|
1211
|
+
const media = medias[i]
|
|
1212
|
+
if (media.image) {
|
|
1213
|
+
msg = await Utils_1.generateWAMessage(jid, {
|
|
1214
|
+
image: media.image,
|
|
1215
|
+
...media,
|
|
1216
|
+
...options
|
|
1217
|
+
}, {
|
|
1218
|
+
userJid,
|
|
1219
|
+
upload: async (readStream, opts) => {
|
|
1220
|
+
const up = await waUploadToServer(readStream, {
|
|
1221
|
+
...opts,
|
|
1222
|
+
newsletter: WABinary_1.isJidNewsletter(jid)
|
|
1223
|
+
})
|
|
1224
|
+
mediaHandle = up.handle
|
|
1225
|
+
return up
|
|
1226
|
+
},
|
|
1227
|
+
...options
|
|
1228
|
+
})
|
|
1229
|
+
} else if (media.video) {
|
|
1230
|
+
msg = await Utils_1.generateWAMessage(jid, {
|
|
1231
|
+
video: media.video,
|
|
1232
|
+
...media,
|
|
1233
|
+
...options
|
|
1234
|
+
}, {
|
|
1235
|
+
userJid,
|
|
1236
|
+
upload: async (readStream, opts) => {
|
|
1237
|
+
const up = await waUploadToServer(readStream, {
|
|
1238
|
+
...opts,
|
|
1239
|
+
newsletter: WABinary_1.isJidNewsletter(jid)
|
|
1240
|
+
})
|
|
1241
|
+
mediaHandle = up.handle
|
|
1242
|
+
return up
|
|
1243
|
+
},
|
|
1244
|
+
...options,
|
|
1245
|
+
})
|
|
1246
|
+
}
|
|
1247
|
+
if (msg) {
|
|
1248
|
+
msg.message.messageContextInfo = {
|
|
1249
|
+
messageSecret: randomBytes(32),
|
|
1250
|
+
messageAssociation: {
|
|
1251
|
+
associationType: 1,
|
|
1252
|
+
parentMessageKey: album.key
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
await relayMessage(jid, msg.message, {
|
|
1257
|
+
messageId: msg.key.id
|
|
1258
|
+
})
|
|
1259
|
+
await Utils_1.delay(time)
|
|
1260
|
+
}
|
|
1261
|
+
return album
|
|
1262
|
+
},
|
|
936
1263
|
sendMessage: async (jid, content, options = {}) => {
|
|
937
1264
|
const userJid = authState.creds.me.id;
|
|
1265
|
+
const additionalAttributes = {}
|
|
1266
|
+
const { filter = false, quoted } = options;
|
|
1267
|
+
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
1268
|
+
const messageType = kelvdra.detectType(content);
|
|
1269
|
+
|
|
1270
|
+
if (messageType) {
|
|
1271
|
+
switch (messageType) {
|
|
1272
|
+
case 'PAYMENT':
|
|
1273
|
+
const paymentContent = await kelvdra.handlePayment(content, quoted);
|
|
1274
|
+
return await relayMessage(jid, paymentContent, {
|
|
1275
|
+
messageId: Utils_1.generateMessageID(),
|
|
1276
|
+
...getParticipantAttr()
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
case 'PRODUCT':
|
|
1280
|
+
const productContent = await kelvdra.handleProduct(content, jid, quoted);
|
|
1281
|
+
const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
|
|
1282
|
+
return await relayMessage(jid, productMsg.message, {
|
|
1283
|
+
messageId: productMsg.key.id,
|
|
1284
|
+
...getParticipantAttr()
|
|
1285
|
+
});
|
|
1286
|
+
|
|
1287
|
+
case 'INTERACTIVE':
|
|
1288
|
+
const interactiveContent = await kelvdra.handleInteractive(content, jid, quoted);
|
|
1289
|
+
const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
|
|
1290
|
+
return await relayMessage(jid, interactiveMsg.message, {
|
|
1291
|
+
messageId: interactiveMsg.key.id,
|
|
1292
|
+
...getParticipantAttr()
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
case 'ALBUM':
|
|
1296
|
+
const albumContent = await kelvdra.handleAlbum(content, jid, quoted);
|
|
1297
|
+
return albumContent;
|
|
1298
|
+
|
|
1299
|
+
case 'EVENT':
|
|
1300
|
+
return await kelvdra.handleEvent(content, jid, quoted);
|
|
1301
|
+
|
|
1302
|
+
case 'POLL_RESULT':
|
|
1303
|
+
return await kelvdra.handlePollResult(content, jid, quoted);
|
|
1304
|
+
|
|
1305
|
+
case 'CAROUSEL':
|
|
1306
|
+
return await kelvdra.handleCarousel(content, jid, quoted);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
938
1309
|
if (typeof content === 'object' &&
|
|
939
1310
|
'disappearingMessagesInChat' in content &&
|
|
940
1311
|
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
@@ -1017,7 +1388,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1017
1388
|
});
|
|
1018
1389
|
if (config.emitOwnEvents) {
|
|
1019
1390
|
process.nextTick(async () => {
|
|
1020
|
-
await
|
|
1391
|
+
await processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1021
1392
|
});
|
|
1022
1393
|
}
|
|
1023
1394
|
return fullMsg;
|