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