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