@realvare/baileys 1.0.0

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 (201) hide show
  1. package/LICENSE +41 -0
  2. package/README.MD +2227 -0
  3. package/WAProto/GenerateStatics.sh +4 -0
  4. package/WAProto/WAProto.proto +5604 -0
  5. package/WAProto/index.d.ts +63156 -0
  6. package/WAProto/index.js +195638 -0
  7. package/WAProto/p.html +1 -0
  8. package/engine-requirements.js +10 -0
  9. package/lib/Defaults/baileys-version.json +3 -0
  10. package/lib/Defaults/index.d.ts +53 -0
  11. package/lib/Defaults/index.js +108 -0
  12. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  13. package/lib/Signal/Group/ciphertext-message.js +15 -0
  14. package/lib/Signal/Group/group-session-builder.d.ts +14 -0
  15. package/lib/Signal/Group/group-session-builder.js +64 -0
  16. package/lib/Signal/Group/group_cipher.d.ts +17 -0
  17. package/lib/Signal/Group/group_cipher.js +96 -0
  18. package/lib/Signal/Group/index.d.ts +11 -0
  19. package/lib/Signal/Group/index.js +57 -0
  20. package/lib/Signal/Group/keyhelper.d.ts +10 -0
  21. package/lib/Signal/Group/keyhelper.js +55 -0
  22. package/lib/Signal/Group/queue-job.d.ts +1 -0
  23. package/lib/Signal/Group/queue-job.js +57 -0
  24. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  25. package/lib/Signal/Group/sender-chain-key.js +34 -0
  26. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  27. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  28. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  29. package/lib/Signal/Group/sender-key-message.js +69 -0
  30. package/lib/Signal/Group/sender-key-name.d.ts +17 -0
  31. package/lib/Signal/Group/sender-key-name.js +51 -0
  32. package/lib/Signal/Group/sender-key-record.d.ts +30 -0
  33. package/lib/Signal/Group/sender-key-record.js +53 -0
  34. package/lib/Signal/Group/sender-key-state.d.ts +38 -0
  35. package/lib/Signal/Group/sender-key-state.js +99 -0
  36. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  37. package/lib/Signal/Group/sender-message-key.js +29 -0
  38. package/lib/Signal/libsignal.d.ts +3 -0
  39. package/lib/Signal/libsignal.js +174 -0
  40. package/lib/Socket/Client/index.d.ts +2 -0
  41. package/lib/Socket/Client/index.js +18 -0
  42. package/lib/Socket/Client/types.d.ts +16 -0
  43. package/lib/Socket/Client/types.js +13 -0
  44. package/lib/Socket/Client/websocket.d.ts +13 -0
  45. package/lib/Socket/Client/websocket.js +111 -0
  46. package/lib/Socket/business.d.ts +172 -0
  47. package/lib/Socket/business.js +260 -0
  48. package/lib/Socket/chats.d.ts +85 -0
  49. package/lib/Socket/chats.js +1094 -0
  50. package/lib/Socket/groups.d.ts +124 -0
  51. package/lib/Socket/groups.js +423 -0
  52. package/lib/Socket/index.d.ts +172 -0
  53. package/lib/Socket/index.js +32 -0
  54. package/lib/Socket/messages-interactive.js +259 -0
  55. package/lib/Socket/messages-recv.d.ts +161 -0
  56. package/lib/Socket/messages-recv.js +1518 -0
  57. package/lib/Socket/messages-send.d.ts +151 -0
  58. package/lib/Socket/messages-send.js +1085 -0
  59. package/lib/Socket/newsletter.d.ts +136 -0
  60. package/lib/Socket/newsletter.js +250 -0
  61. package/lib/Socket/socket.d.ts +43 -0
  62. package/lib/Socket/socket.js +1269 -0
  63. package/lib/Socket/usync.d.ts +36 -0
  64. package/lib/Socket/usync.js +123 -0
  65. package/lib/Store/index.d.ts +2 -0
  66. package/lib/Store/index.js +8 -0
  67. package/lib/Store/make-in-memory-store.d.ts +118 -0
  68. package/lib/Store/make-in-memory-store.js +499 -0
  69. package/lib/Store/make-ordered-dictionary.d.ts +13 -0
  70. package/lib/Store/make-ordered-dictionary.js +81 -0
  71. package/lib/Store/object-repository.d.ts +10 -0
  72. package/lib/Store/object-repository.js +27 -0
  73. package/lib/Types/Auth.d.ts +114 -0
  74. package/lib/Types/Auth.js +2 -0
  75. package/lib/Types/Call.d.ts +13 -0
  76. package/lib/Types/Call.js +2 -0
  77. package/lib/Types/Chat.d.ts +109 -0
  78. package/lib/Types/Chat.js +4 -0
  79. package/lib/Types/Contact.d.ts +29 -0
  80. package/lib/Types/Contact.js +2 -0
  81. package/lib/Types/Events.d.ts +199 -0
  82. package/lib/Types/Events.js +2 -0
  83. package/lib/Types/GroupMetadata.d.ts +64 -0
  84. package/lib/Types/GroupMetadata.js +2 -0
  85. package/lib/Types/Label.d.ts +35 -0
  86. package/lib/Types/Label.js +27 -0
  87. package/lib/Types/LabelAssociation.d.ts +29 -0
  88. package/lib/Types/LabelAssociation.js +9 -0
  89. package/lib/Types/Message.d.ts +741 -0
  90. package/lib/Types/Message.js +7 -0
  91. package/lib/Types/Newsletter.d.ts +22 -0
  92. package/lib/Types/Newsletter.js +18 -0
  93. package/lib/Types/Product.d.ts +78 -0
  94. package/lib/Types/Product.js +2 -0
  95. package/lib/Types/Signal.d.ts +63 -0
  96. package/lib/Types/Signal.js +2 -0
  97. package/lib/Types/Socket.d.ts +134 -0
  98. package/lib/Types/Socket.js +2 -0
  99. package/lib/Types/State.d.ts +27 -0
  100. package/lib/Types/State.js +2 -0
  101. package/lib/Types/USync.d.ts +25 -0
  102. package/lib/Types/USync.js +2 -0
  103. package/lib/Types/index.d.ts +65 -0
  104. package/lib/Types/index.js +43 -0
  105. package/lib/Utils/auth-utils.d.ts +18 -0
  106. package/lib/Utils/auth-utils.js +209 -0
  107. package/lib/Utils/baileys-event-stream.d.ts +16 -0
  108. package/lib/Utils/baileys-event-stream.js +63 -0
  109. package/lib/Utils/business.d.ts +22 -0
  110. package/lib/Utils/business.js +234 -0
  111. package/lib/Utils/cache-manager.d.ts +16 -0
  112. package/lib/Utils/cache-manager.js +137 -0
  113. package/lib/Utils/chat-utils.d.ts +70 -0
  114. package/lib/Utils/chat-utils.js +734 -0
  115. package/lib/Utils/crypto.d.ts +40 -0
  116. package/lib/Utils/crypto.js +193 -0
  117. package/lib/Utils/decode-wa-message.d.ts +35 -0
  118. package/lib/Utils/decode-wa-message.js +207 -0
  119. package/lib/Utils/event-buffer.d.ts +35 -0
  120. package/lib/Utils/event-buffer.js +624 -0
  121. package/lib/Utils/generics.d.ts +89 -0
  122. package/lib/Utils/generics.js +448 -0
  123. package/lib/Utils/history.d.ts +19 -0
  124. package/lib/Utils/history.js +94 -0
  125. package/lib/Utils/index.d.ts +22 -0
  126. package/lib/Utils/index.js +38 -0
  127. package/lib/Utils/jid-validation.d.ts +2 -0
  128. package/lib/Utils/jid-validation.js +186 -0
  129. package/lib/Utils/link-preview.d.ts +21 -0
  130. package/lib/Utils/link-preview.js +152 -0
  131. package/lib/Utils/logger.d.ts +11 -0
  132. package/lib/Utils/logger.js +59 -0
  133. package/lib/Utils/lt-hash.d.ts +12 -0
  134. package/lib/Utils/lt-hash.js +51 -0
  135. package/lib/Utils/make-mutex.d.ts +7 -0
  136. package/lib/Utils/make-mutex.js +43 -0
  137. package/lib/Utils/messages-media.d.ts +120 -0
  138. package/lib/Utils/messages-media.js +848 -0
  139. package/lib/Utils/messages.d.ts +131 -0
  140. package/lib/Utils/messages.js +1843 -0
  141. package/lib/Utils/newsletter-utils.d.ts +2 -0
  142. package/lib/Utils/newsletter-utils.js +48 -0
  143. package/lib/Utils/noise-handler.d.ts +19 -0
  144. package/lib/Utils/noise-handler.js +150 -0
  145. package/lib/Utils/performance-config.d.ts +70 -0
  146. package/lib/Utils/performance-config.js +183 -0
  147. package/lib/Utils/process-message.d.ts +42 -0
  148. package/lib/Utils/process-message.js +498 -0
  149. package/lib/Utils/rate-limiter.js +90 -0
  150. package/lib/Utils/retry.js +66 -0
  151. package/lib/Utils/signal.d.ts +33 -0
  152. package/lib/Utils/signal.js +153 -0
  153. package/lib/Utils/use-multi-file-auth-state.d.ts +12 -0
  154. package/lib/Utils/use-multi-file-auth-state.js +129 -0
  155. package/lib/Utils/validate-connection.d.ts +10 -0
  156. package/lib/Utils/validate-connection.js +233 -0
  157. package/lib/WABinary/constants.d.ts +27 -0
  158. package/lib/WABinary/constants.js +1303 -0
  159. package/lib/WABinary/decode.d.ts +6 -0
  160. package/lib/WABinary/decode.js +279 -0
  161. package/lib/WABinary/encode.d.ts +2 -0
  162. package/lib/WABinary/encode.js +264 -0
  163. package/lib/WABinary/generic-utils.d.ts +14 -0
  164. package/lib/WABinary/generic-utils.js +114 -0
  165. package/lib/WABinary/index.d.ts +5 -0
  166. package/lib/WABinary/index.js +21 -0
  167. package/lib/WABinary/jid-utils.d.ts +38 -0
  168. package/lib/WABinary/jid-utils.js +402 -0
  169. package/lib/WABinary/types.d.ts +18 -0
  170. package/lib/WABinary/types.js +2 -0
  171. package/lib/WAM/BinaryInfo.d.ts +8 -0
  172. package/lib/WAM/BinaryInfo.js +13 -0
  173. package/lib/WAM/constants.d.ts +38 -0
  174. package/lib/WAM/constants.js +15350 -0
  175. package/lib/WAM/encode.d.ts +2 -0
  176. package/lib/WAM/encode.js +155 -0
  177. package/lib/WAM/index.d.ts +3 -0
  178. package/lib/WAM/index.js +19 -0
  179. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -0
  180. package/lib/WAUSync/Protocols/USyncContactProtocol.js +102 -0
  181. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  182. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +110 -0
  183. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  184. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  185. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  186. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  187. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +25 -0
  188. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  189. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +8 -0
  190. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  191. package/lib/WAUSync/Protocols/index.d.ts +4 -0
  192. package/lib/WAUSync/Protocols/index.js +20 -0
  193. package/lib/WAUSync/USyncQuery.d.ts +28 -0
  194. package/lib/WAUSync/USyncQuery.js +147 -0
  195. package/lib/WAUSync/USyncUser.d.ts +12 -0
  196. package/lib/WAUSync/USyncUser.js +26 -0
  197. package/lib/WAUSync/index.d.ts +3 -0
  198. package/lib/WAUSync/index.js +19 -0
  199. package/lib/index.d.ts +17 -0
  200. package/lib/index.js +53 -0
  201. package/package.json +109 -0
