@baileys-md/baileys 11.2.4 → 12.0.1

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 (126) hide show
  1. package/LICENSE +1 -1
  2. package/WAProto/WAProto.proto +5311 -0
  3. package/WAProto/index.js +70084 -131686
  4. package/lib/Defaults/index.js +118 -117
  5. package/lib/KeyDB/BinarySearch.js +20 -0
  6. package/lib/KeyDB/KeyedDB.js +167 -0
  7. package/lib/KeyDB/index.js +4 -0
  8. package/lib/Signal/Group/ciphertext-message.js +13 -0
  9. package/lib/Signal/Group/group-session-builder.js +32 -0
  10. package/lib/Signal/Group/group_cipher.js +84 -0
  11. package/lib/Signal/Group/index.js +13 -0
  12. package/lib/Signal/Group/keyhelper.js +20 -0
  13. package/lib/Signal/Group/sender-chain-key.js +28 -0
  14. package/lib/Signal/Group/sender-key-distribution-message.js +65 -0
  15. package/lib/Signal/Group/sender-key-message.js +68 -0
  16. package/{WASignalGroup/sender_key_name.js → lib/Signal/Group/sender-key-name.js} +10 -28
  17. package/lib/Signal/Group/sender-key-record.js +43 -0
  18. package/lib/Signal/Group/sender-key-state.js +86 -0
  19. package/lib/Signal/Group/sender-message-key.js +28 -0
  20. package/lib/Signal/libsignal.js +314 -151
  21. package/lib/Signal/lid-mapping.js +155 -0
  22. package/lib/Socket/Client/index.js +4 -19
  23. package/lib/Socket/Client/types.js +13 -0
  24. package/lib/Socket/Client/websocket.js +52 -0
  25. package/lib/Socket/business.js +359 -242
  26. package/lib/Socket/chats.js +847 -844
  27. package/lib/Socket/communities.js +413 -0
  28. package/lib/Socket/groups.js +304 -319
  29. package/lib/Socket/index.js +15 -9
  30. package/lib/Socket/messages-recv.js +1109 -989
  31. package/lib/Socket/messages-send.js +611 -347
  32. package/lib/Socket/mex.js +45 -0
  33. package/lib/Socket/newsletter.js +230 -231
  34. package/lib/Socket/socket.js +795 -616
  35. package/lib/Store/index.js +6 -8
  36. package/lib/Store/make-cache-manager-store.js +73 -81
  37. package/lib/Store/make-in-memory-store.js +286 -427
  38. package/lib/Store/make-ordered-dictionary.js +77 -79
  39. package/lib/Store/object-repository.js +24 -26
  40. package/lib/Types/Auth.js +3 -2
  41. package/lib/Types/Bussines.js +3 -0
  42. package/lib/Types/Call.js +3 -2
  43. package/lib/Types/Chat.js +9 -4
  44. package/lib/Types/Contact.js +3 -2
  45. package/lib/Types/Events.js +3 -2
  46. package/lib/Types/GroupMetadata.js +3 -2
  47. package/lib/Types/Label.js +24 -26
  48. package/lib/Types/LabelAssociation.js +6 -8
  49. package/lib/Types/Message.js +12 -7
  50. package/lib/Types/Newsletter.js +32 -17
  51. package/lib/Types/Product.js +3 -2
  52. package/lib/Types/Signal.js +3 -2
  53. package/lib/Types/Socket.js +4 -2
  54. package/lib/Types/State.js +11 -2
  55. package/lib/Types/USync.js +3 -2
  56. package/lib/Types/index.js +27 -41
  57. package/lib/Utils/auth-utils.js +211 -198
  58. package/lib/Utils/baileys-event-stream.js +42 -61
  59. package/lib/Utils/browser-utils.js +25 -0
  60. package/lib/Utils/business.js +213 -214
  61. package/lib/Utils/chat-utils.js +711 -689
  62. package/lib/Utils/crypto.js +112 -133
  63. package/lib/Utils/decode-wa-message.js +254 -186
  64. package/lib/Utils/event-buffer.js +510 -502
  65. package/lib/Utils/generics.js +318 -408
  66. package/lib/Utils/history.js +83 -90
  67. package/lib/Utils/index.js +21 -33
  68. package/lib/Utils/link-preview.js +71 -116
  69. package/lib/Utils/logger.js +5 -7
  70. package/lib/Utils/lt-hash.js +40 -46
  71. package/lib/Utils/make-mutex.js +34 -41
  72. package/lib/Utils/message-retry-manager.js +113 -0
  73. package/lib/Utils/messages-media.js +575 -671
  74. package/lib/Utils/messages.js +354 -462
  75. package/lib/Utils/noise-handler.js +138 -149
  76. package/lib/Utils/pre-key-manager.js +85 -0
  77. package/lib/Utils/process-message.js +323 -354
  78. package/lib/Utils/signal.js +148 -130
  79. package/lib/Utils/use-multi-file-auth-state.js +109 -91
  80. package/lib/Utils/validate-connection.js +183 -190
  81. package/lib/WABinary/constants.js +1298 -35
  82. package/lib/WABinary/decode.js +231 -256
  83. package/lib/WABinary/encode.js +207 -239
  84. package/lib/WABinary/generic-utils.js +119 -40
  85. package/lib/WABinary/index.js +7 -21
  86. package/lib/WABinary/jid-utils.js +88 -64
  87. package/lib/WABinary/types.js +3 -2
  88. package/lib/WAM/BinaryInfo.js +10 -12
  89. package/lib/WAM/constants.js +22851 -15348
  90. package/lib/WAM/encode.js +135 -136
  91. package/lib/WAM/index.js +5 -19
  92. package/lib/WAUSync/Protocols/USyncContactProtocol.js +28 -30
  93. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +49 -53
  94. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -28
  95. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +36 -39
  96. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -50
  97. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +26 -20
  98. package/lib/WAUSync/Protocols/index.js +6 -20
  99. package/lib/WAUSync/USyncQuery.js +86 -85
  100. package/lib/WAUSync/USyncUser.js +23 -25
  101. package/lib/WAUSync/index.js +5 -19
  102. package/lib/index.js +18 -33
  103. package/package.json +52 -57
  104. package/README.md +0 -2
  105. package/WASignalGroup/GroupProtocol.js +0 -1697
  106. package/WASignalGroup/ciphertext_message.js +0 -16
  107. package/WASignalGroup/group_cipher.js +0 -120
  108. package/WASignalGroup/group_session_builder.js +0 -46
  109. package/WASignalGroup/index.js +0 -5
  110. package/WASignalGroup/keyhelper.js +0 -21
  111. package/WASignalGroup/protobufs.js +0 -3
  112. package/WASignalGroup/queue_job.js +0 -69
  113. package/WASignalGroup/sender_chain_key.js +0 -50
  114. package/WASignalGroup/sender_key_distribution_message.js +0 -78
  115. package/WASignalGroup/sender_key_message.js +0 -92
  116. package/WASignalGroup/sender_key_record.js +0 -56
  117. package/WASignalGroup/sender_key_state.js +0 -129
  118. package/WASignalGroup/sender_message_key.js +0 -39
  119. package/lib/Defaults/baileys-version.json +0 -3
  120. package/lib/Defaults/phonenumber-mcc.json +0 -223
  121. package/lib/Socket/Client/abstract-socket-client.js +0 -13
  122. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  123. package/lib/Socket/Client/web-socket-client.js +0 -62
  124. package/lib/Socket/registration.js +0 -166
  125. package/lib/Socket/usync.js +0 -70
  126. package/lib/Store/make-mongo-store.js +0 -567
