@realvare/based 2.7.61 → 2.7.70

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.
Files changed (42) hide show
  1. package/README.MD +25 -114
  2. package/WAProto/WAProto.proto +1073 -244
  3. package/WAProto/index.d.ts +16282 -8183
  4. package/WAProto/index.js +76605 -50628
  5. package/engine-requirements.js +10 -10
  6. package/lib/Defaults/baileys-version.json +1 -1
  7. package/lib/Defaults/index.d.ts +1 -1
  8. package/lib/Defaults/index.js +5 -5
  9. package/lib/Socket/chats.js +53 -16
  10. package/lib/Socket/groups.js +53 -9
  11. package/lib/Socket/messages-recv.js +1298 -1237
  12. package/lib/Socket/messages-send.js +350 -456
  13. package/lib/Socket/socket.js +1 -1
  14. package/lib/Socket/usync.js +57 -4
  15. package/lib/Store/make-in-memory-store.js +28 -15
  16. package/lib/Types/Message.d.ts +316 -6
  17. package/lib/Types/Message.js +1 -1
  18. package/lib/Utils/cache-manager.d.ts +16 -0
  19. package/lib/Utils/cache-manager.js +20 -4
  20. package/lib/Utils/chat-utils.js +17 -13
  21. package/lib/Utils/decode-wa-message.js +1 -11
  22. package/lib/Utils/event-buffer.js +103 -2
  23. package/lib/Utils/generics.js +4 -5
  24. package/lib/Utils/index.d.ts +5 -0
  25. package/lib/Utils/index.js +3 -0
  26. package/lib/Utils/jid-validation.d.ts +2 -0
  27. package/lib/Utils/jid-validation.js +36 -5
  28. package/lib/Utils/link-preview.js +38 -28
  29. package/lib/Utils/messages-media.js +21 -52
  30. package/lib/Utils/messages.js +540 -23
  31. package/lib/Utils/performance-config.d.ts +2 -0
  32. package/lib/Utils/performance-config.js +16 -7
  33. package/lib/Utils/process-message.js +124 -12
  34. package/lib/Utils/rate-limiter.js +15 -20
  35. package/lib/WABinary/jid-utils.js +257 -5
  36. package/lib/WAUSync/Protocols/USyncContactProtocol.js +75 -5
  37. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +59 -6
  38. package/lib/WAUSync/USyncQuery.js +64 -6
  39. package/lib/index.d.ts +1 -0
  40. package/lib/index.js +5 -2
  41. package/package.json +7 -13
  42. package/WAProto/index.ts.ts +0 -53473
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = exports.updateMessageWithPollUpdate = exports.updateMessageWithReaction = exports.updateMessageWithReceipt = exports.getDevice = exports.extractMessageContent = exports.normalizeMessageContent = exports.getContentType = exports.generateWAMessage = exports.generateWAMessageFromContent = exports.generateWAMessageContent = exports.generateForwardMessageContent = exports.prepareDisappearingMessageSettingContent = exports.prepareWAMessageMedia = exports.generateLinkPreviewIfRequired = exports.extractUrlFromText = void 0;
6
+ exports.clearCache = exports.getCacheStats = exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = exports.updateMessageWithPollUpdate = exports.updateMessageWithReaction = exports.updateMessageWithReceipt = exports.getDevice = exports.extractMessageContent = exports.normalizeMessageContent = exports.getContentType = exports.generateWAMessage = exports.generateWAMessageFromContent = exports.generateWAMessageContent = exports.generateForwardMessageContent = exports.prepareDisappearingMessageSettingContent = exports.prepareWAMessageMedia = exports.generateLinkPreviewIfRequired = exports.extractUrlFromText = void 0;
7
7
  exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage;
8
8
  const boom_1 = require("@hapi/boom");
9
9
  const axios_1 = __importDefault(require("axios"));
@@ -117,7 +117,6 @@ const prepareWAMessageMedia = async (message, options) => {
117
117
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
118
118
  opts: options.options
119
119
  });
120
- // url safe Base64 encode the SHA256 hash of the body
121
120
  const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
