@crysnovax/baileys 2.5.5 → 2.5.6
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/WAProto/index.js +3578 -14789
- package/lib/Defaults/index.js +11 -19
- package/lib/Signal/libsignal.js +18 -42
- package/lib/Socket/chats.js +91 -246
- package/lib/Socket/messages-recv.js +322 -618
- package/lib/Socket/messages-send.js +74 -174
- package/lib/Socket/newsletter.js +2 -2
- package/lib/Socket/socket.js +20 -12
- package/lib/Types/index.js +0 -1
- package/lib/Utils/index.js +0 -1
- package/lib/Utils/messages.js +114 -148
- package/lib/WABinary/constants.js +5 -99
- package/package.json +9 -43
- package/lib/Socket/Client//342/234/230 +0 -1
- package/lib/Socket//342/230/201/357/270/216 +0 -1
- package/lib/Types/Mex.js +0 -39
- package/lib/Types//342/234/206 +0 -1
- package/lib/Utils/use-sqlite-auth-state.js +0 -109
- package/lib/Utils//342/232/211 +0 -1
- package/lib/WABinary//342/216/231 +0 -1
package/lib/Utils/messages.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Boom } from '@hapi/boom';
|
|
|
2
2
|
import { randomBytes } from 'crypto';
|
|
3
3
|
import { zip } from 'fflate';
|
|
4
4
|
import { promises as fs } from 'fs';
|
|
5
|
+
import {} from 'stream';
|
|
5
6
|
import { proto } from '../../WAProto/index.js';
|
|
6
7
|
import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, DONATE_URL, LIBRARY_NAME, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
7
8
|
import { AssociationType, ButtonHeaderType, ButtonType, CarouselCardType, ListType, ProtocolType, WAMessageStatus, WAProto } from '../Types/index.js';
|
|
@@ -11,7 +12,6 @@ import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './gener
|
|
|
11
12
|
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getImageProcessingLibrary, getRawMediaUploadData, getStream, toBuffer } from './messages-media.js';
|
|
12
13
|
import { prepareRichResponseMessage } from './rich-message-utils.js';
|
|
13
14
|
import { shouldIncludeReportingToken } from './reporting-utils.js';
|
|
14
|
-
const CONCURRENCY_LIMIT = 15;
|
|
15
15
|
const MIMETYPE_MAP = {
|
|
16
16
|
image: 'image/jpeg',
|
|
17
17
|
video: 'video/mp4',
|
|
@@ -36,7 +36,7 @@ const mediaAnnotation = [
|
|
|
36
36
|
{ x: 20.840980529785156, y: -47.80188751220703 }
|
|
37
37
|
],
|
|
38
38
|
newsletter: {
|
|
39
|
-
//
|
|
39
|
+
// Lia@Note 03-02-26 --- You can change jid, message id, and name via .env (≧▽≦)
|
|
40
40
|
newsletterJid: process.env.NEWSLETTER_ID ||
|
|
41
41
|
'120363402922206865@newsletter',
|
|
42
42
|
serverMessageId: process.env.NEWSLETTER_MESSAGE_ID ||
|
|
@@ -106,9 +106,9 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
106
106
|
'url' in uploadData.media &&
|
|
107
107
|
!!uploadData.media.url &&
|
|
108
108
|
!!options.mediaCache &&
|
|
109
|
-
mediaType + ':' + uploadData.media.url
|
|
109
|
+
mediaType + ':' + uploadData.media.url;
|
|
110
110
|
if (mediaType === 'document' && !uploadData.fileName) {
|
|
111
|
-
uploadData.fileName =
|
|
111
|
+
uploadData.fileName = LIBRARY_NAME;
|
|
112
112
|
}
|
|
113
113
|
if (!uploadData.mimetype) {
|
|
114
114
|
uploadData.mimetype = MIMETYPE_MAP[mediaType];
|
|
@@ -123,13 +123,13 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
123
123
|
return obj;
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
const isNewsletter =
|
|
126
|
+
const isNewsletter = isJidNewsletter(options.jid);
|
|
127
127
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
|
|
128
128
|
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData.jpegThumbnail === 'undefined';
|
|
129
129
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true && typeof uploadData.waveform === 'undefined';
|
|
130
130
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
131
131
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation || requiresWaveformProcessing;
|
|
132
|
-
//
|
|
132
|
+
// Lia@Changes 06-02-26 --- Add few support for sending media to newsletter (≧▽≦)
|
|
133
133
|
if (isNewsletter) {
|
|
134
134
|
logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
|
|
135
135
|
const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
|
|
@@ -285,33 +285,36 @@ export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) =>
|
|
|
285
285
|
ephemeralMessage: {
|
|
286
286
|
message: {
|
|
287
287
|
protocolMessage: {
|
|
288
|
-
type:
|
|
288
|
+
type: ProtocolType.EPHEMERAL_SETTING,
|
|
289
289
|
ephemeralExpiration
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
};
|
|
294
|
-
return
|
|
294
|
+
return content;
|
|
295
295
|
};
|
|
296
|
-
//
|
|
296
|
+
// Lia@Changes 31-01-26 --- Extract product message into a standalone function so it can also be reused as the header for interactive messages
|
|
297
297
|
const prepareProductMessage = async (message, options) => {
|
|
298
298
|
if (!message.businessOwnerJid) {
|
|
299
299
|
throw new Boom('"businessOwnerJid" is missing from the content', { statusCode: 400 });
|
|
300
300
|
}
|
|
301
301
|
const { imageMessage } = await prepareWAMessageMedia({ image: message.image || message.product.productImage }, options);
|
|
302
|
-
//
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
302
|
+
// Lia@Changes 01-02-26 --- Add product message default value
|
|
303
|
+
const content = {
|
|
304
|
+
...message,
|
|
305
|
+
product: {
|
|
306
|
+
currencyCode: 'IDR',
|
|
307
|
+
priceAmount1000: 1000,
|
|
308
|
+
title: LIBRARY_NAME,
|
|
309
|
+
...message.product,
|
|
310
|
+
productImage: imageMessage
|
|
311
|
+
}
|
|
310
312
|
};
|
|
313
|
+
delete content.image;
|
|
311
314
|
return content;
|
|
312
315
|
};
|
|
313
316
|
/**
|
|
314
|
-
*
|
|
317
|
+
* Lia@Note 30-01-26
|
|
315
318
|
* ---
|
|
316
319
|
* Credits: Work on ensuring stickerPackMessage fields are valid by @jlucaso1 (https://github.com/jlucaso1).
|
|
317
320
|
* based on https://github.com/WhiskeySockets/Baileys/pull/1561
|
|
@@ -327,7 +330,7 @@ const prepareStickerPackMessage = async (message, options) => {
|
|
|
327
330
|
if (!cover) {
|
|
328
331
|
throw new Boom('Sticker pack must contain a cover', { statusCode: 400 });
|
|
329
332
|
}
|
|
330
|
-
//
|
|
333
|
+
// Lia@Changes 01-02-26 --- Add caching for sticker pack (similiar to prepareWAMessageMedia)
|
|
331
334
|
const cacheableKey = Array.isArray(stickers) &&
|
|
332
335
|
stickers.length &&
|
|
333
336
|
!!options.mediaCache &&
|
|
@@ -526,18 +529,18 @@ const prepareStickerPackMessage = async (message, options) => {
|
|
|
526
529
|
}
|
|
527
530
|
return WAProto.Message.StickerPackMessage.fromObject(content);
|
|
528
531
|
};
|
|
529
|
-
//
|
|
532
|
+
// Lia@Changes 30-01-26 --- Add native flow button helper for interactive message
|
|
530
533
|
const prepareNativeFlowButtons = (message) => {
|
|
531
|
-
const buttons = message.nativeFlow
|
|
534
|
+
const buttons = message.nativeFlow
|
|
532
535
|
const isButtonsFieldArray = Array.isArray(buttons);
|
|
533
536
|
const correctedField = isButtonsFieldArray ? buttons : buttons.buttons;
|
|
534
537
|
const messageParamsJson = {};
|
|
535
|
-
//
|
|
538
|
+
// Lia@Changes 31-01-26 --- Add offer and options inside interactive message
|
|
536
539
|
if (hasOptionalProperty(message, 'offerText') && !!message.offerText) {
|
|
537
540
|
Object.assign(messageParamsJson, {
|
|
538
541
|
limited_time_offer: {
|
|
539
542
|
text: message.offerText || LIBRARY_NAME,
|
|
540
|
-
url: message.offerUrl || DONATE_URL, //
|
|
543
|
+
url: message.offerUrl || DONATE_URL, // Lia@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
|
|
541
544
|
copy_code: message.offerCode,
|
|
542
545
|
expiration_time: message.offerExpiration
|
|
543
546
|
}
|
|
@@ -587,7 +590,6 @@ const prepareNativeFlowButtons = (message) => {
|
|
|
587
590
|
display_text: buttonText || '🌐 Visit',
|
|
588
591
|
url: button.url,
|
|
589
592
|
merchant_url: button.url,
|
|
590
|
-
webview_interaction: button.useWebview,
|
|
591
593
|
icon: buttonIcon
|
|
592
594
|
})
|
|
593
595
|
};
|
|
@@ -602,7 +604,7 @@ const prepareNativeFlowButtons = (message) => {
|
|
|
602
604
|
})
|
|
603
605
|
};
|
|
604
606
|
}
|
|
605
|
-
//
|
|
607
|
+
// Lia@Changes 12-03-26 --- Add "single_select" shortcut \(°o°)/
|
|
606
608
|
else if (hasOptionalProperty(button, 'sections') && !!button.sections) {
|
|
607
609
|
return {
|
|
608
610
|
name: 'single_select',
|
|
@@ -625,7 +627,7 @@ const prepareNativeFlowButtons = (message) => {
|
|
|
625
627
|
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
626
628
|
*/
|
|
627
629
|
export const generateForwardMessageContent = (message, forceForward) => {
|
|
628
|
-
let content = message.message;
|
|
630
|
+
let content = message.message || message;
|
|
629
631
|
if (!content) {
|
|
630
632
|
throw new Boom('no content in message', { statusCode: 400 });
|
|
631
633
|
}
|
|
@@ -673,35 +675,36 @@ export const hasOptionalProperty = (obj, key) => {
|
|
|
673
675
|
key in obj &&
|
|
674
676
|
obj[key] != null;
|
|
675
677
|
};
|
|
676
|
-
//
|
|
678
|
+
// Lia@Changes 06-02-26 --- Validate album message media to avoid bug 👀
|
|
677
679
|
export const hasValidAlbumMedia = (message) => {
|
|
678
|
-
return
|
|
679
|
-
message.videoMessage
|
|
680
|
+
return message.imageMessage ||
|
|
681
|
+
message.videoMessage;
|
|
680
682
|
};
|
|
681
683
|
export const hasValidInteractiveHeader = (message) => {
|
|
682
|
-
return
|
|
684
|
+
return message.imageMessage ||
|
|
683
685
|
message.videoMessage ||
|
|
684
686
|
message.documentMessage ||
|
|
685
687
|
message.productMessage ||
|
|
686
|
-
message.locationMessage
|
|
688
|
+
message.locationMessage;
|
|
687
689
|
};
|
|
688
|
-
//
|
|
690
|
+
// Lia@Changes 30-01-26 --- Validate carousel cards header to avoid bug 👀
|
|
689
691
|
export const hasValidCarouselHeader = (message) => {
|
|
690
|
-
return
|
|
692
|
+
return message.imageMessage ||
|
|
691
693
|
message.videoMessage ||
|
|
692
|
-
message.productMessage
|
|
694
|
+
message.productMessage;
|
|
693
695
|
};
|
|
694
696
|
export const generateWAMessageContent = async (message, options) => {
|
|
695
697
|
var _a, _b;
|
|
696
698
|
let m = {};
|
|
697
|
-
//
|
|
699
|
+
// Lia@Changes 30-01-26 --- Add "raw" boolean to send raw messages directly via generateWAMessage()
|
|
698
700
|
if (hasNonNullishProperty(message, 'raw')) {
|
|
699
701
|
delete message.raw;
|
|
700
702
|
return message;
|
|
701
703
|
}
|
|
702
|
-
//
|
|
704
|
+
// Lia@Changes 09-04-26 --- Add support for code block, latex, reels carousel, table with richResponseMessage
|
|
703
705
|
else if (hasNonNullishProperty(message, 'code') ||
|
|
704
|
-
hasNonNullishProperty(message, '
|
|
706
|
+
hasNonNullishProperty(message, 'expressions') ||
|
|
707
|
+
hasNonNullishProperty(message, 'items') ||
|
|
705
708
|
hasNonNullishProperty(message, 'table') ||
|
|
706
709
|
hasNonNullishProperty(message, 'richResponse')) {
|
|
707
710
|
m = prepareRichResponseMessage(message);
|
|
@@ -717,8 +720,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
717
720
|
extContent.jpegThumbnail = urlInfo.jpegThumbnail;
|
|
718
721
|
extContent.description = urlInfo.description;
|
|
719
722
|
extContent.title = urlInfo.title;
|
|
720
|
-
extContent.previewType =
|
|
721
|
-
extContent.linkPreviewMetadata = urlInfo.linkPreviewMetadata;
|
|
723
|
+
extContent.previewType = 0;
|
|
722
724
|
const img = urlInfo.highQualityThumbnail;
|
|
723
725
|
if (img) {
|
|
724
726
|
extContent.thumbnailDirectPath = img.directPath;
|
|
@@ -730,21 +732,6 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
730
732
|
extContent.thumbnailEncSha256 = img.fileEncSha256;
|
|
731
733
|
}
|
|
732
734
|
}
|
|
733
|
-
const faviconData = message.favicon;
|
|
734
|
-
if (faviconData && typeof options.upload === 'function') {
|
|
735
|
-
const { imageMessage } = await prepareWAMessageMedia({
|
|
736
|
-
image: faviconData
|
|
737
|
-
}, options);
|
|
738
|
-
extContent.faviconMMSMetadata = {
|
|
739
|
-
thumbnailDirectPath: imageMessage.directPath,
|
|
740
|
-
mediaKey: imageMessage.mediaKey,
|
|
741
|
-
mediaKeyTimestamp: imageMessage.mediaKeyTimestamp,
|
|
742
|
-
thumbnailWidth: 32,
|
|
743
|
-
thumbnailHeight: 32,
|
|
744
|
-
thumbnailSha256: imageMessage.fileSha256,
|
|
745
|
-
thumbnailEncSha256: imageMessage.fileEncSha256
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
735
|
if (options.backgroundColor) {
|
|
749
736
|
extContent.backgroundArgb = await assertColor(options.backgroundColor);
|
|
750
737
|
}
|
|
@@ -759,25 +746,25 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
759
746
|
throw new Boom('require atleast 1 contact', { statusCode: 400 });
|
|
760
747
|
}
|
|
761
748
|
if (contactLen === 1) {
|
|
762
|
-
m.contactMessage =
|
|
749
|
+
m.contactMessage = message.contacts.contacts[0];
|
|
763
750
|
}
|
|
764
751
|
else {
|
|
765
|
-
m.contactsArrayMessage =
|
|
752
|
+
m.contactsArrayMessage = message.contacts;
|
|
766
753
|
}
|
|
767
754
|
}
|
|
768
755
|
else if (hasNonNullishProperty(message, 'location')) {
|
|
769
|
-
m.locationMessage =
|
|
756
|
+
m.locationMessage = message.location;
|
|
770
757
|
}
|
|
771
758
|
else if (hasNonNullishProperty(message, 'react')) {
|
|
772
759
|
if (!message.react.senderTimestampMs) {
|
|
773
760
|
message.react.senderTimestampMs = Date.now();
|
|
774
761
|
}
|
|
775
|
-
m.reactionMessage =
|
|
762
|
+
m.reactionMessage = message.react;
|
|
776
763
|
}
|
|
777
764
|
else if (hasNonNullishProperty(message, 'delete')) {
|
|
778
765
|
m.protocolMessage = {
|
|
779
766
|
key: message.delete,
|
|
780
|
-
type:
|
|
767
|
+
type: ProtocolType.REVOKE
|
|
781
768
|
};
|
|
782
769
|
}
|
|
783
770
|
else if (hasNonNullishProperty(message, 'forward')) {
|
|
@@ -907,26 +894,27 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
907
894
|
statusCode: 400
|
|
908
895
|
});
|
|
909
896
|
}
|
|
897
|
+
m.messageContextInfo = {
|
|
898
|
+
// encKey
|
|
899
|
+
messageSecret: message.poll.messageSecret || randomBytes(32)
|
|
900
|
+
};
|
|
910
901
|
const pollCreationMessage = {
|
|
911
902
|
name: message.poll.name,
|
|
912
903
|
selectableOptionsCount: message.poll.selectableCount,
|
|
913
|
-
options: message.poll.values.map(optionName => ({ optionName }))
|
|
914
|
-
endTime: message.poll.endDate ? message.poll.endDate.getTime() : undefined,
|
|
915
|
-
hideParticipantName: message.poll.hideVoter ?? false,
|
|
916
|
-
allowAddOption: message.poll.canAddOption ?? false
|
|
904
|
+
options: message.poll.values.map(optionName => ({ optionName }))
|
|
917
905
|
};
|
|
918
906
|
if (message.poll.toAnnouncementGroup) {
|
|
919
907
|
// poll v2 is for community announcement groups (single select and multiple)
|
|
920
908
|
m.pollCreationMessageV2 = pollCreationMessage;
|
|
921
909
|
}
|
|
922
910
|
else {
|
|
923
|
-
//
|
|
924
|
-
if (message.poll.pollType
|
|
911
|
+
// Lia@Changes 08-02-26 --- Add quiz message support
|
|
912
|
+
if (message.poll.pollType == 1) {
|
|
925
913
|
if (!message.poll.correctAnswer) {
|
|
926
914
|
throw new Boom('No "correctAnswer" provided for quiz', { statusCode: 400 });
|
|
927
915
|
}
|
|
928
916
|
m.pollCreationMessageV5 = {
|
|
929
|
-
//
|
|
917
|
+
// Lia@Note 08-02-26 --- quiz for newsletter only
|
|
930
918
|
...pollCreationMessage,
|
|
931
919
|
correctAnswer: {
|
|
932
920
|
optionName: message.poll.correctAnswer.toString()
|
|
@@ -944,12 +932,8 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
944
932
|
m.pollCreationMessage = pollCreationMessage;
|
|
945
933
|
}
|
|
946
934
|
}
|
|
947
|
-
m.messageContextInfo = {
|
|
948
|
-
// encKey
|
|
949
|
-
messageSecret: message.poll.messageSecret || randomBytes(32)
|
|
950
|
-
};
|
|
951
935
|
}
|
|
952
|
-
//
|
|
936
|
+
// Lia@Changes 08-02-26 --- Add poll result snapshot message
|
|
953
937
|
else if (hasNonNullishProperty(message, 'pollResult')) {
|
|
954
938
|
const pollResultSnapshotMessage = {
|
|
955
939
|
name: message.pollResult.name,
|
|
@@ -958,7 +942,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
958
942
|
optionVoteCount: parseInt(vote.voteCount)
|
|
959
943
|
}))
|
|
960
944
|
};
|
|
961
|
-
if (message.pollResult.pollType
|
|
945
|
+
if (message.pollResult.pollType == 1) {
|
|
962
946
|
pollResultSnapshotMessage.pollType = proto.Message.PollType.QUIZ;
|
|
963
947
|
m.pollResultSnapshotMessageV3 = pollResultSnapshotMessage;
|
|
964
948
|
}
|
|
@@ -967,7 +951,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
967
951
|
m.pollResultSnapshotMessage = pollResultSnapshotMessage;
|
|
968
952
|
}
|
|
969
953
|
}
|
|
970
|
-
//
|
|
954
|
+
// Lia@Changes 08-02-26 --- Add poll update message
|
|
971
955
|
else if (hasNonNullishProperty(message, 'pollUpdate')) {
|
|
972
956
|
if (!message.pollUpdate.key) {
|
|
973
957
|
throw new Boom('Message key is required', { statusCode: 400 });
|
|
@@ -984,7 +968,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
984
968
|
}
|
|
985
969
|
else if (hasNonNullishProperty(message, 'sharePhoneNumber')) {
|
|
986
970
|
m.protocolMessage = {
|
|
987
|
-
type:
|
|
971
|
+
type: ProtocolType.SHARE_PHONE_NUMBER
|
|
988
972
|
};
|
|
989
973
|
}
|
|
990
974
|
else if (hasNonNullishProperty(message, 'requestPhoneNumber')) {
|
|
@@ -992,7 +976,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
992
976
|
}
|
|
993
977
|
else if (hasNonNullishProperty(message, 'limitSharing')) {
|
|
994
978
|
m.protocolMessage = {
|
|
995
|
-
type:
|
|
979
|
+
type: ProtocolType.LIMIT_SHARING,
|
|
996
980
|
limitSharing: {
|
|
997
981
|
sharingLimited: message.limitSharing === true,
|
|
998
982
|
trigger: 1,
|
|
@@ -1001,14 +985,14 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1001
985
|
}
|
|
1002
986
|
};
|
|
1003
987
|
}
|
|
1004
|
-
//
|
|
988
|
+
// Lia@Changes 01-02-26 --- Add payment invite message
|
|
1005
989
|
else if (hasNonNullishProperty(message, 'paymentInviteServiceType')) {
|
|
1006
990
|
m.paymentInviteMessage = {
|
|
1007
991
|
expiryTimestamp: Date.now(),
|
|
1008
992
|
serviceType: message.paymentInviteServiceType
|
|
1009
993
|
};
|
|
1010
994
|
}
|
|
1011
|
-
//
|
|
995
|
+
// Lia@Changes 01-02-26 --- Add order message
|
|
1012
996
|
else if (hasNonNullishProperty(message, 'orderText')) {
|
|
1013
997
|
if (!Buffer.isBuffer(message.thumbnail)) {
|
|
1014
998
|
throw new Boom('Must provide thumbnail buffer in order message', { statusCode: 400 });
|
|
@@ -1027,21 +1011,19 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1027
1011
|
};
|
|
1028
1012
|
delete m.orderMessage.orderText;
|
|
1029
1013
|
}
|
|
1030
|
-
//
|
|
1014
|
+
// Lia@Changes 31-01-26 --- Add support for album messages
|
|
1031
1015
|
else if (hasNonNullishProperty(message, 'album')) {
|
|
1032
1016
|
if (!Array.isArray(message.album)) {
|
|
1033
1017
|
throw new Boom('Invalid album type. Expected an array.', { statusCode: 400 });
|
|
1034
1018
|
}
|
|
1035
1019
|
let videoCount = 0;
|
|
1036
1020
|
for (let i = 0; i < message.album.length; i++) {
|
|
1037
|
-
if (message.album[i].video)
|
|
1038
|
-
|
|
1039
|
-
}
|
|
1021
|
+
if (message.album[i].video) videoCount++;
|
|
1022
|
+
};
|
|
1040
1023
|
let imageCount = 0;
|
|
1041
1024
|
for (let i = 0; i < message.album.length; i++) {
|
|
1042
|
-
if (message.album[i].image)
|
|
1043
|
-
|
|
1044
|
-
}
|
|
1025
|
+
if (message.album[i].image) imageCount++;
|
|
1026
|
+
};
|
|
1045
1027
|
if ((videoCount + imageCount) < 2) {
|
|
1046
1028
|
throw new Boom('Minimum provide 2 media to upload album message', { statusCode: 400 });
|
|
1047
1029
|
}
|
|
@@ -1053,11 +1035,11 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1053
1035
|
else {
|
|
1054
1036
|
m = await prepareWAMessageMedia(message, options);
|
|
1055
1037
|
}
|
|
1056
|
-
//
|
|
1038
|
+
// Lia@Changes 30-01-26 --- Add interactive messages (buttonsMessage, listMessage, interactiveMessage, templateMessage, and carouselMessage)
|
|
1057
1039
|
if (hasNonNullishProperty(message, 'buttons')) {
|
|
1058
1040
|
const buttonsMessage = {
|
|
1059
1041
|
buttons: message.buttons.map(button => {
|
|
1060
|
-
//
|
|
1042
|
+
// Lia@Changes 12-03-26 --- Add "single_select" shortcut!
|
|
1061
1043
|
const buttonText = button.text || button.buttonText;
|
|
1062
1044
|
if (hasOptionalProperty(button, 'sections')) {
|
|
1063
1045
|
return {
|
|
@@ -1115,7 +1097,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1115
1097
|
};
|
|
1116
1098
|
m = { listMessage };
|
|
1117
1099
|
}
|
|
1118
|
-
//
|
|
1100
|
+
// Lia@Note 03-02-26 --- This message type is shown on WhatsApp Web/Desktop and iOS (I guess 。◕‿◕。). On Android, it only appears in newsletter (so far ಥ‿ಥ)
|
|
1119
1101
|
else if (hasNonNullishProperty(message, 'templateButtons')) {
|
|
1120
1102
|
const hydratedTemplate = {
|
|
1121
1103
|
hydratedButtons: message.templateButtons.map((button, i) => {
|
|
@@ -1164,7 +1146,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1164
1146
|
if (hasOptionalProperty(message, 'footer')) {
|
|
1165
1147
|
hydratedTemplate.hydratedFooterText = message.footer;
|
|
1166
1148
|
}
|
|
1167
|
-
hydratedTemplate.templateId = message.id || 'template-' + Date.now(); //
|
|
1149
|
+
hydratedTemplate.templateId = message.id || 'template-' + Date.now(); // Lia@Note 04-02-26 --- Minimal templateId to satisfy WhatsApp ( ꈍᴗꈍ)
|
|
1168
1150
|
m = {
|
|
1169
1151
|
templateMessage: {
|
|
1170
1152
|
hydratedFourRowTemplate: hydratedTemplate,
|
|
@@ -1236,9 +1218,9 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1236
1218
|
else {
|
|
1237
1219
|
carouselHeader = await prepareWAMessageMedia(card, options).catch(() => ({ }));
|
|
1238
1220
|
}
|
|
1239
|
-
const isValidHeader = hasValidCarouselHeader(carouselHeader)
|
|
1221
|
+
const isValidHeader = hasValidCarouselHeader(carouselHeader)
|
|
1240
1222
|
if (!isValidHeader) {
|
|
1241
|
-
|
|
1223
|
+
throw new Boom('Invalid media type for carousel card', { statusCode: 400 });
|
|
1242
1224
|
}
|
|
1243
1225
|
const carouselCard = {
|
|
1244
1226
|
nativeFlowMessage: prepareNativeFlowButtons(card.nativeFlow ? card : [])
|
|
@@ -1261,11 +1243,11 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1261
1243
|
Object.assign(carouselCard.header, carouselHeader);
|
|
1262
1244
|
}
|
|
1263
1245
|
if (hasOptionalProperty(card, 'audioFooter')) {
|
|
1264
|
-
const
|
|
1246
|
+
const parseFooter = await prepareWAMessageMedia({
|
|
1265
1247
|
audio: card.audioFooter
|
|
1266
1248
|
}, options);
|
|
1267
1249
|
carouselCard.footer = {
|
|
1268
|
-
audioMessage,
|
|
1250
|
+
audioMessage: parseFooter.audioMessage,
|
|
1269
1251
|
hasMediaAttachment: true
|
|
1270
1252
|
};
|
|
1271
1253
|
}
|
|
@@ -1286,7 +1268,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1286
1268
|
}
|
|
1287
1269
|
m = { interactiveMessage };
|
|
1288
1270
|
}
|
|
1289
|
-
//
|
|
1271
|
+
// Lia@Changes 01-02-26 --- Add request payment message
|
|
1290
1272
|
else if (hasNonNullishProperty(message, 'requestPaymentFrom')) {
|
|
1291
1273
|
const requestPaymentMessage = {
|
|
1292
1274
|
amount: {
|
|
@@ -1310,7 +1292,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1310
1292
|
}
|
|
1311
1293
|
m = { requestPaymentMessage };
|
|
1312
1294
|
}
|
|
1313
|
-
//
|
|
1295
|
+
// Lia@Changes 01-02-26 --- Add invoice message
|
|
1314
1296
|
else if (hasNonNullishProperty(message, 'invoiceNote')) {
|
|
1315
1297
|
const attachment = m.imageMessage || m.documentMessage;
|
|
1316
1298
|
const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
|
|
@@ -1336,7 +1318,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1336
1318
|
}
|
|
1337
1319
|
m = { invoiceMessage };
|
|
1338
1320
|
}
|
|
1339
|
-
//
|
|
1321
|
+
// Lia@Changes 31-01-26 --- Add direct externalAdReply access (no need to create contextInfo first)
|
|
1340
1322
|
if (hasOptionalProperty(message, 'externalAdReply') && !!message.externalAdReply) {
|
|
1341
1323
|
const messageType = Object.keys(m)[0];
|
|
1342
1324
|
const key = m[messageType];
|
|
@@ -1345,7 +1327,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1345
1327
|
throw new Boom('Thumbnail must in buffer type', { statusCode: 400 });
|
|
1346
1328
|
}
|
|
1347
1329
|
if (!content.url || typeof content.url !== 'string') {
|
|
1348
|
-
content.url = DONATE_URL; //
|
|
1330
|
+
content.url = DONATE_URL; // Lia@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
|
|
1349
1331
|
}
|
|
1350
1332
|
const externalAdReply = {
|
|
1351
1333
|
...content,
|
|
@@ -1353,9 +1335,9 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1353
1335
|
mediaType: content.mediaType || 1,
|
|
1354
1336
|
mediaUrl: content.url,
|
|
1355
1337
|
renderLargerThumbnail: content.largeThumbnail,
|
|
1356
|
-
sourceUrl: content.url,
|
|
1338
|
+
sourceUrl: content.url + '?update=' + Date.now(),
|
|
1357
1339
|
thumbnail: content.thumbnail,
|
|
1358
|
-
thumbnailUrl: content.url
|
|
1340
|
+
thumbnailUrl: content.url,
|
|
1359
1341
|
title: content.title || LIBRARY_NAME
|
|
1360
1342
|
};
|
|
1361
1343
|
delete externalAdReply.subTitle;
|
|
@@ -1372,21 +1354,18 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1372
1354
|
(hasOptionalProperty(message, 'mentionAll') && message.mentionAll)) {
|
|
1373
1355
|
const messageType = Object.keys(m)[0];
|
|
1374
1356
|
const key = m[messageType];
|
|
1375
|
-
if (
|
|
1376
|
-
key.contextInfo =
|
|
1377
|
-
if (message.mentions?.length) {
|
|
1378
|
-
key.contextInfo.mentionedJid = message.mentions;
|
|
1379
|
-
}
|
|
1380
|
-
if (message.mentionAll) {
|
|
1381
|
-
key.contextInfo.nonJidMentions = 1;
|
|
1382
|
-
}
|
|
1357
|
+
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1358
|
+
key.contextInfo.mentionedJid = message.mentions || [];
|
|
1383
1359
|
}
|
|
1384
1360
|
else if (key) {
|
|
1385
1361
|
key.contextInfo = {
|
|
1386
|
-
mentionedJid: message.mentions
|
|
1387
|
-
nonJidMentions: message.mentionAll ? 1 : 0
|
|
1362
|
+
mentionedJid: message.mentions || []
|
|
1388
1363
|
};
|
|
1389
1364
|
}
|
|
1365
|
+
if (message.mentionAll) {
|
|
1366
|
+
key.contextInfo.mentionedJid = [];
|
|
1367
|
+
key.contextInfo.nonJidMentions = 1;
|
|
1368
|
+
}
|
|
1390
1369
|
}
|
|
1391
1370
|
if (hasOptionalProperty(message, 'contextInfo') && !!message.contextInfo) {
|
|
1392
1371
|
const messageType = Object.keys(m)[0];
|
|
@@ -1398,7 +1377,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1398
1377
|
key.contextInfo = message.contextInfo;
|
|
1399
1378
|
}
|
|
1400
1379
|
}
|
|
1401
|
-
//
|
|
1380
|
+
// Lia@Changes 31-01-26 --- Add "groupStatus" boolean to set contextInfo.isGroupStatus and wrap message into groupStatusMessageV2
|
|
1402
1381
|
if (hasOptionalProperty(message, 'groupStatus') && !!message.groupStatus) {
|
|
1403
1382
|
const messageType = Object.keys(m)[0];
|
|
1404
1383
|
const key = m[messageType];
|
|
@@ -1413,35 +1392,20 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1413
1392
|
m = { groupStatusMessageV2: { message: m } };
|
|
1414
1393
|
delete message.groupStatus;
|
|
1415
1394
|
}
|
|
1416
|
-
//
|
|
1417
|
-
if (hasOptionalProperty(message, 'spoiler') && !!message.spoiler) {
|
|
1418
|
-
const messageType = Object.keys(m)[0];
|
|
1419
|
-
const key = m[messageType];
|
|
1420
|
-
if ('contextInfo' in key && !!key.contextInfo) {
|
|
1421
|
-
key.contextInfo.isSpoiler = message.spoiler;
|
|
1422
|
-
}
|
|
1423
|
-
else if (key) {
|
|
1424
|
-
key.contextInfo = {
|
|
1425
|
-
isSpoiler: message.spoiler
|
|
1426
|
-
};
|
|
1427
|
-
}
|
|
1428
|
-
m = { spoilerMessage: { message: m } };
|
|
1429
|
-
delete message.spoiler;
|
|
1430
|
-
}
|
|
1431
|
-
// crysnovax@Changes 02-02-26 --- Add "interactiveAsTemplate" boolean to wrap interactiveMessage into templateMessage
|
|
1395
|
+
// Lia@Changes 02-02-26 --- Add "interactiveAsTemplate" boolean to wrap interactiveMessage into templateMessage
|
|
1432
1396
|
else if (hasOptionalProperty(message, 'interactiveAsTemplate') && !!message.interactiveAsTemplate) {
|
|
1433
1397
|
if (!m.interactiveMessage) {
|
|
1434
|
-
throw new Boom('Invalid message type for template', { statusCode: 400 }); //
|
|
1398
|
+
throw new Boom('Invalid message type for template', { statusCode: 400 }); // Lia@Note 02-02-26 --- To avoid bug 👀
|
|
1435
1399
|
}
|
|
1436
1400
|
m = {
|
|
1437
1401
|
templateMessage: {
|
|
1438
1402
|
interactiveMessageTemplate: m.interactiveMessage,
|
|
1439
|
-
templateId: message.id || 'template-' + Date.now() //
|
|
1403
|
+
templateId: message.id || 'template-' + Date.now() // Lia@Note 04-02-26 --- Minimal templateId to satisfy WhatsApp ( ꈍᴗꈍ)
|
|
1440
1404
|
}
|
|
1441
1405
|
};
|
|
1442
1406
|
delete message.interactiveAsTemplate;
|
|
1443
1407
|
}
|
|
1444
|
-
//
|
|
1408
|
+
// Lia@Changes 30-01-26 --- Add "ephemeral" boolean to wrap message into ephemeralMessage like "viewOnce"
|
|
1445
1409
|
if (hasOptionalProperty(message, 'ephemeral') && !!message.ephemeral) {
|
|
1446
1410
|
m = { ephemeralMessage: { message: m } };
|
|
1447
1411
|
delete message.ephemeral;
|
|
@@ -1449,12 +1413,12 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1449
1413
|
else if (hasOptionalProperty(message, 'viewOnce') && !!message.viewOnce) {
|
|
1450
1414
|
m = { viewOnceMessage: { message: m } };
|
|
1451
1415
|
}
|
|
1452
|
-
//
|
|
1416
|
+
// Lia@Changes 03-02-26 --- Add "viewOnceV2" boolean to wrap message into viewOnceMessageV2 like "viewOnce"
|
|
1453
1417
|
else if (hasOptionalProperty(message, 'viewOnceV2') && !!message.viewOnceV2) {
|
|
1454
1418
|
m = { viewOnceMessageV2: { message: m } };
|
|
1455
1419
|
delete message.viewOnceV2;
|
|
1456
1420
|
}
|
|
1457
|
-
//
|
|
1421
|
+
// Lia@Changes 03-02-26 --- Add "viewOnceV2Extension" boolean to wrap message into viewOnceMessageV2Extension like "viewOnce"
|
|
1458
1422
|
else if (hasOptionalProperty(message, 'viewOnceV2Extension') && !!message.viewOnceV2Extension) {
|
|
1459
1423
|
m = { viewOnceMessageV2Extension: { message: m } };
|
|
1460
1424
|
delete message.viewOnceV2Extension;
|
|
@@ -1465,7 +1429,7 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1465
1429
|
key: message.edit,
|
|
1466
1430
|
editedMessage: m,
|
|
1467
1431
|
timestampMs: Date.now(),
|
|
1468
|
-
type:
|
|
1432
|
+
type: ProtocolType.MESSAGE_EDIT
|
|
1469
1433
|
}
|
|
1470
1434
|
}
|
|
1471
1435
|
}
|
|
@@ -1475,13 +1439,13 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
1475
1439
|
m.messageContextInfo.messageSecret = randomBytes(32);
|
|
1476
1440
|
}
|
|
1477
1441
|
}
|
|
1478
|
-
return
|
|
1442
|
+
return proto.Message.create(m);
|
|
1479
1443
|
};
|
|
1480
1444
|
export const generateWAMessageFromContent = (jid, message, options) => {
|
|
1481
1445
|
// set timestamp to now
|
|
1482
1446
|
// if not specified
|
|
1483
1447
|
if (!options.timestamp) {
|
|
1484
|
-
options.timestamp =
|
|
1448
|
+
options.timestamp = Date.now();
|
|
1485
1449
|
}
|
|
1486
1450
|
const messageContextInfo = message.messageContextInfo
|
|
1487
1451
|
const innerMessage = normalizeMessageContent(message);
|
|
@@ -1531,7 +1495,7 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1531
1495
|
//ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
|
|
1532
1496
|
};
|
|
1533
1497
|
}
|
|
1534
|
-
//
|
|
1498
|
+
// Lia@Changes 30-01-26 --- Add deviceListMetadata inside messageContextInfo for private chat
|
|
1535
1499
|
if (messageContextInfo?.messageSecret && (isPnUser(jid) || isLidUser(jid))) {
|
|
1536
1500
|
messageContextInfo.deviceListMetadata = {
|
|
1537
1501
|
recipientKeyHash: randomBytes(10),
|
|
@@ -1539,7 +1503,7 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1539
1503
|
};
|
|
1540
1504
|
messageContextInfo.deviceListMetadataVersion = 2
|
|
1541
1505
|
}
|
|
1542
|
-
message =
|
|
1506
|
+
message = proto.Message.create(message);
|
|
1543
1507
|
const messageJSON = {
|
|
1544
1508
|
key: {
|
|
1545
1509
|
remoteJid: jid,
|
|
@@ -1554,11 +1518,11 @@ export const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
1554
1518
|
};
|
|
1555
1519
|
return WAProto.WebMessageInfo.fromObject(messageJSON);
|
|
1556
1520
|
};
|
|
1557
|
-
export const generateWAMessage = async (jid, content, options) => {
|
|
1521
|
+
export const generateWAMessage = async (jid, content, options = {}) => {
|
|
1558
1522
|
// ensure msg ID is with every log
|
|
1559
1523
|
options.logger = options?.logger?.child({ msgId: options.messageId });
|
|
1560
1524
|
// Pass jid in the options to generateWAMessageContent
|
|
1561
|
-
if (jid) {
|
|
1525
|
+
if (jid && typeof options === 'object') {
|
|
1562
1526
|
options.jid = jid;
|
|
1563
1527
|
}
|
|
1564
1528
|
return generateWAMessageFromContent(jid, await generateWAMessageContent(content, options), options);
|
|
@@ -1590,7 +1554,7 @@ export const normalizeMessageContent = (content) => {
|
|
|
1590
1554
|
content = inner.message;
|
|
1591
1555
|
}
|
|
1592
1556
|
return content;
|
|
1593
|
-
//
|
|
1557
|
+
// Lia@Changes 03-02-26 --- Add all futureProofMessage into getFutureProofMessage()
|
|
1594
1558
|
function getFutureProofMessage(message) {
|
|
1595
1559
|
return (
|
|
1596
1560
|
message?.associatedChildMessage ||
|
|
@@ -1607,14 +1571,10 @@ export const normalizeMessageContent = (content) => {
|
|
|
1607
1571
|
message?.groupStatusMessageV2 ||
|
|
1608
1572
|
message?.limitSharingMessage ||
|
|
1609
1573
|
message?.lottieStickerMessage ||
|
|
1610
|
-
message?.newsletterAdminProfileMessage ||
|
|
1611
|
-
message?.newsletterAdminProfileMessageV2 ||
|
|
1612
|
-
message?.newsletterAdminProfileStatusMessage ||
|
|
1613
1574
|
message?.pollCreationMessageV4 ||
|
|
1614
1575
|
message?.pollCreationOptionImageMessage ||
|
|
1615
1576
|
message?.questionMessage ||
|
|
1616
1577
|
message?.questionReplyMessage ||
|
|
1617
|
-
message?.spoilerMessage ||
|
|
1618
1578
|
message?.statusAddYours ||
|
|
1619
1579
|
message?.statusMentionMessage ||
|
|
1620
1580
|
message?.viewOnceMessage ||
|
|
@@ -1912,14 +1872,20 @@ const isWebPBuffer = (buffer) => {
|
|
|
1912
1872
|
);
|
|
1913
1873
|
};
|
|
1914
1874
|
/**
|
|
1915
|
-
*
|
|
1875
|
+
* Lia@Changes 30-01-26
|
|
1916
1876
|
* ---
|
|
1917
1877
|
* Determines whether a message should include a Biz Binary Node.
|
|
1918
1878
|
* A Biz Binary Node is added only for interactive messages
|
|
1919
1879
|
* such as buttons or other supported interactive types.
|
|
1920
1880
|
*/
|
|
1921
|
-
export const shouldIncludeBizBinaryNode = (message) =>
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
message.interactiveMessage.
|
|
1881
|
+
export const shouldIncludeBizBinaryNode = (message) => {
|
|
1882
|
+
const hasValidInteractive =
|
|
1883
|
+
message.interactiveMessage &&
|
|
1884
|
+
!message.interactiveMessage.carouselMessage &&
|
|
1885
|
+
!message.interactiveMessage.collectionMessage &&
|
|
1886
|
+
!message.interactiveMessage.shopStorefrontMessage;
|
|
1887
|
+
return (message.buttonsMessage ||
|
|
1888
|
+
message.interactiveMessage ||
|
|
1889
|
+
message.listMessage ||
|
|
1890
|
+
hasValidInteractive);
|
|
1891
|
+
};
|