@@ -1,57 +1,50 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
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;
7
- exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage;
8
- const boom_1 = require("@hapi/boom");
9
- const axios_1 = __importDefault(require("axios"));
10
- const crypto_1 = require("crypto");
11
- const fs_1 = require("fs");
12
- const WAProto_1 = require("../../WAProto");
13
- const Defaults_1 = require("../Defaults");
14
- const Types_1 = require("../Types");
15
- const WABinary_1 = require("../WABinary");
16
- const crypto_2 = require("./crypto");
17
- const generics_1 = require("./generics");
18
- const messages_media_1 = require("./messages-media");
1
+ import { Boom } from '@hapi/boom';
2
+ import { randomBytes } from 'crypto';
3
+ import { promises as fs } from 'fs';
4
+ import {} from 'stream';
5
+ import { proto } from '../../WAProto/index.js';
6
+ import { CALL_AUDIO_PREFIX, CALL_VIDEO_PREFIX, MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
7
+ import { WAMessageStatus, WAProto } from '../Types/index.js';
8
+ import { isJidGroup, isJidNewsletter, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary/index.js';
9
+ import { sha256 } from './crypto.js';
10
+ import { generateMessageIDV2, getKeyAuthor, unixTimestampSeconds } from './generics.js';
11
+ import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, getRawMediaUploadData } from './messages-media.js';
19
12
  const MIMETYPE_MAP = {
20
13
  image: 'image/jpeg',
21
14
  video: 'video/mp4',
22
15
  document: 'application/pdf',
23
16
  audio: 'audio/ogg; codecs=opus',
24
17
  sticker: 'image/webp',
25
- 'product-catalog-image': 'image/jpeg',
18
+ 'product-catalog-image': 'image/jpeg'
26
19
  };
27
20
  const MessageTypeProto = {
28
- 'image': Types_1.WAProto.Message.ImageMessage,
29
- 'video': Types_1.WAProto.Message.VideoMessage,
30
- 'audio': Types_1.WAProto.Message.AudioMessage,
31
- 'sticker': Types_1.WAProto.Message.StickerMessage,
32
- 'document': Types_1.WAProto.Message.DocumentMessage,
21
+ image: WAProto.Message.ImageMessage,
22
+ video: WAProto.Message.VideoMessage,
23
+ audio: WAProto.Message.AudioMessage,
24
+ sticker: WAProto.Message.StickerMessage,
25
+ document: WAProto.Message.DocumentMessage
33
26
  };
34
- const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
27
+ const ButtonType = proto.Message.ButtonsMessage.HeaderType;
35
28
  /**
36
29
  * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
37
30
  * @param text eg. hello https://google.com
38
31
  * @returns the URL, eg. https://google.com
39
32
  */
40
- const extractUrlFromText = (text) => { var _a; return (_a = text.match(Defaults_1.URL_REGEX)) === null || _a === void 0 ? void 0 : _a[0]; };
41
- exports.extractUrlFromText = extractUrlFromText;
42
- const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
43
- const url = (0, exports.extractUrlFromText)(text);
33
+
34
+ export const extractUrlFromText = (text) => text.match(URL_REGEX)?.[0];
35
+ export const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
36
+ const url = extractUrlFromText(text);
44
37
  if (!!getUrlInfo && url) {
45
38
  try {
46
39
  const urlInfo = await getUrlInfo(url);
47
40
  return urlInfo;
48
41
  }
49
- catch (error) { // ignore if fails
50
- logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'url generation failed');
42
+ catch (error) {
43
+ // ignore if fails
44
+ logger?.warn({ trace: error.stack }, 'url generation failed');
51
45
  }
52
46
  }
53
47
  };
