@badzz88/baileys 8.5.2 → 8.5.4

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 (110) hide show
  1. package/README.md +1 -1
  2. package/WAProto/WAProto.proto +1256 -75
  3. package/WAProto/index.d.ts +36042 -19649
  4. package/WAProto/index.js +181990 -135645
  5. package/engine-requirements.js +7 -15
  6. package/lib/Defaults/index.js +22 -17
  7. package/lib/Signal/Group/group_cipher.js +5 -5
  8. package/lib/Signal/Group/keyhelper.js +4 -4
  9. package/lib/Signal/Group/sender-chain-key.js +2 -2
  10. package/lib/Signal/Group/sender-key-distribution-message.js +1 -1
  11. package/lib/Signal/Group/sender-key-message.js +3 -3
  12. package/lib/Signal/Group/sender-key-record.js +1 -1
  13. package/lib/Signal/Group/sender-message-key.js +5 -5
  14. package/lib/Signal/libsignal.js +39 -59
  15. package/lib/Signal/lid-mapping.js +28 -10
  16. package/lib/Socket/aigroups.js +5 -5
  17. package/lib/Socket/business.js +3 -11
  18. package/lib/Socket/chats.js +668 -319
  19. package/lib/Socket/communities.js +85 -89
  20. package/lib/Socket/graphql.js +435 -228
  21. package/lib/Socket/groups.js +132 -211
  22. package/lib/Socket/index.js +9 -7
  23. package/lib/Socket/interactive-handler.js +117 -60
  24. package/lib/Socket/interop.js +56 -175
  25. package/lib/Socket/managed-account.js +79 -48
  26. package/lib/Socket/messages-recv.js +898 -340
  27. package/lib/Socket/messages-send.js +462 -160
  28. package/lib/Socket/mex.js +40 -53
  29. package/lib/Socket/newsletter.js +291 -291
  30. package/lib/Socket/privacy.js +77 -265
  31. package/lib/Socket/registration.js +164 -157
  32. package/lib/Socket/socket.js +181 -199
  33. package/lib/Socket/username.js +144 -227
  34. package/lib/Store/make-cache-manager-store.js +2 -2
  35. package/lib/Store/make-in-memory-store.js +25 -141
  36. package/lib/Types/Auth.js +3 -3
  37. package/lib/Types/Label.js +1 -1
  38. package/lib/Types/LabelAssociation.js +1 -1
  39. package/lib/Types/Newsletter.js +96 -65
  40. package/lib/Types/State.js +4 -4
  41. package/lib/Types/index.js +1 -1
  42. package/lib/Utils/auth-utils.js +52 -57
  43. package/lib/Utils/browser-utils.js +1 -1
  44. package/lib/Utils/business.js +2 -6
  45. package/lib/Utils/chat-utils.js +102 -38
  46. package/lib/Utils/crypto.js +54 -84
  47. package/lib/Utils/decode-wa-message.js +316 -83
  48. package/lib/Utils/event-buffer.js +37 -61
  49. package/lib/Utils/generics.js +157 -103
  50. package/lib/Utils/group-history.js +3 -12
  51. package/lib/Utils/history.js +15 -15
  52. package/lib/Utils/index.js +1 -5
  53. package/lib/Utils/link-preview.js +3 -8
  54. package/lib/Utils/lt-hash.js +2 -35
  55. package/lib/Utils/make-mutex.js +1 -1
  56. package/lib/Utils/message-inspect.js +393 -0
  57. package/lib/Utils/message-retry-manager.js +27 -92
  58. package/lib/Utils/messages-media.js +159 -130
  59. package/lib/Utils/messages.js +144 -566
  60. package/lib/Utils/meta-ai-msmsg.js +62 -202
  61. package/lib/Utils/noise-handler.js +19 -21
  62. package/lib/Utils/offline-node-processor.js +3 -8
  63. package/lib/Utils/pre-key-manager.js +13 -23
  64. package/lib/Utils/process-message.js +197 -106
  65. package/lib/Utils/reporting-utils.js +2 -2
  66. package/lib/Utils/signal.js +28 -63
  67. package/lib/Utils/stanza-ack.js +39 -12
  68. package/lib/Utils/sync-action-utils.js +4 -7
  69. package/lib/Utils/tc-token-utils.js +20 -25
  70. package/lib/Utils/use-multi-file-auth-state.js +30 -14
  71. package/lib/Utils/validate-connection.js +59 -19
  72. package/lib/WABinary/decode.js +50 -16
  73. package/lib/WABinary/encode.js +54 -224
  74. package/lib/WABinary/generic-utils.js +7 -97
  75. package/lib/WABinary/jid-utils.js +27 -14
  76. package/lib/WAM/encode.js +7 -7
  77. package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +58 -1
  78. package/lib/WAUSync/Protocols/USyncContactProtocol.js +7 -1
  79. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +13 -5
  80. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -4
  81. package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +20 -7
  82. package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +865 -0
  83. package/lib/WAUSync/Protocols/USyncPictureProtocol.js +1 -1
  84. package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +2 -2
  85. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +7 -2
  86. package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +1 -1
  87. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +2 -1
  88. package/lib/WAUSync/Protocols/index.js +1 -0
  89. package/lib/WAUSync/USyncBackoff.js +26 -0
  90. package/lib/WAUSync/USyncQuery.js +77 -6
  91. package/lib/WAUSync/USyncUser.js +16 -8
  92. package/lib/WAUSync/index.js +1 -0
  93. package/lib/antiban.js +608 -854
  94. package/lib/index.js +3 -3
  95. package/package.json +16 -19
  96. package/lib/Socket/luxu.js +0 -387
  97. package/lib/Socket/text-router.js +0 -83
  98. package/lib/Store/keyed-db.js +0 -108
  99. package/lib/Types/Mex.js +0 -112
  100. package/lib/Utils/command-loader.d.ts +0 -31
  101. package/lib/Utils/command-loader.js +0 -100
  102. package/lib/Utils/companion-reg-client-utils.js +0 -42
  103. package/lib/Utils/curve25519-js.js +0 -275
  104. package/lib/Utils/native-bridge.js +0 -82
  105. package/lib/Utils/session-pool.d.ts +0 -16
  106. package/lib/Utils/session-pool.js +0 -94
  107. package/lib/Utils/sticker.d.ts +0 -17
  108. package/lib/Utils/sticker.js +0 -145
  109. package/lib/Utils/view-once-cache.d.ts +0 -9
  110. package/lib/Utils/view-once-cache.js +0 -79