122
121
  const [{ mediaUrl, directPath, handle }] = await Promise.all([
123
122
  (async () => {
@@ -361,25 +360,85 @@ const generateWAMessageContent = async (message, options) => {
361
360
  m.groupInviteMessage.caption = message.groupInvite.text;
362
361
  m.groupInviteMessage.groupJid = message.groupInvite.jid;
363
362
  m.groupInviteMessage.groupName = message.groupInvite.subject;
364
- //TODO: use built-in interface and get disappearing mode info etc.
365
- //TODO: cache / use store!?
363
+
364
+ // Get group metadata to obtain disappearing mode and other group info
365
+ if (options.groupMetadata) {
366
+ try {
367
+ const groupMetadata = await options.groupMetadata(message.groupInvite.jid);
368
+ if (groupMetadata) {
369
+ // Add disappearing mode info if available
370
+ if (groupMetadata.ephemeralDuration !== undefined) {
371
+ m.groupInviteMessage.ephemeralDuration = groupMetadata.ephemeralDuration;
372
+ }
373
+ // Add group subject from metadata if not provided in message
374
+ if (!m.groupInviteMessage.groupName && groupMetadata.subject) {
375
+ m.groupInviteMessage.groupName = groupMetadata.subject;
376
+ }
377
+ // Add group participant count
378
+ if (groupMetadata.participants) {
379
+ m.groupInviteMessage.groupSize = groupMetadata.participants.length;
380
+ }
381
+ }
382
+ } catch (error) {
383
+ options.logger?.debug({ error, jid: message.groupInvite.jid }, 'Failed to fetch group metadata for invite');
384
+ }
385
+ }
386
+
387
+ // Handle profile picture with caching
366
388
  if (options.getProfilePicUrl) {
367
- const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
368
- if (pfpUrl) {
369
- const resp = await axios_1.default.get(pfpUrl, { responseType: 'arraybuffer' });
370
- if (resp.status === 200) {
371
- m.groupInviteMessage.jpegThumbnail = resp.data;
389
+ const cacheKey = `group_pfp:${message.groupInvite.jid}`;
390
+
391
+ // Check cache first if available
392
+ if (options.cache && options.cache.get) {
393
+ const cachedPfp = options.cache.get(cacheKey);
394
+ if (cachedPfp) {
395
+ m.groupInviteMessage.jpegThumbnail = cachedPfp;
396
+ }
397
+ }
398
+
399
+ // Fetch if not in cache
400
+ if (!m.groupInviteMessage.jpegThumbnail) {
401
+ try {
402
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
403
+ if (pfpUrl) {
404
+ const resp = await axios_1.default.get(pfpUrl, {
405
+ responseType: 'arraybuffer',
406
+ timeout: 5000,
407
+ headers: {
408
+ 'User-Agent': 'WhatsApp/2.23.20.15 iOS/16.0 Device/iPhone'
409
+ }
410
+ });
411
+ if (resp.status === 200) {
412
+ m.groupInviteMessage.jpegThumbnail = resp.data;
413
+
414
+ // Cache the result if cache is available
415
+ if (options.cache && options.cache.set) {
416
+ options.cache.set(cacheKey, resp.data, 3600); // Cache for 1 hour
417
+ }
418
+ }
419
+ }
420
+ } catch (error) {
421
+ options.logger?.debug({ error, jid: message.groupInvite.jid }, 'Failed to fetch group profile picture');
372
422
  }
373
423
  }
374
424
  }
375
425
  }
376
426
  else if ('pin' in message) {
377
- m.pinInChatMessage = {};
378
- m.messageContextInfo = {};
379
- m.pinInChatMessage.key = message.pin;
380
- m.pinInChatMessage.type = message.type;
381
- m.pinInChatMessage.senderTimestampMs = Date.now();
382
- m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
427
+ const pinData = typeof message.pin === 'object' ? message.pin : { key: message.pin };
428
+ // Map type: 1 = PIN_FOR_ALL, 2 = UNPIN_FOR_ALL
429
+ const pinType = pinData.type !== undefined ? pinData.type : (message.type !== undefined ? message.type : WAProto_1.proto.Message.PinInChatMessage.Type.PIN_FOR_ALL);
430
+ m.pinInChatMessage = {
431
+ key: pinData.key,
432
+ type: pinType,
433
+ senderTimestampMs: Date.now()
434
+ };
435
+ // Add messageContextInfo only for PIN (type 1), not for UNPIN (type 2)
436
+ if (pinType === WAProto_1.proto.Message.PinInChatMessage.Type.PIN_FOR_ALL) {
437
+ m.messageContextInfo = {
438
+ messageAddOnDurationInSecs: pinData.time || message.time || 86400, // Default 24 hours
439
+ messageAddOnExpiryType: WAProto_1.proto.MessageContextInfo.MessageAddonExpiryType.STATIC
440
+ };
441
+ }
383
442
  }
384
443
  else if ('keep' in message) {
385
444
  m.keepInChatMessage = {};
@@ -409,6 +468,7 @@ const generateWAMessageContent = async (message, options) => {
409
468
  selectedDisplayText: message.buttonReply.displayText,
410
469
  selectedId: message.buttonReply.id,
411
470
  selectedIndex: message.buttonReply.index,
471
+ selectedCarouselCardIndex: message.buttonReply.carouselCardIndex
412
472
  };
413
473
  break;
414
474
  case 'plain':
@@ -486,12 +546,262 @@ const generateWAMessageContent = async (message, options) => {
486
546
  }
487
547
  }
488
548
  }
549
+ else if ('pollResultSnapshotV3' in message && !!message.pollResultSnapshotV3) {
550
+ m.pollResultSnapshotMessageV3 = {
551
+ pollCreationMessageKey: message.pollResultSnapshotV3.pollCreationMessageKey,
552
+ pollResult: message.pollResultSnapshotV3.pollResult,
553
+ selectedOptions: message.pollResultSnapshotV3.selectedOptions,
554
+ contextInfo: message.pollResultSnapshotV3.contextInfo,
555
+ pollType: message.pollResultSnapshotV3.pollType
556
+ };
557
+ }
558
+ else if ('pollV4' in message) {
559
+ const pollCreationMessage = {
560
+ name: message.pollV4.name,
561
+ selectableOptionsCount: message.pollV4.selectableCount,
562
+ options: message.pollV4.values.map(optionName => ({ optionName })),
563
+ pollType: message.pollV4.pollType
564
+ };
565
+ m.pollCreationMessageV4 = pollCreationMessage;
566
+ }
567
+ else if ('pollV5' in message) {
568
+ const pollCreationMessage = {
569
+ name: message.pollV5.name,
570
+ selectableOptionsCount: message.pollV5.selectableCount,
571
+ options: message.pollV5.values.map(optionName => ({ optionName })),
572
+ pollType: message.pollV5.pollType
573
+ };
574
+ m.pollCreationMessageV5 = pollCreationMessage;
575
+ }
489
576
  else if ('event' in message) {
490
577
  m.messageContextInfo = {
491
578
  messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32),
492
579
  };
493
580
  m.eventMessage = { ...message.event };
494
581
  }
582
+ else if ('comment' in message) {
583
+ m.commentMessage = {
584
+ message: message.comment.message,
585
+ targetMessageKey: message.comment.targetMessageKey
586
+ };
587
+ }
588
+ else if ('question' in message) {
589
+ m.questionMessage = {
590
+ text: message.question.text,
591
+ contextInfo: message.question.contextInfo
592
+ };
593
+ }
594
+ else if ('questionResponse' in message) {
595
+ m.questionResponseMessage = {
596
+ key: message.questionResponse.key,
597
+ text: message.questionResponse.text
598
+ };
599
+ }
600
+ else if ('statusQuestionAnswer' in message) {
601
+ m.statusQuestionAnswerMessage = {
602
+ key: message.statusQuestionAnswer.key,
603
+ text: message.statusQuestionAnswer.text
604
+ };
605
+ }
606
+ else if ('statusQuoted' in message) {
607
+ m.statusQuotedMessage = {
608
+ type: message.statusQuoted.type,
609
+ text: message.statusQuoted.text,
610
+ thumbnail: message.statusQuoted.thumbnail,
611
+ originalStatusId: message.statusQuoted.originalStatusId
612
+ };
613
+ }
614
+ else if ('statusStickerInteraction' in message) {
615
+ m.statusStickerInteractionMessage = {
616
+ key: message.statusStickerInteraction.key,
617
+ stickerKey: message.statusStickerInteraction.stickerKey,
618
+ type: message.statusStickerInteraction.type
619
+ };
620
+ }
621
+ else if ('richResponse' in message) {
622
+ m.richResponseMessage = {
623
+ messageType: message.richResponse.messageType !== undefined ? message.richResponse.messageType : 1, // AI_RICH_RESPONSE_TYPE_STANDARD
624
+ submessages: message.richResponse.submessages || [],
625
+ unifiedResponse: message.richResponse.unifiedResponse,
626
+ contextInfo: message.richResponse.contextInfo
627
+ };
628
+ }
629
+ else if ('eventResponse' in message && !!message.eventResponse) {
630
+ m.eventResponseMessage = {
631
+ response: message.eventResponse.response, // GOING = 1, NOT_GOING = 2, MAYBE = 3
632
+ timestampMs: message.eventResponse.timestampMs || Date.now(),
633
+ extraGuestCount: message.eventResponse.extraGuestCount
634
+ };
635
+ }
636
+ else if ('statusMention' in message && !!message.statusMention) {
637
+ m.statusMentionMessage = {
638
+ quotedStatus: message.statusMention.quotedStatus
639
+ };
640
+ }
641
+ else if ('groupStatus' in message && !!message.groupStatus) {
642
+ m.groupStatusMessage = message.groupStatus.message;
643
+ }
644
+ else if ('botTask' in message && !!message.botTask) {
645
+ m.botTaskMessage = message.botTask.message;
646
+ }
647
+ else if ('limitSharing' in message && !!message.limitSharing) {
648
+ m.limitSharingMessage = message.limitSharing.message;
649
+ }
650
+ else if ('statusAddYours' in message && !!message.statusAddYours) {
651
+ m.statusAddYours = message.statusAddYours.message;
652
+ }
653
+ else if ('botForwarded' in message && !!message.botForwarded) {
654
+ m.botForwardedMessage = message.botForwarded.message;
655
+ }
656
+ else if ('eventCoverImage' in message && !!message.eventCoverImage) {
657
+ m.eventCoverImage = message.eventCoverImage.message;
658
+ }
659
+ else if ('stickerPack' in message && !!message.stickerPack) {
660
+ const pack = message.stickerPack;
661
+ const stickerPackMessage = {
662
+ name: pack.name,
663
+ publisher: pack.publisher,
664
+ packDescription: pack.description,
665
+ stickerPackId: pack.stickerPackId || (0, crypto_1.randomBytes)(16).toString('hex'),
666
+ stickerPackOrigin: pack.origin || 2 // USER_CREATED = 2
667
+ };
668
+ // Process cover if provided
669
+ if (pack.cover) {
670
+ const coverMedia = await (0, exports.prepareWAMessageMedia)({ image: pack.cover }, options);
671
+ stickerPackMessage.thumbnailDirectPath = coverMedia.imageMessage.directPath;
672
+ stickerPackMessage.thumbnailSha256 = coverMedia.imageMessage.thumbnailSha256;
673
+ stickerPackMessage.thumbnailEncSha256 = coverMedia.imageMessage.thumbnailEncSha256;
674
+ stickerPackMessage.thumbnailHeight = coverMedia.imageMessage.height;
675
+ stickerPackMessage.thumbnailWidth = coverMedia.imageMessage.width;
676
+ }
677
+ // Process stickers
678
+ if (pack.stickers && pack.stickers.length > 0) {
679
+ const processedStickers = await Promise.all(pack.stickers.map(async (sticker) => {
680
+ const stickerMedia = await (0, exports.prepareWAMessageMedia)({ sticker: sticker.sticker }, options);
681
+ return {
682
+ fileName: sticker.fileName || `sticker_${Date.now()}.webp`,
683
+ isAnimated: sticker.isAnimated || false,
684
+ emojis: sticker.emojis || [],
685
+ accessibilityLabel: sticker.accessibilityLabel,
686
+ isLottie: sticker.isLottie || false,
687
+ mimetype: sticker.mimetype || stickerMedia.stickerMessage.mimetype
688
+ };
689
+ }));
690
+ stickerPackMessage.stickers = processedStickers;
691
+ stickerPackMessage.stickerPackSize = processedStickers.length;
692
+ }
693
+ if (pack.caption) {
694
+ stickerPackMessage.caption = pack.caption;
695
+ }
696
+ m.stickerPackMessage = stickerPackMessage;
697
+ }
698
+ else if ('interactiveResponse' in message && !!message.interactiveResponse) {
699
+ const response = message.interactiveResponse;
700
+ const interactiveResponseMessage = {
701
+ body: {
702
+ text: response.body?.text || '',
703
+ format: response.body?.format || 0 // DEFAULT = 0
704
+ }
705
+ };
706
+ if (response.nativeFlowResponse) {
707
+ interactiveResponseMessage.nativeFlowResponseMessage = {
708
+ name: response.nativeFlowResponse.name,
709
+ paramsJson: response.nativeFlowResponse.paramsJson,
710
+ version: response.nativeFlowResponse.version || 1
711
+ };
712
+ }
713
+ if (response.contextInfo) {
714
+ interactiveResponseMessage.contextInfo = response.contextInfo;
715
+ }
716
+ m.interactiveResponseMessage = interactiveResponseMessage;
717
+ }
718
+ else if ('bCall' in message && !!message.bCall) {
719
+ m.bcallMessage = {
720
+ sessionId: message.bCall.sessionId,
721
+ mediaType: message.bCall.mediaType || 0, // UNKNOWN = 0, AUDIO = 1, VIDEO = 2
722
+ masterKey: message.bCall.masterKey,
723
+ caption: message.bCall.caption
724
+ };
725
+ }
726
+ else if ('callLog' in message && !!message.callLog) {
727
+ m.callLogMesssage = {
728
+ isVideo: message.callLog.isVideo || false,
729
+ callOutcome: message.callLog.callOutcome || 0, // CONNECTED = 0
730
+ durationSecs: message.callLog.durationSecs,
731
+ callType: message.callLog.callType || 0, // REGULAR = 0
732
+ participants: message.callLog.participants || []
733
+ };
734
+ }
735
+ else if ('encComment' in message && !!message.encComment) {
736
+ m.encCommentMessage = {
737
+ targetMessageKey: message.encComment.targetMessageKey,
738
+ encPayload: message.encComment.encPayload,
739
+ encIv: message.encComment.encIv
740
+ };
741
+ }
742
+ else if ('encEventResponse' in message && !!message.encEventResponse) {
743
+ m.encEventResponseMessage = {
744
+ eventCreationMessageKey: message.encEventResponse.eventCreationMessageKey,
745
+ encPayload: message.encEventResponse.encPayload,
746
+ encIv: message.encEventResponse.encIv
747
+ };
748
+ }
749
+ else if ('messageHistoryBundle' in message && !!message.messageHistoryBundle) {
750
+ const bundle = message.messageHistoryBundle;
751
+ const bundleMedia = bundle.media ? await (0, exports.prepareWAMessageMedia)({ document: bundle.media }, options) : null;
752
+ m.messageHistoryBundle = {
753
+ mimetype: bundle.mimetype || 'application/octet-stream',
754
+ fileSha256: bundleMedia?.documentMessage?.fileSha256,
755
+ mediaKey: bundleMedia?.documentMessage?.mediaKey,
756
+ fileEncSha256: bundleMedia?.documentMessage?.fileEncSha256,
757
+ directPath: bundleMedia?.documentMessage?.directPath,
758
+ mediaKeyTimestamp: bundleMedia?.documentMessage?.mediaKeyTimestamp,
759
+ contextInfo: bundle.contextInfo,
760
+ messageHistoryMetadata: bundle.messageHistoryMetadata
761
+ };
762
+ }
763
+ else if ('messageHistoryNotice' in message && !!message.messageHistoryNotice) {
764
+ m.messageHistoryNotice = {
765
+ contextInfo: message.messageHistoryNotice.contextInfo,
766
+ messageHistoryMetadata: message.messageHistoryNotice.messageHistoryMetadata
767
+ };
768
+ }
769
+ else if ('inviteFollower' in message && !!message.inviteFollower) {
770
+ m.newsletterFollowerInviteMessageV2 = {
771
+ newsletterJid: message.inviteFollower.newsletterJid,
772
+ newsletterName: message.inviteFollower.newsletterName,
773
+ jpegThumbnail: message.inviteFollower.thumbnail,
774
+ caption: message.inviteFollower.caption,
775
+ contextInfo: message.inviteFollower.contextInfo
776
+ };
777
+ }
778
+ else if ('placeholder' in message && !!message.placeholder) {
779
+ m.placeholderMessage = {
780
+ type: message.placeholder.type || 0 // MASK_LINKED_DEVICES = 0
781
+ };
782
+ }
783
+ else if ('secretEncrypted' in message && !!message.secretEncrypted) {
784
+ m.secretEncryptedMessage = {
785
+ targetMessageKey: message.secretEncrypted.targetMessageKey,
786
+ encPayload: message.secretEncrypted.encPayload,
787
+ encIv: message.secretEncrypted.encIv,
788
+ secretEncType: message.secretEncrypted.secretEncType || 0 // UNKNOWN = 0, EVENT_EDIT = 1, MESSAGE_EDIT = 2
789
+ };
790
+ }
791
+ else if ('statusNotification' in message && !!message.statusNotification) {
792
+ m.statusNotificationMessage = {
793
+ responseMessageKey: message.statusNotification.responseMessageKey,
794
+ originalMessageKey: message.statusNotification.originalMessageKey,
795
+ type: message.statusNotification.type || 0 // UNKNOWN = 0, STATUS_ADD_YOURS = 1, STATUS_RESHARE = 2, STATUS_QUESTION_ANSWER_RESHARE = 3
796
+ };
797
+ }
798
+ else if ('stickerSyncRMR' in message && !!message.stickerSyncRMR) {
799
+ m.stickerSyncRmrMessage = {
800
+ filehash: message.stickerSyncRMR.filehash || [],
801
+ rmrSource: message.stickerSyncRMR.rmrSource,
802
+ requestTimestamp: message.stickerSyncRMR.requestTimestamp || Date.now()
803
+ };
804
+ }
495
805
  else if ('inviteAdmin' in message) {
496
806
  m.newsletterAdminInviteMessage = {};
497
807
  m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration;
@@ -578,6 +888,62 @@ const generateWAMessageContent = async (message, options) => {
578
888
  }
579
889
  };
580
890
  }
891
+ else if ('sendPayment' in message && !!message.sendPayment) {
892
+ const payment = message.sendPayment;
893
+ m.sendPaymentMessage = {
894
+ requestMessageKey: payment.requestMessageKey,
895
+ noteMessage: payment.noteMessage,
896
+ background: payment.background,
897
+ transactionData: payment.transactionData
898
+ };
899
+ }
900
+ else if ('declinePayment' in message && !!message.declinePayment) {
901
+ m.declinePaymentRequestMessage = {
902
+ key: message.declinePayment.key
903
+ };
904
+ }
905
+ else if ('cancelPayment' in message && !!message.cancelPayment) {
906
+ m.cancelPaymentRequestMessage = {
907
+ key: message.cancelPayment.key
908
+ };
909
+ }
910
+ else if ('scheduledCallEdit' in message && !!message.scheduledCallEdit) {
911
+ m.scheduledCallEditMessage = {
912
+ key: message.scheduledCallEdit.key,
913
+ editType: message.scheduledCallEdit.editType || 0 // UNKNOWN = 0, CANCEL = 1
914
+ };
915
+ }
916
+ else if ('pollResultSnapshot' in message && !!message.pollResultSnapshot) {
917
+ m.pollResultSnapshotMessage = {
918
+ name: message.pollResultSnapshot.name,
919
+ pollVotes: message.pollResultSnapshot.pollVotes || [],
920
+ contextInfo: message.pollResultSnapshot.contextInfo,
921
+ pollType: message.pollResultSnapshot.pollType || 0 // POLL = 0, QUIZ = 1
922
+ };
923
+ }
924
+ else if ('pollUpdate' in message && !!message.pollUpdate) {
925
+ m.pollUpdateMessage = {
926
+ pollCreationMessageKey: message.pollUpdate.pollCreationMessageKey,
927
+ vote: message.pollUpdate.vote,
928
+ metadata: message.pollUpdate.metadata,
929
+ senderTimestampMs: message.pollUpdate.senderTimestampMs || Date.now()
930
+ };
931
+ }
932
+ else if ('deviceSent' in message && !!message.deviceSent) {
933
+ const deviceSent = message.deviceSent;
934
+ const innerMessage = await (0, exports.generateWAMessageContent)(deviceSent.message, options);
935
+ m.deviceSentMessage = {
936
+ destinationJid: deviceSent.destinationJid,
937
+ message: innerMessage,
938
+ phash: deviceSent.phash
939
+ };
940
+ }
941
+ else if ('chat' in message && !!message.chat) {
942
+ m.chat = {
943
+ displayName: message.chat.displayName,
944
+ id: message.chat.id
945
+ };
946
+ }
581
947
  else if ('payment' in message) {
582
948
  // Handle sendPayment functionality
583
949
  m.requestPaymentMessage = Types_1.WAProto.Message.RequestPaymentMessage.fromObject({
@@ -675,6 +1041,7 @@ const generateWAMessageContent = async (message, options) => {
675
1041
  const interactiveMessage = {
676
1042
  nativeFlowMessage: Types_1.WAProto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
677
1043
  buttons: message.interactiveButtons,
1044
+ messageVersion: 1,
678
1045
  })
679
1046
  };
680
1047
  if ('text' in message) {
@@ -694,9 +1061,20 @@ const generateWAMessageContent = async (message, options) => {
694
1061
  Object.assign(interactiveMessage.header, m);
695
1062
  }
696
1063
  if ('footer' in message && !!message.footer) {
697
- interactiveMessage.footer = {
698
- text: message.footer
699
- };
1064
+ if (typeof message.footer === 'string') {
1065
+ interactiveMessage.footer = {
1066
+ text: message.footer
1067
+ };
1068
+ } else if (typeof message.footer === 'object' && message.footer.text) {
1069
+ interactiveMessage.footer = {
1070
+ text: message.footer.text,
1071
+ hasMediaAttachment: !!message.footer.audio
1072
+ };
1073
+ if (message.footer.audio) {
1074
+ const audioMedia = await (0, exports.prepareWAMessageMedia)({ audio: message.footer.audio }, options);
1075
+ interactiveMessage.footer.audioMessage = audioMedia.audioMessage;
1076
+ }
1077
+ }
700
1078
  }
701
1079
  if ('title' in message && !!message.title) {
702
1080
  interactiveMessage.header = {
@@ -704,7 +1082,19 @@ const generateWAMessageContent = async (message, options) => {
704
1082
  subtitle: message.subtitle,
705
1083
  hasMediaAttachment: (_k = message === null || message === void 0 ? void 0 : message.media) !== null && _k !== void 0 ? _k : false,
706
1084
  };
707
- Object.assign(interactiveMessage.header, m);
1085
+ // Support for ProductMessage in header
1086
+ if (message.headerProduct) {
1087
+ const productMedia = await (0, exports.prepareWAMessageMedia)({ image: message.headerProduct.productImage }, options);
1088
+ interactiveMessage.header.productMessage = {
1089
+ product: {
1090
+ ...message.headerProduct,
1091
+ productImage: productMedia.imageMessage
1092
+ }
1093
+ };
1094
+ interactiveMessage.header.hasMediaAttachment = true;
1095
+ } else {
1096
+ Object.assign(interactiveMessage.header, m);
1097
+ }
708
1098
  }
709
1099
  if ('contextInfo' in message && !!message.contextInfo) {
710
1100
  interactiveMessage.contextInfo = message.contextInfo;
@@ -758,7 +1148,68 @@ const generateWAMessageContent = async (message, options) => {
758
1148
  }
759
1149
  m = { interactiveMessage };
760
1150
  }
1151
+ else if ('collection' in message && !!message.collection) {
1152
+ const interactiveMessage = {
1153
+ collectionMessage: Types_1.WAProto.Message.InteractiveMessage.CollectionMessage.fromObject({
1154
+ bizJid: message.collection.bizJid,
1155
+ id: message.collection.id,
1156
+ messageVersion: message.collection.messageVersion || 1
1157
+ })
1158
+ };
1159
+ if ('text' in message) {
1160
+ interactiveMessage.body = {
1161
+ text: message.text
1162
+ };
1163
+ }
1164
+ if ('footer' in message && !!message.footer) {
1165
+ interactiveMessage.footer = {
1166
+ text: message.footer
1167
+ };
1168
+ }
1169
+ if ('title' in message && !!message.title) {
1170
+ interactiveMessage.header = {
1171
+ title: message.title,
1172
+ subtitle: message.subtitle,
1173
+ hasMediaAttachment: false
1174
+ };
1175
+ }
1176
+ if ('contextInfo' in message && !!message.contextInfo) {
1177
+ interactiveMessage.contextInfo = message.contextInfo;
1178
+ }
1179
+ m = { interactiveMessage };
1180
+ }
1181
+ else if ('invoice' in message && !!message.invoice) {
1182
+ const invoiceData = message.invoice;
1183
+ const invoiceMessage = {
1184
+ note: invoiceData.note,
1185
+ token: invoiceData.token,
1186
+ attachmentType: invoiceData.attachmentType || 0 // IMAGE = 0, PDF = 1
1187
+ };
1188
+ if (invoiceData.attachment) {
1189
+ const attachmentMedia = await (0, exports.prepareWAMessageMedia)({
1190
+ [invoiceData.attachmentType === 1 ? 'document' : 'image']: invoiceData.attachment
1191
+ }, options);
1192
+ if (invoiceData.attachmentType === 1) {
1193
+ invoiceMessage.attachmentMimetype = attachmentMedia.documentMessage.mimetype;
1194
+ invoiceMessage.attachmentMediaKey = attachmentMedia.documentMessage.mediaKey;
1195
+ invoiceMessage.attachmentMediaKeyTimestamp = attachmentMedia.documentMessage.mediaKeyTimestamp;
1196
+ invoiceMessage.attachmentFileSha256 = attachmentMedia.documentMessage.fileSha256;
1197
+ invoiceMessage.attachmentFileEncSha256 = attachmentMedia.documentMessage.fileEncSha256;
1198
+ invoiceMessage.attachmentDirectPath = attachmentMedia.documentMessage.directPath;
1199
+ } else {
1200
+ invoiceMessage.attachmentMimetype = attachmentMedia.imageMessage.mimetype;
1201
+ invoiceMessage.attachmentMediaKey = attachmentMedia.imageMessage.mediaKey;
1202
+ invoiceMessage.attachmentMediaKeyTimestamp = attachmentMedia.imageMessage.mediaKeyTimestamp;
1203
+ invoiceMessage.attachmentFileSha256 = attachmentMedia.imageMessage.fileSha256;
1204
+ invoiceMessage.attachmentFileEncSha256 = attachmentMedia.imageMessage.fileEncSha256;
1205
+ invoiceMessage.attachmentDirectPath = attachmentMedia.imageMessage.directPath;
1206
+ invoiceMessage.attachmentJpegThumbnail = attachmentMedia.imageMessage.jpegThumbnail;
1207
+ }
1208
+ }
1209
+ m = { invoiceMessage };
1210
+ }
761
1211
  if ('cards' in message && !!message.cards && message.cards.length > 0) {
1212
+ const carouselCardType = message.carouselCardType || 1; // HSCROLL_CARDS = 1, ALBUM_IMAGE = 2
762
1213
  const carouselCards = await Promise.all(message.cards.map(async (card) => {
763
1214
  const cardMessage = {
764
1215
  header: {
@@ -792,7 +1243,8 @@ const generateWAMessageContent = async (message, options) => {
792
1243
  buttons: card.buttons.map(button => ({
793
1244
  name: button.name,
794
1245
  buttonParamsJson: button.buttonParamsJson
795
- }))
1246
+ })),
1247
+ messageVersion: 1,
796
1248
  };
797
1249
  }
798
1250
  // Add footer if present
@@ -806,7 +1258,8 @@ const generateWAMessageContent = async (message, options) => {
806
1258
  const interactiveMessage = {
807
1259
  carouselMessage: Types_1.WAProto.Message.InteractiveMessage.CarouselMessage.fromObject({
808
1260
  cards: carouselCards,
809
- messageVersion: 1
1261
+ messageVersion: 1,
1262
+ carouselCardType: carouselCardType
810
1263
  })
811
1264
  };
812
1265
  if ('text' in message) {
@@ -834,8 +1287,12 @@ const generateWAMessageContent = async (message, options) => {
834
1287
  }
835
1288
  m = { interactiveMessage };
836
1289
  }
837
- if ('viewOnce' in message && !!message.viewOnce) {
838
- m = { viewOnceMessage: { message: m } };
1290
+ // Interactive messages are commonly sent wrapped in a view-once container on MD.
1291
+ // This improves client compatibility (avoids "update WhatsApp" / invisible messages on some clients).
1292
+ const shouldWrapInteractive = !!(m === null || m === void 0 ? void 0 : m.interactiveMessage);
1293
+ const hasViewOnceAlready = !!(m === null || m === void 0 ? void 0 : m.viewOnceMessage) || !!(m === null || m === void 0 ? void 0 : m.viewOnceMessageV2) || !!(m === null || m === void 0 ? void 0 : m.viewOnceMessageV2Extension);
1294
+ if ((('viewOnce' in message && !!message.viewOnce) || shouldWrapInteractive) && !hasViewOnceAlready) {
1295
+ m = { viewOnceMessageV2: { message: m } };
839
1296
  }
840
1297
  if ('mentions' in message && ((_o = message.mentions) === null || _o === void 0 ? void 0 : _o.length)) {
841
1298
  const [messageType] = Object.keys(m);
@@ -1203,3 +1660,63 @@ const assertMediaContent = (content) => {
1203
1660
  return mediaContent;
1204
1661
  };
1205
1662
  exports.assertMediaContent = assertMediaContent;
1663
+ const cache_manager_1 = require("./cache-manager");
1664
+ const performance_config_1 = require("./performance-config");
1665
+ /**
1666
+ * Get cache statistics for monitoring performance
1667
+ */
1668
+ const getCacheStats = () => {
1669
+ try {
1670
+ const cacheManager = cache_manager_1.default;
1671
+ const config = performance_config_1.getPerformanceConfig();
1672
+
1673
+ if (!cacheManager || !cacheManager.caches) {
1674
+ return {
1675
+ lidCache: { size: 0, maxSize: 0, ttl: config.cache.lidCache.ttl },
1676
+ jidCache: { size: 0, maxSize: 0, ttl: config.cache.jidCache.ttl }
1677
+ };
1678
+ }
1679
+
1680
+ const lidStats = cacheManager.getStats('lidCache');
1681
+ const jidStats = cacheManager.getStats('jidCache');
1682
+
1683
+ return {
1684
+ lidCache: {
1685
+ size: lidStats?.keys || 0,
1686
+ maxSize: lidStats?.max || config.cache.lidCache.maxSize || 0,
1687
+ ttl: config.cache.lidCache.ttl
1688
+ },
1689
+ jidCache: {
1690
+ size: jidStats?.keys || 0,
1691
+ maxSize: jidStats?.max || config.cache.jidCache.maxSize || 0,
1692
+ ttl: config.cache.jidCache.ttl
1693
+ }
1694
+ };
1695
+ } catch (error) {
1696
+ const config = performance_config_1.getPerformanceConfig();
1697
+ return {
1698
+ lidCache: { size: 0, maxSize: 0, ttl: config.cache.lidCache.ttl },
1699
+ jidCache: { size: 0, maxSize: 0, ttl: config.cache.jidCache.ttl }
1700
+ };
1701
+ }
1702
+ };
1703
+ exports.getCacheStats = getCacheStats;
1704
+ /**
1705
+ * Clear all caches (useful for testing or memory management)
1706
+ */
1707
+ const clearCache = () => {
1708
+ try {
1709
+ const cacheManager = cache_manager_1.default;
1710
+ if (cacheManager && cacheManager.caches) {
1711
+ Object.keys(cacheManager.caches).forEach(cacheName => {
1712
+ const cache = cacheManager.caches[cacheName];
1713
+ if (cache && typeof cache.flushAll === 'function') {
1714
+ cache.flushAll();
1715
+ }
1716
+ });
1717
+ }
1718
+ } catch (error) {
1719
+ // Silently fail if cache manager is not available
1720
+ }
1721
+ };
1722
+ exports.clearCache = clearCache;