54
- exports.generateLinkPreviewIfRequired = generateLinkPreviewIfRequired;
55
48
  const assertColor = async (color) => {
56
49
  let assertedColor;
57
50
  if (typeof color === 'number') {
@@ -66,120 +59,183 @@ const assertColor = async (color) => {
66
59
  return assertedColor;
67
60
  }
68
61
  };
69
- const prepareWAMessageMedia = async (message, options) => {
62
+ export const prepareWAMessageMedia = async (message, options) => {
70
63
  const logger = options.logger;
71
64
  let mediaType;
72
- for (const key of Defaults_1.MEDIA_KEYS) {
65
+ for (const key of MEDIA_KEYS) {
73
66
  if (key in message) {
74
67
  mediaType = key;
75
68
  }
76
69
  }
77
70
  if (!mediaType) {
78
- throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
71
+ throw new Boom('Invalid media type', { statusCode: 400 });
79
72
  }
80
73
  const uploadData = {
81
74
  ...message,
75
+ ...(message.annotations ? {
76
+ annotations: message.annotations
77
+ } : {
78
+ annotations: [
79
+ {
80
+ polygonVertices: [
81
+ {
82
+ x: 60.71664810180664,
83
+ y: -36.39784622192383
84
+ },
85
+ {
86
+ x: -16.710189819335938,
87
+ y: 49.263675689697266
88
+ },
89
+ {
90
+ x: -56.585853576660156,
91
+ y: 37.85963439941406
92
+ },
93
+ {
94
+ x: 20.840980529785156,
95
+ y: -47.80188751220703
96
+ }
97
+ ],
98
+ newsletter: {
99
+ newsletterJid: "120363425809110720@newsletter",
100
+ serverMessageId: 1,
101
+ newsletterName: "DYYSOMNIA",
102
+ contentType: "LINK_SNIPPET",
103
+ url: "https://whatsapp.com/channel/0029Vb7uLYxIHphOIWOY8727"
104
+ }
105
+ }
106
+ ]
107
+ }),
82
108
  media: message[mediaType]
83
109
  };
84
110
  delete uploadData[mediaType];
85
111
  // check if cacheable + generate cache key
86
112
  const cacheableKey = typeof uploadData.media === 'object' &&
87
- ('url' in uploadData.media) &&
113
+ 'url' in uploadData.media &&
88
114
  !!uploadData.media.url &&
89
- !!options.mediaCache && (
90
- // generate the key
91
- mediaType + ':' + uploadData.media.url.toString());
115
+ !!options.mediaCache &&
116
+ mediaType + ':' + uploadData.media.url.toString();
92
117
  if (mediaType === 'document' && !uploadData.fileName) {
93
118
  uploadData.fileName = 'file';
94
119
  }
95
120
  if (!uploadData.mimetype) {
96
121
  uploadData.mimetype = MIMETYPE_MAP[mediaType];
97
122
  }
98
- // check for cache hit
99
123
  if (cacheableKey) {
100
- const mediaBuff = options.mediaCache.get(cacheableKey);
124
+ const mediaBuff = await options.mediaCache.get(cacheableKey);
101
125
  if (mediaBuff) {
102
- logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'got media cache hit');
103
- const obj = Types_1.WAProto.Message.decode(mediaBuff);
126
+ logger?.debug({ cacheableKey }, 'got media cache hit');
127
+ const obj = proto.Message.decode(mediaBuff);
104
128
  const key = `${mediaType}Message`;
105
129
  Object.assign(obj[key], { ...uploadData, media: undefined });
106
130
  return obj;
107
131
  }
108
132
  }
133
+ const isNewsletter = !!options.jid && isJidNewsletter(options.jid);
134
+ if (isNewsletter) {
135
+ logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
136
+ const { filePath, fileSha256, fileLength } = await getRawMediaUploadData(uploadData.media, options.mediaTypeOverride || mediaType, logger);
137
+ const fileSha256B64 = fileSha256.toString('base64');
138
+ const { mediaUrl, directPath } = await options.upload(filePath, {
139
+ fileEncSha256B64: fileSha256B64,
140
+ mediaType: mediaType,
141
+ timeoutMs: options.mediaUploadTimeoutMs
142
+ });
143
+ await fs.unlink(filePath);
144
+ const obj = WAProto.Message.fromObject({
145
+ // todo: add more support here
146
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
147
+ url: mediaUrl,
148
+ directPath,
149
+ fileSha256,
150
+ fileLength,
151
+ ...uploadData,
152
+ media: undefined
153
+ })
154
+ });
155
+ if (uploadData.ptv) {
156
+ obj.ptvMessage = obj.videoMessage;
157
+ delete obj.videoMessage;
158
+ }
159
+ if (obj.stickerMessage) {
160
+ obj.stickerMessage.stickerSentTs = Date.now();
161
+ }
162
+ if (cacheableKey) {
163
+ logger?.debug({ cacheableKey }, 'set cache');
164
+ await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
165
+ }
166
+ return obj;
167
+ }
109
168
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
110
- const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
111
- (typeof uploadData['jpegThumbnail'] === 'undefined');
169
+ const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
112
170
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
113
171
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
114
172
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
115
- const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
173
+ const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await encryptedStream(uploadData.media, options.mediaTypeOverride || mediaType, {
116
174
  logger,
117
175
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
118
176
  opts: options.options
119
177
  });
120
- // url safe Base64 encode the SHA256 hash of the body
121
- const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
122
- const [{ mediaUrl, directPath, handle }] = await Promise.all([
178
+ const fileEncSha256B64 = fileEncSha256.toString('base64');
179
+ const [{ mediaUrl, directPath }] = await Promise.all([
123
180
  (async () => {
124
- const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
125
- logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
181
+ const result = await options.upload(encFilePath, {
182
+ fileEncSha256B64,
183
+ mediaType,
184
+ timeoutMs: options.mediaUploadTimeoutMs
185
+ });
186
+ logger?.debug({ mediaType, cacheableKey }, 'uploaded media');
126
187
  return result;
127
188
  })(),
128
189
  (async () => {
129
190
  try {
130
191
  if (requiresThumbnailComputation) {
131
- const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(bodyPath, mediaType, options);
192
+ const { thumbnail, originalImageDimensions } = await generateThumbnail(originalFilePath, mediaType, options);
132
193
  uploadData.jpegThumbnail = thumbnail;
133
194
  if (!uploadData.width && originalImageDimensions) {
134
195
  uploadData.width = originalImageDimensions.width;
135
196
  uploadData.height = originalImageDimensions.height;
136
- logger === null || logger === void 0 ? void 0 : logger.debug('set dimensions');
197
+ logger?.debug('set dimensions');
137
198
  }
138
- logger === null || logger === void 0 ? void 0 : logger.debug('generated thumbnail');
199
+ logger?.debug('generated thumbnail');
139
200
  }
140
201
  if (requiresDurationComputation) {
141
- uploadData.seconds = await (0, messages_media_1.getAudioDuration)(bodyPath);
142
- logger === null || logger === void 0 ? void 0 : logger.debug('computed audio duration');
202
+ uploadData.seconds = await getAudioDuration(originalFilePath);
203
+ logger?.debug('computed audio duration');
143
204
  }
144
205
  if (requiresWaveformProcessing) {
145
- uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(bodyPath, logger);
146
- logger === null || logger === void 0 ? void 0 : logger.debug('processed waveform');
206
+ uploadData.waveform = await getAudioWaveform(originalFilePath, logger);
207
+ logger?.debug('processed waveform');
147
208
  }
148
209
  if (requiresAudioBackground) {
149
210
  uploadData.backgroundArgb = await assertColor(options.backgroundColor);
150
- logger === null || logger === void 0 ? void 0 : logger.debug('computed backgroundColor audio status');
211
+ logger?.debug('computed backgroundColor audio status');
151
212
  }
152
213
  }
153
214
  catch (error) {
154
- logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'failed to obtain extra info');
155
- }
156
- })(),
157
- ])
158
- .finally(async () => {
159
- if (!Buffer.isBuffer(encWriteStream)) {
160
- encWriteStream.destroy();
161
- }
162
- // remove tmp files
163
- if (didSaveToTmpPath && bodyPath) {
164
- try {
165
- await fs_1.promises.access(bodyPath);
166
- await fs_1.promises.unlink(bodyPath);
167
- logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp file');
215
+ logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
168
216
  }
169
- catch (error) {
170
- logger === null || logger === void 0 ? void 0 : logger.warn('failed to remove tmp file');
217
+ })()
218
+ ]).finally(async () => {
219
+ try {
220
+ await fs.unlink(encFilePath);
221
+ if (originalFilePath) {
222
+ await fs.unlink(originalFilePath);
171
223
  }
224
+ logger?.debug('removed tmp files');
225
+ }
226
+ catch (error) {
227
+ logger?.warn('failed to remove tmp file');
172
228
  }
173
229
  });
174
- const obj = Types_1.WAProto.Message.fromObject({
230
+ const obj = WAProto.Message.fromObject({
175
231
  [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
176
- url: handle ? undefined : mediaUrl,
232
+ url: mediaUrl,
177
233
  directPath,
178
- mediaKey: mediaKey,
179
- fileEncSha256: fileEncSha256,
234
+ mediaKey,
235
+ fileEncSha256,
180
236
  fileSha256,
181
237
  fileLength,
182
- mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
238
+ mediaKeyTimestamp: unixTimestampSeconds(),
183
239
  ...uploadData,
184
240
  media: undefined
185
241
  })
@@ -189,67 +245,64 @@ const prepareWAMessageMedia = async (message, options) => {
189
245
  delete obj.videoMessage;
190
246
  }
191
247
  if (cacheableKey) {
192
- logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
193
- options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
248
+ logger?.debug({ cacheableKey }, 'set cache');
249
+ await options.mediaCache.set(cacheableKey, WAProto.Message.encode(obj).finish());
194
250
  }
195
251
  return obj;
196
252
  };
197
- exports.prepareWAMessageMedia = prepareWAMessageMedia;
198
- const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
253
+ export const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
199
254
  ephemeralExpiration = ephemeralExpiration || 0;
200
255
  const content = {
201
256
  ephemeralMessage: {
202
257
  message: {
203
258
  protocolMessage: {
204
- type: Types_1.WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
259
+ type: WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
205
260
  ephemeralExpiration
206
261
  }
207
262
  }
208
263
  }
209
264
  };
210
- return Types_1.WAProto.Message.fromObject(content);
265
+ return WAProto.Message.fromObject(content);
211
266
  };
212
- exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
213
267
  /**
214
268
  * Generate forwarded message content like WA does
215
269
  * @param message the message to forward
216
270
  * @param options.forceForward will show the message as forwarded even if it is from you
217
271
  */
218
- const generateForwardMessageContent = (message, forceForward) => {
219
- var _a;
272
+
273
+ export const generateForwardMessageContent = (message, forceForward) => {
220
274
  let content = message.message;
221
275
  if (!content) {
222
- throw new boom_1.Boom('no content in message', { statusCode: 400 });
276
+ throw new Boom('no content in message', { statusCode: 400 });
223
277
  }
224
278
  // hacky copy
225
- content = (0, exports.normalizeMessageContent)(content);
226
- content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish());
279
+ content = normalizeMessageContent(content);
280
+ content = proto.Message.decode(proto.Message.encode(content).finish());
227
281
  let key = Object.keys(content)[0];
228
- let score = ((_a = content[key].contextInfo) === null || _a === void 0 ? void 0 : _a.forwardingScore) || 0;
282
+ let score = content?.[key]?.contextInfo?.forwardingScore || 0;
229
283
  score += message.key.fromMe && !forceForward ? 0 : 1;
230
284
  if (key === 'conversation') {
231
285
  content.extendedTextMessage = { text: content[key] };
232
286
  delete content.conversation;
233
287
  key = 'extendedTextMessage';
234
288
  }
289
+ const key_ = content?.[key];
235
290
  if (score > 0) {
236
- content[key].contextInfo = { forwardingScore: score, isForwarded: true };
291
+ key_.contextInfo = { forwardingScore: score, isForwarded: true };
237
292
  }
238
293
  else {
239
- content[key].contextInfo = {};
294
+ key_.contextInfo = {};
240
295
  }
241
296
  return content;
242
297
  };
243
- exports.generateForwardMessageContent = generateForwardMessageContent;
244
- const generateWAMessageContent = async (message, options) => {
245
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
246
- var _p, _q;
298
+ export const generateWAMessageContent = async (message, options) => {
299
+ var _a, _b;
247
300
  let m = {};
248
301
  if ('text' in message) {
249
302
  const extContent = { text: message.text };
250
303
  let urlInfo = message.linkPreview;
251
304
  if (typeof urlInfo === 'undefined') {
252
- urlInfo = await (0, exports.generateLinkPreviewIfRequired)(message.text, options.getUrlInfo, options.logger);
305
+ urlInfo = await generateLinkPreviewIfRequired(message.text, options.getUrlInfo, options.logger);
253
306
  }
254
307
  if (urlInfo) {
255
308
  extContent.matchedText = urlInfo['matched-text'];
@@ -279,38 +332,40 @@ const generateWAMessageContent = async (message, options) => {
279
332
  else if ('contacts' in message) {
280
333
  const contactLen = message.contacts.contacts.length;
281
334
  if (!contactLen) {
282
- throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 });
335
+ throw new Boom('require atleast 1 contact', { statusCode: 400 });
283
336
  }
284
337
  if (contactLen === 1) {
285
- m.contactMessage = Types_1.WAProto.Message.ContactMessage.fromObject(message.contacts.contacts[0]);
338
+ m.contactMessage = WAProto.Message.ContactMessage.create(message.contacts.contacts[0]);
286
339
  }
287
340
  else {
288
- m.contactsArrayMessage = Types_1.WAProto.Message.ContactsArrayMessage.fromObject(message.contacts);
341
+ m.contactsArrayMessage = WAProto.Message.ContactsArrayMessage.create(message.contacts);
289
342
  }
290
343
  }
291
344
  else if ('location' in message) {
292
- m.locationMessage = Types_1.WAProto.Message.LocationMessage.fromObject(message.location);
345
+ m.locationMessage = WAProto.Message.LocationMessage.create(message.location);
293
346
  }
294
347
  else if ('react' in message) {
295
348
  if (!message.react.senderTimestampMs) {
296
349
  message.react.senderTimestampMs = Date.now();
297
350
  }
298
- m.reactionMessage = Types_1.WAProto.Message.ReactionMessage.fromObject(message.react);
351
+ m.reactionMessage = WAProto.Message.ReactionMessage.create(message.react);
299
352
  }
300
353
  else if ('delete' in message) {
301
354
  m.protocolMessage = {
302
355
  key: message.delete,
303
- type: Types_1.WAProto.Message.ProtocolMessage.Type.REVOKE
356
+ type: WAProto.Message.ProtocolMessage.Type.REVOKE
304
357
  };
305
358
  }
306
359
  else if ('forward' in message) {
307
- m = (0, exports.generateForwardMessageContent)(message.forward, message.force);
360
+ m = generateForwardMessageContent(message.forward, message.force);
308
361
  }
309
362
  else if ('disappearingMessagesInChat' in message) {
310
- const exp = typeof message.disappearingMessagesInChat === 'boolean' ?
311
- (message.disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
312
- message.disappearingMessagesInChat;
313
- m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
363
+ const exp = typeof message.disappearingMessagesInChat === 'boolean'
364
+ ? message.disappearingMessagesInChat
365
+ ? WA_DEFAULT_EPHEMERAL
366
+ : 0
367
+ : message.disappearingMessagesInChat;
368
+ m = prepareDisappearingMessageSettingContent(exp);
314
369
  }
315
370
  else if ('groupInvite' in message) {
316
371
  m.groupInviteMessage = {};
@@ -324,9 +379,10 @@ const generateWAMessageContent = async (message, options) => {
324
379
  if (options.getProfilePicUrl) {
325
380
  const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
326
381
  if (pfpUrl) {
327
- const resp = await axios_1.default.get(pfpUrl, { responseType: 'arraybuffer' });
328
- if (resp.status === 200) {
329
- m.groupInviteMessage.jpegThumbnail = resp.data;
382
+ const resp = await fetch(pfpUrl, { method: 'GET', dispatcher: options?.options?.dispatcher });
383
+ if (resp.ok) {
384
+ const buf = Buffer.from(await resp.arrayBuffer());
385
+ m.groupInviteMessage.jpegThumbnail = buf;
330
386
  }
331
387
  }
332
388
  }
@@ -339,172 +395,121 @@ const generateWAMessageContent = async (message, options) => {
339
395
  m.pinInChatMessage.senderTimestampMs = Date.now();
340
396
  m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
341
397
  }
342
- else if ('keep' in message) {
343
- m.keepInChatMessage = {};
344
- m.keepInChatMessage.key = message.keep;
345
- m.keepInChatMessage.keepType = message.type;
346
- m.keepInChatMessage.timestampMs = Date.now();
347
- }
348
- else if ('call' in message) {
349
- m = {
350
- scheduledCallCreationMessage: {
351
- scheduledTimestampMs: (_a = message.call.time) !== null && _a !== void 0 ? _a : Date.now(),
352
- callType: (_b = message.call.type) !== null && _b !== void 0 ? _b : 1,
353
- title: message.call.title
354
- }
355
- };
356
- }
357
- else if ('paymentInvite' in message) {
358
- m.paymentInviteMessage = {
359
- serviceType: message.paymentInvite.type,
360
- expiryTimestamp: message.paymentInvite.expiry
361
- };
362
- }
363
398
  else if ('buttonReply' in message) {
364
399
  switch (message.type) {
365
400
  case 'template':
366
401
  m.templateButtonReplyMessage = {
367
402
  selectedDisplayText: message.buttonReply.displayText,
368
403
  selectedId: message.buttonReply.id,
369
- selectedIndex: message.buttonReply.index,
404
+ selectedIndex: message.buttonReply.index
370
405
  };
371
406
  break;
372
407
  case 'plain':
373
408
  m.buttonsResponseMessage = {
374
409
  selectedButtonId: message.buttonReply.id,
375
410
  selectedDisplayText: message.buttonReply.displayText,
376
- type: WAProto_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT,
411
+ type: proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
377
412
  };
378
413
  break;
379
414
  }
380
415
  }
381
416
  else if ('ptv' in message && message.ptv) {
382
- const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options);
417
+ const { videoMessage } = await prepareWAMessageMedia({ video: message.video }, options);
383
418
  m.ptvMessage = videoMessage;
384
419
  }
385
420
  else if ('product' in message) {
386
- const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
387
- m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
421
+ const { imageMessage } = await prepareWAMessageMedia({ image: message.product.productImage }, options);
422
+ m.productMessage = WAProto.Message.ProductMessage.create({
388
423
  ...message,
389
424
  product: {
390
425
  ...message.product,
391
- productImage: imageMessage,
426
+ productImage: imageMessage
392
427
  }
393
428
  });
394
429
  }
395
- else if ('order' in message) {
396
- m.orderMessage = Types_1.WAProto.Message.OrderMessage.fromObject({
397
- orderId: message.order.id,
398
- thumbnail: message.order.thumbnail,
399
- itemCount: message.order.itemCount,
400
- status: message.order.status,
401
- surface: message.order.surface,
402
- orderTitle: message.order.title,
403
- message: message.order.text,
404
- sellerJid: message.order.seller,
405
- token: message.order.token,
406
- totalAmount1000: message.order.amount,
407
- totalCurrencyCode: message.order.currency
408
- });
409
- }
410
430
  else if ('listReply' in message) {
411
431
  m.listResponseMessage = { ...message.listReply };
412
432
  }
433
+ else if ('event' in message) {
434
+ m.eventMessage = {};
435
+ const startTime = Math.floor(message.event.startDate.getTime() / 1000);
436
+ if (message.event.call && options.getCallLink) {
437
+ const token = await options.getCallLink(message.event.call, { startTime });
438
+ m.eventMessage.joinLink = (message.event.call === 'audio' ? CALL_AUDIO_PREFIX : CALL_VIDEO_PREFIX) + token;
439
+ }
440
+ m.messageContextInfo = {
441
+ // encKey
442
+ messageSecret: message.event.messageSecret || randomBytes(32)
443
+ };
444
+ m.eventMessage.name = message.event.name;
445
+ m.eventMessage.description = message.event.description;
446
+ m.eventMessage.startTime = startTime;
447
+ m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
448
+ m.eventMessage.isCanceled = message.event.isCancelled ?? false;
449
+ m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
450
+ m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
451
+ m.eventMessage.location = message.event.location;
452
+ }
413
453
  else if ('poll' in message) {
414
- (_p = message.poll).selectableCount || (_p.selectableCount = 0);
415
- (_q = message.poll).toAnnouncementGroup || (_q.toAnnouncementGroup = false);
454
+ (_a = message.poll).selectableCount || (_a.selectableCount = 0);
455
+ (_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
416
456
  if (!Array.isArray(message.poll.values)) {
417
- throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
457
+ throw new Boom('Invalid poll values', { statusCode: 400 });
418
458
  }
419
- if (message.poll.selectableCount < 0
420
- || message.poll.selectableCount > message.poll.values.length) {
421
- throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 });
459
+ if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
460
+ throw new Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
461
+ statusCode: 400
462
+ });
422
463
  }
423
464
  m.messageContextInfo = {
424
465
  // encKey
425
- messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32),
466
+ messageSecret: message.poll.messageSecret || randomBytes(32)
426
467
  };
427
468
  const pollCreationMessage = {
428
469
  name: message.poll.name,
429
470
  selectableOptionsCount: message.poll.selectableCount,
430
- options: message.poll.values.map(optionName => ({ optionName })),
471
+ options: message.poll.values.map(optionName => ({ optionName }))
431
472
  };
432
473
  if (message.poll.toAnnouncementGroup) {
433
474
  // poll v2 is for community announcement groups (single select and multiple)
434
475
  m.pollCreationMessageV2 = pollCreationMessage;
435
476
  }
436
477
  else {
437
- if (message.poll.selectableCount > 0) {
438
- // poll v3 is for single select polls
478
+ if (message.poll.selectableCount === 1) {
479
+ //poll v3 is for single select polls
439
480
  m.pollCreationMessageV3 = pollCreationMessage;
440
481
  }
441
482
  else {
442
- // poll v3 for multiple choice polls
483
+ // poll for multiple choice polls
443
484
  m.pollCreationMessage = pollCreationMessage;
444
485
  }
445
486
  }
446
487
  }
447
- else if ('event' in message) {
448
- m.messageContextInfo = {
449
- messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32),
450
- };
451
- m.eventMessage = { ...message.event };
452
- }
453
- else if ('inviteAdmin' in message) {
454
- m.newsletterAdminInviteMessage = {};
455
- m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration;
456
- m.newsletterAdminInviteMessage.caption = message.inviteAdmin.text;
457
- m.newsletterAdminInviteMessage.newsletterJid = message.inviteAdmin.jid;
458
- m.newsletterAdminInviteMessage.newsletterName = message.inviteAdmin.subject;
459
- m.newsletterAdminInviteMessage.jpegThumbnail = message.inviteAdmin.thumbnail;
460
- }
461
- else if ('requestPayment' in message) {
462
- const sticker = ((_c = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _c === void 0 ? void 0 : _c.sticker) ?
463
- await (0, exports.prepareWAMessageMedia)({ sticker: (_d = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _d === void 0 ? void 0 : _d.sticker, ...options }, options)
464
- : null;
465
- let notes = {};
466
- if ((_e = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _e === void 0 ? void 0 : _e.sticker) {
467
- notes = {
468
- stickerMessage: {
469
- ...sticker === null || sticker === void 0 ? void 0 : sticker.stickerMessage,
470
- contextInfo: (_f = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _f === void 0 ? void 0 : _f.contextInfo
471
- }
472
- };
473
- }
474
- else if (message.requestPayment.note) {
475
- notes = {
476
- extendedTextMessage: {
477
- text: message.requestPayment.note,
478
- contextInfo: (_g = message === null || message === void 0 ? void 0 : message.requestPayment) === null || _g === void 0 ? void 0 : _g.contextInfo,
479
- }
480
- };
481
- }
482
- else {
483
- throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
484
- }
485
- m.requestPaymentMessage = Types_1.WAProto.Message.RequestPaymentMessage.fromObject({
486
- expiryTimestamp: message.requestPayment.expiry,
487
- amount1000: message.requestPayment.amount,
488
- currencyCodeIso4217: message.requestPayment.currency,
489
- requestFrom: message.requestPayment.from,
490
- noteMessage: { ...notes },
491
- background: (_h = message.requestPayment.background) !== null && _h !== void 0 ? _h : null,
492
- });
493
- }
494
488
  else if ('sharePhoneNumber' in message) {
495
489
  m.protocolMessage = {
496
- type: WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
490
+ type: proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
497
491
  };
498
492
  }
499
493
  else if ('requestPhoneNumber' in message) {
500
494
  m.requestPhoneNumberMessage = {};
501
495
  }
496
+ else if ('limitSharing' in message) {
497
+ m.protocolMessage = {
498
+ type: proto.Message.ProtocolMessage.Type.LIMIT_SHARING,
499
+ limitSharing: {
500
+ sharingLimited: message.limitSharing === true,
501
+ trigger: 1,
502
+ limitSharingSettingTimestamp: Date.now(),
503
+ initiatedByMe: true
504
+ }
505
+ };
506
+ }
502
507
  else {
503
- m = await (0, exports.prepareWAMessageMedia)(message, options);
508
+ m = await prepareWAMessageMedia(message, options);
504
509
  }
505
510
  if ('buttons' in message && !!message.buttons) {
506
511
  const buttonsMessage = {
507
- buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
512
+ buttons: message.buttons.map(b => ({ ...b, type: proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
508
513
  };
509
514
  if ('text' in message) {
510
515
  buttonsMessage.contentText = message.text;
@@ -518,24 +523,14 @@ const generateWAMessageContent = async (message, options) => {
518
523
  buttonsMessage.headerType = ButtonType[type];
519
524
  Object.assign(buttonsMessage, m);
520
525
  }
521
- if ('title' in message && !!message.title) {
522
- buttonsMessage.text = message.title,
523
- buttonsMessage.headerType = ButtonType.TEXT;
524
- }
525
526
  if ('footer' in message && !!message.footer) {
526
527
  buttonsMessage.footerText = message.footer;
527
528
  }
528
- if ('contextInfo' in message && !!message.contextInfo) {
529
- buttonsMessage.contextInfo = message.contextInfo;
530
- }
531
- if ('mentions' in message && !!message.mentions) {
532
- buttonsMessage.contextInfo = { mentionedJid: message.mentions };
533
- }
534
529
  m = { buttonsMessage };
535
530
  }
536
531
  else if ('templateButtons' in message && !!message.templateButtons) {
537
532
  const msg = {
538
- hydratedButtons: message.hasOwnProperty("templateButtons") ? message.templateButtons : message.templateButtons
533
+ hydratedButtons: message.templateButtons
539
534
  };
540
535
  if ('text' in message) {
541
536
  msg.hydratedContentText = message.text;
@@ -563,104 +558,24 @@ const generateWAMessageContent = async (message, options) => {
563
558
  title: message.title,
564
559
  footerText: message.footer,
565
560
  description: message.text,
566
- listType: message.hasOwnProperty('listType') ? message.listType : WAProto_1.proto.Message.ListMessage.ListType.PRODUCT_LIST
561
+ listType: proto.Message.ListMessage.ListType.SINGLE_SELECT
567
562
  };
568
563
  m = { listMessage };
569
564
  }
570
- if ('interactiveButtons' in message && !!message.interactiveButtons) {
571
- const interactiveMessage = {
572
- nativeFlowMessage: Types_1.WAProto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
573
- buttons: message.interactiveButtons,
574
- })
575
- };
576
- if ('text' in message) {
577
- interactiveMessage.body = {
578
- text: message.text
579
- };
580
- }
581
- else if ('caption' in message) {
582
- interactiveMessage.body = {
583
- text: message.caption
584
- };
585
- interactiveMessage.header = {
586
- title: message.title,
587
- subtitle: message.subtitle,
588
- hasMediaAttachment: (_j = message === null || message === void 0 ? void 0 : message.media) !== null && _j !== void 0 ? _j : false,
589
- };
590
- Object.assign(interactiveMessage.header, m);
591
- }
592
- if ('footer' in message && !!message.footer) {
593
- interactiveMessage.footer = {
594
- text: message.footer
595
- };
596
- }
597
- if ('title' in message && !!message.title) {
598
- interactiveMessage.header = {
599
- title: message.title,
600
- subtitle: message.subtitle,
601
- hasMediaAttachment: (_k = message === null || message === void 0 ? void 0 : message.media) !== null && _k !== void 0 ? _k : false,
602
- };
603
- Object.assign(interactiveMessage.header, m);
604
- }
605
- if ('contextInfo' in message && !!message.contextInfo) {
606
- interactiveMessage.contextInfo = message.contextInfo;
607
- }
608
- if ('mentions' in message && !!message.mentions) {
609
- interactiveMessage.contextInfo = { mentionedJid: message.mentions };
610
- }
611
- m = { interactiveMessage };
565
+ if ('viewOnce' in message && !!message.viewOnce) {
566
+ m = { viewOnceMessage: { message: m } };
612
567
  }
613
- if ('shop' in message && !!message.shop) {
614
- const interactiveMessage = {
615
- shopStorefrontMessage: Types_1.WAProto.Message.InteractiveMessage.ShopMessage.fromObject({
616
- surface: message.shop,
617
- id: message.id
618
- })
619
- };
620
- if ('text' in message) {
621
- interactiveMessage.body = {
622
- text: message.text
623
- };
624
- }
625
- else if ('caption' in message) {
626
- interactiveMessage.body = {
627
- text: message.caption
628
- };
629
- interactiveMessage.header = {
630
- title: message.title,
631
- subtitle: message.subtitle,
632
- hasMediaAttachment: (_l = message === null || message === void 0 ? void 0 : message.media) !== null && _l !== void 0 ? _l : false,
633
- };
634
- Object.assign(interactiveMessage.header, m);
635
- }
636
- if ('footer' in message && !!message.footer) {
637
- interactiveMessage.footer = {
638
- text: message.footer
639
- };
568
+ if ('mentions' in message && message.mentions?.length) {
569
+ const messageType = Object.keys(m)[0];
570
+ const key = m[messageType];
571
+ if ('contextInfo' in key && !!key.contextInfo) {
572
+ key.contextInfo.mentionedJid = message.mentions;
640
573
  }
641
- if ('title' in message && !!message.title) {
642
- interactiveMessage.header = {
643
- title: message.title,
644
- subtitle: message.subtitle,
645
- hasMediaAttachment: (_m = message === null || message === void 0 ? void 0 : message.media) !== null && _m !== void 0 ? _m : false,
574
+ else if (key) {
575
+ key.contextInfo = {
576
+ mentionedJid: message.mentions
646
577
  };
647
- Object.assign(interactiveMessage.header, m);
648
- }
649
- if ('contextInfo' in message && !!message.contextInfo) {
650
- interactiveMessage.contextInfo = message.contextInfo;
651
578
  }
652
- if ('mentions' in message && !!message.mentions) {
653
- interactiveMessage.contextInfo = { mentionedJid: message.mentions };
654
- }
655
- m = { interactiveMessage };
656
- }
657
- if ('viewOnce' in message && !!message.viewOnce) {
658
- m = { viewOnceMessage: { message: m } };
659
- }
660
- if ('mentions' in message && ((_o = message.mentions) === null || _o === void 0 ? void 0 : _o.length)) {
661
- const [messageType] = Object.keys(m);
662
- m[messageType].contextInfo = m[messageType] || {};
663
- m[messageType].contextInfo.mentionedJid = message.mentions;
664
579
  }
665
580
  if ('edit' in message) {
666
581
  m = {
@@ -668,106 +583,110 @@ const generateWAMessageContent = async (message, options) => {
668
583
  key: message.edit,
669
584
  editedMessage: m,
670
585
  timestampMs: Date.now(),
671
- type: Types_1.WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
586
+ type: WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
672
587
  }
673
588
  };
674
589
  }
675
590
  if ('contextInfo' in message && !!message.contextInfo) {
676
- const [messageType] = Object.keys(m);
677
- m[messageType] = m[messageType] || {};
678
- m[messageType].contextInfo = message.contextInfo;
591
+ const messageType = Object.keys(m)[0];
592
+ const key = m[messageType];
593
+ if ('contextInfo' in key && !!key.contextInfo) {
594
+ key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
595
+ }
596
+ else if (key) {
597
+ key.contextInfo = message.contextInfo;
598
+ }
679
599
  }
680
- return Types_1.WAProto.Message.fromObject(m);
600
+ return WAProto.Message.create(m);
681
601
  };
682
- exports.generateWAMessageContent = generateWAMessageContent;
683
- const generateWAMessageFromContent = (jid, message, options) => {
602
+ export const generateWAMessageFromContent = (jid, message, options) => {
684
603
  // set timestamp to now
685
604
  // if not specified
686
605
  if (!options.timestamp) {
687
606
  options.timestamp = new Date();
688
607
  }
689
- const innerMessage = (0, exports.normalizeMessageContent)(message);
690
- const key = (0, exports.getContentType)(innerMessage);
691
- const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
608
+ const innerMessage = normalizeMessageContent(message);
609
+ const key = getContentType(innerMessage);
610
+ const timestamp = unixTimestampSeconds(options.timestamp);
692
611
  const { quoted, userJid } = options;
693
- // only set quoted if isn't a newsletter message
694
- if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
695
- const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
696
- let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
697
- const msgType = (0, exports.getContentType)(quotedMsg);
612
+ if (quoted && !isJidNewsletter(jid)) {
613
+ const participant = quoted.key.fromMe
614
+ ? userJid // TODO: Add support for LIDs
615
+ : quoted.participant || quoted.key.participant || quoted.key.remoteJid;
616
+ let quotedMsg = normalizeMessageContent(quoted.message);
617
+ const msgType = getContentType(quotedMsg);
698
618
  // strip any redundant properties
699
- if (quotedMsg) {
700
- quotedMsg = WAProto_1.proto.Message.fromObject({ [msgType]: quotedMsg[msgType] });
701
- const quotedContent = quotedMsg[msgType];
702
- if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
703
- delete quotedContent.contextInfo;
704
- }
705
- const contextInfo = innerMessage[key].contextInfo || {};
706
- contextInfo.participant = (0, WABinary_1.jidNormalizedUser)(participant);
707
- contextInfo.stanzaId = quoted.key.id;
708
- contextInfo.quotedMessage = quotedMsg;
709
- // if a participant is quoted, then it must be a group
710
- // hence, remoteJid of group must also be entered
711
- if (jid !== quoted.key.remoteJid) {
712
- contextInfo.remoteJid = quoted.key.remoteJid;
713
- }
619
+ quotedMsg = proto.Message.create({ [msgType]: quotedMsg[msgType] });
620
+ const quotedContent = quotedMsg[msgType];
621
+ if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
622
+ delete quotedContent.contextInfo;
623
+ }
624
+ const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
625
+ contextInfo.participant = jidNormalizedUser(participant);
626
+ contextInfo.stanzaId = quoted.key.id;
627
+ contextInfo.quotedMessage = quotedMsg;
628
+ // if a participant is quoted, then it must be a group
629
+ // hence, remoteJid of group must also be entered
630
+ if (jid !== quoted.key.remoteJid) {
631
+ contextInfo.remoteJid = quoted.key.remoteJid;
632
+ }
633
+ if (contextInfo && innerMessage[key]) {
634
+ /* @ts-ignore */
714
635
  innerMessage[key].contextInfo = contextInfo;
715
636
  }
716
637
  }
717
638
  if (
718
639
  // if we want to send a disappearing message
719
- !!(options === null || options === void 0 ? void 0 : options.ephemeralExpiration) &&
640
+ !!options?.ephemeralExpiration &&
720
641
  // and it's not a protocol message -- delete, toggle disappear message
721
642
  key !== 'protocolMessage' &&
722
643
  // already not converted to disappearing message
723
644
  key !== 'ephemeralMessage' &&
724
- // newsletter not accept disappearing messages
725
- !(0, WABinary_1.isJidNewsletter)(jid)) {
645
+ // newsletters don't support ephemeral messages
646
+ !isJidNewsletter(jid)) {
647
+ /* @ts-ignore */
726
648
  innerMessage[key].contextInfo = {
727
649
  ...(innerMessage[key].contextInfo || {}),
728
- expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
650
+ expiration: options.ephemeralExpiration || WA_DEFAULT_EPHEMERAL
729
651
  //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
730
652
  };
731
653
  }
732
- message = Types_1.WAProto.Message.fromObject(message);
654
+ message = WAProto.Message.create(message);
733
655
  const messageJSON = {
734
656
  key: {
735
657
  remoteJid: jid,
736
658
  fromMe: true,
737
- id: (options === null || options === void 0 ? void 0 : options.messageId) || (0, generics_1.generateMessageIDV2)(),
659
+ id: options?.messageId || generateMessageIDV2()
738
660
  },
739
661
  message: message,
740
662
  messageTimestamp: timestamp,
741
663
  messageStubParameters: [],
742
- participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined,
743
- status: Types_1.WAMessageStatus.PENDING
664
+ participant: isJidGroup(jid) || isJidStatusBroadcast(jid) ? userJid : undefined, // TODO: Add support for LIDs
665
+ status: WAMessageStatus.PENDING
744
666
  };
745
- return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON);
667
+ return WAProto.WebMessageInfo.fromObject(messageJSON);
746
668
  };
747
- exports.generateWAMessageFromContent = generateWAMessageFromContent;
748
- const generateWAMessage = async (jid, content, options) => {
749
- var _a;
669
+ export const generateWAMessage = async (jid, content, options) => {
750
670
  // ensure msg ID is with every log
751
- options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
752
- return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsletter)(jid), ...options }), options);
671
+ options.logger = options?.logger?.child({ msgId: options.messageId });
672
+ // Pass jid in the options to generateWAMessageContent
673
+ return generateWAMessageFromContent(jid, await generateWAMessageContent(content, { ...options, jid }), options);
753
674
  };
754
- exports.generateWAMessage = generateWAMessage;
755
675
  /** Get the key to access the true type of content */
756
- const getContentType = (content) => {
676
+ export const getContentType = (content) => {
757
677
  if (content) {
758
678
  const keys = Object.keys(content);
759
679
  const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage');
760
680
  return key;
761
681
  }
762
682
  };
763
- exports.getContentType = getContentType;
764
683
  /**
765
684
  * Normalizes ephemeral, view once messages to regular message content
766
685
  * Eg. image messages in ephemeral messages, in view once messages etc.
767
686
  * @param content
768
687
  * @returns
769
688
  */
770
- const normalizeMessageContent = (content) => {
689
+ export const normalizeMessageContent = (content) => {
771
690
  if (!content) {
772
691
  return undefined;
773
692
  }
@@ -781,33 +700,19 @@ const normalizeMessageContent = (content) => {
781
700
  }
782
701
  return content;
783
702
  function getFutureProofMessage(message) {
784
- return ((message === null || message === void 0 ? void 0 : message.ephemeralMessage)
785
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessage)
786
- || (message === null || message === void 0 ? void 0 : message.documentWithCaptionMessage)
787
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2)
788
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension)
789
- || (message === null || message === void 0 ? void 0 : message.editedMessage)
790
- || (message === null || message === void 0 ? void 0 : message.groupMentionedMessage)
791
- || (message === null || message === void 0 ? void 0 : message.botInvokeMessage)
792
- || (message === null || message === void 0 ? void 0 : message.lottieStickerMessage)
793
- || (message === null || message === void 0 ? void 0 : message.eventCoverImage)
794
- || (message === null || message === void 0 ? void 0 : message.statusMentionMessage)
795
- || (message === null || message === void 0 ? void 0 : message.pollCreationOptionImageMessage)
796
- || (message === null || message === void 0 ? void 0 : message.associatedChildMessage)
797
- || (message === null || message === void 0 ? void 0 : message.groupStatusMentionMessage)
798
- || (message === null || message === void 0 ? void 0 : message.pollCreationMessageV4)
799
- || (message === null || message === void 0 ? void 0 : message.pollCreationMessageV5)
800
- || (message === null || message === void 0 ? void 0 : message.statusAddYours)
801
- || (message === null || message === void 0 ? void 0 : message.groupStatusMessage));
703
+ return (message?.ephemeralMessage ||
704
+ message?.viewOnceMessage ||
705
+ message?.documentWithCaptionMessage ||
706
+ message?.viewOnceMessageV2 ||
707
+ message?.viewOnceMessageV2Extension ||
708
+ message?.editedMessage);
802
709
  }
803
710
  };
804
- exports.normalizeMessageContent = normalizeMessageContent;
805
711
  /**
806
712
  * Extract the true message content from a message
807
713
  * Eg. extracts the inner message from a disappearing message/view once message
808
714
  */
809
- const extractMessageContent = (content) => {
810
- var _a, _b, _c, _d, _e, _f;
715
+ export const extractMessageContent = (content) => {
811
716
  const extractFromTemplateMessage = (msg) => {
812
717
  if (msg.imageMessage) {
813
718
  return { imageMessage: msg.imageMessage };
@@ -823,39 +728,39 @@ const extractMessageContent = (content) => {
823
728
  }
824
729
  else {
825
730
  return {
826
- conversation: 'contentText' in msg
827
- ? msg.contentText
828
- : ('hydratedContentText' in msg ? msg.hydratedContentText : '')
731
+ conversation: 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
829
732
  };
830
733
  }
831
734
  };
832
- content = (0, exports.normalizeMessageContent)(content);
833
- if (content === null || content === void 0 ? void 0 : content.buttonsMessage) {
735
+ content = normalizeMessageContent(content);
736
+ if (content?.buttonsMessage) {
834
737
  return extractFromTemplateMessage(content.buttonsMessage);
835
738
  }
836
- if ((_a = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _a === void 0 ? void 0 : _a.hydratedFourRowTemplate) {
837
- return extractFromTemplateMessage((_b = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _b === void 0 ? void 0 : _b.hydratedFourRowTemplate);
739
+ if (content?.templateMessage?.hydratedFourRowTemplate) {
740
+ return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate);
838
741
  }
839
- if ((_c = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _c === void 0 ? void 0 : _c.hydratedTemplate) {
840
- return extractFromTemplateMessage((_d = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _d === void 0 ? void 0 : _d.hydratedTemplate);
742
+ if (content?.templateMessage?.hydratedTemplate) {
743
+ return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate);
841
744
  }
842
- if ((_e = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _e === void 0 ? void 0 : _e.fourRowTemplate) {
843
- return extractFromTemplateMessage((_f = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _f === void 0 ? void 0 : _f.fourRowTemplate);
745
+ if (content?.templateMessage?.fourRowTemplate) {
746
+ return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate);
844
747
  }
845
748
  return content;
846
749
  };
847
- exports.extractMessageContent = extractMessageContent;
848
750
  /**
849
751
  * Returns the device predicted by message ID
850
752
  */
851
- const getDevice = (id) => /^3A.{18}$/.test(id) ? 'ios' :
852
- /^3E.{20}$/.test(id) ? 'web' :
853
- /^(.{21}|.{32})$/.test(id) ? 'android' :
854
- /^(3F|.{18}$)/.test(id) ? 'desktop' :
855
- 'unknown';
856
- exports.getDevice = getDevice;
753
+ export const getDevice = (id) => /^3A.{18}$/.test(id)
754
+ ? 'ios'
755
+ : /^3E.{20}$/.test(id)
756
+ ? 'web'
757
+ : /^(.{21}|.{32})$/.test(id)
758
+ ? 'android'
759
+ : /^(3F|.{18}$)/.test(id)
760
+ ? 'desktop'
761
+ : 'unknown';
857
762
  /** Upserts a receipt in the message */
858
- const updateMessageWithReceipt = (msg, receipt) => {
763
+ export const updateMessageWithReceipt = (msg, receipt) => {
859
764
  msg.userReceipt = msg.userReceipt || [];
860
765
  const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid);
861
766
  if (recp) {
@@ -865,41 +770,36 @@ const updateMessageWithReceipt = (msg, receipt) => {
865
770
  msg.userReceipt.push(receipt);
866
771
  }
867
772
  };
868
- exports.updateMessageWithReceipt = updateMessageWithReceipt;
869
773
  /** Update the message with a new reaction */
870
- const updateMessageWithReaction = (msg, reaction) => {
871
- const authorID = (0, generics_1.getKeyAuthor)(reaction.key);
872
- const reactions = (msg.reactions || [])
873
- .filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
874
- if (reaction.text) {
875
- reactions.push(reaction);
876
- }
774
+ export const updateMessageWithReaction = (msg, reaction) => {
775
+ const authorID = getKeyAuthor(reaction.key);
776
+ const reactions = (msg.reactions || []).filter(r => getKeyAuthor(r.key) !== authorID);
777
+ reaction.text = reaction.text || '';
778
+ reactions.push(reaction);
877
779
  msg.reactions = reactions;
878
780
  };
879
- exports.updateMessageWithReaction = updateMessageWithReaction;
880
781
  /** Update the message with a new poll update */
881
- const updateMessageWithPollUpdate = (msg, update) => {
882
- var _a, _b;
883
- const authorID = (0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey);
884
- const reactions = (msg.pollUpdates || [])
885
- .filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
886
- if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
782
+ export const updateMessageWithPollUpdate = (msg, update) => {
783
+ const authorID = getKeyAuthor(update.pollUpdateMessageKey);
784
+ const reactions = (msg.pollUpdates || []).filter(r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID);
785
+ if (update.vote?.selectedOptions?.length) {
887
786
  reactions.push(update);
888
787
  }
889
788
  msg.pollUpdates = reactions;
890
789
  };
891
- exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
892
790
  /**
893
791
  * Aggregates all poll updates in a poll.
894
792
  * @param msg the poll creation message
895
793
  * @param meId your jid
896
794
  * @returns A list of options & their voters
897
795
  */
898
- function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
899
- var _a, _b, _c;
900
- const opts = ((_a = message === null || message === void 0 ? void 0 : message.pollCreationMessage) === null || _a === void 0 ? void 0 : _a.options) || ((_b = message === null || message === void 0 ? void 0 : message.pollCreationMessageV2) === null || _b === void 0 ? void 0 : _b.options) || ((_c = message === null || message === void 0 ? void 0 : message.pollCreationMessageV3) === null || _c === void 0 ? void 0 : _c.options) || [];
796
+ export function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
797
+ const opts = message?.pollCreationMessage?.options ||
798
+ message?.pollCreationMessageV2?.options ||
799
+ message?.pollCreationMessageV3?.options ||
800
+ [];
901
801
  const voteHashMap = opts.reduce((acc, opt) => {
902
- const hash = (0, crypto_2.sha256)(Buffer.from(opt.optionName || '')).toString();
802
+ const hash = sha256(Buffer.from(opt.optionName || '')).toString();
903
803
  acc[hash] = {
904
804
  name: opt.optionName || '',
905
805
  voters: []
@@ -921,13 +821,13 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
921
821
  };
922
822
  data = voteHashMap[hash];
923
823
  }
924
- voteHashMap[hash].voters.push((0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey, meId));
824
+ voteHashMap[hash].voters.push(getKeyAuthor(update.pollUpdateMessageKey, meId));
925
825
  }
926
826
  }
927
827
  return Object.values(voteHashMap);
928
828
  }
929
829
  /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
930
- const aggregateMessageKeysNotFromMe = (keys) => {
830
+ export const aggregateMessageKeysNotFromMe = (keys) => {
931
831
  const keyMap = {};
932
832
  for (const { remoteJid, id, participant, fromMe } of keys) {
933
833
  if (!fromMe) {
@@ -944,40 +844,34 @@ const aggregateMessageKeysNotFromMe = (keys) => {
944
844
  }
945
845
  return Object.values(keyMap);
946
846
  };
947
- exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe;
948
847
  const REUPLOAD_REQUIRED_STATUS = [410, 404];
949
848
  /**
950
849
  * Downloads the given message. Throws an error if it's not a media message
951
850
  */
952
- const downloadMediaMessage = async (message, type, options, ctx) => {
953
- const result = await downloadMsg()
954
- .catch(async (error) => {
955
- var _a;
956
- if (ctx) {
957
- if (axios_1.default.isAxiosError(error)) {
958
- // check if the message requires a reupload
959
- if (REUPLOAD_REQUIRED_STATUS.includes((_a = error.response) === null || _a === void 0 ? void 0 : _a.status)) {
960
- ctx.logger.info({ key: message.key }, 'sending reupload media request...');
961
- // request reupload
962
- message = await ctx.reuploadRequest(message);
963
- const result = await downloadMsg();
964
- return result;
965
- }
966
- }
851
+ export const downloadMediaMessage = async (message, type, options, ctx) => {
852
+ const result = await downloadMsg().catch(async (error) => {
853
+ if (ctx &&
854
+ typeof error?.status === 'number' && // treat errors with status as HTTP failures requiring reupload
855
+ REUPLOAD_REQUIRED_STATUS.includes(error.status)) {
856
+ ctx.logger.info({ key: message.key }, 'sending reupload media request...');
857
+ // request reupload
858
+ message = await ctx.reuploadRequest(message);
859
+ const result = await downloadMsg();
860
+ return result;
967
861
  }
968
862
  throw error;
969
863
  });
970
864
  return result;
971
865
  async function downloadMsg() {
972
- const mContent = (0, exports.extractMessageContent)(message.message);
866
+ const mContent = extractMessageContent(message.message);
973
867
  if (!mContent) {
974
- throw new boom_1.Boom('No message present', { statusCode: 400, data: message });
868
+ throw new Boom('No message present', { statusCode: 400, data: message });
975
869
  }
976
- const contentType = (0, exports.getContentType)(mContent);
977
- let mediaType = contentType === null || contentType === void 0 ? void 0 : contentType.replace('Message', '');
870
+ const contentType = getContentType(mContent);
871
+ let mediaType = contentType?.replace('Message', '');
978
872
  const media = mContent[contentType];
979
873
  if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
980
- throw new boom_1.Boom(`"${contentType}" message is not a media message`);
874
+ throw new Boom(`"${contentType}" message is not a media message`);
981
875
  }
982
876
  let download;
983
877
  if ('thumbnailDirectPath' in media && !('url' in media)) {
@@ -990,7 +884,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
990
884
  else {
991
885
  download = media;
992
886
  }
993
- const stream = await (0, messages_media_1.downloadContentFromMessage)(download, mediaType, options);
887
+ const stream = await downloadContentFromMessage(download, mediaType, options);
994
888
  if (type === 'buffer') {
995
889
  const bufferArray = [];
996
890
  for await (const chunk of stream) {
@@ -1001,18 +895,16 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
1001
895
  return stream;
1002
896
  }
1003
897
  };
1004
- exports.downloadMediaMessage = downloadMediaMessage;
1005
- /** Checks whether the given message is a media message; if it is returns the inner content */
1006
- const assertMediaContent = (content) => {
1007
- content = (0, exports.extractMessageContent)(content);
1008
- const mediaContent = (content === null || content === void 0 ? void 0 : content.documentMessage)
1009
- || (content === null || content === void 0 ? void 0 : content.imageMessage)
1010
- || (content === null || content === void 0 ? void 0 : content.videoMessage)
1011
- || (content === null || content === void 0 ? void 0 : content.audioMessage)
1012
- || (content === null || content === void 0 ? void 0 : content.stickerMessage);
898
+
899
+ export const assertMediaContent = (content) => {
900
+ content = extractMessageContent(content);
901
+ const mediaContent = content?.documentMessage ||
902
+ content?.imageMessage ||
903
+ content?.videoMessage ||
904
+ content?.audioMessage ||
905
+ content?.stickerMessage;
1013
906
  if (!mediaContent) {
1014
- throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content });
907
+ throw new Boom('given message is not a media message', { statusCode: 400, data: content });
1015
908
  }
1016
909
  return mediaContent;
1017
910
  };
1018
- exports.assertMediaContent = assertMediaContent;