@@ -1,17 +1,6 @@
1
1
  'use strict'
2
2
  Object.defineProperty(exports, '__esModule', { value: true })
3
- exports.assertMediaContent =
4
- exports.downloadMediaMessage =
5
- exports.aggregateMessageKeysNotFromMe =
6
- exports.updateMessageWithEventResponse =
7
- exports.updateMessageWithPollUpdate =
8
- exports.updateMessageWithReaction =
9
- exports.updateMessageWithReceipt =
10
- exports.getDevice =
11
- exports.extractMessageContent =
12
- exports.normalizeMessageContent =
13
- exports.getContentType =
14
- exports.generateWAMessage =
3
+ exports.generateWAMessage =
15
4
  exports.generateWAMessageFromContent =
16
5
  exports.generateWAMessageContent =
17
6
  exports.hasNonNullishProperty =
@@ -21,12 +10,10 @@ exports.assertMediaContent =
21
10
  exports.generateLinkPreviewIfRequired =
22
11
  exports.extractUrlFromText =
23
12
  void 0
24
- exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage
25
- exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage
26
13
  const boom_1 = require('@hapi/boom')
27
14
  const crypto_1 = require('crypto')
28
15
  const fs_1 = require('fs')
29
- const index_js_1 = require('../../WAProto/index.js')
16
+ const lru_cache_1 = require('lru-cache')
30
17
  const WAProto_1 = require('../../WAProto/index.js')
31
18
  const Defaults_1 = require('../Defaults')
32
19
  const Types_1 = require('../Types')
@@ -36,6 +23,12 @@ const generics_1 = require('./generics')
36
23
  const messages_media_1 = require('./messages-media')
37
24
  const reporting_utils_1 = require('./reporting-utils')
38
25
  const jid_display_normalization_1 = require('./jid-display-normalization')
26
+ const message_inspect_1 = require('./message-inspect')
27
+ Object.assign(exports, message_inspect_1)
28
+
29
+
30
+
31
+ const groupInviteThumbnailCache = new lru_cache_1.LRUCache({ max: 100, ttl: 5 * 60 * 1000 })
39
32
  const MIMETYPE_MAP = {
40
33
  image: 'image/jpeg',
41
34
  video: 'video/mp4',
@@ -52,14 +45,14 @@ const MessageTypeProto = {
52
45
  document: WAProto_1.proto.Message.DocumentMessage
53
46
  }
54
47
 
55
- // Input payloads can carry protobuf media message keys (e.g. imageMessage).
48
+
56
49
  const MEDIA_MESSAGE_TYPE_ALIASES = {
57
50
  imageMessage: 'image',
58
51
  videoMessage: 'video',
59
52
  audioMessage: 'audio',
60
53
  documentMessage: 'document',
61
54
  stickerMessage: 'sticker',
62
- // PTV = push-to-video (video note) payload.
55
+
63
56
  ptvMessage: 'video'
64
57
  }
65
58
  const MEDIA_MESSAGE_TYPE_ALIAS_KEYS = Object.keys(MEDIA_MESSAGE_TYPE_ALIASES)
@@ -196,11 +189,7 @@ const tokenizeCode = code => {
196
189
  return merged
197
190
  }
198
191
 
199
- /**
200
- * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
201
- * @param text eg. hello https://google.com
202
- * @returns the URL, eg. https://google.com
203
- */
192
+
204
193
  const extractUrlFromText = text => text.match(Defaults_1.URL_REGEX)?.[0]
205
194
  exports.extractUrlFromText = extractUrlFromText
206
195
  const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
@@ -210,7 +199,7 @@ const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
210
199
  const urlInfo = await getUrlInfo(url)
211
200
  return urlInfo
212
201
  } catch (error) {
213
- // ignore if fails
202
+
214
203
  logger?.warn({ trace: error.stack }, 'url generation failed')
215
204
  }
216
205
  }
@@ -231,6 +220,9 @@ const assertColor = async color => {
231
220
  }