@@ -0,0 +1,1843 @@
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.clearCache = exports.getCacheStats = exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = exports.updateMessageWithPollUpdate = exports.updateMessageWithReaction = exports.updateMessageWithReceipt = exports.getDevice = exports.extractMessageContent = exports.normalizeMessageContent = exports.getContentType = exports.generateWAMessage = exports.generateWAMessageFromContent = exports.generateWAMessageContent = exports.generateForwardMessageContent = exports.prepareDisappearingMessageSettingContent = exports.prepareWAMessageMedia = exports.generateLinkPreviewIfRequired = exports.extractUrlFromText = void 0;
7
+ 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");
19
+ const MIMETYPE_MAP = {
20
+ image: 'image/jpeg',
21
+ video: 'video/mp4',
22
+ document: 'application/pdf',
23
+ audio: 'audio/ogg; codecs=opus',
24
+ sticker: 'image/webp',
25
+ 'product-catalog-image': 'image/jpeg',
26
+ };
27
+ const normalizeMentionedJids = (mentions) => {
28
+ if (!Array.isArray(mentions) || !mentions.length) {
29
+ return mentions;
30
+ }
31
+ return mentions
32
+ .map(jid => {
33
+ if (!jid || typeof jid !== 'string') {
34
+ return jid;
35
+ }
36
+ let out = jid;
37
+ if (out.endsWith('@bot')) {
38
+ out = (0, WABinary_1.getBotJid)(out);
39
+ }
40
+ out = (0, WABinary_1.resolveJid)(out);
41
+ return out;
42
+ })
43
+ .filter(jid => !!jid);
44
+ };
45
+ const MessageTypeProto = {
46
+ 'image': Types_1.WAProto.Message.ImageMessage,
47
+ 'video': Types_1.WAProto.Message.VideoMessage,
48
+ 'audio': Types_1.WAProto.Message.AudioMessage,
49
+ 'sticker': Types_1.WAProto.Message.StickerMessage,
50
+ 'document': Types_1.WAProto.Message.DocumentMessage,
51
+ };
52
+ const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
53
+ /**
54
+ * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
55
+ * @param text eg. hello https://google.com
56
+ * @returns the URL, eg. https://google.com
57
+ */
58
+ const extractUrlFromText = (text) => { var _a; return (_a = text.match(Defaults_1.URL_REGEX)) === null || _a === void 0 ? void 0 : _a[0]; };
59
+ exports.extractUrlFromText = extractUrlFromText;
60
+ const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
61
+ const url = (0, exports.extractUrlFromText)(text);
62
+ if (!!getUrlInfo && url) {
63
+ try {
64
+ const urlInfo = await getUrlInfo(url);
65
+ return urlInfo;
66
+ }
67
+ catch (error) { // ignore if fails
68
+ logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'url generation failed');
69
+ }
70
+ }
71
+ };
72
+ exports.generateLinkPreviewIfRequired = generateLinkPreviewIfRequired;
73
+ const assertColor = async (color) => {
74
+ let assertedColor;
75
+ if (typeof color === 'number') {
76
+ assertedColor = color > 0 ? color : 0xffffffff + Number(color) + 1;
77
+ return assertedColor;
78
+ }
79
+ else {
80
+ let hex = color.trim().replace('#', '');
81
+ if (hex.length <= 6) {
82
+ hex = 'FF' + hex.padStart(6, '0');
83
+ }
84
+ assertedColor = parseInt(hex, 16);
85
+ return assertedColor;
86
+ }
87
+ };
88
+ const prepareWAMessageMedia = async (message, options) => {
89
+ const logger = options.logger;
90
+ let mediaType;
91
+ for (const key of Defaults_1.MEDIA_KEYS) {
92
+ if (key in message) {
93
+ mediaType = key;
94
+ }
95
+ }
96
+ if (!mediaType) {
97
+ throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
98
+ }
99
+ const uploadData = {
100
+ ...message,
101
+ media: message[mediaType]
102
+ };
103
+ delete uploadData[mediaType];
104
+ // check if cacheable + generate cache key
105
+ const cacheableKey = typeof uploadData.media === 'object' &&
106
+ ('url' in uploadData.media) &&
107
+ !!uploadData.media.url &&
108
+ !!options.mediaCache && (
109
+ // generate the key
110
+ mediaType + ':' + uploadData.media.url.toString());
111
+ if (mediaType === 'document' && !uploadData.fileName) {
112
+ uploadData.fileName = 'file';
113
+ }
114
+ if (!uploadData.mimetype) {
115
+ uploadData.mimetype = MIMETYPE_MAP[mediaType];
116
+ }
117
+ // check for cache hit
118
+ if (cacheableKey) {
119
+ const mediaBuff = options.mediaCache.get(cacheableKey);
120
+ if (mediaBuff) {
121
+ logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'got media cache hit');
122
+ const obj = Types_1.WAProto.Message.decode(mediaBuff);
123
+ const key = `${mediaType}Message`;
124
+ Object.assign(obj[key], { ...uploadData, media: undefined });
125
+ return obj;
126
+ }
127
+ }
128
+ const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
129
+ const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
130
+ (typeof uploadData['jpegThumbnail'] === 'undefined');
131
+ const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
132
+ const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
133
+ const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
134
+ const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
135
+ logger,
136
+ saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
137
+ opts: options.options
138
+ });
139
+ const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
140
+ const [{ mediaUrl, directPath, handle }] = await Promise.all([
141
+ (async () => {
142
+ const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
143
+ logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
144
+ return result;
145
+ })(),
146
+ (async () => {
147
+ try {
148
+ if (requiresThumbnailComputation) {
149
+ const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(bodyPath, mediaType, options);
150
+ uploadData.jpegThumbnail = thumbnail;
151
+ if (!uploadData.width && originalImageDimensions) {
152
+ uploadData.width = originalImageDimensions.width;
153
+ uploadData.height = originalImageDimensions.height;
154
+ logger === null || logger === void 0 ? void 0 : logger.debug('set dimensions');
155
+ }
156
+ logger === null || logger === void 0 ? void 0 : logger.debug('generated thumbnail');
157
+ }
158
+ if (requiresDurationComputation) {
159
+ uploadData.seconds = await (0, messages_media_1.getAudioDuration)(bodyPath);
160
+ logger === null || logger === void 0 ? void 0 : logger.debug('computed audio duration');
161
+ }
162
+ if (requiresWaveformProcessing) {
163
+ uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(bodyPath, logger);
164
+ logger === null || logger === void 0 ? void 0 : logger.debug('processed waveform');
165
+ }
166
+ if (requiresAudioBackground) {
167
+ uploadData.backgroundArgb = await assertColor(options.backgroundColor);
168
+ logger === null || logger === void 0 ? void 0 : logger.debug('computed backgroundColor audio status');
169
+ }
170
+ }
171
+ catch (error) {
172
+ logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'failed to obtain extra info');
173
+ }
174
+ })(),
175
+ ])
176
+ .finally(async () => {
177
+ if (!Buffer.isBuffer(encWriteStream)) {
178
+ encWriteStream.destroy();
179
+ }
180
+ // remove tmp files
181
+ if (didSaveToTmpPath && bodyPath) {
182
+ try {
183
+ await fs_1.promises.access(bodyPath);
184
+ await fs_1.promises.unlink(bodyPath);
185
+ logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp file');
186
+ }
187
+ catch (error) {
188
+ logger === null || logger === void 0 ? void 0 : logger.warn('failed to remove tmp file');
189
+ }
190
+ }
191
+ });
192
+ const obj = Types_1.WAProto.Message.fromObject({
193
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
194
+ url: handle ? undefined : mediaUrl,
195
+ directPath,
196
+ mediaKey: mediaKey,
197
+ fileEncSha256: fileEncSha256,
198
+ fileSha256,
199
+ fileLength,
200
+ mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
201
+ ...uploadData,
202
+ media: undefined
203
+ })
204
+ });
205
+ if (uploadData.ptv) {
206
+ obj.ptvMessage = obj.videoMessage;
207
+ delete obj.videoMessage;
208
+ }
209
+ if (cacheableKey) {
210
+ logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
211
+ options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
212
+ }
213
+ return obj;
214
+ };
215
+ exports.prepareWAMessageMedia = prepareWAMessageMedia;
216
+ const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
217
+ ephemeralExpiration = ephemeralExpiration || 0;
218
+ const content = {
219
+ ephemeralMessage: {
220
+ message: {
221
+ protocolMessage: {
222
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
223
+ ephemeralExpiration
224
+ }
225
+ }
226
+ }
227
+ };
228
+ return Types_1.WAProto.Message.fromObject(content);
229
+ };
230
+ exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
231
+ /**
232
+ * Generate forwarded message content like WA does
233
+ * @param message the message to forward
234
+ * @param options.forceForward will show the message as forwarded even if it is from you
235
+ */
236
+ const generateForwardMessageContent = (message, forceForward) => {
237
+ var _a;
238
+ let content = message.message;
239
+ if (!content) {
240
+ throw new boom_1.Boom('no content in message', { statusCode: 400 });
241
+ }
242
+ // hacky copy
243
+ content = (0, exports.normalizeMessageContent)(content);
244
+ content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish());
245
+ let key = Object.keys(content)[0];
246
+ let score = ((_a = content[key].contextInfo) === null || _a === void 0 ? void 0 : _a.forwardingScore) || 0;
247
+ score += message.key.fromMe && !forceForward ? 0 : 1;
248
+ if (key === 'conversation') {
249
+ content.extendedTextMessage = { text: content[key] };
250
+ delete content.conversation;
251
+ key = 'extendedTextMessage';
252
+ }
253
+ if (score > 0) {
254
+ content[key].contextInfo = { forwardingScore: score, isForwarded: true };
255
+ }
256
+ else {
257
+ content[key].contextInfo = {};
258
+ }
259
+ return content;
260
+ };
261
+ exports.generateForwardMessageContent = generateForwardMessageContent;
262
+ const generateWAMessageContent = async (message, options) => {
263
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
264
+ var _p, _q;
265
+
266
+ // Cross-platform externalAdReply thumbnail handling
267
+ const fixupExternalAdReplyThumb = async (externalAdReply) => {
268
+ const thumbUrl = externalAdReply.originalImageUrl || externalAdReply.thumbnailUrl;
269
+ const currentThumb = externalAdReply.thumbnail;
270
+ const currentThumbLen = currentThumb && typeof currentThumb.length === 'number' ? currentThumb.length : 0;
271
+ if (thumbUrl && (!currentThumb || currentThumbLen < 2000)) {
272
+ try {
273
+ const stream = await (0, messages_media_1.getHttpStream)(thumbUrl, {
274
+ timeout: 8000,
275
+ headers: {
276
+ 'User-Agent': 'WhatsApp/2.23.20.15 iOS/16.0 Device/iPhone'
277
+ }
278
+ });
279
+ const { buffer } = await (0, messages_media_1.extractImageThumb)(stream, 512, 80);
280
+ externalAdReply.thumbnail = buffer;
281
+ }
282
+ catch (error) {
283
+ options.logger?.warn('Failed to generate externalAdReply thumbnail for cross-platform compatibility:', error.message);
284
+ }
285
+ }
286
+ if (externalAdReply.renderLargerThumbnail === undefined) {
287
+ externalAdReply.renderLargerThumbnail = true;
288
+ }
289
+ return externalAdReply;
290
+ };
291
+ if (message.contextInfo?.externalAdReply) {
292
+ message.contextInfo.externalAdReply = await fixupExternalAdReplyThumb(message.contextInfo.externalAdReply);
293
+ }
294
+ if (message.externalAdReply) {
295
+ message.externalAdReply = await fixupExternalAdReplyThumb(message.externalAdReply);
296
+ }
297
+
298
+ let m = {};
299
+ if ('text' in message) {
300
+ const extContent = { text: message.text };
301
+ let urlInfo = message.linkPreview;
302
+ if (urlInfo === true) {
303
+ urlInfo = await (0, exports.generateLinkPreviewIfRequired)(message.text, options.getUrlInfo, options.logger);
304
+ }
305
+ if (urlInfo && typeof urlInfo === 'object') {
306
+ extContent.matchedText = urlInfo['matched-text'];
307
+ extContent.jpegThumbnail = urlInfo.jpegThumbnail;
308
+ extContent.description = urlInfo.description;
309
+ extContent.title = urlInfo.title;
310
+ extContent.previewType = 0;
311
+ const img = urlInfo.highQualityThumbnail;
312
+ if (img) {
313
+ extContent.thumbnailDirectPath = img.directPath;
314
+ extContent.mediaKey = img.mediaKey;
315
+ extContent.mediaKeyTimestamp = img.mediaKeyTimestamp;
316
+ extContent.thumbnailWidth = img.width;
317
+ extContent.thumbnailHeight = img.height;
318
+ extContent.thumbnailSha256 = img.fileSha256;
319
+ extContent.thumbnailEncSha256 = img.fileEncSha256;
320
+ }
321
+ }
322
+ if (options.backgroundColor) {
323
+ extContent.backgroundArgb = await assertColor(options.backgroundColor);
324
+ }
325
+ if (options.font) {
326
+ extContent.font = options.font;
327
+ }
328
+ m.extendedTextMessage = extContent;
329
+ }
330
+ else if ('contacts' in message) {
331
+ const contactLen = message.contacts.contacts.length;
332
+ if (!contactLen) {
333
+ throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 });
334
+ }
335
+ if (contactLen === 1) {
336
+ m.contactMessage = Types_1.WAProto.Message.ContactMessage.fromObject(message.contacts.contacts[0]);
337
+ }
338
+ else {
339
+ m.contactsArrayMessage = Types_1.WAProto.Message.ContactsArrayMessage.fromObject(message.contacts);
340
+ }
341
+ }
342
+ else if ('location' in message) {
343
+ m.locationMessage = Types_1.WAProto.Message.LocationMessage.fromObject(message.location);
344
+ }
345
+ else if ('liveLocation' in message) {
346
+ m.liveLocationMessage = Types_1.WAProto.Message.LiveLocationMessage.fromObject(message.liveLocation);
347
+ }
348
+ else if ('react' in message) {
349
+ if (!message.react.senderTimestampMs) {
350
+ message.react.senderTimestampMs = Date.now();
351
+ }
352
+ m.reactionMessage = Types_1.WAProto.Message.ReactionMessage.fromObject(message.react);
353
+ }
354
+ else if ('delete' in message) {
355
+ m.protocolMessage = {
356
+ key: message.delete,
357
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.REVOKE
358
+ };
359
+ }
360
+ else if ('forward' in message) {
361
+ m = (0, exports.generateForwardMessageContent)(message.forward, message.force);
362
+ }
363
+ else if ('disappearingMessagesInChat' in message) {
364
+ const exp = typeof message.disappearingMessagesInChat === 'boolean' ?
365
+ (message.disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
366
+ message.disappearingMessagesInChat;
367
+ m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
368
+ }
369
+ else if ('groupInvite' in message) {
370
+ m.groupInviteMessage = {};
371
+ m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
372
+ m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
373
+ m.groupInviteMessage.caption = message.groupInvite.text;
374
+ m.groupInviteMessage.groupJid = message.groupInvite.jid;
375
+ m.groupInviteMessage.groupName = message.groupInvite.subject;
376
+
377
+ // Get group metadata to obtain disappearing mode and other group info
378
+ if (options.groupMetadata) {
379
+ try {
380
+ const groupMetadata = await options.groupMetadata(message.groupInvite.jid);
381
+ if (groupMetadata) {
382
+ // Add disappearing mode info if available
383
+ if (groupMetadata.ephemeralDuration !== undefined) {
384
+ m.groupInviteMessage.ephemeralDuration = groupMetadata.ephemeralDuration;
385
+ }
386
+ // Add group subject from metadata if not provided in message
387
+ if (!m.groupInviteMessage.groupName && groupMetadata.subject) {
388
+ m.groupInviteMessage.groupName = groupMetadata.subject;
389
+ }
390
+ // Add group participant count
391
+ if (groupMetadata.participants) {
392
+ m.groupInviteMessage.groupSize = groupMetadata.participants.length;
393
+ }
394
+ }
395
+ } catch (error) {
396
+ options.logger?.debug({ error, jid: message.groupInvite.jid }, 'Failed to fetch group metadata for invite');
397
+ }
398
+ }
399
+
400
+ // Handle profile picture with caching
401
+ if (options.getProfilePicUrl) {
402
+ const cacheKey = `group_pfp:${message.groupInvite.jid}`;
403
+
404
+ // Check cache first if available
405
+ if (options.cache && options.cache.get) {
406
+ const cachedPfp = options.cache.get(cacheKey);
407
+ if (cachedPfp) {
408
+ m.groupInviteMessage.jpegThumbnail = cachedPfp;
409
+ }
410
+ }
411
+
412
+ // Fetch if not in cache
413
+ if (!m.groupInviteMessage.jpegThumbnail) {
414
+ try {
415
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
416
+ if (pfpUrl) {
417
+ const resp = await axios_1.default.get(pfpUrl, {
418
+ responseType: 'arraybuffer',
419
+ timeout: 5000,
420
+ headers: {
421
+ 'User-Agent': 'WhatsApp/2.23.20.15 iOS/16.0 Device/iPhone'
422
+ }
423
+ });
424
+ if (resp.status === 200) {
425
+ m.groupInviteMessage.jpegThumbnail = resp.data;
426
+
427
+ // Cache the result if cache is available
428
+ if (options.cache && options.cache.set) {
429
+ options.cache.set(cacheKey, resp.data, 3600); // Cache for 1 hour
430
+ }
431
+ }
432
+ }
433
+ } catch (error) {
434
+ options.logger?.debug({ error, jid: message.groupInvite.jid }, 'Failed to fetch group profile picture');
435
+ }
436
+ }
437
+ }
438
+ }
439
+ else if ('pin' in message) {
440
+ const pinData = typeof message.pin === 'object' ? message.pin : { key: message.pin };
441
+ // Map type: 1 = PIN_FOR_ALL, 2 = UNPIN_FOR_ALL
442
+ const pinType = pinData.type !== undefined ? pinData.type : (message.type !== undefined ? message.type : WAProto_1.proto.Message.PinInChatMessage.Type.PIN_FOR_ALL);
443
+ m.pinInChatMessage = {
444
+ key: pinData.key,
445
+ type: pinType,
446
+ senderTimestampMs: Date.now()
447
+ };
448
+ // Add messageContextInfo only for PIN (type 1), not for UNPIN (type 2)
449
+ if (pinType === WAProto_1.proto.Message.PinInChatMessage.Type.PIN_FOR_ALL) {
450
+ m.messageContextInfo = {
451
+ messageAddOnDurationInSecs: pinData.time || message.time || 86400, // Default 24 hours
452
+ messageAddOnExpiryType: WAProto_1.proto.MessageContextInfo.MessageAddonExpiryType.STATIC
453
+ };
454
+ }
455
+ }
456
+ else if ('keep' in message) {
457
+ m.keepInChatMessage = {};
458
+ m.keepInChatMessage.key = message.keep;
459
+ m.keepInChatMessage.keepType = message.type;
460
+ m.keepInChatMessage.timestampMs = Date.now();
461
+ }
462
+ else if ('call' in message) {
463
+ const call = message.call;
464
+ if (call && typeof call === 'object' && (
465
+ 'callKey' in call
466
+ || 'conversionSource' in call
467
+ || 'conversionData' in call
468
+ || 'conversionDelaySeconds' in call
469
+ || 'ctwaSignals' in call
470
+ || 'ctwaPayload' in call
471
+ || 'nativeFlowCallButtonPayload' in call
472
+ || 'deeplinkPayload' in call
473
+ )) {
474
+ m.call = WAProto_1.proto.Message.Call.fromObject(call);
475
+ }
476
+ else {
477
+ m = {
478
+ scheduledCallCreationMessage: {
479
+ scheduledTimestampMs: (_a = call === null || call === void 0 ? void 0 : call.time) !== null && _a !== void 0 ? _a : Date.now(),
480
+ callType: (_b = call === null || call === void 0 ? void 0 : call.type) !== null && _b !== void 0 ? _b : 1,
481
+ title: call === null || call === void 0 ? void 0 : call.title
482
+ }
483
+ };
484
+ }
485
+ }
486
+ else if ('paymentInvite' in message) {
487
+ m.paymentInviteMessage = {
488
+ serviceType: message.paymentInvite.type,
489
+ expiryTimestamp: message.paymentInvite.expiry
490
+ };
491
+ }
492
+ else if ('buttonReply' in message) {
493
+ switch (message.type) {
494
+ case 'template':
495
+ m.templateButtonReplyMessage = {
496
+ selectedDisplayText: message.buttonReply.displayText,
497
+ selectedId: message.buttonReply.id,
498
+ selectedIndex: message.buttonReply.index,
499
+ selectedCarouselCardIndex: message.buttonReply.carouselCardIndex
500
+ };
501
+ break;
502
+ case 'plain':
503
+ m.buttonsResponseMessage = {
504
+ selectedButtonId: message.buttonReply.id,
505
+ selectedDisplayText: message.buttonReply.displayText,
506
+ type: WAProto_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT,
507
+ };
508
+ break;
509
+ }
510
+ }
511
+ else if ('ptv' in message && message.ptv) {
512
+ const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options);
513
+ m.ptvMessage = videoMessage;
514
+ }
515
+ else if ('product' in message) {
516
+ const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
517
+ m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
518
+ ...message,
519
+ product: {
520
+ ...message.product,
521
+ productImage: imageMessage,
522
+ }
523
+ });
524
+ }
525
+ else if ('order' in message) {
526
+ m.orderMessage = Types_1.WAProto.Message.OrderMessage.fromObject({
527
+ orderId: message.order.id,
528
+ thumbnail: message.order.thumbnail,
529
+ itemCount: message.order.itemCount,
530
+ status: message.order.status,
531
+ surface: message.order.surface,
532
+ orderTitle: message.order.title,
533
+ message: message.order.text,
534
+ sellerJid: message.order.seller,
535
+ token: message.order.token,
536
+ totalAmount1000: message.order.amount,
537
+ totalCurrencyCode: message.order.currency
538
+ });
539
+ }
540
+ else if ('listReply' in message) {
541
+ m.listResponseMessage = { ...message.listReply };
542
+ }
543
+ else if ('poll' in message) {
544
+ (_p = message.poll).selectableCount || (_p.selectableCount = 0);
545
+ (_q = message.poll).toAnnouncementGroup || (_q.toAnnouncementGroup = false);
546
+ if (!Array.isArray(message.poll.values)) {
547
+ throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
548
+ }
549
+ if (message.poll.selectableCount < 0
550
+ || message.poll.selectableCount > message.poll.values.length) {
551
+ throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 });
552
+ }
553
+ m.messageContextInfo = {
554
+ // encKey
555
+ messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32),
556
+ };
557
+ const pollCreationMessage = {
558
+ name: message.poll.name,
559
+ selectableOptionsCount: message.poll.selectableCount,
560
+ options: message.poll.values.map(optionName => ({ optionName })),
561
+ };
562
+ if (message.poll.toAnnouncementGroup) {
563
+ // poll v2 is for community announcement groups (single select and multiple)
564
+ m.pollCreationMessageV2 = pollCreationMessage;
565
+ }
566
+ else {
567
+ if (message.poll.selectableCount === 1) {
568
+ // poll v3 is for single select polls
569
+ m.pollCreationMessageV3 = pollCreationMessage;
570
+ }
571
+ else {
572
+ // poll for multiple choice polls
573
+ m.pollCreationMessage = pollCreationMessage;
574
+ }
575
+ }
576
+ }
577
+ else if ('pollResultSnapshotV3' in message && !!message.pollResultSnapshotV3) {
578
+ m.pollResultSnapshotMessageV3 = {
579
+ pollCreationMessageKey: message.pollResultSnapshotV3.pollCreationMessageKey,
580
+ pollResult: message.pollResultSnapshotV3.pollResult,
581
+ selectedOptions: message.pollResultSnapshotV3.selectedOptions,
582
+ contextInfo: message.pollResultSnapshotV3.contextInfo,
583
+ pollType: message.pollResultSnapshotV3.pollType
584
+ };
585
+ }
586
+ else if ('pollV4' in message) {
587
+ const pollCreationMessage = {
588
+ name: message.pollV4.name,
589
+ selectableOptionsCount: message.pollV4.selectableCount,
590
+ options: message.pollV4.values.map(optionName => ({ optionName })),
591
+ pollType: message.pollV4.pollType
592
+ };
593
+ m.pollCreationMessageV4 = pollCreationMessage;
594
+ }
595
+ else if ('pollV5' in message) {
596
+ const pollCreationMessage = {
597
+ name: message.pollV5.name,
598
+ selectableOptionsCount: message.pollV5.selectableCount,
599
+ options: message.pollV5.values.map(optionName => ({ optionName })),
600
+ pollType: message.pollV5.pollType
601
+ };
602
+ m.pollCreationMessageV5 = pollCreationMessage;
603
+ }
604
+ else if ('event' in message) {
605
+ m.messageContextInfo = {
606
+ messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32),
607
+ };
608
+ m.eventMessage = { ...message.event };
609
+ }
610
+ else if ('comment' in message) {
611
+ m.commentMessage = {
612
+ message: message.comment.message,
613
+ targetMessageKey: message.comment.targetMessageKey
614
+ };
615
+ }
616
+ else if ('question' in message) {
617
+ m.questionMessage = {
618
+ text: message.question.text,
619
+ contextInfo: message.question.contextInfo
620
+ };
621
+ }
622
+ else if ('questionResponse' in message) {
623
+ m.questionResponseMessage = {
624
+ key: message.questionResponse.key,
625
+ text: message.questionResponse.text
626
+ };
627
+ }
628
+ else if ('statusQuestionAnswer' in message) {
629
+ m.statusQuestionAnswerMessage = {
630
+ key: message.statusQuestionAnswer.key,
631
+ text: message.statusQuestionAnswer.text
632
+ };
633
+ }
634
+ else if ('statusQuoted' in message) {
635
+ m.statusQuotedMessage = {
636
+ type: message.statusQuoted.type,
637
+ text: message.statusQuoted.text,
638
+ thumbnail: message.statusQuoted.thumbnail,
639
+ originalStatusId: message.statusQuoted.originalStatusId
640
+ };
641
+ }
642
+ else if ('statusStickerInteraction' in message) {
643
+ m.statusStickerInteractionMessage = {
644
+ key: message.statusStickerInteraction.key,
645
+ stickerKey: message.statusStickerInteraction.stickerKey,
646
+ type: message.statusStickerInteraction.type
647
+ };
648
+ }
649
+ else if ('richResponse' in message) {
650
+ m.richResponseMessage = WAProto_1.proto.AIRichResponseMessage.fromObject({
651
+ messageType: message.richResponse.messageType !== undefined ? message.richResponse.messageType : 1, // AI_RICH_RESPONSE_TYPE_STANDARD
652
+ submessages: message.richResponse.submessages || [],
653
+ unifiedResponse: message.richResponse.unifiedResponse,
654
+ contextInfo: message.richResponse.contextInfo
655
+ });
656
+ }
657
+ else if ('eventResponse' in message && !!message.eventResponse) {
658
+ m.eventResponseMessage = {
659
+ response: message.eventResponse.response, // GOING = 1, NOT_GOING = 2, MAYBE = 3
660
+ timestampMs: message.eventResponse.timestampMs || Date.now(),
661
+ extraGuestCount: message.eventResponse.extraGuestCount
662
+ };
663
+ }
664
+ else if ('statusMention' in message && !!message.statusMention) {
665
+ m.statusMentionMessage = {
666
+ quotedStatus: message.statusMention.quotedStatus
667
+ };
668
+ }
669
+ else if ('groupStatus' in message && !!message.groupStatus) {
670
+ m.groupStatusMessage = message.groupStatus.message;
671
+ }
672
+ else if ('botTask' in message && !!message.botTask) {
673
+ m.botTaskMessage = message.botTask.message;
674
+ }
675
+ else if ('limitSharing' in message && !!message.limitSharing) {
676
+ m.limitSharingMessage = message.limitSharing.message;
677
+ }
678
+ else if ('statusAddYours' in message && !!message.statusAddYours) {
679
+ m.statusAddYours = message.statusAddYours.message;
680
+ }
681
+ else if ('botForwarded' in message && !!message.botForwarded) {
682
+ m.botForwardedMessage = message.botForwarded.message;
683
+ }
684
+ else if ('eventCoverImage' in message && !!message.eventCoverImage) {
685
+ m.eventCoverImage = message.eventCoverImage.message;
686
+ }
687
+ else if ('stickerPack' in message && !!message.stickerPack) {
688
+ const pack = message.stickerPack;
689
+ const stickerPackId = pack.stickerPackId || crypto_1.randomUUID();
690
+ const stickerPackMessage = {
691
+ name: pack.name || '',
692
+ publisher: pack.publisher || '',
693
+ packDescription: pack.description || '',
694
+ stickerPackId,
695
+ stickerPackOrigin: pack.origin ?? 2, // USER_CREATED = 2
696
+ contextInfo: pack.contextInfo || {}
697
+ };
698
+ if (pack.stickers && pack.stickers.length > 0) {
699
+ const processedStickers = [];
700
+ const stickerMediaResults = [];
701
+ let totalStickerSize = 0;
702
+ for (const sticker of pack.stickers) {
703
+ const stickerMedia = await (0, exports.prepareWAMessageMedia)({ sticker: sticker.sticker }, options);
704
+ const stickerMsg = stickerMedia.stickerMessage;
705
+ stickerMediaResults.push(stickerMsg);
706
+ const fileName = sticker.fileName
707
+ || (stickerMsg.fileSha256
708
+ ? Buffer.from(stickerMsg.fileSha256).toString('base64') + '.webp'
709
+ : `sticker_${Date.now()}.webp`);
710
+ totalStickerSize += Number(stickerMsg.fileLength || 0);
711
+ processedStickers.push({
712
+ fileName,
713
+ isAnimated: sticker.isAnimated || false,
714
+ emojis: sticker.emojis || [''],
715
+ accessibilityLabel: sticker.accessibilityLabel || '',
716
+ isLottie: sticker.isLottie || false,
717
+ mimetype: sticker.mimetype || stickerMsg.mimetype || 'image/webp'
718
+ });
719
+ }
720
+ stickerPackMessage.stickers = processedStickers;
721
+ stickerPackMessage.stickerPackSize = totalStickerSize;
722
+ // Pack-level media fields from the first sticker upload
723
+ const firstMedia = stickerMediaResults[0];
724
+ stickerPackMessage.fileSha256 = firstMedia.fileSha256;
725
+ stickerPackMessage.fileEncSha256 = firstMedia.fileEncSha256;
726
+ stickerPackMessage.mediaKey = firstMedia.mediaKey;
727
+ stickerPackMessage.directPath = firstMedia.directPath;
728
+ stickerPackMessage.fileLength = firstMedia.fileLength;
729
+ stickerPackMessage.mediaKeyTimestamp = firstMedia.mediaKeyTimestamp;
730
+ // imageDataHash = base64(hex(sha256))
731
+ if (firstMedia.fileSha256) {
732
+ const hexHash = Buffer.from(firstMedia.fileSha256).toString('hex');
733
+ stickerPackMessage.imageDataHash = Buffer.from(hexHash).toString('base64');
734
+ }
735
+ // Thumbnail/tray icon
736
+ stickerPackMessage.trayIconFileName = stickerPackId + '.png';
737
+ if (pack.cover) {
738
+ const coverMedia = await (0, exports.prepareWAMessageMedia)({ sticker: pack.cover }, options);
739
+ const coverMsg = coverMedia.stickerMessage;
740
+ stickerPackMessage.thumbnailDirectPath = coverMsg.directPath;
741
+ stickerPackMessage.thumbnailSha256 = coverMsg.fileSha256;
742
+ stickerPackMessage.thumbnailEncSha256 = coverMsg.fileEncSha256;
743
+ stickerPackMessage.thumbnailHeight = coverMsg.height || 252;
744
+ stickerPackMessage.thumbnailWidth = coverMsg.width || 252;
745
+ } else {
746
+ stickerPackMessage.thumbnailDirectPath = firstMedia.directPath;
747
+ stickerPackMessage.thumbnailSha256 = firstMedia.fileSha256;
748
+ stickerPackMessage.thumbnailEncSha256 = firstMedia.fileEncSha256;
749
+ stickerPackMessage.thumbnailHeight = firstMedia.height || 252;
750
+ stickerPackMessage.thumbnailWidth = firstMedia.width || 252;
751
+ }
752
+ }
753
+ if (pack.caption) {
754
+ stickerPackMessage.caption = pack.caption;
755
+ }
756
+ m.stickerPackMessage = stickerPackMessage;
757
+ }
758
+ else if ('interactiveResponse' in message && !!message.interactiveResponse) {
759
+ const response = message.interactiveResponse;
760
+ const interactiveResponseMessage = {
761
+ body: {
762
+ text: response.body?.text || '',
763
+ format: response.body?.format || 0 // DEFAULT = 0
764
+ }
765
+ };
766
+ if (response.nativeFlowResponse) {
767
+ interactiveResponseMessage.nativeFlowResponseMessage = {
768
+ name: response.nativeFlowResponse.name,
769
+ paramsJson: response.nativeFlowResponse.paramsJson,
770
+ version: response.nativeFlowResponse.version || 1
771
+ };
772
+ }
773
+ if (response.contextInfo) {
774
+ interactiveResponseMessage.contextInfo = response.contextInfo;
775
+ }
776
+ m.interactiveResponseMessage = interactiveResponseMessage;
777
+ }
778
+ else if ('bCall' in message && !!message.bCall) {
779
+ m.bcallMessage = {
780
+ sessionId: message.bCall.sessionId,
781
+ mediaType: message.bCall.mediaType || 0, // UNKNOWN = 0, AUDIO = 1, VIDEO = 2
782
+ masterKey: message.bCall.masterKey,
783
+ caption: message.bCall.caption
784
+ };
785
+ }
786
+ else if ('callLog' in message && !!message.callLog) {
787
+ m.callLogMesssage = {
788
+ isVideo: message.callLog.isVideo || false,
789
+ callOutcome: message.callLog.callOutcome || 0, // CONNECTED = 0
790
+ durationSecs: message.callLog.durationSecs,
791
+ callType: message.callLog.callType || 0, // REGULAR = 0
792
+ participants: message.callLog.participants || []
793
+ };
794
+ }
795
+ else if ('encComment' in message && !!message.encComment) {
796
+ m.encCommentMessage = {
797
+ targetMessageKey: message.encComment.targetMessageKey,
798
+ encPayload: message.encComment.encPayload,
799
+ encIv: message.encComment.encIv
800
+ };
801
+ }
802
+ else if ('encEventResponse' in message && !!message.encEventResponse) {
803
+ m.encEventResponseMessage = {
804
+ eventCreationMessageKey: message.encEventResponse.eventCreationMessageKey,
805
+ encPayload: message.encEventResponse.encPayload,
806
+ encIv: message.encEventResponse.encIv
807
+ };
808
+ }
809
+ else if ('messageHistoryBundle' in message && !!message.messageHistoryBundle) {
810
+ const bundle = message.messageHistoryBundle;
811
+ const bundleMedia = bundle.media ? await (0, exports.prepareWAMessageMedia)({ document: bundle.media }, options) : null;
812
+ m.messageHistoryBundle = {
813
+ mimetype: bundle.mimetype || 'application/octet-stream',
814
+ fileSha256: bundleMedia?.documentMessage?.fileSha256,
815
+ mediaKey: bundleMedia?.documentMessage?.mediaKey,
816
+ fileEncSha256: bundleMedia?.documentMessage?.fileEncSha256,
817
+ directPath: bundleMedia?.documentMessage?.directPath,
818
+ mediaKeyTimestamp: bundleMedia?.documentMessage?.mediaKeyTimestamp,
819
+ contextInfo: bundle.contextInfo,
820
+ messageHistoryMetadata: bundle.messageHistoryMetadata
821
+ };
822
+ }
823
+ else if ('messageHistoryNotice' in message && !!message.messageHistoryNotice) {
824
+ m.messageHistoryNotice = {
825
+ contextInfo: message.messageHistoryNotice.contextInfo,
826
+ messageHistoryMetadata: message.messageHistoryNotice.messageHistoryMetadata
827
+ };
828
+ }
829
+ else if ('inviteFollower' in message && !!message.inviteFollower) {
830
+ m.newsletterFollowerInviteMessageV2 = {
831
+ newsletterJid: message.inviteFollower.newsletterJid,
832
+ newsletterName: message.inviteFollower.newsletterName,
833
+ jpegThumbnail: message.inviteFollower.thumbnail,
834
+ caption: message.inviteFollower.caption,
835
+ contextInfo: message.inviteFollower.contextInfo
836
+ };
837
+ }
838
+ else if ('placeholder' in message && !!message.placeholder) {
839
+ m.placeholderMessage = {
840
+ type: message.placeholder.type || 0 // MASK_LINKED_DEVICES = 0
841
+ };
842
+ }
843
+ else if ('secretEncrypted' in message && !!message.secretEncrypted) {
844
+ m.secretEncryptedMessage = {
845
+ targetMessageKey: message.secretEncrypted.targetMessageKey,
846
+ encPayload: message.secretEncrypted.encPayload,
847
+ encIv: message.secretEncrypted.encIv,
848
+ secretEncType: message.secretEncrypted.secretEncType || 0 // UNKNOWN = 0, EVENT_EDIT = 1, MESSAGE_EDIT = 2
849
+ };
850
+ }
851
+ else if ('statusNotification' in message && !!message.statusNotification) {
852
+ m.statusNotificationMessage = {
853
+ responseMessageKey: message.statusNotification.responseMessageKey,
854
+ originalMessageKey: message.statusNotification.originalMessageKey,
855
+ type: message.statusNotification.type || 0 // UNKNOWN = 0, STATUS_ADD_YOURS = 1, STATUS_RESHARE = 2, STATUS_QUESTION_ANSWER_RESHARE = 3
856
+ };
857
+ }
858
+ else if ('stickerSyncRMR' in message && !!message.stickerSyncRMR) {
859
+ m.stickerSyncRmrMessage = {
860
+ filehash: message.stickerSyncRMR.filehash || [],
861
+ rmrSource: message.stickerSyncRMR.rmrSource,
862
+ requestTimestamp: message.stickerSyncRMR.requestTimestamp || Date.now()
863
+ };
864
+ }
865
+ else if ('inviteAdmin' in message) {
866
+ m.newsletterAdminInviteMessage = {};
867
+ m.newsletterAdminInviteMessage.inviteExpiration = message.inviteAdmin.inviteExpiration;
868
+ m.newsletterAdminInviteMessage.caption = message.inviteAdmin.text;
869
+ m.newsletterAdminInviteMessage.newsletterJid = message.inviteAdmin.jid;
870
+ m.newsletterAdminInviteMessage.newsletterName = message.inviteAdmin.subject;
871
+ m.newsletterAdminInviteMessage.jpegThumbnail = message.inviteAdmin.thumbnail;
872
+ }
873
+ else if ('requestPayment' in message) {
874
+ const reqPayment = message.requestPayment;
875
+ const sticker = reqPayment.sticker ?
876
+ await (0, exports.prepareWAMessageMedia)({ sticker: reqPayment.sticker }, options)
877
+ : null;
878
+ let notes = {};
879
+ if (reqPayment.sticker) {
880
+ notes = {
881
+ stickerMessage: {
882
+ ...sticker.stickerMessage,
883
+ contextInfo: reqPayment.contextInfo
884
+ }
885
+ };
886
+ }
887
+ else if (reqPayment.note) {
888
+ notes = {
889
+ extendedTextMessage: {
890
+ text: reqPayment.note,
891
+ contextInfo: reqPayment.contextInfo,
892
+ }
893
+ };
894
+ }
895
+ else {
896
+ throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
897
+ }
898
+ m.requestPaymentMessage = Types_1.WAProto.Message.RequestPaymentMessage.fromObject({
899
+ expiryTimestamp: reqPayment.expiryTimestamp || reqPayment.expiry,
900
+ amount1000: reqPayment.amount1000 || reqPayment.amount,
901
+ currencyCodeIso4217: reqPayment.currencyCodeIso4217 || reqPayment.currency,
902
+ requestFrom: reqPayment.requestFrom || reqPayment.from,
903
+ noteMessage: { ...notes },
904
+ background: reqPayment.background,
905
+ // Aggiungi altri parametri se disponibili
906
+ ...reqPayment
907
+ });
908
+
909
+ // Pix adaptation for Brazilian payments
910
+ if (reqPayment.currencyCodeIso4217 === 'BRL' && reqPayment.pixKey) {
911
+ // Embed Pix key in note for dynamic requests
912
+ if (!m.requestPaymentMessage.noteMessage.extendedTextMessage) {
913
+ m.requestPaymentMessage.noteMessage = { extendedTextMessage: { text: '' } };
914
+ }
915
+ m.requestPaymentMessage.noteMessage.extendedTextMessage.text += `\nPix Key: ${reqPayment.pixKey}`;
916
+ }
917
+ }
918
+ else if ('sharePhoneNumber' in message) {
919
+ m.protocolMessage = {
920
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
921
+ };
922
+ }
923
+ else if ('requestPhoneNumber' in message) {
924
+ m.requestPhoneNumberMessage = {};
925
+ }
926
+ else if ('newsletterMessage' in message) {
927
+ m.newsletterMessage = Types_1.WAProto.Message.NewsletterMessage.fromObject(message.newsletterMessage);
928
+ }
929
+ else if ('externalAdReply' in message) {
930
+ // Handle sendNyanCat functionality - external ad reply
931
+ const extAdReply = message.externalAdReply;
932
+ m.extendedTextMessage = {
933
+ text: message.text || '',
934
+ contextInfo: {
935
+ externalAdReply: {
936
+ title: extAdReply.title,
937
+ body: extAdReply.body,
938
+ mediaType: extAdReply.mediaType || 1,
939
+ thumbnailUrl: extAdReply.thumbnailUrl,
940
+ thumbnail: extAdReply.thumbnail,
941
+ sourceUrl: extAdReply.sourceUrl,
942
+ showAdAttribution: extAdReply.showAdAttribution || false,
943
+ renderLargerThumbnail: extAdReply.renderLargerThumbnail !== false
944
+ }
945
+ }
946
+ };
947
+ }
948
+ else if ('sendPayment' in message && !!message.sendPayment) {
949
+ const payment = message.sendPayment;
950
+ m.sendPaymentMessage = {
951
+ requestMessageKey: payment.requestMessageKey,
952
+ noteMessage: payment.noteMessage,
953
+ background: payment.background,
954
+ transactionData: payment.transactionData
955
+ };
956
+ }
957
+ else if ('declinePayment' in message && !!message.declinePayment) {
958
+ m.declinePaymentRequestMessage = {
959
+ key: message.declinePayment.key
960
+ };
961
+ }
962
+ else if ('cancelPayment' in message && !!message.cancelPayment) {
963
+ m.cancelPaymentRequestMessage = {
964
+ key: message.cancelPayment.key
965
+ };
966
+ }
967
+ else if ('scheduledCallEdit' in message && !!message.scheduledCallEdit) {
968
+ m.scheduledCallEditMessage = {
969
+ key: message.scheduledCallEdit.key,
970
+ editType: message.scheduledCallEdit.editType || 0 // UNKNOWN = 0, CANCEL = 1
971
+ };
972
+ }
973
+ else if ('pollResultSnapshot' in message && !!message.pollResultSnapshot) {
974
+ m.pollResultSnapshotMessage = {
975
+ name: message.pollResultSnapshot.name,
976
+ pollVotes: message.pollResultSnapshot.pollVotes || [],
977
+ contextInfo: message.pollResultSnapshot.contextInfo,
978
+ pollType: message.pollResultSnapshot.pollType || 0 // POLL = 0, QUIZ = 1
979
+ };
980
+ }
981
+ else if ('pollUpdate' in message && !!message.pollUpdate) {
982
+ m.pollUpdateMessage = {
983
+ pollCreationMessageKey: message.pollUpdate.pollCreationMessageKey,
984
+ vote: message.pollUpdate.vote,
985
+ metadata: message.pollUpdate.metadata,
986
+ senderTimestampMs: message.pollUpdate.senderTimestampMs || Date.now()
987
+ };
988
+ }
989
+ else if ('deviceSent' in message && !!message.deviceSent) {
990
+ const deviceSent = message.deviceSent;
991
+ const innerMessage = await (0, exports.generateWAMessageContent)(deviceSent.message, options);
992
+ m.deviceSentMessage = {
993
+ destinationJid: deviceSent.destinationJid,
994
+ message: innerMessage,
995
+ phash: deviceSent.phash
996
+ };
997
+ }
998
+ else if ('chat' in message && !!message.chat) {
999
+ m.chat = {
1000
+ displayName: message.chat.displayName,
1001
+ id: message.chat.id
1002
+ };
1003
+ }
1004
+ else if ('payment' in message) {
1005
+ // Handle sendPayment functionality
1006
+ m.requestPaymentMessage = Types_1.WAProto.Message.RequestPaymentMessage.fromObject({
1007
+ currencyCodeIso4217: message.payment.currency || 'EUR',
1008
+ amount1000: message.payment.amount1000 || message.payment.amount * 1000,
1009
+ requestFrom: message.payment.requestFrom || message.payment.from,
1010
+ noteMessage: {
1011
+ extendedTextMessage: {
1012
+ text: message.payment.text || message.payment.note || '',
1013
+ contextInfo: message.payment.contextInfo
1014
+ }
1015
+ },
1016
+ expiryTimestamp: message.payment.expiryTimestamp || message.payment.expiry,
1017
+ background: message.payment.background
1018
+ });
1019
+ }
1020
+ else if ('comment' in message) {
1021
+ m.commentMessage = {
1022
+ message: message.comment.message,
1023
+ targetMessageKey: message.comment.targetMessageKey
1024
+ };
1025
+ }
1026
+ else if ('question' in message) {
1027
+ m.questionMessage = {
1028
+ text: message.question.text,
1029
+ contextInfo: message.question.contextInfo
1030
+ };
1031
+ }
1032
+ else if ('questionResponse' in message) {
1033
+ m.questionResponseMessage = {
1034
+ key: message.questionResponse.key,
1035
+ text: message.questionResponse.text
1036
+ };
1037
+ }
1038
+ else if ('statusQuestionAnswer' in message) {
1039
+ m.statusQuestionAnswerMessage = {
1040
+ key: message.statusQuestionAnswer.key,
1041
+ text: message.statusQuestionAnswer.text
1042
+ };
1043
+ }
1044
+ else if ('statusQuoted' in message) {
1045
+ m.statusQuotedMessage = {
1046
+ type: message.statusQuoted.type,
1047
+ text: message.statusQuoted.text,
1048
+ thumbnail: message.statusQuoted.thumbnail,
1049
+ jid: message.statusQuoted.jid,
1050
+ originalStatusId: message.statusQuoted.originalStatusId
1051
+ };
1052
+ }
1053
+ else if ('statusStickerInteraction' in message) {
1054
+ m.statusStickerInteractionMessage = {
1055
+ key: message.statusStickerInteraction.key,
1056
+ stickerKey: message.statusStickerInteraction.stickerKey,
1057
+ type: message.statusStickerInteraction.type
1058
+ };
1059
+ }
1060
+ else if ('album' in message) {
1061
+ const imageMessages = message.album.filter(item => 'image' in item);
1062
+ const videoMessages = message.album.filter(item => 'video' in item);
1063
+ m.albumMessage = WAProto_1.proto.Message.AlbumMessage.fromObject({
1064
+ expectedImageCount: imageMessages.length,
1065
+ expectedVideoCount: videoMessages.length,
1066
+ });
1067
+ }
1068
+ else {
1069
+ m = await (0, exports.prepareWAMessageMedia)(message, options);
1070
+ }
1071
+ if ('buttons' in message && !!message.buttons) {
1072
+ const buttonsMessage = {
1073
+ buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
1074
+ };
1075
+ if ('text' in message) {
1076
+ buttonsMessage.contentText = message.text;
1077
+ buttonsMessage.headerType = ButtonType.EMPTY;
1078
+ }
1079
+ else {
1080
+ if ('caption' in message) {
1081
+ buttonsMessage.contentText = message.caption;
1082
+ }
1083
+ const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
1084
+ buttonsMessage.headerType = ButtonType[type];
1085
+ Object.assign(buttonsMessage, m);
1086
+ }
1087
+ if ('title' in message && !!message.title) {
1088
+ buttonsMessage.text = message.title,
1089
+ buttonsMessage.headerType = ButtonType.TEXT;
1090
+ }
1091
+ if ('footer' in message && !!message.footer) {
1092
+ buttonsMessage.footerText = message.footer;
1093
+ }
1094
+ if ('contextInfo' in message && !!message.contextInfo) {
1095
+ buttonsMessage.contextInfo = message.contextInfo;
1096
+ }
1097
+ if ('mentions' in message && !!message.mentions) {
1098
+ buttonsMessage.contextInfo = { mentionedJid: normalizeMentionedJids(message.mentions) };
1099
+ }
1100
+ m = { buttonsMessage };
1101
+ }
1102
+ else if ('templateButtons' in message && !!message.templateButtons) {
1103
+ const templateMsg = {
1104
+ hydratedButtons: message.templateButtons
1105
+ };
1106
+ if ('text' in message) {
1107
+ templateMsg.hydratedContentText = message.text;
1108
+ }
1109
+ else if ('caption' in message) {
1110
+ templateMsg.hydratedContentText = message.caption;
1111
+ }
1112
+ if ('footer' in message && !!message.footer) {
1113
+ templateMsg.hydratedFooterText = message.footer;
1114
+ }
1115
+ // Add media to template if present
1116
+ if (m && Object.keys(m).length > 0) {
1117
+ Object.assign(templateMsg, m);
1118
+ }
1119
+ m = {
1120
+ templateMessage: {
1121
+ fourRowTemplate: templateMsg,
1122
+ hydratedTemplate: templateMsg
1123
+ }
1124
+ };
1125
+ }
1126
+ if ('sections' in message && !!message.sections) {
1127
+ const listMessage = {
1128
+ sections: message.sections,
1129
+ buttonText: message.buttonText,
1130
+ title: message.title,
1131
+ footerText: message.footer,
1132
+ description: message.text,
1133
+ listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
1134
+ };
1135
+ m = { listMessage };
1136
+ }
1137
+ if ('interactiveButtons' in message && !!message.interactiveButtons) {
1138
+ const interactiveMessage = {
1139
+ nativeFlowMessage: Types_1.WAProto.Message.InteractiveMessage.NativeFlowMessage.fromObject({
1140
+ buttons: message.interactiveButtons,
1141
+ messageVersion: 1,
1142
+ })
1143
+ };
1144
+ if ('text' in message) {
1145
+ interactiveMessage.body = {
1146
+ text: message.text
1147
+ };
1148
+ }
1149
+ else if ('caption' in message) {
1150
+ interactiveMessage.body = {
1151
+ text: message.caption
1152
+ };
1153
+ interactiveMessage.header = {
1154
+ title: message.title,
1155
+ subtitle: message.subtitle,
1156
+ hasMediaAttachment: !!(message === null || message === void 0 ? void 0 : message.media),
1157
+ };
1158
+ Object.assign(interactiveMessage.header, m);
1159
+ }
1160
+ if ('footer' in message && !!message.footer) {
1161
+ if (typeof message.footer === 'string') {
1162
+ interactiveMessage.footer = {
1163
+ text: message.footer
1164
+ };
1165
+ } else if (typeof message.footer === 'object' && message.footer.text) {
1166
+ interactiveMessage.footer = {
1167
+ text: message.footer.text,
1168
+ hasMediaAttachment: !!message.footer.audio
1169
+ };
1170
+ if (message.footer.audio) {
1171
+ const audioMedia = await (0, exports.prepareWAMessageMedia)({ audio: message.footer.audio }, options);
1172
+ interactiveMessage.footer.audioMessage = audioMedia.audioMessage;
1173
+ }
1174
+ }
1175
+ }
1176
+ if ('title' in message && !!message.title) {
1177
+ const headerData = {
1178
+ title: message.title,
1179
+ subtitle: message.subtitle,
1180
+ hasMediaAttachment: !!message.media,
1181
+ };
1182
+
1183
+ // Process media attachments for interactive buttons
1184
+ if (message.media) {
1185
+ if (message.media.image) {
1186
+ const mediaMessage = await prepareWAMessageMedia({ image: message.media.image }, options);
1187
+ if (mediaMessage.imageMessage) {
1188
+ headerData.imageMessage = mediaMessage.imageMessage;
1189
+ }
1190
+ }
1191
+ else if (message.media.video) {
1192
+ const mediaMessage = await prepareWAMessageMedia({ video: message.media.video }, options);
1193
+ if (mediaMessage.videoMessage) {
1194
+ headerData.videoMessage = mediaMessage.videoMessage;
1195
+ }
1196
+ }
1197
+ else if (message.media.document) {
1198
+ const mediaMessage = await prepareWAMessageMedia({ document: message.media.document }, options);
1199
+ if (mediaMessage.documentMessage) {
1200
+ headerData.documentMessage = mediaMessage.documentMessage;
1201
+ }
1202
+ }
1203
+ }
1204
+
1205
+ interactiveMessage.header = headerData;
1206
+ // Support for ProductMessage in header
1207
+ if (message.headerProduct) {
1208
+ const productMedia = await (0, exports.prepareWAMessageMedia)({ image: message.headerProduct.productImage }, options);
1209
+ interactiveMessage.header.productMessage = {
1210
+ product: {
1211
+ ...message.headerProduct,
1212
+ productImage: productMedia.imageMessage
1213
+ }
1214
+ };
1215
+ interactiveMessage.header.hasMediaAttachment = true;
1216
+ } else {
1217
+ Object.assign(interactiveMessage.header, m);
1218
+ }
1219
+ }
1220
+ if ('contextInfo' in message && !!message.contextInfo) {
1221
+ interactiveMessage.contextInfo = message.contextInfo;
1222
+ }
1223
+ if ('mentions' in message && !!message.mentions) {
1224
+ interactiveMessage.contextInfo = { mentionedJid: normalizeMentionedJids(message.mentions) };
1225
+ }
1226
+ m = { interactiveMessage };
1227
+ }
1228
+ if ('shop' in message && !!message.shop) {
1229
+ const interactiveMessage = {
1230
+ shopStorefrontMessage: Types_1.WAProto.Message.InteractiveMessage.ShopMessage.fromObject({
1231
+ surface: message.shop,
1232
+ id: message.id
1233
+ })
1234
+ };
1235
+ if ('text' in message) {
1236
+ interactiveMessage.body = {
1237
+ text: message.text
1238
+ };
1239
+ }
1240
+ else if ('caption' in message) {
1241
+ interactiveMessage.body = {
1242
+ text: message.caption
1243
+ };
1244
+ interactiveMessage.header = {
1245
+ title: message.title,
1246
+ subtitle: message.subtitle,
1247
+ hasMediaAttachment: !!(message === null || message === void 0 ? void 0 : message.media),
1248
+ };
1249
+ Object.assign(interactiveMessage.header, m);
1250
+ }
1251
+ if ('footer' in message && !!message.footer) {
1252
+ interactiveMessage.footer = {
1253
+ text: message.footer
1254
+ };
1255
+ }
1256
+ if ('title' in message && !!message.title) {
1257
+ interactiveMessage.header = {
1258
+ title: message.title,
1259
+ subtitle: message.subtitle,
1260
+ hasMediaAttachment: !!(message === null || message === void 0 ? void 0 : message.media),
1261
+ };
1262
+ Object.assign(interactiveMessage.header, m);
1263
+ }
1264
+ if ('contextInfo' in message && !!message.contextInfo) {
1265
+ interactiveMessage.contextInfo = message.contextInfo;
1266
+ }
1267
+ if ('mentions' in message && !!message.mentions) {
1268
+ interactiveMessage.contextInfo = { mentionedJid: normalizeMentionedJids(message.mentions) };
1269
+ }
1270
+ m = { interactiveMessage };
1271
+ }
1272
+ else if ('collection' in message && !!message.collection) {
1273
+ const interactiveMessage = {
1274
+ collectionMessage: Types_1.WAProto.Message.InteractiveMessage.CollectionMessage.fromObject({
1275
+ bizJid: message.collection.bizJid,
1276
+ id: message.collection.id,
1277
+ messageVersion: message.collection.messageVersion || 1
1278
+ })
1279
+ };
1280
+ if ('text' in message) {
1281
+ interactiveMessage.body = {
1282
+ text: message.text
1283
+ };
1284
+ }
1285
+ if ('footer' in message && !!message.footer) {
1286
+ interactiveMessage.footer = {
1287
+ text: message.footer
1288
+ };
1289
+ }
1290
+ if ('title' in message && !!message.title) {
1291
+ interactiveMessage.header = {
1292
+ title: message.title,
1293
+ subtitle: message.subtitle,
1294
+ hasMediaAttachment: false
1295
+ };
1296
+ }
1297
+ if ('contextInfo' in message && !!message.contextInfo) {
1298
+ interactiveMessage.contextInfo = message.contextInfo;
1299
+ }
1300
+ m = { interactiveMessage };
1301
+ }
1302
+ else if ('invoice' in message && !!message.invoice) {
1303
+ const invoiceData = message.invoice;
1304
+ const invoiceMessage = {
1305
+ note: invoiceData.note,
1306
+ token: invoiceData.token,
1307
+ attachmentType: invoiceData.attachmentType || 0 // IMAGE = 0, PDF = 1
1308
+ };
1309
+ if (invoiceData.attachment) {
1310
+ const attachmentMedia = await (0, exports.prepareWAMessageMedia)({
1311
+ [invoiceData.attachmentType === 1 ? 'document' : 'image']: invoiceData.attachment
1312
+ }, options);
1313
+ if (invoiceData.attachmentType === 1) {
1314
+ invoiceMessage.attachmentMimetype = attachmentMedia.documentMessage.mimetype;
1315
+ invoiceMessage.attachmentMediaKey = attachmentMedia.documentMessage.mediaKey;
1316
+ invoiceMessage.attachmentMediaKeyTimestamp = attachmentMedia.documentMessage.mediaKeyTimestamp;
1317
+ invoiceMessage.attachmentFileSha256 = attachmentMedia.documentMessage.fileSha256;
1318
+ invoiceMessage.attachmentFileEncSha256 = attachmentMedia.documentMessage.fileEncSha256;
1319
+ invoiceMessage.attachmentDirectPath = attachmentMedia.documentMessage.directPath;
1320
+ } else {
1321
+ invoiceMessage.attachmentMimetype = attachmentMedia.imageMessage.mimetype;
1322
+ invoiceMessage.attachmentMediaKey = attachmentMedia.imageMessage.mediaKey;
1323
+ invoiceMessage.attachmentMediaKeyTimestamp = attachmentMedia.imageMessage.mediaKeyTimestamp;
1324
+ invoiceMessage.attachmentFileSha256 = attachmentMedia.imageMessage.fileSha256;
1325
+ invoiceMessage.attachmentFileEncSha256 = attachmentMedia.imageMessage.fileEncSha256;
1326
+ invoiceMessage.attachmentDirectPath = attachmentMedia.imageMessage.directPath;
1327
+ invoiceMessage.attachmentJpegThumbnail = attachmentMedia.imageMessage.jpegThumbnail;
1328
+ }
1329
+ }
1330
+ m = { invoiceMessage };
1331
+ }
1332
+ if ('cards' in message && !!message.cards && message.cards.length > 0) {
1333
+ const carouselCardType = message.carouselCardType || 1; // HSCROLL_CARDS = 1, ALBUM_IMAGE = 2
1334
+ const carouselCards = await Promise.all(message.cards.map(async (card) => {
1335
+ const cardMessage = {
1336
+ header: {
1337
+ title: card.title || '',
1338
+ hasMediaAttachment: !!(card.image || card.video)
1339
+ }
1340
+ };
1341
+
1342
+ // Add body as separate field if present
1343
+ if (card.body) {
1344
+ cardMessage.body = {
1345
+ text: card.body
1346
+ };
1347
+ }
1348
+ // Handle media attachments
1349
+ if (card.image) {
1350
+ const mediaMessage = await prepareWAMessageMedia({ image: card.image }, options);
1351
+ if (mediaMessage.imageMessage) {
1352
+ cardMessage.header.imageMessage = mediaMessage.imageMessage;
1353
+ }
1354
+ }
1355
+ else if (card.video) {
1356
+ const mediaMessage = await prepareWAMessageMedia({ video: card.video }, options);
1357
+ if (mediaMessage.videoMessage) {
1358
+ cardMessage.header.videoMessage = mediaMessage.videoMessage;
1359
+ }
1360
+ }
1361
+ // Handle buttons
1362
+ if (card.buttons && card.buttons.length > 0) {
1363
+ cardMessage.nativeFlowMessage = {
1364
+ buttons: card.buttons.map(button => ({
1365
+ name: button.name,
1366
+ buttonParamsJson: button.buttonParamsJson
1367
+ })),
1368
+ messageVersion: 1,
1369
+ };
1370
+ }
1371
+ // Add footer if present
1372
+ if (card.footer) {
1373
+ cardMessage.footer = {
1374
+ text: card.footer
1375
+ };
1376
+ }
1377
+ return cardMessage;
1378
+ }));
1379
+ const interactiveMessage = {
1380
+ carouselMessage: Types_1.WAProto.Message.InteractiveMessage.CarouselMessage.fromObject({
1381
+ cards: carouselCards,
1382
+ messageVersion: 1,
1383
+ carouselCardType: carouselCardType
1384
+ })
1385
+ };
1386
+ if ('text' in message) {
1387
+ interactiveMessage.body = {
1388
+ text: message.text
1389
+ };
1390
+ }
1391
+ if ('footer' in message && !!message.footer) {
1392
+ interactiveMessage.footer = {
1393
+ text: message.footer
1394
+ };
1395
+ }
1396
+ if ('title' in message && !!message.title) {
1397
+ interactiveMessage.header = {
1398
+ title: message.title,
1399
+ subtitle: message.subtitle,
1400
+ hasMediaAttachment: false
1401
+ };
1402
+ }
1403
+ if ('contextInfo' in message && !!message.contextInfo) {
1404
+ interactiveMessage.contextInfo = message.contextInfo;
1405
+ }
1406
+ if ('mentions' in message && !!message.mentions) {
1407
+ interactiveMessage.contextInfo = { mentionedJid: normalizeMentionedJids(message.mentions) };
1408
+ }
1409
+ m = { interactiveMessage };
1410
+ }
1411
+ // Interactive messages are commonly sent wrapped in a view-once container on MD.
1412
+ // This improves client compatibility (avoids "update WhatsApp" / invisible messages on some clients).
1413
+ const shouldWrapInteractive = !!(m === null || m === void 0 ? void 0 : m.interactiveMessage);
1414
+ const hasViewOnceAlready = !!(m === null || m === void 0 ? void 0 : m.viewOnceMessage) || !!(m === null || m === void 0 ? void 0 : m.viewOnceMessageV2) || !!(m === null || m === void 0 ? void 0 : m.viewOnceMessageV2Extension);
1415
+ if ((('viewOnce' in message && !!message.viewOnce) || shouldWrapInteractive) && !hasViewOnceAlready) {
1416
+ m = { viewOnceMessageV2: { message: m } };
1417
+ }
1418
+ if ('mentions' in message && ((_o = message.mentions) === null || _o === void 0 ? void 0 : _o.length)) {
1419
+ const [messageType] = Object.keys(m);
1420
+ m[messageType].contextInfo = m[messageType] || {};
1421
+ m[messageType].contextInfo.mentionedJid = normalizeMentionedJids(message.mentions);
1422
+ }
1423
+ if ('edit' in message) {
1424
+ m = {
1425
+ protocolMessage: {
1426
+ key: message.edit,
1427
+ editedMessage: m,
1428
+ timestampMs: Date.now(),
1429
+ type: Types_1.WAProto.Message.ProtocolMessage.Type.MESSAGE_EDIT
1430
+ }
1431
+ };
1432
+ }
1433
+ if ('contextInfo' in message && !!message.contextInfo) {
1434
+ const [messageType] = Object.keys(m);
1435
+ m[messageType] = m[messageType] || {};
1436
+ m[messageType].contextInfo = {
1437
+ ...m[messageType].contextInfo,
1438
+ ...message.contextInfo
1439
+ };
1440
+ }
1441
+ return Types_1.WAProto.Message.fromObject(m);
1442
+ };
1443
+ exports.generateWAMessageContent = generateWAMessageContent;
1444
+ const generateWAMessageFromContent = (jid, message, options) => {
1445
+ // set timestamp to now
1446
+ // if not specified
1447
+ if (!options.timestamp) {
1448
+ options.timestamp = new Date();
1449
+ }
1450
+ const innerMessage = (0, exports.normalizeMessageContent)(message);
1451
+ const key = (0, exports.getContentType)(innerMessage);
1452
+ const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
1453
+ const { quoted, userJid } = options;
1454
+ // only set quoted if isn't a newsletter message
1455
+ if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
1456
+ const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
1457
+ let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
1458
+ const msgType = (0, exports.getContentType)(quotedMsg);
1459
+ // strip any redundant properties
1460
+ if (quotedMsg) {
1461
+ quotedMsg = WAProto_1.proto.Message.fromObject({ [msgType]: quotedMsg[msgType] });
1462
+ const quotedContent = quotedMsg[msgType];
1463
+ if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
1464
+ delete quotedContent.contextInfo;
1465
+ }
1466
+ const contextInfo = innerMessage[key].contextInfo || {};
1467
+ contextInfo.participant = (0, WABinary_1.jidNormalizedUser)(participant);
1468
+ contextInfo.stanzaId = quoted.key.id;
1469
+ contextInfo.quotedMessage = quotedMsg;
1470
+ // if a participant is quoted, then it must be a group
1471
+ // hence, remoteJid of group must also be entered
1472
+ if (jid !== quoted.key.remoteJid) {
1473
+ contextInfo.remoteJid = quoted.key.remoteJid;
1474
+ }
1475
+ innerMessage[key].contextInfo = contextInfo;
1476
+ }
1477
+ }
1478
+ if (
1479
+ // if we want to send a disappearing message
1480
+ !!(options === null || options === void 0 ? void 0 : options.ephemeralExpiration) &&
1481
+ // and it's not a protocol message -- delete, toggle disappear message
1482
+ key !== 'protocolMessage' &&
1483
+ // already not converted to disappearing message
1484
+ key !== 'ephemeralMessage' &&
1485
+ // newsletter not accept disappearing messages
1486
+ !(0, WABinary_1.isJidNewsletter)(jid)) {
1487
+ innerMessage[key].contextInfo = {
1488
+ ...(innerMessage[key].contextInfo || {}),
1489
+ expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
1490
+ //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
1491
+ };
1492
+ }
1493
+ message = Types_1.WAProto.Message.fromObject(message);
1494
+ const messageJSON = {
1495
+ key: {
1496
+ remoteJid: jid,
1497
+ fromMe: true,
1498
+ id: (options === null || options === void 0 ? void 0 : options.messageId) || (0, generics_1.generateMessageIDV2)(),
1499
+ },
1500
+ message: message,
1501
+ messageTimestamp: timestamp,
1502
+ messageStubParameters: [],
1503
+ participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined,
1504
+ status: Types_1.WAMessageStatus.PENDING
1505
+ };
1506
+ return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON);
1507
+ };
1508
+ exports.generateWAMessageFromContent = generateWAMessageFromContent;
1509
+ const generateWAMessage = async (jid, content, options) => {
1510
+ var _a;
1511
+ // ensure msg ID is with every log
1512
+ options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
1513
+ return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsletter)(jid), ...options }), options);
1514
+ };
1515
+ exports.generateWAMessage = generateWAMessage;
1516
+ /** Get the key to access the true type of content */
1517
+ const getContentType = (content) => {
1518
+ if (content) {
1519
+ const keys = Object.keys(content);
1520
+ const key = keys.find(k => (k === 'conversation' || k.includes('Message')) && k !== 'senderKeyDistributionMessage');
1521
+ return key;
1522
+ }
1523
+ };
1524
+ exports.getContentType = getContentType;
1525
+ /**
1526
+ * Normalizes ephemeral, view once messages to regular message content
1527
+ * Eg. image messages in ephemeral messages, in view once messages etc.
1528
+ * @param content
1529
+ * @returns
1530
+ */
1531
+ const normalizeMessageContent = (content) => {
1532
+ if (!content) {
1533
+ return undefined;
1534
+ }
1535
+ // set max iterations to prevent an infinite loop
1536
+ for (let i = 0; i < 5; i++) {
1537
+ const inner = getFutureProofMessage(content);
1538
+ if (!inner) {
1539
+ break;
1540
+ }
1541
+ content = inner.message;
1542
+ }
1543
+ return content;
1544
+ function getFutureProofMessage(message) {
1545
+ return ((message === null || message === void 0 ? void 0 : message.ephemeralMessage)
1546
+ || (message === null || message === void 0 ? void 0 : message.viewOnceMessage)
1547
+ || (message === null || message === void 0 ? void 0 : message.documentWithCaptionMessage)
1548
+ || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2)
1549
+ || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension)
1550
+ || (message === null || message === void 0 ? void 0 : message.editedMessage)
1551
+ || (message === null || message === void 0 ? void 0 : message.groupMentionedMessage)
1552
+ || (message === null || message === void 0 ? void 0 : message.botInvokeMessage)
1553
+ || (message === null || message === void 0 ? void 0 : message.lottieStickerMessage)
1554
+ || (message === null || message === void 0 ? void 0 : message.eventCoverImage)
1555
+ || (message === null || message === void 0 ? void 0 : message.statusMentionMessage)
1556
+ || (message === null || message === void 0 ? void 0 : message.pollCreationOptionImageMessage)
1557
+ || (message === null || message === void 0 ? void 0 : message.associatedChildMessage)
1558
+ || (message === null || message === void 0 ? void 0 : message.groupStatusMentionMessage)
1559
+ || (message === null || message === void 0 ? void 0 : message.pollCreationMessageV4)
1560
+ || (message === null || message === void 0 ? void 0 : message.pollCreationMessageV5)
1561
+ || (message === null || message === void 0 ? void 0 : message.statusAddYours)
1562
+ || (message === null || message === void 0 ? void 0 : message.groupStatusMessage)
1563
+ || (message === null || message === void 0 ? void 0 : message.limitSharingMessage)
1564
+ || (message === null || message === void 0 ? void 0 : message.botTaskMessage)
1565
+ || (message === null || message === void 0 ? void 0 : message.questionMessage)
1566
+ || (message === null || message === void 0 ? void 0 : message.groupStatusMessageV2)
1567
+ || (message === null || message === void 0 ? void 0 : message.botForwardedMessage));
1568
+ }
1569
+ };
1570
+ exports.normalizeMessageContent = normalizeMessageContent;
1571
+ /**
1572
+ * Extract the true message content from a message
1573
+ * Eg. extracts the inner message from a disappearing message/view once message
1574
+ */
1575
+ const extractMessageContent = (content) => {
1576
+ var _a, _b, _c, _d, _e, _f;
1577
+ const extractFromTemplateMessage = (msg) => {
1578
+ if (msg.imageMessage) {
1579
+ return { imageMessage: msg.imageMessage };
1580
+ }
1581
+ else if (msg.documentMessage) {
1582
+ return { documentMessage: msg.documentMessage };
1583
+ }
1584
+ else if (msg.videoMessage) {
1585
+ return { videoMessage: msg.videoMessage };
1586
+ }
1587
+ else if (msg.locationMessage) {
1588
+ return { locationMessage: msg.locationMessage };
1589
+ }
1590
+ else {
1591
+ return {
1592
+ conversation: 'contentText' in msg
1593
+ ? msg.contentText
1594
+ : ('hydratedContentText' in msg ? msg.hydratedContentText : '')
1595
+ };
1596
+ }
1597
+ };
1598
+ content = (0, exports.normalizeMessageContent)(content);
1599
+ if (content === null || content === void 0 ? void 0 : content.buttonsMessage) {
1600
+ return extractFromTemplateMessage(content.buttonsMessage);
1601
+ }
1602
+ if ((_a = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _a === void 0 ? void 0 : _a.hydratedFourRowTemplate) {
1603
+ return extractFromTemplateMessage((_b = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _b === void 0 ? void 0 : _b.hydratedFourRowTemplate);
1604
+ }
1605
+ if ((_c = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _c === void 0 ? void 0 : _c.hydratedTemplate) {
1606
+ return extractFromTemplateMessage((_d = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _d === void 0 ? void 0 : _d.hydratedTemplate);
1607
+ }
1608
+ if ((_e = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _e === void 0 ? void 0 : _e.fourRowTemplate) {
1609
+ return extractFromTemplateMessage((_f = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _f === void 0 ? void 0 : _f.fourRowTemplate);
1610
+ }
1611
+ return content;
1612
+ };
1613
+ exports.extractMessageContent = extractMessageContent;
1614
+ /**
1615
+ * Returns the device predicted by message ID
1616
+ */
1617
+ const getDevice = (id) => /^3A.{18}$/.test(id) ? 'ios' :
1618
+ /^3E.{20}$/.test(id) ? 'web' :
1619
+ /^(.{21}|.{32})$/.test(id) ? 'android' :
1620
+ /^(3F|.{18}$)/.test(id) ? 'desktop' :
1621
+ 'unknown';
1622
+ exports.getDevice = getDevice;
1623
+ /** Upserts a receipt in the message */
1624
+ const updateMessageWithReceipt = (msg, receipt) => {
1625
+ msg.userReceipt = msg.userReceipt || [];
1626
+ const recp = msg.userReceipt.find(m => m.userJid === receipt.userJid);
1627
+ if (recp) {
1628
+ Object.assign(recp, receipt);
1629
+ }
1630
+ else {
1631
+ msg.userReceipt.push(receipt);
1632
+ }
1633
+ };
1634
+ exports.updateMessageWithReceipt = updateMessageWithReceipt;
1635
+ /** Update the message with a new reaction */
1636
+ const updateMessageWithReaction = (msg, reaction) => {
1637
+ const authorID = (0, generics_1.getKeyAuthor)(reaction.key);
1638
+ const reactions = (msg.reactions || [])
1639
+ .filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
1640
+ reaction.text = reaction.text || '';
1641
+ reactions.push(reaction);
1642
+ msg.reactions = reactions;
1643
+ };
1644
+ exports.updateMessageWithReaction = updateMessageWithReaction;
1645
+ /** Update the message with a new poll update */
1646
+ const updateMessageWithPollUpdate = (msg, update) => {
1647
+ var _a, _b;
1648
+ const authorID = (0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey);
1649
+ const reactions = (msg.pollUpdates || [])
1650
+ .filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
1651
+ if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
1652
+ reactions.push(update);
1653
+ }
1654
+ msg.pollUpdates = reactions;
1655
+ };
1656
+ exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
1657
+ /**
1658
+ * Aggregates all poll updates in a poll.
1659
+ * @param msg the poll creation message
1660
+ * @param meId your jid
1661
+ * @returns A list of options & their voters
1662
+ */
1663
+ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
1664
+ var _a, _b, _c;
1665
+ 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) || [];
1666
+ const voteHashMap = opts.reduce((acc, opt) => {
1667
+ const hash = (0, crypto_2.sha256)(Buffer.from(opt.optionName || '')).toString();
1668
+ acc[hash] = {
1669
+ name: opt.optionName || '',
1670
+ voters: []
1671
+ };
1672
+ return acc;
1673
+ }, {});
1674
+ for (const update of pollUpdates || []) {
1675
+ const { vote } = update;
1676
+ if (!vote) {
1677
+ continue;
1678
+ }
1679
+ for (const option of vote.selectedOptions || []) {
1680
+ const hash = option.toString();
1681
+ let data = voteHashMap[hash];
1682
+ if (!data) {
1683
+ voteHashMap[hash] = {
1684
+ name: 'Unknown',
1685
+ voters: []
1686
+ };
1687
+ data = voteHashMap[hash];
1688
+ }
1689
+ voteHashMap[hash].voters.push((0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey, meId));
1690
+ }
1691
+ }
1692
+ return Object.values(voteHashMap);
1693
+ }
1694
+ /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
1695
+ const aggregateMessageKeysNotFromMe = (keys) => {
1696
+ const keyMap = {};
1697
+ for (const { remoteJid, id, participant, fromMe } of keys) {
1698
+ if (!fromMe) {
1699
+ const uqKey = `${remoteJid}:${participant || ''}`;
1700
+ if (!keyMap[uqKey]) {
1701
+ keyMap[uqKey] = {
1702
+ jid: remoteJid,
1703
+ participant: participant,
1704
+ messageIds: []
1705
+ };
1706
+ }
1707
+ keyMap[uqKey].messageIds.push(id);
1708
+ }
1709
+ }
1710
+ return Object.values(keyMap);
1711
+ };
1712
+ exports.aggregateMessageKeysNotFromMe = aggregateMessageKeysNotFromMe;
1713
+ const REUPLOAD_REQUIRED_STATUS = [410, 404];
1714
+ /**
1715
+ * Downloads the given message. Throws an error if it's not a media message
1716
+ */
1717
+ const downloadMediaMessage = async (message, type, options, ctx) => {
1718
+ const result = await downloadMsg()
1719
+ .catch(async (error) => {
1720
+ var _a;
1721
+ if (ctx) {
1722
+ if (axios_1.default.isAxiosError(error)) {
1723
+ // check if the message requires a reupload
1724
+ if (REUPLOAD_REQUIRED_STATUS.includes((_a = error.response) === null || _a === void 0 ? void 0 : _a.status)) {
1725
+ ctx.logger.info({ key: message.key }, 'sending reupload media request...');
1726
+ // request reupload
1727
+ message = await ctx.reuploadRequest(message);
1728
+ const result = await downloadMsg();
1729
+ return result;
1730
+ }
1731
+ }
1732
+ }
1733
+ throw error;
1734
+ });
1735
+ return result;
1736
+ async function downloadMsg() {
1737
+ const mContent = (0, exports.extractMessageContent)(message.message);
1738
+ if (!mContent) {
1739
+ throw new boom_1.Boom('No message present', { statusCode: 400, data: message });
1740
+ }
1741
+ const contentType = (0, exports.getContentType)(mContent);
1742
+ let mediaType = contentType === null || contentType === void 0 ? void 0 : contentType.replace('Message', '');
1743
+ const media = mContent[contentType];
1744
+ if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
1745
+ throw new boom_1.Boom(`"${contentType}" message is not a media message`);
1746
+ }
1747
+ let download;
1748
+ if ('thumbnailDirectPath' in media && !('url' in media)) {
1749
+ download = {
1750
+ directPath: media.thumbnailDirectPath,
1751
+ mediaKey: media.mediaKey
1752
+ };
1753
+ mediaType = 'thumbnail-link';
1754
+ }
1755
+ else {
1756
+ download = media;
1757
+ }
1758
+ const stream = await (0, messages_media_1.downloadContentFromMessage)(download, mediaType, options);
1759
+ if (type === 'buffer') {
1760
+ const bufferArray = [];
1761
+ for await (const chunk of stream) {
1762
+ bufferArray.push(chunk);
1763
+ }
1764
+ return Buffer.concat(bufferArray);
1765
+ }
1766
+ return stream;
1767
+ }
1768
+ };
1769
+ exports.downloadMediaMessage = downloadMediaMessage;
1770
+ /** Checks whether the given message is a media message; if it is returns the inner content */
1771
+ const assertMediaContent = (content) => {
1772
+ content = (0, exports.extractMessageContent)(content);
1773
+ const mediaContent = (content === null || content === void 0 ? void 0 : content.documentMessage)
1774
+ || (content === null || content === void 0 ? void 0 : content.imageMessage)
1775
+ || (content === null || content === void 0 ? void 0 : content.videoMessage)
1776
+ || (content === null || content === void 0 ? void 0 : content.audioMessage)
1777
+ || (content === null || content === void 0 ? void 0 : content.stickerMessage);
1778
+ if (!mediaContent) {
1779
+ throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content });
1780
+ }
1781
+ return mediaContent;
1782
+ };
1783
+ exports.assertMediaContent = assertMediaContent;
1784
+ const cache_manager_1 = require("./cache-manager");
1785
+ const performance_config_1 = require("./performance-config");
1786
+ /**
1787
+ * Get cache statistics for monitoring performance
1788
+ */
1789
+ const getCacheStats = () => {
1790
+ try {
1791
+ const cacheManager = cache_manager_1.default;
1792
+ const config = performance_config_1.getPerformanceConfig();
1793
+
1794
+ if (!cacheManager || !cacheManager.caches) {
1795
+ return {
1796
+ lidCache: { size: 0, maxSize: 0, ttl: config.cache.lidCache.ttl },
1797
+ jidCache: { size: 0, maxSize: 0, ttl: config.cache.jidCache.ttl }
1798
+ };
1799
+ }
1800
+
1801
+ const lidStats = cacheManager.getStats('lidCache');
1802
+ const jidStats = cacheManager.getStats('jidCache');
1803
+
1804
+ return {
1805
+ lidCache: {
1806
+ size: lidStats?.keys || 0,
1807
+ maxSize: lidStats?.max || config.cache.lidCache.maxSize || 0,
1808
+ ttl: config.cache.lidCache.ttl
1809
+ },
1810
+ jidCache: {
1811
+ size: jidStats?.keys || 0,
1812
+ maxSize: jidStats?.max || config.cache.jidCache.maxSize || 0,
1813
+ ttl: config.cache.jidCache.ttl
1814
+ }
1815
+ };
1816
+ } catch (error) {
1817
+ const config = performance_config_1.getPerformanceConfig();
1818
+ return {
1819
+ lidCache: { size: 0, maxSize: 0, ttl: config.cache.lidCache.ttl },
1820
+ jidCache: { size: 0, maxSize: 0, ttl: config.cache.jidCache.ttl }
1821
+ };
1822
+ }
1823
+ };
1824
+ exports.getCacheStats = getCacheStats;
1825
+ /**
1826
+ * Clear all caches (useful for testing or memory management)
1827
+ */
1828
+ const clearCache = () => {
1829
+ try {
1830
+ const cacheManager = cache_manager_1.default;
1831
+ if (cacheManager && cacheManager.caches) {
1832
+ Object.keys(cacheManager.caches).forEach(cacheName => {
1833
+ const cache = cacheManager.caches[cacheName];
1834
+ if (cache && typeof cache.flushAll === 'function') {
1835
+ cache.flushAll();
1836
+ }
1837
+ });
1838
+ }
1839
+ } catch (error) {
1840
+ // Silently fail if cache manager is not available
1841
+ }
1842
+ };
1843
+ exports.clearCache = clearCache;