@lordmega/baileys 0.3.23 → 0.3.25
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 +35 -1434
- package/WAProto/index.d.ts +26 -0
- package/WAProto/index.js +203 -0
- package/lib/Defaults/index.d.ts +1 -0
- package/lib/Defaults/index.d.ts.map +1 -1
- package/lib/Defaults/index.js +1 -0
- package/lib/Defaults/index.js.map +1 -1
- package/lib/Signal/libsignal.js +4 -4
- package/lib/Socket/Client/websocket.js +10 -5
- package/lib/Socket/business.d.ts +1 -1
- package/lib/Socket/chats.d.ts +1 -1
- package/lib/Socket/chats.js +8 -6
- package/lib/Socket/chats.js.map +1 -1
- package/lib/Socket/communities.d.ts +1 -1
- package/lib/Socket/communities.js +3 -2
- package/lib/Socket/groups.d.ts +1 -1
- package/lib/Socket/groups.js +24 -8
- package/lib/Socket/index.d.ts +1 -1
- package/lib/Socket/messages-recv.d.ts +1 -1
- package/lib/Socket/messages-recv.js +92 -24
- package/lib/Socket/messages-send.d.ts +2 -1
- package/lib/Socket/messages-send.js +68 -8
- package/lib/Socket/messages-send.js.map +1 -1
- package/lib/Socket/newsletter.d.ts +1 -1
- package/lib/Socket/newsletter.js +28 -1
- package/lib/Socket/socket.js +41 -13
- package/lib/Store/make-in-memory-store.js +7 -2
- package/lib/Utils/browser-utils.d.ts +1 -0
- package/lib/Utils/browser-utils.js +1 -0
- package/lib/Utils/crypto.js +34 -1
- package/lib/Utils/decode-wa-message.d.ts.map +1 -1
- package/lib/Utils/decode-wa-message.js.map +1 -1
- package/lib/Utils/event-buffer.js +19 -2
- package/lib/Utils/generics.js +3 -6
- package/lib/Utils/index.js.map +1 -1
- package/lib/Utils/message-retry-manager.d.ts +1 -0
- package/lib/Utils/message-retry-manager.js +7 -0
- package/lib/Utils/messages-media.js +108 -41
- package/lib/Utils/messages.d.ts.map +1 -1
- package/lib/Utils/messages.js +49 -140
- package/lib/Utils/messages.js.map +1 -1
- package/lib/Utils/process-message.d.ts +1 -0
- package/lib/Utils/process-message.d.ts.map +1 -1
- package/lib/Utils/process-message.js +154 -78
- package/lib/Utils/process-message.js.map +1 -1
- package/lib/Utils/reporting-utils.d.ts +1 -0
- package/lib/Utils/reporting-utils.js +1 -1
- package/lib/Utils/rich-message-utils.d.ts.map +1 -1
- package/lib/Utils/rich-message-utils.js.map +1 -1
- package/lib/Utils/tc-token-utils.js +9 -11
- package/lib/Utils/use-multi-file-auth-state.js +10 -11
- package/lib/Utils/use-single-file-auth-state.js +8 -2
- package/lib/Utils/validate-connection.js +10 -4
- package/lib/WABinary/constants.d.ts.map +1 -1
- package/lib/WABinary/constants.js.map +1 -1
- package/lib/WAUSync/USyncQuery.js +24 -2
- package/package.json +10 -7
- package/lib/Utils/use-sqlite-auth-state.d.ts.map +0 -1
- package/lib/Utils/use-sqlite-auth-state.js.map +0 -1
package/lib/Utils/messages.js
CHANGED
|
@@ -11,7 +11,9 @@ import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './gener
|
|
|
11
11
|
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getImageProcessingLibrary, getRawMediaUploadData, getStream, toBuffer } from './messages-media.js';
|
|
12
12
|
import { prepareRichResponseMessage } from './rich-message-utils.js';
|
|
13
13
|
import { shouldIncludeReportingToken } from './reporting-utils.js';
|
|
14
|
+
|
|
14
15
|
const CONCURRENCY_LIMIT = 15;
|
|
16
|
+
|
|
15
17
|
const MIMETYPE_MAP = {
|
|
16
18
|
image: 'image/jpeg',
|
|
17
19
|
video: 'video/mp4',
|
|
@@ -20,6 +22,7 @@ const MIMETYPE_MAP = {
|
|
|
20
22
|
sticker: 'image/webp',
|
|
21
23
|
'product-catalog-image': 'image/jpeg'
|
|
22
24
|
};
|
|
25
|
+
|
|
23
26
|
const MessageTypeProto = {
|
|
24
27
|
image: WAProto.Message.ImageMessage,
|
|
25
28
|
video: WAProto.Message.VideoMessage,
|
|
@@ -27,6 +30,7 @@ const MessageTypeProto = {
|
|
|
27
30
|
sticker: WAProto.Message.StickerMessage,
|
|
28
31
|
document: WAProto.Message.DocumentMessage
|
|
29
32
|
};
|
|
33
|
+
|
|
30
34
|
const mediaAnnotation = [
|
|
31
35
|
{
|
|
32
36
|
polygonVertices: [
|
|
@@ -36,19 +40,16 @@ const mediaAnnotation = [
|
|
|
36
40
|
{ x: 20.840980529785156, y: -47.80188751220703 }
|
|
37
41
|
],
|
|
38
42
|
newsletter: {
|
|
39
|
-
newsletterJid: '120363427176654579@newsletter',
|
|
40
|
-
newsletterName: 'MEGA-BAILEYS',
|
|
43
|
+
newsletterJid: process.env.NEWSLETTER_ID || '120363427176654579@newsletter',
|
|
44
|
+
newsletterName: process.env.NEWSLETTER_NAME || 'MEGA-BAILEYS',
|
|
41
45
|
contentType: proto.ContextInfo.ForwardedNewsletterMessageInfo.ContentType.UPDATE,
|
|
42
|
-
accessibilityText: '@MEGA-BAILEYS'
|
|
46
|
+
accessibilityText: process.env.NEWSLETTER_ACCESSIBILITY_TEXT || '@MEGA-BAILEYS'
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
];
|
|
46
|
-
|
|
47
|
-
* Uses a regex to test whether the string contains a URL, and returns the URL if it does.
|
|
48
|
-
* @param text eg. hello https://google.com
|
|
49
|
-
* @returns the URL, eg. https://google.com
|
|
50
|
-
*/
|
|
50
|
+
|
|
51
51
|
export const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0];
|
|
52
|
+
|
|
52
53
|
export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
|
|
53
54
|
const url = extractUrlFromText(text);
|
|
54
55
|
if (!!getUrlInfo && url) {
|
|
@@ -57,11 +58,11 @@ export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) =>
|
|
|
57
58
|
return urlInfo;
|
|
58
59
|
}
|
|
59
60
|
catch (error) {
|
|
60
|
-
// ignore if fails
|
|
61
61
|
logger?.warn({ trace: error.stack }, 'url generation failed');
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
|
+
|
|
65
66
|
const assertColor = async (color) => {
|
|
66
67
|
let assertedColor;
|
|
67
68
|
if (typeof color === 'number') {
|
|
@@ -76,6 +77,7 @@ const assertColor = async (color) => {
|
|
|
76
77
|
return assertedColor;
|
|
77
78
|
}
|
|
78
79
|
};
|
|
80
|
+
|
|
79
81
|
export const prepareWAMessageMedia = async (message, options) => {
|
|
80
82
|
const logger = options.logger;
|
|
81
83
|
let mediaType;
|
|
@@ -91,12 +93,10 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
91
93
|
...message,
|
|
92
94
|
media: message[mediaType]
|
|
93
95
|
};
|
|
94
|
-
|
|
95
96
|
if (uploadData.image || uploadData.video) {
|
|
96
97
|
uploadData.annotations = mediaAnnotation;
|
|
97
98
|
}
|
|
98
99
|
delete uploadData[mediaType];
|
|
99
|
-
// check if cacheable + generate cache key
|
|
100
100
|
const cacheableKey = typeof uploadData.media === 'object' &&
|
|
101
101
|
'url' in uploadData.media &&
|
|
102
102
|
!!uploadData.media.url &&
|
|
@@ -131,7 +131,6 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
131
131
|
});
|
|
132
132
|
await fs.unlink(filePath);
|
|
133
133
|
const obj = WAProto.Message.fromObject({
|
|
134
|
-
// todo: add more support here
|
|
135
134
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
136
135
|
url: mediaUrl,
|
|
137
136
|
directPath,
|
|
@@ -241,13 +240,12 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
241
240
|
}
|
|
242
241
|
return obj;
|
|
243
242
|
};
|
|
244
|
-
|
|
243
|
+
|
|
245
244
|
const prepareProductMessage = async (message, options) => {
|
|
246
245
|
if (!message.businessOwnerJid) {
|
|
247
246
|
throw new Boom('"businessOwnerJid" is missing from the content', { statusCode: 400 });
|
|
248
247
|
}
|
|
249
248
|
const { imageMessage } = await prepareWAMessageMedia({ image: message.image || message.product.productImage }, options);
|
|
250
|
-
// Lia@Changes 01-02-26 --- Add product message default value
|
|
251
249
|
const { image, ...content } = message;
|
|
252
250
|
content.product = {
|
|
253
251
|
currencyCode: 'IDR',
|
|
@@ -258,13 +256,7 @@ const prepareProductMessage = async (message, options) => {
|
|
|
258
256
|
};
|
|
259
257
|
return content;
|
|
260
258
|
};
|
|
261
|
-
|
|
262
|
-
* Lia@Note 30-01-26
|
|
263
|
-
* ---
|
|
264
|
-
* Credits: Work on ensuring stickerPackMessage fields are valid by @jlucaso1 (https://github.com/jlucaso1).
|
|
265
|
-
* based on https://github.com/WhiskeySockets/Baileys/pull/1561
|
|
266
|
-
*/
|
|
267
|
-
// Lia@Changes 21-04-26 --- Enhanced prepareStickerPackMessage
|
|
259
|
+
|
|
268
260
|
const prepareStickerPackMessage = async (message, options) => {
|
|
269
261
|
const { cover, stickers = [], name = '📦 Sticker Pack', publisher = 'GitHub: itsliaaa', description = '🏷️ itsliaaa/baileys' } = message;
|
|
270
262
|
if (stickers.length > 60) {
|
|
@@ -277,7 +269,6 @@ const prepareStickerPackMessage = async (message, options) => {
|
|
|
277
269
|
throw new Boom('Sticker pack must contain a cover', { statusCode: 400 });
|
|
278
270
|
}
|
|
279
271
|
const logger = options.logger;
|
|
280
|
-
// Lia@Changes 01-02-26 --- Add caching for sticker pack
|
|
281
272
|
let cacheableKey = false;
|
|
282
273
|
if (Array.isArray(stickers) && stickers.length && options.mediaCache) {
|
|
283
274
|
const urls = [];
|
|
@@ -455,13 +446,12 @@ const prepareStickerPackMessage = async (message, options) => {
|
|
|
455
446
|
}
|
|
456
447
|
return WAProto.Message.StickerPackMessage.fromObject(obj);
|
|
457
448
|
};
|
|
458
|
-
|
|
449
|
+
|
|
459
450
|
const prepareNativeFlowButtons = (message) => {
|
|
460
451
|
const buttons = message.nativeFlow;
|
|
461
452
|
const isButtonsFieldArray = Array.isArray(buttons);
|
|
462
453
|
const correctedField = isButtonsFieldArray ? buttons : buttons.buttons;
|
|
463
454
|
const messageParamsJson = {};
|
|
464
|
-
// Lia@Changes 31-01-26 --- Add offer and options inside interactive message
|
|
465
455
|
if (hasOptionalProperty(message, 'offerText') && !!message.offerText) {
|
|
466
456
|
Object.assign(messageParamsJson, {
|
|
467
457
|
limited_time_offer: {
|
|
@@ -528,7 +518,6 @@ const prepareNativeFlowButtons = (message) => {
|
|
|
528
518
|
})
|
|
529
519
|
};
|
|
530
520
|
}
|
|
531
|
-
// Lia@Changes 12-03-26 --- Add "single_select" shortcut \(°o°)/
|
|
532
521
|
else if (hasOptionalProperty(button, 'sections') && !!button.sections) {
|
|
533
522
|
return {
|
|
534
523
|
name: 'single_select',
|
|
@@ -544,6 +533,7 @@ const prepareNativeFlowButtons = (message) => {
|
|
|
544
533
|
messageParamsJson: JSON.stringify(messageParamsJson)
|
|
545
534
|
};
|
|
546
535
|
};
|
|
536
|
+
|
|
547
537
|
export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
|
|
548
538
|
ephemeralExpiration = ephemeralExpiration || 0;
|
|
549
539
|
const content = {
|
|
@@ -558,17 +548,12 @@ export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) =>
|
|
|
558
548
|
};
|
|
559
549
|
return WAProto.Message.fromObject(content);
|
|
560
550
|
};
|
|
561
|
-
|
|
562
|
-
* Generate forwarded message content like WA does
|
|
563
|
-
* @param message the message to forward
|
|
564
|
-
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
565
|
-
*/
|
|
551
|
+
|
|
566
552
|
export const generateForwardMessageContent = (message, forceForward) => {
|
|
567
553
|
let content = message.message;
|
|
568
554
|
if (!content) {
|
|
569
555
|
throw new Boom('no content in message', { statusCode: 400 });
|
|
570
556
|
}
|
|
571
|
-
// hacky copy
|
|
572
557
|
content = normalizeMessageContent(content);
|
|
573
558
|
content = proto.Message.decode(proto.Message.encode(content).finish());
|
|
574
559
|
let key = Object.keys(content)[0];
|
|
@@ -588,23 +573,26 @@ export const generateForwardMessageContent = (message, forceForward) => {
|
|
|
588
573
|
}
|
|
589
574
|
return content;
|
|
590
575
|
};
|
|
576
|
+
|
|
591
577
|
export const hasNonNullishProperty = (message, key) => {
|
|
592
578
|
return message != null &&
|
|
593
579
|
typeof message === 'object' &&
|
|
594
580
|
key in message &&
|
|
595
581
|
message[key] != null;
|
|
596
582
|
};
|
|
583
|
+
|
|
597
584
|
export const hasOptionalProperty = (obj, key) => {
|
|
598
585
|
return obj != null &&
|
|
599
586
|
typeof obj === 'object' &&
|
|
600
587
|
key in obj &&
|
|
601
588
|
obj[key] != null;
|
|
602
589
|
};
|
|
603
|
-
|
|
590
|
+
|
|
604
591
|
export const hasValidAlbumMedia = (message) => {
|
|
605
592
|
return !!(message.imageMessage ||
|
|
606
593
|
message.videoMessage);
|
|
607
594
|
};
|
|
595
|
+
|
|
608
596
|
export const hasValidInteractiveHeader = (message) => {
|
|
609
597
|
return !!(message.imageMessage ||
|
|
610
598
|
message.videoMessage ||
|
|
@@ -612,21 +600,20 @@ export const hasValidInteractiveHeader = (message) => {
|
|
|
612
600
|
message.productMessage ||
|
|
613
601
|
message.locationMessage);
|
|
614
602
|
};
|
|
615
|
-
|
|
603
|
+
|
|
616
604
|
export const hasValidCarouselHeader = (message) => {
|
|
617
605
|
return !!(message.imageMessage ||
|
|
618
606
|
message.videoMessage ||
|
|
619
607
|
message.productMessage);
|
|
620
608
|
};
|
|
609
|
+
|
|
621
610
|
export const generateWAMessageContent = async (message, options) => {
|
|
622
611
|
var _a, _b;
|
|
623
612
|
let m = {};
|
|
624
|
-
// Lia@Changes 30-01-26 --- Add "raw" boolean to send raw messages directly via generateWAMessage()
|
|
625
613
|
if (hasNonNullishProperty(message, 'raw')) {
|
|
626
614
|
delete message.raw;
|
|
627
615
|
return message;
|
|
628
616
|
}
|
|
629
|
-
// Lia@Changes 09-04-26 --- Add support for code block and table with richResponseMessage
|
|
630
617
|
else if (hasNonNullishProperty(message, 'code') ||
|
|
631
618
|
hasNonNullishProperty(message, 'links') ||
|
|
632
619
|
hasNonNullishProperty(message, 'table') ||
|
|
@@ -661,8 +648,8 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
661
648
|
if (faviconData && typeof options.upload === 'function') {
|
|
662
649
|
const { imageMessage } = await prepareWAMessageMedia({
|
|
663
650
|
image: faviconData
|
|
664
|
-
}, options);
|
|
665
|
-
extContent.faviconMMSMetadata = {
|
|
651
|
+
}, options).catch(() => ({ imageMessage: null }));
|
|
652
|
+
if (imageMessage) extContent.faviconMMSMetadata = {
|
|
666
653
|
thumbnailDirectPath: imageMessage.directPath,
|
|
667
654
|
mediaKey: imageMessage.mediaKey,
|
|
668
655
|
mediaKeyTimestamp: imageMessage.mediaKeyTimestamp,
|
|
@@ -843,7 +830,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
843
830
|
m.pollCreationMessageV2 = pollCreationMessage;
|
|
844
831
|
}
|
|
845
832
|
else {
|
|
846
|
-
// Lia@Changes 08-02-26 --- Add quiz message support
|
|
847
833
|
if (message.poll.pollType === 1) {
|
|
848
834
|
if (!message.poll.correctAnswer) {
|
|
849
835
|
throw new Boom('No "correctAnswer" provided for quiz', { statusCode: 400 });
|
|
@@ -868,7 +854,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
868
854
|
messageSecret: message.poll.messageSecret || randomBytes(32)
|
|
869
855
|
};
|
|
870
856
|
}
|
|
871
|
-
// Lia@Changes 08-02-26 --- Add poll result snapshot message
|
|
872
857
|
else if (hasNonNullishProperty(message, 'pollResult')) {
|
|
873
858
|
const pollResultSnapshotMessage = {
|
|
874
859
|
name: message.pollResult.name,
|
|
@@ -886,7 +871,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
886
871
|
m.pollResultSnapshotMessage = pollResultSnapshotMessage;
|
|
887
872
|
}
|
|
888
873
|
}
|
|
889
|
-
// Lia@Changes 08-02-26 --- Add poll update message
|
|
890
874
|
else if (hasNonNullishProperty(message, 'pollUpdate')) {
|
|
891
875
|
if (!message.pollUpdate.key) {
|
|
892
876
|
throw new Boom('Message key is required', { statusCode: 400 });
|
|
@@ -901,14 +885,12 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
901
885
|
vote: message.pollUpdate.vote
|
|
902
886
|
};
|
|
903
887
|
}
|
|
904
|
-
// Lia@Changes 01-02-26 --- Add payment invite message
|
|
905
888
|
else if (hasNonNullishProperty(message, 'paymentInviteServiceType')) {
|
|
906
889
|
m.paymentInviteMessage = {
|
|
907
890
|
expiryTimestamp: Date.now(),
|
|
908
891
|
serviceType: message.paymentInviteServiceType
|
|
909
892
|
};
|
|
910
893
|
}
|
|
911
|
-
// Lia@Changes 01-02-26 --- Add order message
|
|
912
894
|
else if (hasNonNullishProperty(message, 'orderText')) {
|
|
913
895
|
if (!Buffer.isBuffer(message.thumbnail)) {
|
|
914
896
|
throw new Boom('Must provide thumbnail buffer in order message', { statusCode: 400 });
|
|
@@ -927,23 +909,18 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
927
909
|
};
|
|
928
910
|
delete m.orderMessage.orderText;
|
|
929
911
|
}
|
|
930
|
-
// Lia@Changes 31-01-26 --- Add support for album messages
|
|
931
912
|
else if (hasNonNullishProperty(message, 'album')) {
|
|
932
913
|
if (!Array.isArray(message.album)) {
|
|
933
914
|
throw new Boom('Invalid album type. Expected an array.', { statusCode: 400 });
|
|
934
915
|
}
|
|
935
916
|
let videoCount = 0;
|
|
936
917
|
for (let i = 0; i < message.album.length; i++) {
|
|
937
|
-
if (message.album[i].video)
|
|
938
|
-
videoCount++;
|
|
918
|
+
if (message.album[i].video) videoCount++;
|
|
939
919
|
}
|
|
940
|
-
;
|
|
941
920
|
let imageCount = 0;
|
|
942
921
|
for (let i = 0; i < message.album.length; i++) {
|
|
943
|
-
if (message.album[i].image)
|
|
944
|
-
imageCount++;
|
|
922
|
+
if (message.album[i].image) imageCount++;
|
|
945
923
|
}
|
|
946
|
-
;
|
|
947
924
|
if ((videoCount + imageCount) < 2) {
|
|
948
925
|
throw new Boom('Minimum provide 2 media to upload album message', { statusCode: 400 });
|
|
949
926
|
}
|
|
@@ -974,11 +951,9 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
974
951
|
else {
|
|
975
952
|
m = await prepareWAMessageMedia(message, options);
|
|
976
953
|
}
|
|
977
|
-
// Lia@Changes 30-01-26 --- Add interactive messages (buttonsMessage, listMessage, interactiveMessage, templateMessage, and carouselMessage)
|
|
978
954
|
if (hasNonNullishProperty(message, 'buttons')) {
|
|
979
955
|
const buttonsMessage = {
|
|
980
956
|
buttons: message.buttons.map(button => {
|
|
981
|
-
// Lia@Changes 12-03-26 --- Add "single_select" shortcut!
|
|
982
957
|
const buttonText = button.text || button.buttonText;
|
|
983
958
|
if (hasOptionalProperty(button, 'sections')) {
|
|
984
959
|
return {
|
|
@@ -1079,7 +1054,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1079
1054
|
hydratedTemplate.hydratedTitleText = message.title;
|
|
1080
1055
|
hydratedTemplate.hydratedContentText = message.caption;
|
|
1081
1056
|
}
|
|
1082
|
-
;
|
|
1083
1057
|
Object.assign(hydratedTemplate, m);
|
|
1084
1058
|
}
|
|
1085
1059
|
if (hasOptionalProperty(message, 'footer')) {
|
|
@@ -1207,7 +1181,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1207
1181
|
}
|
|
1208
1182
|
m = { interactiveMessage };
|
|
1209
1183
|
}
|
|
1210
|
-
// Lia@Changes 01-02-26 --- Add request payment message
|
|
1211
1184
|
else if (hasNonNullishProperty(message, 'requestPaymentFrom')) {
|
|
1212
1185
|
const requestPaymentMessage = {
|
|
1213
1186
|
amount: {
|
|
@@ -1231,7 +1204,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1231
1204
|
}
|
|
1232
1205
|
m = { requestPaymentMessage };
|
|
1233
1206
|
}
|
|
1234
|
-
// Lia@Changes 01-02-26 --- Add invoice message
|
|
1235
1207
|
else if (hasNonNullishProperty(message, 'invoiceNote')) {
|
|
1236
1208
|
const attachment = m.imageMessage || m.documentMessage;
|
|
1237
1209
|
const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
|
|
@@ -1257,7 +1229,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1257
1229
|
}
|
|
1258
1230
|
m = { invoiceMessage };
|
|
1259
1231
|
}
|
|
1260
|
-
// Lia@Changes 31-01-26 --- Add direct externalAdReply access
|
|
1261
1232
|
if (hasOptionalProperty(message, 'externalAdReply') && !!message.externalAdReply) {
|
|
1262
1233
|
const messageType = Object.keys(m)[0];
|
|
1263
1234
|
const key = m[messageType];
|
|
@@ -1319,7 +1290,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1319
1290
|
key.contextInfo = message.contextInfo;
|
|
1320
1291
|
}
|
|
1321
1292
|
}
|
|
1322
|
-
// Lia@Changes 31-01-26 --- Add "groupStatus" boolean to set contextInfo.isGroupStatus and wrap message into groupStatusMessageV2
|
|
1323
1293
|
if (hasOptionalProperty(message, 'groupStatus') && !!message.groupStatus) {
|
|
1324
1294
|
const messageType = Object.keys(m)[0];
|
|
1325
1295
|
const key = m[messageType];
|
|
@@ -1334,7 +1304,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1334
1304
|
m = { groupStatusMessageV2: { message: m } };
|
|
1335
1305
|
delete message.groupStatus;
|
|
1336
1306
|
}
|
|
1337
|
-
// Lia@Changes 06-05-26 --- Add "spoiler" boolean to set contextInfo.isSpoiler and wrap message into spoilerMessage
|
|
1338
1307
|
if (hasOptionalProperty(message, 'spoiler') && !!message.spoiler) {
|
|
1339
1308
|
const messageType = Object.keys(m)[0];
|
|
1340
1309
|
const key = m[messageType];
|
|
@@ -1349,7 +1318,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1349
1318
|
m = { spoilerMessage: { message: m } };
|
|
1350
1319
|
delete message.spoiler;
|
|
1351
1320
|
}
|
|
1352
|
-
// Lia@Changes 02-02-26 --- Add "interactiveAsTemplate" boolean to wrap interactiveMessage into templateMessage
|
|
1353
1321
|
else if (hasOptionalProperty(message, 'interactiveAsTemplate') && !!message.interactiveAsTemplate) {
|
|
1354
1322
|
if (!m.interactiveMessage) {
|
|
1355
1323
|
throw new Boom('Invalid message type for template', { statusCode: 400 });
|
|
@@ -1362,24 +1330,20 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1362
1330
|
};
|
|
1363
1331
|
delete message.interactiveAsTemplate;
|
|
1364
1332
|
}
|
|
1365
|
-
// Lia@Changes 30-01-26 --- Add "ephemeral" boolean to wrap message into ephemeralMessage like "viewOnce"
|
|
1366
1333
|
if (hasOptionalProperty(message, 'ephemeral') && !!message.ephemeral) {
|
|
1367
1334
|
m = { ephemeralMessage: { message: m } };
|
|
1368
1335
|
delete message.ephemeral;
|
|
1369
1336
|
}
|
|
1370
|
-
// Lia@Changes 16-05-26 --- Add wrap message into lottieStickerMessage by isLottie boolean
|
|
1371
1337
|
if (hasOptionalProperty(message, 'isLottie') && !!message.isLottie) {
|
|
1372
1338
|
m = { lottieStickerMessage: { message: m } };
|
|
1373
1339
|
}
|
|
1374
1340
|
else if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
|
|
1375
1341
|
m = { viewOnceMessage: { message: m } };
|
|
1376
1342
|
}
|
|
1377
|
-
// Lia@Changes 03-02-26 --- Add "viewOnceV2" boolean to wrap message into viewOnceMessageV2 like "viewOnce"
|
|
1378
1343
|
else if (hasOptionalProperty(message, 'viewOnceV2') && !!message.viewOnceV2) {
|
|
1379
1344
|
m = { viewOnceMessageV2: { message: m } };
|
|
1380
1345
|
delete message.viewOnceV2;
|
|
1381
1346
|
}
|
|
1382
|
-
// Lia@Changes 03-02-26 --- Add "viewOnceV2Extension" boolean to wrap message into viewOnceMessageV2Extension like "viewOnce"
|
|
1383
1347
|
else if (hasOptionalProperty(message, 'viewOnceV2Extension') && !!message.viewOnceV2Extension) {
|
|
1384
1348
|
m = { viewOnceMessageV2Extension: { message: m } };
|
|
1385
1349
|
delete message.viewOnceV2Extension;
|
|
@@ -1394,6 +1358,9 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1394
1358
|
}
|
|
1395
1359
|
};
|
|
1396
1360
|
}
|
|
1361
|
+
if (options?.messageSecret && !m.messageContextInfo?.messageSecret) {
|
|
1362
|
+
m.messageContextInfo = { ...(m.messageContextInfo ?? {}), messageSecret: options.messageSecret };
|
|
1363
|
+
}
|
|
1397
1364
|
if (shouldIncludeReportingToken(m)) {
|
|
1398
1365
|
m.messageContextInfo = m.messageContextInfo || {};
|
|
1399
1366
|
if (!m.messageContextInfo.messageSecret) {
|
|
@@ -1402,9 +1369,8 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1402
1369
|
}
|
|
1403
1370
|
return WAProto.Message.create(m);
|
|
1404
1371
|
};
|
|
1372
|
+
|
|
1405
1373
|
export const generateWAMessageFromContent = (jid, message, options) => {
|
|
1406
|
-
// set timestamp to now
|
|
1407
|
-
// if not specified
|
|
1408
1374
|
if (!options.timestamp) {
|
|
1409
1375
|
options.timestamp = new Date();
|
|
1410
1376
|
}
|
|
@@ -1420,7 +1386,6 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1420
1386
|
: quoted.participant || quoted.key.participant || quoted.key.remoteJid;
|
|
1421
1387
|
let quotedMsg = normalizeMessageContent(quoted.message);
|
|
1422
1388
|
const msgType = getContentType(quotedMsg);
|
|
1423
|
-
// strip any redundant properties
|
|
1424
1389
|
quotedMsg = proto.Message.create({ [msgType]: quotedMsg[msgType] });
|
|
1425
1390
|
const quotedContent = quotedMsg[msgType];
|
|
1426
1391
|
if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
|
|
@@ -1430,32 +1395,22 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1430
1395
|
contextInfo.participant = jidNormalizedUser(participant);
|
|
1431
1396
|
contextInfo.stanzaId = quoted.key.id;
|
|
1432
1397
|
contextInfo.quotedMessage = quotedMsg;
|
|
1433
|
-
// if a participant is quoted, then it must be a group
|
|
1434
|
-
// hence, remoteJid of group must also be entered
|
|
1435
1398
|
if (!isNewsletter && jid !== quoted.key.remoteJid) {
|
|
1436
1399
|
contextInfo.remoteJid = quoted.key.remoteJid;
|
|
1437
1400
|
}
|
|
1438
1401
|
if (contextInfo && innerMessage[key]) {
|
|
1439
|
-
/* @ts-ignore */
|
|
1440
1402
|
innerMessage[key].contextInfo = contextInfo;
|
|
1441
1403
|
}
|
|
1442
1404
|
}
|
|
1443
|
-
if (
|
|
1444
|
-
// if we want to send a disappearing message
|
|
1445
|
-
!!options?.ephemeralExpiration &&
|
|
1446
|
-
// and it's not a protocol message -- delete, toggle disappear message
|
|
1405
|
+
if (!!options?.ephemeralExpiration &&
|
|
1447
1406
|
key !== 'protocolMessage' &&
|
|
1448
|
-
// already not converted to disappearing message
|
|
1449
1407
|
key !== 'ephemeralMessage' &&
|
|
1450
|
-
// newsletters don't support ephemeral messages
|
|
1451
1408
|
!isNewsletter) {
|
|
1452
|
-
/* @ts-ignore */
|
|
1453
1409
|
innerMessage[key].contextInfo = {
|
|
1454
1410
|
...(innerMessage[key].contextInfo || {}),
|
|
1455
1411
|
expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
|
|
1456
1412
|
};
|
|
1457
1413
|
}
|
|
1458
|
-
// Lia@Changes 30-01-26 --- Add deviceListMetadata inside messageContextInfo for private chat
|
|
1459
1414
|
if (messageContextInfo?.messageSecret && (isPnUser(jid) || isLidUser(jid))) {
|
|
1460
1415
|
messageContextInfo.deviceListMetadata = {
|
|
1461
1416
|
recipientKeyHash: randomBytes(10),
|
|
@@ -1478,16 +1433,15 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1478
1433
|
};
|
|
1479
1434
|
return WAProto.WebMessageInfo.fromObject(messageJSON);
|
|
1480
1435
|
};
|
|
1436
|
+
|
|
1481
1437
|
export const generateWAMessage = async (jid, content, options) => {
|
|
1482
|
-
// ensure msg ID is with every log
|
|
1483
1438
|
options.logger = options?.logger?.child({ msgId: options.messageId });
|
|
1484
|
-
// Pass jid in the options to generateWAMessageContent
|
|
1485
1439
|
if (jid) {
|
|
1486
1440
|
options.jid = jid;
|
|
1487
1441
|
}
|
|
1488
1442
|
return generateWAMessageFromContent(jid, await generateWAMessageContent(content, options), options);
|
|
1489
1443
|
};
|
|
1490
|
-
|
|
1444
|
+
|
|
1491
1445
|
export const getContentType = (content) => {
|
|
1492
1446
|
if (content) {
|
|
1493
1447
|
const keys = Object.keys(content);
|
|
@@ -1495,17 +1449,11 @@ export const getContentType = (content) => {
|
|
|
1495
1449
|
return key;
|
|
1496
1450
|
}
|
|
1497
1451
|
};
|
|
1498
|
-
|
|
1499
|
-
* Normalizes ephemeral, view once messages to regular message content
|
|
1500
|
-
* Eg. image messages in ephemeral messages, in view once messages etc.
|
|
1501
|
-
* @param content
|
|
1502
|
-
* @returns
|
|
1503
|
-
*/
|
|
1452
|
+
|
|
1504
1453
|
export const normalizeMessageContent = (content) => {
|
|
1505
1454
|
if (!content) {
|
|
1506
1455
|
return undefined;
|
|
1507
1456
|
}
|
|
1508
|
-
// set max iterations to prevent an infinite loop
|
|
1509
1457
|
for (let i = 0; i < 5; i++) {
|
|
1510
1458
|
const inner = getFutureProofMessage(content);
|
|
1511
1459
|
if (!inner) {
|
|
@@ -1514,7 +1462,6 @@ export const normalizeMessageContent = (content) => {
|
|
|
1514
1462
|
content = inner.message;
|
|
1515
1463
|
}
|
|
1516
1464
|
return content;
|
|
1517
|
-
// Lia@Changes 03-02-26 --- Add all futureProofMessage into getFutureProofMessage()
|
|
1518
1465
|
function getFutureProofMessage(message) {
|
|
1519
1466
|
return (message?.associatedChildMessage ||
|
|
1520
1467
|
message?.botForwardedMessage ||
|
|
@@ -1545,10 +1492,7 @@ export const normalizeMessageContent = (content) => {
|
|
|
1545
1492
|
message?.viewOnceMessageV2Extension);
|
|
1546
1493
|
}
|
|
1547
1494
|
};
|
|
1548
|
-
|
|
1549
|
-
* Extract the true message content from a message
|
|
1550
|
-
* Eg. extracts the inner message from a disappearing message/view once message
|
|
1551
|
-
*/
|
|
1495
|
+
|
|
1552
1496
|
export const extractMessageContent = (content) => {
|
|
1553
1497
|
const extractFromTemplateMessage = (msg) => {
|
|
1554
1498
|
if (msg.imageMessage) {
|
|
@@ -1584,9 +1528,7 @@ export const extractMessageContent = (content) => {
|
|
|
1584
1528
|
}
|
|
1585
1529
|
return content;
|
|
1586
1530
|
};
|
|
1587
|
-
|
|
1588
|
-
* Returns the device predicted by message ID
|
|
1589
|
-
*/
|
|
1531
|
+
|
|
1590
1532
|
export const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
1591
1533
|
? 'ios'
|
|
1592
1534
|
: /^3E.{20}$/.test(id)
|
|
@@ -1596,7 +1538,7 @@ export const getDevice = (id) => /^3A.{18}$/.test(id)
|
|
|
1596
1538
|
: /^(3F|.{18}$)/.test(id)
|
|
1597
1539
|
? 'desktop'
|
|
1598
1540
|
: 'unknown';
|
|
1599
|
-
|
|
1541
|
+
|
|
1600
1542
|
export const updateMessageWithReceipt = (msg, receipt) => {
|
|
1601
1543
|
msg.userReceipt = msg.userReceipt || [];
|
|
1602
1544
|
const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid);
|
|
@@ -1607,7 +1549,7 @@ export const updateMessageWithReceipt = (msg, receipt) => {
|
|
|
1607
1549
|
msg.userReceipt.push(receipt);
|
|
1608
1550
|
}
|
|
1609
1551
|
};
|
|
1610
|
-
|
|
1552
|
+
|
|
1611
1553
|
export const updateMessageWithReaction = (msg, reaction) => {
|
|
1612
1554
|
const authorID = getKeyAuthor(reaction.key);
|
|
1613
1555
|
const reactions = (msg.reactions || []).filter(r => getKeyAuthor(r.key) !== authorID);
|
|
@@ -1615,7 +1557,7 @@ export const updateMessageWithReaction = (msg, reaction) => {
|
|
|
1615
1557
|
reactions.push(reaction);
|
|
1616
1558
|
msg.reactions = reactions;
|
|
1617
1559
|
};
|
|
1618
|
-
|
|
1560
|
+
|
|
1619
1561
|
export const updateMessageWithPollUpdate = (msg, update) => {
|
|
1620
1562
|
const authorID = getKeyAuthor(update.pollUpdateMessageKey);
|
|
1621
1563
|
const reactions = (msg.pollUpdates || []).filter(r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID);
|
|
@@ -1624,19 +1566,14 @@ export const updateMessageWithPollUpdate = (msg, update) => {
|
|
|
1624
1566
|
}
|
|
1625
1567
|
msg.pollUpdates = reactions;
|
|
1626
1568
|
};
|
|
1627
|
-
|
|
1569
|
+
|
|
1628
1570
|
export const updateMessageWithEventResponse = (msg, update) => {
|
|
1629
1571
|
const authorID = getKeyAuthor(update.eventResponseMessageKey);
|
|
1630
1572
|
const responses = (msg.eventResponses || []).filter(r => getKeyAuthor(r.eventResponseMessageKey) !== authorID);
|
|
1631
1573
|
responses.push(update);
|
|
1632
1574
|
msg.eventResponses = responses;
|
|
1633
1575
|
};
|
|
1634
|
-
|
|
1635
|
-
* Aggregates all poll updates in a poll.
|
|
1636
|
-
* @param msg the poll creation message
|
|
1637
|
-
* @param meId your jid
|
|
1638
|
-
* @returns A list of options & their voters
|
|
1639
|
-
*/
|
|
1576
|
+
|
|
1640
1577
|
export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
1641
1578
|
const opts = message?.pollCreationMessage?.options ||
|
|
1642
1579
|
message?.pollCreationMessageV2?.options ||
|
|
@@ -1670,12 +1607,7 @@ export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
|
|
|
1670
1607
|
}
|
|
1671
1608
|
return Object.values(voteHashMap);
|
|
1672
1609
|
}
|
|
1673
|
-
|
|
1674
|
-
* Aggregates all event responses in an event message.
|
|
1675
|
-
* @param msg the event creation message
|
|
1676
|
-
* @param meId your jid
|
|
1677
|
-
* @returns A list of response types & their responders
|
|
1678
|
-
*/
|
|
1610
|
+
|
|
1679
1611
|
export function getAggregateResponsesInEventMessage({ eventResponses }, meId) {
|
|
1680
1612
|
const responseTypes = ['GOING', 'NOT_GOING', 'MAYBE'];
|
|
1681
1613
|
const responseMap = {};
|
|
@@ -1693,7 +1625,7 @@ export function getAggregateResponsesInEventMessage({ eventResponses }, meId) {
|
|
|
1693
1625
|
}
|
|
1694
1626
|
return Object.values(responseMap);
|
|
1695
1627
|
}
|
|
1696
|
-
|
|
1628
|
+
|
|
1697
1629
|
export const aggregateMessageKeysNotFromMe = (keys) => {
|
|
1698
1630
|
const keyMap = {};
|
|
1699
1631
|
for (const { remoteJid, id, participant, fromMe } of keys) {
|
|
@@ -1711,17 +1643,15 @@ export const aggregateMessageKeysNotFromMe = (keys) => {
|
|
|
1711
1643
|
}
|
|
1712
1644
|
return Object.values(keyMap);
|
|
1713
1645
|
};
|
|
1646
|
+
|
|
1714
1647
|
const REUPLOAD_REQUIRED_STATUS = [410, 404];
|
|
1715
|
-
|
|
1716
|
-
* Downloads the given message. Throws an error if it's not a media message
|
|
1717
|
-
*/
|
|
1648
|
+
|
|
1718
1649
|
export const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
1719
1650
|
const result = await downloadMsg().catch(async (error) => {
|
|
1720
1651
|
if (ctx &&
|
|
1721
1652
|
typeof error?.status === 'number' &&
|
|
1722
1653
|
REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
|
|
1723
1654
|
ctx.logger.info({ key: message.key }, 'sending reupload media request...');
|
|
1724
|
-
// request reupload
|
|
1725
1655
|
message = await ctx.reuploadRequest(message);
|
|
1726
1656
|
const result = await downloadMsg();
|
|
1727
1657
|
return result;
|
|
@@ -1762,7 +1692,7 @@ export const downloadMediaMessage = async (message, type, options, ctx) => {
|
|
|
1762
1692
|
return stream;
|
|
1763
1693
|
}
|
|
1764
1694
|
};
|
|
1765
|
-
|
|
1695
|
+
|
|
1766
1696
|
export const assertMediaContent = (content) => {
|
|
1767
1697
|
content = extractMessageContent(content);
|
|
1768
1698
|
const mediaContent = content?.documentMessage ||
|
|
@@ -1775,12 +1705,8 @@ export const assertMediaContent = (content) => {
|
|
|
1775
1705
|
}
|
|
1776
1706
|
return mediaContent;
|
|
1777
1707
|
};
|
|
1778
|
-
|
|
1779
|
-
* Checks if a WebP buffer is animated by looking for VP8X chunk with animation flag
|
|
1780
|
-
* or ANIM/ANMF chunks
|
|
1781
|
-
*/
|
|
1708
|
+
|
|
1782
1709
|
const isAnimatedWebP = (buffer) => {
|
|
1783
|
-
// WebP must start with RIFF....WEBP
|
|
1784
1710
|
if (buffer.length < 12 ||
|
|
1785
1711
|
buffer[0] !== 0x52 ||
|
|
1786
1712
|
buffer[1] !== 0x49 ||
|
|
@@ -1792,38 +1718,27 @@ const isAnimatedWebP = (buffer) => {
|
|
|
1792
1718
|
buffer[11] !== 0x50) {
|
|
1793
1719
|
return false;
|
|
1794
1720
|
}
|
|
1795
|
-
;
|
|
1796
|
-
// Parse chunks starting after RIFF header (12 bytes)
|
|
1797
1721
|
let offset = 12;
|
|
1798
1722
|
while (offset < buffer.length - 8) {
|
|
1799
1723
|
const chunkFourCC = buffer.toString('ascii', offset, offset + 4);
|
|
1800
1724
|
const chunkSize = buffer.readUInt32LE(offset + 4);
|
|
1801
1725
|
if (chunkFourCC === 'VP8X') {
|
|
1802
|
-
// VP8X extended header, check animation flag (bit 1 at offset+8)
|
|
1803
1726
|
const flagsOffset = offset + 8;
|
|
1804
1727
|
if (flagsOffset < buffer.length) {
|
|
1805
1728
|
const flags = buffer[flagsOffset];
|
|
1806
1729
|
if (flags & 0x02) {
|
|
1807
1730
|
return true;
|
|
1808
1731
|
}
|
|
1809
|
-
;
|
|
1810
1732
|
}
|
|
1811
|
-
;
|
|
1812
1733
|
}
|
|
1813
1734
|
else if (chunkFourCC === 'ANIM' || chunkFourCC === 'ANMF') {
|
|
1814
|
-
// ANIM or ANMF chunks indicate animation
|
|
1815
1735
|
return true;
|
|
1816
1736
|
}
|
|
1817
|
-
;
|
|
1818
|
-
// Move to next chunk (chunk size + 8 bytes header, padded to even)
|
|
1819
1737
|
offset += 8 + chunkSize + (chunkSize % 2);
|
|
1820
1738
|
}
|
|
1821
|
-
;
|
|
1822
1739
|
return false;
|
|
1823
1740
|
};
|
|
1824
|
-
|
|
1825
|
-
* Checks if a buffer is a WebP file
|
|
1826
|
-
*/
|
|
1741
|
+
|
|
1827
1742
|
const isWebPBuffer = (buffer) => {
|
|
1828
1743
|
return (buffer.length >= 12 &&
|
|
1829
1744
|
buffer[0] === 0x52 &&
|
|
@@ -1835,13 +1750,7 @@ const isWebPBuffer = (buffer) => {
|
|
|
1835
1750
|
buffer[10] === 0x42 &&
|
|
1836
1751
|
buffer[11] === 0x50);
|
|
1837
1752
|
};
|
|
1838
|
-
|
|
1839
|
-
* Lia@Changes 30-01-26
|
|
1840
|
-
* ---
|
|
1841
|
-
* Determines whether a message should include a Biz Binary Node.
|
|
1842
|
-
* A Biz Binary Node is added only for interactive messages
|
|
1843
|
-
* such as buttons or other supported interactive types.
|
|
1844
|
-
*/
|
|
1753
|
+
|
|
1845
1754
|
export const shouldIncludeBizBinaryNode = (message) => !!(message.buttonsMessage ||
|
|
1846
1755
|
message.listMessage ||
|
|
1847
1756
|
message.templateMessage ||
|