232
221
  const prepareWAMessageMedia = async (message, options) => {
233
222
  const logger = options.logger
223
+
224
+ const mediaAbProps = options.mediaAbProps || null
225
+ const getMediaProp = propName => (0, messages_media_1.getMediaProp)(mediaAbProps, propName)
234
226
  let mediaType
235
227
  for (const key of Defaults_1.MEDIA_KEYS) {
236
228
  if (key in message) {
@@ -245,7 +237,20 @@ const prepareWAMessageMedia = async (message, options) => {
245
237
  media: message[mediaType]
246
238
  }
247
239
  delete uploadData[mediaType]
248
- // check if cacheable + generate cache key
240
+
241
+
242
+
243
+
244
+ if (mediaType === 'video' && uploadData.mimetype) {
245
+ const isHevc = uploadData.mimetype.includes('hevc') || uploadData.mimetype.includes('x-matroska')
246
+ if (isHevc && !getMediaProp('hevc_video_dual_upload')) {
247
+
248
+ uploadData.mimetype = MIMETYPE_MAP['video']
249
+ }
250
+
251
+ }
252
+
253
+
249
254
  const cacheableKey =
250
255
  typeof uploadData.media === 'object' &&
251
256
  'url' in uploadData.media &&
@@ -262,7 +267,7 @@ const prepareWAMessageMedia = async (message, options) => {
262
267
  const mediaBuff = await options.mediaCache.get(cacheableKey)
263
268
  if (mediaBuff) {
264
269
  logger?.debug({ cacheableKey }, 'got media cache hit')
265
- const obj = index_js_1.proto.Message.decode(mediaBuff)
270
+ const obj = WAProto_1.proto.Message.decode(mediaBuff)
266
271
  const key = `${mediaType}Message`
267
272
  Object.assign(obj[key], { ...uploadData, media: undefined })
268
273
  return obj
@@ -284,7 +289,7 @@ const prepareWAMessageMedia = async (message, options) => {
284
289
  })
285
290
  await fs_1.promises.unlink(filePath)
286
291
  const obj = WAProto_1.proto.Message.fromObject({
287
- // todo: add more support here
292
+
288
293
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
289
294
  url: mediaUrl,
290
295
  directPath,
@@ -375,6 +380,27 @@ const prepareWAMessageMedia = async (message, options) => {
375
380
  logger?.warn('failed to remove tmp file')
376
381
  }
377
382
  })
383
+
384
+
385
+
386
+ const hdImageEnabled = mediaType === 'image' && getMediaProp('hd_image_dual_upload') && !!uploadData.hd
387
+ const hdVideoEnabled = mediaType === 'video' && getMediaProp('hd_video_dual_upload') && !!uploadData.hd
388
+ if (hdImageEnabled || hdVideoEnabled) {
389
+ uploadData.mediaHd = true
390
+ logger?.debug({ mediaType }, 'HD dual upload enabled, setting mediaHd flag')
391
+ }
392
+
393
+
394
+
395
+ if (mediaType === 'image' && uploadData.motionPhoto != null) {
396
+
397
+
398
+ if (typeof uploadData.motionPhoto === 'boolean') {
399
+ uploadData.motionPhoto = uploadData.motionPhoto ? 1 : 0
400
+ }
401
+ logger?.debug('motion photo field set on image message')
402
+ }
403
+
378
404
  const obj = WAProto_1.proto.Message.fromObject({
379
405
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
380
406
  url: mediaUrl,
@@ -414,19 +440,15 @@ const prepareDisappearingMessageSettingContent = ephemeralExpiration => {
414
440
  return WAProto_1.proto.Message.fromObject(content)
415
441
  }
416
442
  exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent
417
- /**
418
- * Generate forwarded message content like WA does
419
- * @param message the message to forward
420
- * @param options.forceForward will show the message as forwarded even if it is from you
421
- */
443
+
422
444
  const generateForwardMessageContent = (message, forceForward) => {
423
445
  let content = message.message
424
446
  if (!content) {
425
447
  throw new boom_1.Boom('no content in message', { statusCode: 400 })
426
448
  }
427
- // hacky copy
449
+
428
450
  content = (0, exports.normalizeMessageContent)(content)
429
- content = index_js_1.proto.Message.decode(index_js_1.proto.Message.encode(content).finish())
451
+ content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish())
430
452
  let key = Object.keys(content)[0]
431
453
  let score = content?.[key]?.contextInfo?.forwardingScore || 0
432
454
  score += message.key.fromMe && !forceForward ? 0 : 1
@@ -654,15 +676,19 @@ const generateWAMessageContent = async (message, options) => {
654
676
  m.groupInviteMessage.caption = message.groupInvite.text
655
677
  m.groupInviteMessage.groupJid = message.groupInvite.jid
656
678
  m.groupInviteMessage.groupName = message.groupInvite.subject
657
- //TODO: use built-in interface and get disappearing mode info etc.
658
- //TODO: cache / use store!?
659
679
  if (options.getProfilePicUrl) {
660
- const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview')
661
- if (pfpUrl) {
662
- const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher })
663
- if (resp.ok) {
664
- const buf = Buffer.from(await resp.arrayBuffer())
665
- m.groupInviteMessage.jpegThumbnail = buf
680
+ const cached = groupInviteThumbnailCache.get(message.groupInvite.jid)
681
+ if (cached) {
682
+ m.groupInviteMessage.jpegThumbnail = cached
683
+ } else {
684
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview')
685
+ if (pfpUrl) {
686
+ const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher })
687
+ if (resp.ok) {
688
+ const buf = Buffer.from(await resp.arrayBuffer())
689
+ m.groupInviteMessage.jpegThumbnail = buf
690
+ groupInviteThumbnailCache.set(message.groupInvite.jid, buf)
691
+ }
666
692
  }
667
693
  }
668
694
  }
@@ -686,7 +712,7 @@ const generateWAMessageContent = async (message, options) => {
686
712
  m.buttonsResponseMessage = {
687
713
  selectedButtonId: message.buttonReply.id,
688
714
  selectedDisplayText: message.buttonReply.displayText,
689
- type: index_js_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
715
+ type: WAProto_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
690
716
  }
691
717
  break
692
718
  case 'interactive':
@@ -736,7 +762,7 @@ const generateWAMessageContent = async (message, options) => {
736
762
  (message.event.call === 'audio' ? Defaults_1.CALL_AUDIO_PREFIX : Defaults_1.CALL_VIDEO_PREFIX) + token
737
763
  }
738
764
  m.messageContextInfo = {
739
- // encKey
765
+
740
766
  messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32)
741
767
  }
742
768
  m.eventMessage.name = message.event.name
@@ -780,21 +806,26 @@ const generateWAMessageContent = async (message, options) => {
780
806
  ...(message.poll.hideParticipantName !== undefined
781
807
  ? { hideParticipantName: !!message.poll.hideParticipantName }
782
808
  : {}),
783
- ...(message.poll.allowAddOption !== undefined ? { allowAddOption: !!message.poll.allowAddOption } : {})
809
+ ...(message.poll.allowAddOption !== undefined ? { allowAddOption: !!message.poll.allowAddOption } : {}),
810
+
811
+
812
+ ...((0, messages_media_1.getMediaProp)(options.mediaAbProps, 'media_poll') && message.poll.mediaPoll != null
813
+ ? { mediaPoll: !!message.poll.mediaPoll }
814
+ : {})
784
815
  }
785
816
  if (message.poll.version === 6 || message.poll.v6) {
786
817
  m.pollCreationMessageV6 = pollCreationMessage
787
818
  } else if (message.poll.version === 5 || message.poll.v5) {
788
819
  m.pollCreationMessageV5 = pollCreationMessage
789
820
  } else if (message.poll.toAnnouncementGroup) {
790
- // poll v2 is for community announcement groups (single select and multiple)
821
+
791
822
  m.pollCreationMessageV2 = pollCreationMessage
792
823
  } else {
793
824
  if (message.poll.selectableCount === 1) {
794
- //poll v3 is for single select polls
825
+
795
826
  m.pollCreationMessageV3 = pollCreationMessage
796
827
  } else {
797
- // poll for multiple choice polls
828
+
798
829
  m.pollCreationMessage = pollCreationMessage
799
830
  }
800
831
  }
@@ -923,13 +954,13 @@ const generateWAMessageContent = async (message, options) => {
923
954
  }
924
955
  } else if ((0, exports.hasNonNullishProperty)(message, 'sharePhoneNumber')) {
925
956
  m.protocolMessage = {
926
- type: index_js_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
957
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
927
958
  }
928
959
  } else if ((0, exports.hasNonNullishProperty)(message, 'requestPhoneNumber')) {
929
960
  m.requestPhoneNumberMessage = {}
930
961
  } else if ((0, exports.hasNonNullishProperty)(message, 'limitSharing')) {
931
962
  m.protocolMessage = {
932
- type: index_js_1.proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
963
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
933
964
  limitSharing: {
934
965
  sharingLimited: message.limitSharing === true,
935
966
  trigger: 1,
@@ -986,7 +1017,7 @@ const generateWAMessageContent = async (message, options) => {
986
1017
  } else if ('interactiveMessage' in message) {
987
1018
  m = { interactiveMessage: message.interactiveMessage }
988
1019
  } else if ('richResponse' in message) {
989
- // handled in richResponse block below
1020
+
990
1021
  } else if ('groupStatusMessage' in message) {
991
1022
  m = { groupStatusMessage: WAProto_1.proto.Message.GroupStatusMessage.fromObject(message.groupStatusMessage) }
992
1023
  } else if (hasCaptionWithoutMedia && !hasCaptionContainer) {
@@ -1032,7 +1063,7 @@ const generateWAMessageContent = async (message, options) => {
1032
1063
  m = { interactiveMessage }
1033
1064
  } else if ('templateButtons' in message && !!message.templateButtons) {
1034
1065
  const msg = {
1035
- hydratedButtons: message.hasOwnProperty('templateButtons') ? message.templateButtons : message.templateButtons
1066
+ hydratedButtons: message.templateButtons
1036
1067
  }
1037
1068
  if ('text' in message) {
1038
1069
  msg.hydratedContentText = message.text
@@ -1089,73 +1120,42 @@ const generateWAMessageContent = async (message, options) => {
1089
1120
  }
1090
1121
  }
1091
1122
  if ('interactiveButtons' in message && !!message.interactiveButtons) {
1092
- const nativeFlow = WAProto_1.proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
1093
- buttons: message.interactiveButtons,
1094
- messageParamsJson: message.messageParams ?? "{}"
1095
- });
1096
- let interactiveMessage = { nativeFlowMessage: nativeFlow };
1097
- if ('text' in message) {
1098
- interactiveMessage.body = { text: message.text };
1099
- } else if ('caption' in message) {
1100
- interactiveMessage.body = { text: message.caption };
1101
- }
1102
- if ('title' in message && !!message.title) {
1103
- interactiveMessage.header = {
1104
- title: message.title,
1105
- subtitle: message.subtitle || "",
1106
- hasMediaAttachment: false
1107
- };
1108
- let media = null;
1109
- if ('image' in message && !!message.image) {
1110
- media = await prepareWAMessageMedia({ image: message.image }, options);
1111
- interactiveMessage.header.imageMessage = media.imageMessage;
1112
- if (message.image.caption) {
1113
- interactiveMessage.header.imageMessage.caption = message.image.caption;
1114
- }
1115
- } else if ('video' in message && !!message.video) {
1116
- media = await prepareWAMessageMedia({ video: message.video }, options);
1117
- interactiveMessage.header.videoMessage = media.videoMessage;
1118
- if (message.video.caption) {
1119
- interactiveMessage.header.videoMessage.caption = message.video.caption;
1120
- }
1121
- } else if ('gif' in message && !!message.gif) {
1122
- media = await prepareWAMessageMedia({ video: message.gif }, options);
1123
- interactiveMessage.header.videoMessage = media.videoMessage;
1124
- interactiveMessage.header.videoMessage.gifPlayback = true;
1125
- if (message.gif.caption) {
1126
- interactiveMessage.header.videoMessage.caption = message.gif.caption;
1127
- }
1128
- } else if ('document' in message && !!message.document) {
1129
- media = await prepareWAMessageMedia({ document: message.document }, options);
1130
- interactiveMessage.header.documentMessage = media.documentMessage;
1131
- let docuR = interactiveMessage.header.documentMessage;
1132
- docuR.fileName = message.document.fileName || "Document";
1133
- docuR.mimetype = message.document.mimetype || docuR.mimetype;
1134
- if (message.document.caption) docuR.caption = message.document.caption;
1135
- if (message.document.jpegThumbnail) docuR.jpegThumbnail = message.document.jpegThumbnail;
1136
- } else if ('location' in message && !!message.location) {
1137
- let mLoc = message.location;
1138
- interactiveMessage.header.locationMessage = {
1139
- degreesLongitude: mLoc.longitude || 0,
1140
- degreesLatitude: mLoc.latitude || 0,
1141
- name: mLoc.name || null,
1142
- address: mLoc.address || null,
1143
- url: mLoc.url || null
1144
- };
1145
- media = true;
1146
- } else if ('thumbnail' in message && !!message.thumbnail) {
1147
- interactiveMessage.header.jpegThumbnail = message.thumbnail;
1148
- }
1149
- if (media || ('thumbnail' in message && !!message.thumbnail)) {
1150
- interactiveMessage.header.hasMediaAttachment = true;
1151
- }
1152
- }
1153
- if ('footer' in message && !!message.footer) {
1154
- interactiveMessage.footer = { text: message.footer };
1155
- }
1156
- applyContextInfoAndMentions(interactiveMessage, message);
1157
- m = { interactiveMessage };
1158
- }
1123
+ const interactiveMessage = {
1124
+ nativeFlowMessage: WAProto_1.proto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
1125
+ buttons: message.interactiveButtons
1126
+ })
1127
+ }
1128
+ if ('text' in message) {
1129
+ interactiveMessage.body = {
1130
+ text: message.text
1131
+ }
1132
+ } else if ('caption' in message) {
1133
+ interactiveMessage.body = {
1134
+ text: message.caption
1135
+ }
1136
+ interactiveMessage.header = {
1137
+ title: message.title,
1138
+ subtitle: message.subtitle,
1139
+ hasMediaAttachment: Boolean(message.hasMediaAttachment)
1140
+ }
1141
+ Object.assign(interactiveMessage.header, m)
1142
+ }
1143
+ if ('footer' in message && !!message.footer) {
1144
+ interactiveMessage.footer = {
1145
+ text: message.footer
1146
+ }
1147
+ }
1148
+ if ('title' in message && !!message.title) {
1149
+ interactiveMessage.header = {
1150
+ title: message.title,
1151
+ subtitle: message.subtitle,
1152
+ hasMediaAttachment: Boolean(message.hasMediaAttachment)
1153
+ }
1154
+ Object.assign(interactiveMessage.header, m)
1155
+ }
1156
+ applyContextInfoAndMentions(interactiveMessage, message)
1157
+ m = { interactiveMessage }
1158
+ }
1159
1159
  if ('shop' in message && !!message.shop) {
1160
1160
  const interactiveMessage = {
1161
1161
  shopStorefrontMessage: WAProto_1.proto.Message.InteractiveMessage.ShopMessage.fromObject({
@@ -1232,22 +1232,12 @@ const generateWAMessageContent = async (message, options) => {
1232
1232
  }
1233
1233
  })
1234
1234
  }
1235
- if (table) {
1236
- const isPlainArrayTable = Array.isArray(table)
1237
- const rows = isPlainArrayTable ? table : table.rows
1238
- if (!Array.isArray(rows)) {
1239
- throw new boom_1.Boom(
1240
- 'richResponse.table must be an array of rows (e.g. [["h1","h2"],["a","b"]]) or { rows: [...] }',
1241
- { statusCode: 400 }
1242
- )
1243
- }
1235
+ if (table && Array.isArray(table.rows)) {
1244
1236
  sections.push({
1245
1237
  view_model: {
1246
1238
  primitive: {
1247
- rows: rows.map((row, idx) => ({
1248
- cells: Array.isArray(row) ? row.map(c => ({ text: String(c) })) : row.cells,
1249
- // when a plain 2D array is passed, the first row is treated as the table header
1250
- isHeading: Array.isArray(row) ? isPlainArrayTable && idx === 0 : row.isHeading
1239
+ rows: table.rows.map(row => ({
1240
+ cells: Array.isArray(row) ? row.map(c => ({ text: String(c) })) : row.cells
1251
1241
  })),
1252
1242
  __typename: 'GenAITableUXPrimitive'
1253
1243
  },
@@ -1878,9 +1868,10 @@ const generateWAMessageContent = async (message, options) => {
1878
1868
  ...existing,
1879
1869
  botThreadInfo: {
1880
1870
  clientInfo: {
1881
- type: typeof bt.type === 'string'
1882
- ? (threadTypeMap[bt.type.toLowerCase()] ?? threadTypeEnum.UNKNOWN)
1883
- : (bt.type ?? threadTypeEnum.UNKNOWN),
1871
+ type:
1872
+ typeof bt.type === 'string'
1873
+ ? (threadTypeMap[bt.type.toLowerCase()] ?? threadTypeEnum.UNKNOWN)
1874
+ : (bt.type ?? threadTypeEnum.UNKNOWN),
1884
1875
  sourceChatJid: bt.sourceChatJid || ''
1885
1876
  }
1886
1877
  }
@@ -2281,7 +2272,7 @@ const generateWAMessageContent = async (message, options) => {
2281
2272
  m.messageContextInfo = {
2282
2273
  ...(m.messageContextInfo || {}),
2283
2274
  messageAddOnDurationInSecs: message.afterReadDuration,
2284
- messageAddOnExpiryType: index_js_1.proto.MessageContextInfo.MessageAddonExpiryType.DEPENDENT_ON_PARENT
2275
+ messageAddOnExpiryType: WAProto_1.proto.MessageContextInfo.MessageAddonExpiryType.DEPENDENT_ON_PARENT
2285
2276
  }
2286
2277
  }
2287
2278
  if ('raw' in message && !!message.raw) {
@@ -2410,8 +2401,8 @@ const generateWAMessageContent = async (message, options) => {
2410
2401
  }
2411
2402
  exports.generateWAMessageContent = generateWAMessageContent
2412
2403
  const generateWAMessageFromContent = (jid, message, options) => {
2413
- // set timestamp to now
2414
- // if not specified
2404
+
2405
+
2415
2406
  if (!options.timestamp) {
2416
2407
  options.timestamp = new Date()
2417
2408
  }
@@ -2421,12 +2412,12 @@ const generateWAMessageFromContent = (jid, message, options) => {
2421
2412
  const { quoted, userJid } = options
2422
2413
  if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
2423
2414
  const participant = quoted.key.fromMe
2424
- ? userJid // TODO: Add support for LIDs
2415
+ ? userJid
2425
2416
  : quoted.participant || quoted.key.participant || quoted.key.remoteJid
2426
2417
  let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message)
2427
2418
  const msgType = (0, exports.getContentType)(quotedMsg)
2428
- // strip any redundant properties
2429
- quotedMsg = index_js_1.proto.Message.create({ [msgType]: quotedMsg[msgType] })
2419
+
2420
+ quotedMsg = WAProto_1.proto.Message.create({ [msgType]: quotedMsg[msgType] })
2430
2421
  const quotedContent = quotedMsg[msgType]
2431
2422
  if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
2432
2423
  delete quotedContent.contextInfo
@@ -2435,62 +2426,53 @@ const generateWAMessageFromContent = (jid, message, options) => {
2435
2426
  contextInfo.participant = (0, WABinary_1.jidNormalizedUser)(participant)
2436
2427
  contextInfo.stanzaId = quoted.key.id
2437
2428
  contextInfo.quotedMessage = quotedMsg
2438
- // if a participant is quoted, then it must be a group
2439
- // hence, remoteJid of group must also be entered
2429
+
2430
+
2440
2431
  if (jid !== quoted.key.remoteJid) {
2441
2432
  contextInfo.remoteJid = quoted.key.remoteJid
2442
2433
  }
2443
2434
  if (contextInfo && innerMessage[key]) {
2444
- /* @ts-ignore */
2435
+
2445
2436
  innerMessage[key].contextInfo = contextInfo
2446
2437
  }
2447
2438
  }
2448
2439
  if (
2449
- // if we want to send a disappearing message
2440
+
2450
2441
  !!options.ephemeralExpiration &&
2451
- // and it's not a protocol message -- delete, toggle disappear message
2442
+
2452
2443
  key !== 'protocolMessage' &&
2453
- // already not converted to disappearing message
2444
+
2454
2445
  key !== 'ephemeralMessage' &&
2455
- // newsletters don't support ephemeral messages
2446
+
2456
2447
  !(0, WABinary_1.isJidNewsletter)(jid)
2457
2448
  ) {
2458
- /* @ts-ignore */
2449
+
2459
2450
  innerMessage[key].contextInfo = {
2460
2451
  ...(innerMessage[key].contextInfo || {}),
2461
2452
  expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL
2462
- //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
2453
+
2463
2454
  }
2464
2455
  }
2465
2456
  message = WAProto_1.proto.Message.create(message)
2466
- const iosBros = options?.browser?.[0] === 'iOS' || options?.browser?.[1] === 'Safari'
2467
- const androidBros = options?.browser?.[0] === 'Android'
2468
- const pickedMessageId =
2469
- options?.messageId ||
2470
- (iosBros
2471
- ? (0, generics_1.generateIOSMessageID)()
2472
- : androidBros
2473
- ? (0, generics_1.generateAndroMessageID)()
2474
- : (0, generics_1.generateMessageIDV2)(userJid))
2475
2457
  const messageJSON = {
2476
2458
  key: {
2477
2459
  remoteJid: jid,
2478
2460
  fromMe: true,
2479
- id: pickedMessageId
2461
+ id: options?.messageId || (0, generics_1.generateMessageIDV2)()
2480
2462
  },
2481
2463
  message: message,
2482
2464
  messageTimestamp: timestamp,
2483
2465
  messageStubParameters: [],
2484
- participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined, // TODO: Add support for LIDs
2466
+ participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined,
2485
2467
  status: Types_1.WAMessageStatus.PENDING
2486
2468
  }
2487
2469
  return WAProto_1.proto.WebMessageInfo.fromObject(messageJSON)
2488
2470
  }
2489
2471
  exports.generateWAMessageFromContent = generateWAMessageFromContent
2490
2472
  const generateWAMessage = async (jid, content, options) => {
2491
- // ensure msg ID is with every log
2473
+
2492
2474
  options.logger = options?.logger?.child({ msgId: options.messageId })
2493
- // Pass jid in the options to generateWAMessageContent
2475
+
2494
2476
  return (0, exports.generateWAMessageFromContent)(
2495
2477
  jid,
2496
2478
  await (0, exports.generateWAMessageContent)(content, { ...options, jid }),
@@ -2498,407 +2480,3 @@ const generateWAMessage = async (jid, content, options) => {
2498
2480
  )
2499
2481
  }
2500
2482
  exports.generateWAMessage = generateWAMessage
2501
- /** Get the key to access the true type of content */
2502
- const getContentType = content => {
2503
- if (content) {
2504
- const keys = Object.keys(content)
2505
- const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage')
2506
- return key
2507
- }
2508
- }
2509
- exports.getContentType = getContentType
2510
- /**
2511
- * Normalizes ephemeral, view once messages to regular message content
2512
- * Eg. image messages in ephemeral messages, in view once messages etc.
2513
- * @param content
2514
- * @returns
2515
- */
2516
- const normalizeMessageContent = content => {
2517
- if (!content) {
2518
- return undefined
2519
- }
2520
- // set max iterations to prevent an infinite loop
2521
- for (let i = 0; i < 5; i++) {
2522
- const inner = getFutureProofMessage(content)
2523
- if (!inner) {
2524
- break
2525
- }
2526
- content = inner.message
2527
- }
2528
- return content
2529
- function getFutureProofMessage(message) {
2530
- return (
2531
- message.ephemeralMessage ||
2532
- message.viewOnceMessage ||
2533
- message.documentWithCaptionMessage ||
2534
- message.viewOnceMessageV2 ||
2535
- message.viewOnceMessageV2Extension ||
2536
- message.editedMessage ||
2537
- message.groupMentionedMessage ||
2538
- message.botInvokeMessage ||
2539
- message.lottieStickerMessage ||
2540
- message.eventCoverImage ||
2541
- message.statusMentionMessage ||
2542
- message.pollCreationOptionImageMessage ||
2543
- message.associatedChildMessage ||
2544
- message.groupStatusMentionMessage ||
2545
- message.pollCreationMessageV4 ||
2546
- message.pollCreationMessageV5 ||
2547
- message.statusAddYours ||
2548
- message.groupStatusMessage ||
2549
- message.limitSharingMessage ||
2550
- message.botTaskMessage ||
2551
- message.questionMessage ||
2552
- message.groupStatusMessageV2 ||
2553
- message.botForwardedMessage ||
2554
- message.questionReplyMessage ||
2555
- message.newsletterAdminProfileMessage ||
2556
- message.newsletterAdminProfileMessageV2 ||
2557
- message.newsletterAdminProfileStatusMessage ||
2558
- message.spoilerMessage ||
2559
- message.groupStatusV3Message ||
2560
- message.pollCreationMessageV6
2561
- )
2562
- }
2563
- }
2564
- exports.normalizeMessageContent = normalizeMessageContent
2565
- /**
2566
- * Extract the true message content from a message
2567
- * Eg. extracts the inner message from a disappearing message/view once message
2568
- */
2569
- const extractMessageContent = content => {
2570
- const extractFromTemplateMessage = msg => {
2571
- if (msg.imageMessage) {
2572
- return { imageMessage: msg.imageMessage }
2573
- } else if (msg.documentMessage) {
2574
- return { documentMessage: msg.documentMessage }
2575
- } else if (msg.videoMessage) {
2576
- return { videoMessage: msg.videoMessage }
2577
- } else if (msg.locationMessage) {
2578
- return { locationMessage: msg.locationMessage }
2579
- } else {
2580
- return {
2581
- conversation:
2582
- 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
2583
- }
2584
- }
2585
- }
2586
- content = (0, exports.normalizeMessageContent)(content)
2587
- if (content?.buttonsMessage) {
2588
- return extractFromTemplateMessage(content.buttonsMessage)
2589
- }
2590
- if (content?.templateMessage?.hydratedFourRowTemplate) {
2591
- return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate)
2592
- }
2593
- if (content?.templateMessage?.hydratedTemplate) {
2594
- return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate)
2595
- }
2596
- if (content?.templateMessage?.fourRowTemplate) {
2597
- return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate)
2598
- }
2599
- return content
2600
- }
2601
- exports.extractMessageContent = extractMessageContent
2602
- /**
2603
- * Returns the device predicted by message ID
2604
- */
2605
- const getDevice = id =>
2606
- /^3A.{18}$/.test(id)
2607
- ? 'ios'
2608
- : /^3E.{20}$/.test(id)
2609
- ? 'web'
2610
- : /^(.{21}|.{32})$/.test(id)
2611
- ? 'android'
2612
- : /^(3F|.{18}$)/.test(id)
2613
- ? 'desktop'
2614
- : 'api/baileys'
2615
- exports.getDevice = getDevice
2616
- /** Upserts a receipt in the message */
2617
- const updateMessageWithReceipt = (msg, receipt) => {
2618
- msg.userReceipt = msg.userReceipt || []
2619
- const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid)
2620
- if (recp) {
2621
- Object.assign(recp, receipt)
2622
- } else {
2623
- msg.userReceipt.push(receipt)
2624
- }
2625
- }
2626
- exports.updateMessageWithReceipt = updateMessageWithReceipt
2627
- /** Update the message with a new reaction */
2628
- const updateMessageWithReaction = (msg, reaction) => {
2629
- const authorID = (0, generics_1.getKeyAuthor)(reaction.key)
2630
- const reactions = (msg.reactions || []).filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID)
2631
- reaction.text = reaction.text || ''
2632
- reactions.push(reaction)
2633
- msg.reactions = reactions
2634
- }
2635
- exports.updateMessageWithReaction = updateMessageWithReaction
2636
- /** Update the message with a new poll update */
2637
- const updateMessageWithPollUpdate = (msg, update) => {
2638
- const authorID = (0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey)
2639
- const reactions = (msg.pollUpdates || []).filter(
2640
- r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID
2641
- )
2642
- if (update.vote?.selectedOptions?.length) {
2643
- reactions.push(update)
2644
- }
2645
- msg.pollUpdates = reactions
2646
- }
2647
- exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate
2648
- /** Update the message with a new event response */
2649
- const updateMessageWithEventResponse = (msg, update) => {
2650
- const authorID = (0, generics_1.getKeyAuthor)(update.eventResponseMessageKey)
2651
- const responses = (msg.eventResponses || []).filter(
2652
- r => (0, generics_1.getKeyAuthor)(r.eventResponseMessageKey) !== authorID
2653
- )
2654
- responses.push(update)
2655
- msg.eventResponses = responses
2656
- }
2657
- exports.updateMessageWithEventResponse = updateMessageWithEventResponse
2658
- /**
2659
- * Aggregates all poll updates in a poll.
2660
- * @param msg the poll creation message
2661
- * @param meId your jid
2662
- * @returns A list of options & their voters
2663
- */
2664
- function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
2665
- const opts =
2666
- message?.pollCreationMessage?.options ||
2667
- message?.pollCreationMessageV2?.options ||
2668
- message?.pollCreationMessageV3?.options ||
2669
- message?.pollCreationMessageV5?.options ||
2670
- message?.pollCreationMessageV6?.options ||
2671
- message?.pollCreationMessageV4?.message?.pollCreationMessage?.options ||
2672
- message?.pollCreationMessageV4?.message?.pollCreationMessageV3?.options ||
2673
- []
2674
- const voteHashMap = opts.reduce((acc, opt) => {
2675
- const hash = (0, crypto_2.sha256)(Buffer.from(opt.optionName || '')).toString()
2676
- acc[hash] = {
2677
- name: opt.optionName || '',
2678
- voters: []
2679
- }
2680
- return acc
2681
- }, {})
2682
- for (const update of pollUpdates || []) {
2683
- const { vote } = update
2684
- if (!vote) {
2685
- continue
2686
- }
2687
- for (const option of vote.selectedOptions || []) {
2688
- const hash = option.toString()
2689
- let data = voteHashMap[hash]
2690
- if (!data) {
2691
- voteHashMap[hash] = {
2692
- name: 'Unknown',
2693
- voters: []
2694
- }
2695
- data = voteHashMap[hash]
2696
- }
2697
- voteHashMap[hash].voters.push((0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey, meId))
2698
- }
2699
- }
2700
- return Object.values(voteHashMap)
2701
- }
2702
- /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
2703
- const aggregateMessageKeysNotFromMe = keys => {
2704
- const keyMap = {}
2705
- for (const { remoteJid, id, participant, fromMe, sts } of keys) {
2706
- if (!fromMe) {
2707
- const uqKey = `${remoteJid}:${participant || ''}`
2708
- if (!keyMap[uqKey]) {
2709
- keyMap[uqKey] = {
2710
- jid: remoteJid,
2711
- participant: participant,
2712
- messageIds: [],
2713
- // sts is per-message; kept only for single-message interop receipts
2714
- sts: sts
2715
- }
2716
- } else if (keyMap[uqKey].sts !== sts) {
2717
- // Multiple messages with different sts — can't aggregate a single sts
2718
- keyMap[uqKey].sts = undefined
2719
- }
2720
- keyMap[uqKey].messageIds.push(id)
2721
- }
2722
- }
2723
- return Object.values(keyMap)
2724
- }
2725
- exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe
2726
-
2727
- /**
2728
- * Check if a WebMessageInfo has a scheduled reveal time (ConditionalRevealMessage)
2729
- */
2730
- const isScheduledMessage = msg => !!msg?.scheduledMessageMetadata?.scheduledTime
2731
- exports.isScheduledMessage = isScheduledMessage
2732
-
2733
- /**
2734
- * Get scheduled reveal time of a message as a Date, or null
2735
- */
2736
- const getScheduledMessageTime = msg => {
2737
- const t = msg?.scheduledMessageMetadata?.scheduledTime
2738
- if (!t) return null
2739
- return new Date(Number(t) * 1000)
2740
- }
2741
- exports.getScheduledMessageTime = getScheduledMessageTime
2742
-
2743
- /**
2744
- * Extract PaymentInfo from a WebMessageInfo (the payment status field, not the message content)
2745
- */
2746
- const getMessagePaymentInfo = msg => msg?.paymentInfo || msg?.quotedPaymentInfo || null
2747
- exports.getMessagePaymentInfo = getMessagePaymentInfo
2748
-
2749
- /**
2750
- * Get all comment metadata from a WebMessageInfo
2751
- */
2752
- const getMessageCommentMetadata = msg => msg?.commentMetadata || null
2753
- exports.getMessageCommentMetadata = getMessageCommentMetadata
2754
-
2755
- /**
2756
- * Get all message add-ons (reactions, poll updates, pins) from a WebMessageInfo
2757
- */
2758
- const getMessageAddOns = msg => msg?.messageAddOns || []
2759
- exports.getMessageAddOns = getMessageAddOns
2760
-
2761
- /**
2762
- * Get the quiz correct answer from a poll creation message, if it's a quiz
2763
- */
2764
- const getPollCorrectAnswer = pollMsg => {
2765
- const poll =
2766
- pollMsg?.pollCreationMessage ||
2767
- pollMsg?.pollCreationMessageV2 ||
2768
- pollMsg?.pollCreationMessageV3 ||
2769
- pollMsg?.pollCreationMessageV5 ||
2770
- pollMsg?.pollCreationMessageV6
2771
- if (!poll) return null
2772
- const isQuiz = poll.pollType === WAProto_1.proto.Message.PollType?.QUIZ || poll.pollType === 1
2773
- return isQuiz ? poll.correctAnswer?.optionName || null : null
2774
- }
2775
- exports.getPollCorrectAnswer = getPollCorrectAnswer
2776
-
2777
- /**
2778
- * Aggregates all event responses in an event message.
2779
- * @param msg the event creation message
2780
- * @param meLid your lid
2781
- * @returns A list of response types & their responders
2782
- */
2783
- function getAggregateResponsesInEventMessage({ eventResponses }, meLid) {
2784
- const responseTypes = ['GOING', 'NOT_GOING', 'MAYBE']
2785
- const responseMap = {}
2786
-
2787
- for (const type of responseTypes) {
2788
- responseMap[type] = {
2789
- response: type,
2790
- responders: []
2791
- }
2792
- }
2793
- for (const update of eventResponses) {
2794
- const { response } = update.response || {}
2795
- const responseType = index_js_1.proto.Message.EventResponseMessage.EventResponseType[response]
2796
- if (responseType !== 'UNKNOWN' && responseMap[responseType]) {
2797
- responseMap[responseType].responders.push(generics_1.getKeyAuthor(update.eventResponseMessageKey, meLid))
2798
- }
2799
- }
2800
-
2801
- return Object.values(responseMap)
2802
- }
2803
-
2804
- exports.getAggregateResponsesInEventMessage = getAggregateResponsesInEventMessage
2805
-
2806
- const REUPLOAD_REQUIRED_STATUS = [410, 404]
2807
- /**
2808
- * Downloads the given message. Throws an error if it's not a media message
2809
- */
2810
- const downloadMediaMessage = async (message, type, options, ctx) => {
2811
- const result = await downloadMsg().catch(async error => {
2812
- if (
2813
- ctx &&
2814
- typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
2815
- REUPLOAD_REQUIRED_STATUS.includes(error.status)
2816
- ) {
2817
- ctx.logger.info({ key: message.key }, 'sending reupload media request...')
2818
- // request reupload
2819
- message = await ctx.reuploadRequest(message)
2820
- const result = await downloadMsg()
2821
- return result
2822
- }
2823
- throw error
2824
- })
2825
- return result
2826
- async function downloadMsg() {
2827
- const mContent = (0, exports.extractMessageContent)(message.message)
2828
- if (!mContent) {
2829
- throw new boom_1.Boom('No message present', { statusCode: 400, data: message })
2830
- }
2831
- const contentType = (0, exports.getContentType)(mContent)
2832
- let mediaType = contentType?.replace('Message', '')
2833
- const media = mContent[contentType]
2834
- if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
2835
- throw new boom_1.Boom(`"${contentType}" message is not a media message`)
2836
- }
2837
- let download
2838
- if ('thumbnailDirectPath' in media && !('url' in media)) {
2839
- download = {
2840
- directPath: media.thumbnailDirectPath,
2841
- mediaKey: media.mediaKey
2842
- }
2843
- mediaType = 'thumbnail-link'
2844
- } else {
2845
- download = media
2846
- }
2847
- const stream = await (0, messages_media_1.downloadContentFromMessage)(download, mediaType, options)
2848
- if (type === 'buffer') {
2849
- const bufferArray = []
2850
- for await (const chunk of stream) {
2851
- bufferArray.push(chunk)
2852
- }
2853
- return Buffer.concat(bufferArray)
2854
- }
2855
- return stream
2856
- }
2857
- }
2858
- exports.downloadMediaMessage = downloadMediaMessage
2859
- /** Checks whether the given message is a media message; if it is returns the inner content */
2860
- const assertMediaContent = content => {
2861
- content = (0, exports.extractMessageContent)(content)
2862
- const mediaContent =
2863
- content?.documentMessage ||
2864
- content?.imageMessage ||
2865
- content?.videoMessage ||
2866
- content?.audioMessage ||
2867
- content?.stickerMessage
2868
- if (!mediaContent) {
2869
- throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content })
2870
- }
2871
- return mediaContent
2872
- }
2873
- exports.assertMediaContent = assertMediaContent
2874
- /**
2875
- * Normalizes a bare user id to @s.whatsapp.net. Does not convert LID↔PN; use lidMapping / PN in key.remoteJidAlt when needed.
2876
- */
2877
- const toJid = id => {
2878
- if (!id) return ''
2879
- if (id.includes('@')) return id
2880
- return `${id}@s.whatsapp.net`
2881
- }
2882
- exports.toJid = toJid
2883
- /**
2884
- * Returns the peer LID JID when the key is LID-primary (decode sets remoteJid/participant to @lid when WA sends LID).
2885
- */
2886
- const getSenderLid = message => {
2887
- const k = message.key
2888
- if (!k) {
2889
- return { jid: '', lid: '' }
2890
- }
2891
- const jid = k.participant || k.remoteJid || ''
2892
- if (jid.endsWith('@lid') || jid.endsWith('@hosted.lid')) {
2893
- return { jid, lid: jid }
2894
- }
2895
- if (k.lid && typeof k.lid === 'string') {
2896
- const lid = k.lid.includes('@') ? k.lid : (0, WABinary_1.jidEncode)(k.lid, 'lid')
2897
- return { jid, lid }
2898
- }
2899
- if (k.participantLid && (0, WABinary_1.isLidUser)(k.participantLid)) {
2900
- return { jid, lid: k.participantLid }
2901
- }
2902
- return { jid, lid: '' }
2903
- }
2904
- exports.getSenderLid = getSenderLid