@hbmodsofc/baileys 1.5.2 → 1.7.6

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 (156) hide show
  1. package/LICENSE +1 -1
  2. package/WAProto/index.js +19671 -152026
  3. package/engine-requirements.js +4 -4
  4. package/lib/Defaults/index.d.ts +12 -8
  5. package/lib/Defaults/index.js +90 -124
  6. package/lib/Signal/Group/group_cipher.d.ts +0 -1
  7. package/lib/Signal/Group/group_cipher.js +28 -39
  8. package/lib/Signal/Group/sender-chain-key.d.ts +1 -1
  9. package/lib/Signal/Group/sender-chain-key.js +9 -2
  10. package/lib/Signal/Group/sender-key-distribution-message.js +3 -3
  11. package/lib/Signal/Group/sender-key-message.js +3 -3
  12. package/lib/Signal/Group/sender-key-state.d.ts +4 -4
  13. package/lib/Signal/Group/sender-key-state.js +47 -16
  14. package/lib/Signal/libsignal.d.ts +7 -3
  15. package/lib/Signal/libsignal.js +224 -39
  16. package/lib/Signal/lid-mapping.d.ts +26 -0
  17. package/lib/Signal/lid-mapping.js +146 -0
  18. package/lib/Socket/Client/index.d.ts +2 -3
  19. package/lib/Socket/Client/index.js +2 -3
  20. package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +1 -3
  21. package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +1 -1
  22. package/lib/Socket/Client/{web-socket-client.js → websocket.js} +10 -16
  23. package/lib/Socket/business.d.ts +94 -78
  24. package/lib/Socket/business.js +130 -11
  25. package/lib/Socket/chats.d.ts +63 -233
  26. package/lib/Socket/chats.js +234 -184
  27. package/lib/Socket/communities.d.ts +232 -0
  28. package/lib/Socket/communities.js +402 -0
  29. package/lib/Socket/groups.d.ts +62 -41
  30. package/lib/Socket/groups.js +76 -64
  31. package/lib/Socket/index.d.ts +129 -83
  32. package/lib/Socket/index.js +13 -6
  33. package/lib/Socket/messages-recv.d.ts +59 -48
  34. package/lib/Socket/messages-recv.js +516 -371
  35. package/lib/Socket/messages-send.d.ts +86 -67
  36. package/lib/Socket/messages-send.js +1091 -1
  37. package/lib/Socket/mex.d.ts +2 -0
  38. package/lib/Socket/mex.js +45 -0
  39. package/lib/Socket/newsletter.d.ts +76 -64
  40. package/lib/Socket/newsletter.js +184 -1
  41. package/lib/Socket/socket.d.ts +19 -13
  42. package/lib/Socket/socket.js +805 -1
  43. package/lib/Types/Auth.d.ts +4 -10
  44. package/lib/Types/Bussines.d.ts +24 -0
  45. package/lib/Types/Bussines.js +2 -0
  46. package/lib/Types/Call.d.ts +1 -1
  47. package/lib/Types/Chat.d.ts +29 -9
  48. package/lib/Types/Chat.js +7 -1
  49. package/lib/Types/Contact.d.ts +5 -1
  50. package/lib/Types/Events.d.ts +55 -14
  51. package/lib/Types/GroupMetadata.d.ts +15 -5
  52. package/lib/Types/Label.d.ts +11 -0
  53. package/lib/Types/Label.js +1 -1
  54. package/lib/Types/LabelAssociation.js +1 -1
  55. package/lib/Types/Message.d.ts +75 -49
  56. package/lib/Types/Message.js +10 -7
  57. package/lib/Types/Newsletter.d.ts +129 -98
  58. package/lib/Types/Newsletter.js +33 -38
  59. package/lib/Types/Product.d.ts +1 -1
  60. package/lib/Types/Signal.d.ts +29 -1
  61. package/lib/Types/Socket.d.ts +48 -22
  62. package/lib/Types/State.d.ts +13 -2
  63. package/lib/Types/State.js +12 -0
  64. package/lib/Types/USync.d.ts +1 -1
  65. package/lib/Types/index.d.ts +10 -3
  66. package/lib/Types/index.js +2 -2
  67. package/lib/Utils/auth-utils.d.ts +3 -3
  68. package/lib/Utils/auth-utils.js +378 -102
  69. package/lib/Utils/baileys-event-stream.js +1 -1
  70. package/lib/Utils/business.d.ts +2 -2
  71. package/lib/Utils/business.js +19 -13
  72. package/lib/Utils/chat-utils.d.ts +21 -22
  73. package/lib/Utils/chat-utils.js +201 -154
  74. package/lib/Utils/crypto.d.ts +18 -19
  75. package/lib/Utils/crypto.js +78 -37
  76. package/lib/Utils/decode-wa-message.d.ts +34 -7
  77. package/lib/Utils/decode-wa-message.js +138 -66
  78. package/lib/Utils/event-buffer.d.ts +6 -8
  79. package/lib/Utils/event-buffer.js +81 -43
  80. package/lib/Utils/generics.d.ts +27 -27
  81. package/lib/Utils/generics.js +128 -133
  82. package/lib/Utils/history.d.ts +9 -5
  83. package/lib/Utils/history.js +17 -23
  84. package/lib/Utils/index.d.ts +2 -0
  85. package/lib/Utils/index.js +2 -0
  86. package/lib/Utils/lidToJid-test.d.ts +11 -0
  87. package/lib/Utils/lidToJid-test.js +27 -0
  88. package/lib/Utils/link-preview.d.ts +4 -4
  89. package/lib/Utils/link-preview.js +40 -12
  90. package/lib/Utils/logger.d.ts +11 -3
  91. package/lib/Utils/lt-hash.d.ts +8 -8
  92. package/lib/Utils/lt-hash.js +23 -24
  93. package/lib/Utils/make-mutex.d.ts +2 -2
  94. package/lib/Utils/make-mutex.js +3 -2
  95. package/lib/Utils/message-retry-manager.d.ts +81 -0
  96. package/lib/Utils/message-retry-manager.js +152 -0
  97. package/lib/Utils/messages-media.d.ts +37 -41
  98. package/lib/Utils/messages-media.js +252 -368
  99. package/lib/Utils/messages.d.ts +13 -15
  100. package/lib/Utils/messages.js +274 -261
  101. package/lib/Utils/noise-handler.d.ts +13 -15
  102. package/lib/Utils/noise-handler.js +20 -26
  103. package/lib/Utils/process-message.d.ts +9 -8
  104. package/lib/Utils/process-message.js +157 -93
  105. package/lib/Utils/signal.d.ts +6 -5
  106. package/lib/Utils/signal.js +37 -29
  107. package/lib/Utils/use-multi-file-auth-state.d.ts +1 -2
  108. package/lib/Utils/use-multi-file-auth-state.js +12 -7
  109. package/lib/Utils/validate-connection.d.ts +5 -6
  110. package/lib/Utils/validate-connection.js +39 -97
  111. package/lib/WABinary/constants.d.ts +24 -27
  112. package/lib/WABinary/constants.js +1276 -13
  113. package/lib/WABinary/decode.d.ts +3 -4
  114. package/lib/WABinary/decode.js +28 -14
  115. package/lib/WABinary/encode.d.ts +1 -2
  116. package/lib/WABinary/encode.js +134 -147
  117. package/lib/WABinary/generic-utils.d.ts +4 -7
  118. package/lib/WABinary/generic-utils.js +40 -125
  119. package/lib/WABinary/jid-utils.d.ts +13 -8
  120. package/lib/WABinary/jid-utils.js +27 -16
  121. package/lib/WAM/BinaryInfo.d.ts +2 -11
  122. package/lib/WAM/constants.d.ts +3 -2
  123. package/lib/WAM/constants.js +2252 -2359
  124. package/lib/WAM/encode.d.ts +1 -2
  125. package/lib/WAM/encode.js +8 -11
  126. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +2 -2
  127. package/lib/WAUSync/Protocols/USyncContactProtocol.js +3 -4
  128. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -2
  129. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +5 -5
  130. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -2
  131. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +5 -5
  132. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -2
  133. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +5 -6
  134. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +2 -2
  135. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +1 -1
  136. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +4 -3
  137. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +11 -3
  138. package/lib/WAUSync/USyncQuery.d.ts +2 -2
  139. package/lib/WAUSync/USyncQuery.js +19 -15
  140. package/lib/WAUSync/USyncUser.d.ts +5 -5
  141. package/lib/WAUSync/index.d.ts +1 -1
  142. package/lib/WAUSync/index.js +1 -1
  143. package/package.json +102 -102
  144. package/lib/Defaults/baileys-version.json +0 -3
  145. package/lib/Defaults/phonenumber-mcc.json +0 -223
  146. package/lib/Signal/Group/queue-job.d.ts +0 -1
  147. package/lib/Signal/Group/queue-job.js +0 -57
  148. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  149. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  150. package/lib/Socket/hbmods.d.ts +0 -253
  151. package/lib/Socket/hbmods.js +0 -1
  152. package/lib/Socket/registration.d.ts +0 -267
  153. package/lib/Socket/registration.js +0 -166
  154. package/lib/Socket/usync.d.ts +0 -36
  155. package/lib/Socket/usync.js +0 -70
  156. /package/lib/Socket/Client/{abstract-socket-client.js → types.js} +0 -0
@@ -1,14 +1,15 @@
1
- "use strict";
1
+ "use strict";
2
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.assertMediaContent = exports.downloadMediaMessage = exports.aggregateMessageKeysNotFromMe = exports.getAggregateVotesInPollMessage = 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;
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;
7
8
  const boom_1 = require("@hapi/boom");
8
9
  const axios_1 = __importDefault(require("axios"));
9
10
  const crypto_1 = require("crypto");
10
11
  const fs_1 = require("fs");
11
- const WAProto_1 = require("../../WAProto");
12
+ const index_js_1 = require("../../WAProto/index.js");
12
13
  const Defaults_1 = require("../Defaults");
13
14
  const Types_1 = require("../Types");
14
15
  const WABinary_1 = require("../WABinary");
@@ -21,22 +22,21 @@ const MIMETYPE_MAP = {
21
22
  document: 'application/pdf',
22
23
  audio: 'audio/ogg; codecs=opus',
23
24
  sticker: 'image/webp',
24
- 'product-catalog-image': 'image/jpeg',
25
+ 'product-catalog-image': 'image/jpeg'
25
26
  };
26
27
  const MessageTypeProto = {
27
- 'image': Types_1.WAProto.Message.ImageMessage,
28
- 'video': Types_1.WAProto.Message.VideoMessage,
29
- 'audio': Types_1.WAProto.Message.AudioMessage,
30
- 'sticker': Types_1.WAProto.Message.StickerMessage,
31
- 'document': Types_1.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
32
33
  };
33
- const ButtonType = WAProto_1.proto.Message.ButtonsMessage.HeaderType;
34
34
  /**
35
35
  * Uses a regex to test whether the string contains a URL, and returns the URL if it does.
36
36
  * @param text eg. hello https://google.com
37
37
  * @returns the URL, eg. https://google.com
38
38
  */
39
- const extractUrlFromText = (text) => { var _a; return (_a = text.match(Defaults_1.URL_REGEX)) === null || _a === void 0 ? void 0 : _a[0]; };
39
+ const extractUrlFromText = (text) => text.match(Defaults_1.URL_REGEX)?.[0];
40
40
  exports.extractUrlFromText = extractUrlFromText;
41
41
  const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
42
42
  const url = (0, exports.extractUrlFromText)(text);
@@ -45,8 +45,9 @@ const generateLinkPreviewIfRequired = async (text, getUrlInfo, logger) => {
45
45
  const urlInfo = await getUrlInfo(url);
46
46
  return urlInfo;
47
47
  }
48
- catch (error) { // ignore if fails
49
- logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'url generation failed');
48
+ catch (error) {
49
+ // ignore if fails
50
+ logger?.warn({ trace: error.stack }, 'url generation failed');
50
51
  }
51
52
  }
52
53
  };
@@ -74,165 +75,150 @@ const prepareWAMessageMedia = async (message, options) => {
74
75
  }
75
76
  }
76
77
  if (!mediaType) {
77
- throw new boom_1.Boom('Invalid media type', {
78
- statusCode: 400
79
- });
78
+ throw new boom_1.Boom('Invalid media type', { statusCode: 400 });
80
79
  }
81
-
82
80
  const uploadData = {
83
81
  ...message,
84
- ...(message.annotations ? {
85
- annotations: message.annotations
86
- } : {
87
- annotations: [
88
- {
89
- polygonVertices: [
90
- {
91
- x: 60.71664810180664,
92
- y: -36.39784622192383
93
- },
94
- {
95
- x: -16.710189819335938,
96
- y: 49.263675689697266
97
- },
98
- {
99
- x: -56.585853576660156,
100
- y: 37.85963439941406
101
- },
102
- {
103
- x: 20.840980529785156,
104
- y: -47.80188751220703
105
- }
106
- ],
107
- newsletter: {
108
- newsletterJid: "120363191549232941@newsletter",
109
- serverMessageId: 0,
110
- newsletterName: "HBWABot Support",
111
- contentType: "UPDATE",
112
- }
113
- }
114
- ]
115
- }),
116
82
  media: message[mediaType]
117
83
  };
118
84
  delete uploadData[mediaType];
85
+ // check if cacheable + generate cache key
119
86
  const cacheableKey = typeof uploadData.media === 'object' &&
120
- ('url' in uploadData.media) &&
87
+ 'url' in uploadData.media &&
121
88
  !!uploadData.media.url &&
122
- !!options.mediaCache && (
123
- mediaType + ':' + uploadData.media.url.toString());
124
-
89
+ !!options.mediaCache &&
90
+ mediaType + ':' + uploadData.media.url.toString();
125
91
  if (mediaType === 'document' && !uploadData.fileName) {
126
92
  uploadData.fileName = 'file';
127
93
  }
128
-
129
94
  if (!uploadData.mimetype) {
130
95
  uploadData.mimetype = MIMETYPE_MAP[mediaType];
131
96
  }
132
-
133
97
  if (cacheableKey) {
134
- const mediaBuff = options.mediaCache.get(cacheableKey);
98
+ const mediaBuff = await options.mediaCache.get(cacheableKey);
135
99
  if (mediaBuff) {
136
- logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'got media cache hit');
100
+ logger?.debug({ cacheableKey }, 'got media cache hit');
137
101
  const obj = Types_1.WAProto.Message.decode(mediaBuff);
138
102
  const key = `${mediaType}Message`;
139
103
  Object.assign(obj[key], { ...uploadData, media: undefined });
140
104
  return obj;
141
105
  }
142
106
  }
143
-
107
+ const isNewsletter = !!options.jid && (0, WABinary_1.isJidNewsletter)(options.jid);
108
+ if (isNewsletter) {
109
+ logger?.info({ key: cacheableKey }, 'Preparing raw media for newsletter');
110
+ const { filePath, fileSha256, fileLength } = await (0, messages_media_1.getRawMediaUploadData)(uploadData.media, options.mediaTypeOverride || mediaType, logger);
111
+ const fileSha256B64 = fileSha256.toString('base64');
112
+ const { mediaUrl, directPath } = await options.upload(filePath, {
113
+ fileEncSha256B64: fileSha256B64,
114
+ mediaType: mediaType,
115
+ timeoutMs: options.mediaUploadTimeoutMs
116
+ });
117
+ await fs_1.promises.unlink(filePath);
118
+ const obj = Types_1.WAProto.Message.create({
119
+ // todo: add more support here
120
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].create({
121
+ url: mediaUrl,
122
+ directPath,
123
+ fileSha256,
124
+ fileLength,
125
+ ...uploadData,
126
+ media: undefined
127
+ })
128
+ });
129
+ if (uploadData.ptv) {
130
+ obj.ptvMessage = obj.videoMessage;
131
+ delete obj.videoMessage;
132
+ }
133
+ if (cacheableKey) {
134
+ logger?.debug({ cacheableKey }, 'set cache');
135
+ await options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
136
+ }
137
+ return obj;
138
+ }
144
139
  const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined';
145
- const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') &&
146
- (typeof uploadData['jpegThumbnail'] === 'undefined');
140
+ const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && typeof uploadData['jpegThumbnail'] === 'undefined';
147
141
  const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
148
142
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
149
143
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
150
-
151
- const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, opusConverted } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
144
+ const { mediaKey, encFilePath, originalFilePath, fileEncSha256, fileSha256, fileLength } = await (0, messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
152
145
  logger,
153
146
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
154
- opts: options.options,
155
- isPtt: uploadData.ptt,
156
- forceOpus: (mediaType === "audio" && uploadData.mimetype && uploadData.mimetype.includes('opus'))
147
+ opts: options.options
157
148
  });
158
-
159
- if (mediaType === 'audio' && opusConverted) {
160
- uploadData.mimetype = 'audio/ogg; codecs=opus';
161
- }
162
-
163
- const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
164
-
165
- const [{ mediaUrl, directPath, handle }] = await Promise.all([
149
+ const fileEncSha256B64 = fileEncSha256.toString('base64');
150
+ const [{ mediaUrl, directPath }] = await Promise.all([
166
151
  (async () => {
167
- const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
168
- logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
152
+ const result = await options.upload(encFilePath, {
153
+ fileEncSha256B64,
154
+ mediaType,
155
+ timeoutMs: options.mediaUploadTimeoutMs
156
+ });
157
+ logger?.debug({ mediaType, cacheableKey }, 'uploaded media');
169
158
  return result;
170
159
  })(),
171
160
  (async () => {
172
161
  try {
173
162
  if (requiresThumbnailComputation) {
174
- const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(bodyPath, mediaType, options);
163
+ const { thumbnail, originalImageDimensions } = await (0, messages_media_1.generateThumbnail)(originalFilePath, mediaType, options);
175
164
  uploadData.jpegThumbnail = thumbnail;
176
165
  if (!uploadData.width && originalImageDimensions) {
177
166
  uploadData.width = originalImageDimensions.width;
178
167
  uploadData.height = originalImageDimensions.height;
179
- logger === null || logger === void 0 ? void 0 : logger.debug('set dimensions');
168
+ logger?.debug('set dimensions');
180
169
  }
181
- logger === null || logger === void 0 ? void 0 : logger.debug('generated thumbnail');
170
+ logger?.debug('generated thumbnail');
182
171
  }
183
172
  if (requiresDurationComputation) {
184
- uploadData.seconds = await (0, messages_media_1.getAudioDuration)(bodyPath);
185
- logger === null || logger === void 0 ? void 0 : logger.debug('computed audio duration');
173
+ uploadData.seconds = await (0, messages_media_1.getAudioDuration)(originalFilePath);
174
+ logger?.debug('computed audio duration');
186
175
  }
187
176
  if (requiresWaveformProcessing) {
188
- uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(bodyPath, logger);
189
- logger === null || logger === void 0 ? void 0 : logger.debug('processed waveform');
177
+ uploadData.waveform = await (0, messages_media_1.getAudioWaveform)(originalFilePath, logger);
178
+ logger?.debug('processed waveform');
190
179
  }
191
180
  if (requiresAudioBackground) {
192
181
  uploadData.backgroundArgb = await assertColor(options.backgroundColor);
193
- logger === null || logger === void 0 ? void 0 : logger.debug('computed backgroundColor audio status');
182
+ logger?.debug('computed backgroundColor audio status');
194
183
  }
195
184
  }
196
185
  catch (error) {
197
- logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'failed to obtain extra info');
186
+ logger?.warn({ trace: error.stack }, 'failed to obtain extra info');
198
187
  }
199
- })(),
200
- ])
201
- .finally(async () => {
202
- if (!Buffer.isBuffer(encWriteStream)) {
203
- encWriteStream.destroy();
188
+ })()
189
+ ]).finally(async () => {
190
+ try {
191
+ await fs_1.promises.unlink(encFilePath);
192
+ if (originalFilePath) {
193
+ await fs_1.promises.unlink(originalFilePath);
194
+ }
195
+ logger?.debug('removed tmp files');
204
196
  }
205
-
206
- if (didSaveToTmpPath && bodyPath) {
207
- await fs_1.promises.unlink(bodyPath);
208
- logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp files');
197
+ catch (error) {
198
+ logger?.warn('failed to remove tmp file');
209
199
  }
210
200
  });
211
-
212
- const obj = Types_1.WAProto.Message.fromObject({
213
- [`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
214
- url: handle ? undefined : mediaUrl,
201
+ const obj = Types_1.WAProto.Message.create({
202
+ [`${mediaType}Message`]: MessageTypeProto[mediaType].create({
203
+ url: mediaUrl,
215
204
  directPath,
216
- mediaKey: mediaKey,
217
- fileEncSha256: fileEncSha256,
205
+ mediaKey,
206
+ fileEncSha256,
218
207
  fileSha256,
219
208
  fileLength,
220
- mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
209
+ mediaKeyTimestamp: (0, generics_1.unixTimestampSeconds)(),
221
210
  ...uploadData,
222
211
  media: undefined
223
212
  })
224
213
  });
225
-
226
214
  if (uploadData.ptv) {
227
215
  obj.ptvMessage = obj.videoMessage;
228
216
  delete obj.videoMessage;
229
217
  }
230
-
231
218
  if (cacheableKey) {
232
- logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'set cache');
233
- options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
219
+ logger?.debug({ cacheableKey }, 'set cache');
220
+ await options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish());
234
221
  }
235
-
236
222
  return obj;
237
223
  };
238
224
  exports.prepareWAMessageMedia = prepareWAMessageMedia;
@@ -248,7 +234,7 @@ const prepareDisappearingMessageSettingContent = (ephemeralExpiration) => {
248
234
  }
249
235
  }
250
236
  };
251
- return Types_1.WAProto.Message.fromObject(content);
237
+ return Types_1.WAProto.Message.create(content);
252
238
  };
253
239
  exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSettingContent;
254
240
  /**
@@ -257,34 +243,33 @@ exports.prepareDisappearingMessageSettingContent = prepareDisappearingMessageSet
257
243
  * @param options.forceForward will show the message as forwarded even if it is from you
258
244
  */
259
245
  const generateForwardMessageContent = (message, forceForward) => {
260
- var _a;
261
246
  let content = message.message;
262
247
  if (!content) {
263
248
  throw new boom_1.Boom('no content in message', { statusCode: 400 });
264
249
  }
265
250
  // hacky copy
266
251
  content = (0, exports.normalizeMessageContent)(content);
267
- content = WAProto_1.proto.Message.decode(WAProto_1.proto.Message.encode(content).finish());
252
+ content = index_js_1.proto.Message.decode(index_js_1.proto.Message.encode(content).finish());
268
253
  let key = Object.keys(content)[0];
269
- let score = ((_a = content[key].contextInfo) === null || _a === void 0 ? void 0 : _a.forwardingScore) || 0;
254
+ let score = content?.[key]?.contextInfo?.forwardingScore || 0;
270
255
  score += message.key.fromMe && !forceForward ? 0 : 1;
271
256
  if (key === 'conversation') {
272
257
  content.extendedTextMessage = { text: content[key] };
273
258
  delete content.conversation;
274
259
  key = 'extendedTextMessage';
275
260
  }
261
+ const key_ = content?.[key];
276
262
  if (score > 0) {
277
- content[key].contextInfo = { forwardingScore: score, isForwarded: true };
263
+ key_.contextInfo = { forwardingScore: score, isForwarded: true };
278
264
  }
279
265
  else {
280
- content[key].contextInfo = {};
266
+ key_.contextInfo = {};
281
267
  }
282
268
  return content;
283
269
  };
284
270
  exports.generateForwardMessageContent = generateForwardMessageContent;
285
271
  const generateWAMessageContent = async (message, options) => {
286
- var _a;
287
- var _b;
272
+ var _a, _b;
288
273
  let m = {};
289
274
  if ('text' in message) {
290
275
  const extContent = { text: message.text };
@@ -293,7 +278,6 @@ const generateWAMessageContent = async (message, options) => {
293
278
  urlInfo = await (0, exports.generateLinkPreviewIfRequired)(message.text, options.getUrlInfo, options.logger);
294
279
  }
295
280
  if (urlInfo) {
296
- extContent.canonicalUrl = urlInfo['canonical-url'];
297
281
  extContent.matchedText = urlInfo['matched-text'];
298
282
  extContent.jpegThumbnail = urlInfo.jpegThumbnail;
299
283
  extContent.description = urlInfo.description;
@@ -324,20 +308,20 @@ const generateWAMessageContent = async (message, options) => {
324
308
  throw new boom_1.Boom('require atleast 1 contact', { statusCode: 400 });
325
309
  }
326
310
  if (contactLen === 1) {
327
- m.contactMessage = Types_1.WAProto.Message.ContactMessage.fromObject(message.contacts.contacts[0]);
311
+ m.contactMessage = Types_1.WAProto.Message.ContactMessage.create(message.contacts.contacts[0]);
328
312
  }
329
313
  else {
330
- m.contactsArrayMessage = Types_1.WAProto.Message.ContactsArrayMessage.fromObject(message.contacts);
314
+ m.contactsArrayMessage = Types_1.WAProto.Message.ContactsArrayMessage.create(message.contacts);
331
315
  }
332
316
  }
333
317
  else if ('location' in message) {
334
- m.locationMessage = Types_1.WAProto.Message.LocationMessage.fromObject(message.location);
318
+ m.locationMessage = Types_1.WAProto.Message.LocationMessage.create(message.location);
335
319
  }
336
320
  else if ('react' in message) {
337
321
  if (!message.react.senderTimestampMs) {
338
322
  message.react.senderTimestampMs = Date.now();
339
323
  }
340
- m.reactionMessage = Types_1.WAProto.Message.ReactionMessage.fromObject(message.react);
324
+ m.reactionMessage = Types_1.WAProto.Message.ReactionMessage.create(message.react);
341
325
  }
342
326
  else if ('delete' in message) {
343
327
  m.protocolMessage = {
@@ -349,64 +333,133 @@ const generateWAMessageContent = async (message, options) => {
349
333
  m = (0, exports.generateForwardMessageContent)(message.forward, message.force);
350
334
  }
351
335
  else if ('disappearingMessagesInChat' in message) {
352
- const exp = typeof message.disappearingMessagesInChat === 'boolean' ?
353
- (message.disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
354
- message.disappearingMessagesInChat;
336
+ const exp = typeof message.disappearingMessagesInChat === 'boolean'
337
+ ? message.disappearingMessagesInChat
338
+ ? Defaults_1.WA_DEFAULT_EPHEMERAL
339
+ : 0
340
+ : message.disappearingMessagesInChat;
355
341
  m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
356
342
  }
343
+ else if ('groupInvite' in message) {
344
+ m.groupInviteMessage = {};
345
+ m.groupInviteMessage.inviteCode = message.groupInvite.inviteCode;
346
+ m.groupInviteMessage.inviteExpiration = message.groupInvite.inviteExpiration;
347
+ m.groupInviteMessage.caption = message.groupInvite.text;
348
+ m.groupInviteMessage.groupJid = message.groupInvite.jid;
349
+ m.groupInviteMessage.groupName = message.groupInvite.subject;
350
+ //TODO: use built-in interface and get disappearing mode info etc.
351
+ //TODO: cache / use store!?
352
+ if (options.getProfilePicUrl) {
353
+ const pfpUrl = await options.getProfilePicUrl(message.groupInvite.jid, 'preview');
354
+ if (pfpUrl) {
355
+ const resp = await axios_1.default.get(pfpUrl, { responseType: 'arraybuffer' });
356
+ if (resp.status === 200) {
357
+ m.groupInviteMessage.jpegThumbnail = resp.data;
358
+ }
359
+ }
360
+ }
361
+ }
362
+ else if ('pin' in message) {
363
+ m.pinInChatMessage = {};
364
+ m.messageContextInfo = {};
365
+ m.pinInChatMessage.key = message.pin;
366
+ m.pinInChatMessage.type = message.type;
367
+ m.pinInChatMessage.senderTimestampMs = Date.now();
368
+ m.messageContextInfo.messageAddOnDurationInSecs = message.type === 1 ? message.time || 86400 : 0;
369
+ }
357
370
  else if ('buttonReply' in message) {
358
371
  switch (message.type) {
359
372
  case 'template':
360
373
  m.templateButtonReplyMessage = {
361
374
  selectedDisplayText: message.buttonReply.displayText,
362
375
  selectedId: message.buttonReply.id,
363
- selectedIndex: message.buttonReply.index,
376
+ selectedIndex: message.buttonReply.index
364
377
  };
365
378
  break;
366
379
  case 'plain':
367
380
  m.buttonsResponseMessage = {
368
381
  selectedButtonId: message.buttonReply.id,
369
382
  selectedDisplayText: message.buttonReply.displayText,
370
- type: WAProto_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT,
383
+ type: index_js_1.proto.Message.ButtonsResponseMessage.Type.DISPLAY_TEXT
371
384
  };
372
385
  break;
373
386
  }
374
387
  }
388
+ else if ('ptv' in message && message.ptv) {
389
+ const { videoMessage } = await (0, exports.prepareWAMessageMedia)({ video: message.video }, options);
390
+ m.ptvMessage = videoMessage;
391
+ }
375
392
  else if ('product' in message) {
376
393
  const { imageMessage } = await (0, exports.prepareWAMessageMedia)({ image: message.product.productImage }, options);
377
- m.productMessage = Types_1.WAProto.Message.ProductMessage.fromObject({
394
+ m.productMessage = Types_1.WAProto.Message.ProductMessage.create({
378
395
  ...message,
379
396
  product: {
380
397
  ...message.product,
381
- productImage: imageMessage,
398
+ productImage: imageMessage
382
399
  }
383
400
  });
384
401
  }
385
402
  else if ('listReply' in message) {
386
403
  m.listResponseMessage = { ...message.listReply };
387
404
  }
405
+ else if ('event' in message) {
406
+ m.eventMessage = {};
407
+ const startTime = Math.floor(message.event.startDate.getTime() / 1000);
408
+ if (message.event.call && options.getCallLink) {
409
+ const token = await options.getCallLink(message.event.call, { startTime });
410
+ m.eventMessage.joinLink = (message.event.call === 'audio' ? Defaults_1.CALL_AUDIO_PREFIX : Defaults_1.CALL_VIDEO_PREFIX) + token;
411
+ }
412
+ m.messageContextInfo = {
413
+ // encKey
414
+ messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32)
415
+ };
416
+ m.eventMessage.name = message.event.name;
417
+ m.eventMessage.description = message.event.description;
418
+ m.eventMessage.startTime = startTime;
419
+ m.eventMessage.endTime = message.event.endDate ? message.event.endDate.getTime() / 1000 : undefined;
420
+ m.eventMessage.isCanceled = message.event.isCancelled ?? false;
421
+ m.eventMessage.extraGuestsAllowed = message.event.extraGuestsAllowed;
422
+ m.eventMessage.isScheduleCall = message.event.isScheduleCall ?? false;
423
+ m.eventMessage.location = message.event.location;
424
+ }
388
425
  else if ('poll' in message) {
389
- (_b = message.poll).selectableCount || (_b.selectableCount = 0);
426
+ (_a = message.poll).selectableCount || (_a.selectableCount = 0);
427
+ (_b = message.poll).toAnnouncementGroup || (_b.toAnnouncementGroup = false);
390
428
  if (!Array.isArray(message.poll.values)) {
391
429
  throw new boom_1.Boom('Invalid poll values', { statusCode: 400 });
392
430
  }
393
- if (message.poll.selectableCount < 0
394
- || message.poll.selectableCount > message.poll.values.length) {
395
- throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, { statusCode: 400 });
431
+ if (message.poll.selectableCount < 0 || message.poll.selectableCount > message.poll.values.length) {
432
+ throw new boom_1.Boom(`poll.selectableCount in poll should be >= 0 and <= ${message.poll.values.length}`, {
433
+ statusCode: 400
434
+ });
396
435
  }
397
436
  m.messageContextInfo = {
398
437
  // encKey
399
- messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32),
438
+ messageSecret: message.poll.messageSecret || (0, crypto_1.randomBytes)(32)
400
439
  };
401
- m.pollCreationMessage = {
440
+ const pollCreationMessage = {
402
441
  name: message.poll.name,
403
442
  selectableOptionsCount: message.poll.selectableCount,
404
- options: message.poll.values.map(optionName => ({ optionName })),
443
+ options: message.poll.values.map(optionName => ({ optionName }))
405
444
  };
445
+ if (message.poll.toAnnouncementGroup) {
446
+ // poll v2 is for community announcement groups (single select and multiple)
447
+ m.pollCreationMessageV2 = pollCreationMessage;
448
+ }
449
+ else {
450
+ if (message.poll.selectableCount === 1) {
451
+ //poll v3 is for single select polls
452
+ m.pollCreationMessageV3 = pollCreationMessage;
453
+ }
454
+ else {
455
+ // poll for multiple choice polls
456
+ m.pollCreationMessage = pollCreationMessage;
457
+ }
458
+ }
406
459
  }
407
460
  else if ('sharePhoneNumber' in message) {
408
461
  m.protocolMessage = {
409
- type: WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
462
+ type: index_js_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER
410
463
  };
411
464
  }
412
465
  else if ('requestPhoneNumber' in message) {
@@ -415,68 +468,20 @@ const generateWAMessageContent = async (message, options) => {
415
468
  else {
416
469
  m = await (0, exports.prepareWAMessageMedia)(message, options);
417
470
  }
418
- if ('buttons' in message && !!message.buttons) {
419
- const buttonsMessage = {
420
- buttons: message.buttons.map(b => ({ ...b, type: WAProto_1.proto.Message.ButtonsMessage.Button.Type.RESPONSE }))
421
- };
422
- if ('text' in message) {
423
- buttonsMessage.contentText = message.text;
424
- buttonsMessage.headerType = ButtonType.EMPTY;
425
- }
426
- else {
427
- if ('caption' in message) {
428
- buttonsMessage.contentText = message.caption;
429
- }
430
- const type = Object.keys(m)[0].replace('Message', '').toUpperCase();
431
- buttonsMessage.headerType = ButtonType[type];
432
- Object.assign(buttonsMessage, m);
433
- }
434
- if ('footer' in message && !!message.footer) {
435
- buttonsMessage.footerText = message.footer;
436
- }
437
- m = { buttonsMessage };
438
- }
439
- else if ('templateButtons' in message && !!message.templateButtons) {
440
- const msg = {
441
- hydratedButtons: message.templateButtons
442
- };
443
- if ('text' in message) {
444
- msg.hydratedContentText = message.text;
445
- }
446
- else {
447
- if ('caption' in message) {
448
- msg.hydratedContentText = message.caption;
449
- }
450
- Object.assign(msg, m);
451
- }
452
- if ('footer' in message && !!message.footer) {
453
- msg.hydratedFooterText = message.footer;
454
- }
455
- m = {
456
- templateMessage: {
457
- fourRowTemplate: msg,
458
- hydratedTemplate: msg
459
- }
460
- };
461
- }
462
- if ('sections' in message && !!message.sections) {
463
- const listMessage = {
464
- sections: message.sections,
465
- buttonText: message.buttonText,
466
- title: message.title,
467
- footerText: message.footer,
468
- description: message.text,
469
- listType: WAProto_1.proto.Message.ListMessage.ListType.SINGLE_SELECT
470
- };
471
- m = { listMessage };
472
- }
473
471
  if ('viewOnce' in message && !!message.viewOnce) {
474
472
  m = { viewOnceMessage: { message: m } };
475
473
  }
476
- if ('mentions' in message && ((_a = message.mentions) === null || _a === void 0 ? void 0 : _a.length)) {
477
- const [messageType] = Object.keys(m);
478
- m[messageType].contextInfo = m[messageType] || {};
479
- m[messageType].contextInfo.mentionedJid = message.mentions;
474
+ if ('mentions' in message && message.mentions?.length) {
475
+ const messageType = Object.keys(m)[0];
476
+ const key = m[messageType];
477
+ if ('contextInfo' in key && !!key.contextInfo) {
478
+ key.contextInfo.mentionedJid = message.mentions;
479
+ }
480
+ else if (key) {
481
+ key.contextInfo = {
482
+ mentionedJid: message.mentions
483
+ };
484
+ }
480
485
  }
481
486
  if ('edit' in message) {
482
487
  m = {
@@ -489,11 +494,16 @@ const generateWAMessageContent = async (message, options) => {
489
494
  };
490
495
  }
491
496
  if ('contextInfo' in message && !!message.contextInfo) {
492
- const [messageType] = Object.keys(m);
493
- m[messageType] = m[messageType] || {};
494
- m[messageType].contextInfo = message.contextInfo;
497
+ const messageType = Object.keys(m)[0];
498
+ const key = m[messageType];
499
+ if ('contextInfo' in key && !!key.contextInfo) {
500
+ key.contextInfo = { ...key.contextInfo, ...message.contextInfo };
501
+ }
502
+ else if (key) {
503
+ key.contextInfo = message.contextInfo;
504
+ }
495
505
  }
496
- return Types_1.WAProto.Message.fromObject(m);
506
+ return Types_1.WAProto.Message.create(m);
497
507
  };
498
508
  exports.generateWAMessageContent = generateWAMessageContent;
499
509
  const generateWAMessageFromContent = (jid, message, options) => {
@@ -506,17 +516,19 @@ const generateWAMessageFromContent = (jid, message, options) => {
506
516
  const key = (0, exports.getContentType)(innerMessage);
507
517
  const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
508
518
  const { quoted, userJid } = options;
509
- if (quoted && !(0, WABinary_1.isJidNewsLetter)(jid)) {
510
- const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
519
+ if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
520
+ const participant = quoted.key.fromMe
521
+ ? userJid
522
+ : quoted.participant || quoted.key.participant || quoted.key.remoteJid;
511
523
  let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
512
524
  const msgType = (0, exports.getContentType)(quotedMsg);
513
525
  // strip any redundant properties
514
- quotedMsg = WAProto_1.proto.Message.fromObject({ [msgType]: quotedMsg[msgType] });
526
+ quotedMsg = index_js_1.proto.Message.create({ [msgType]: quotedMsg[msgType] });
515
527
  const quotedContent = quotedMsg[msgType];
516
528
  if (typeof quotedContent === 'object' && quotedContent && 'contextInfo' in quotedContent) {
517
529
  delete quotedContent.contextInfo;
518
530
  }
519
- const contextInfo = innerMessage[key].contextInfo || {};
531
+ const contextInfo = ('contextInfo' in innerMessage[key] && innerMessage[key]?.contextInfo) || {};
520
532
  contextInfo.participant = (0, WABinary_1.jidNormalizedUser)(participant);
521
533
  contextInfo.stanzaId = quoted.key.id;
522
534
  contextInfo.quotedMessage = quotedMsg;
@@ -525,29 +537,33 @@ const generateWAMessageFromContent = (jid, message, options) => {
525
537
  if (jid !== quoted.key.remoteJid) {
526
538
  contextInfo.remoteJid = quoted.key.remoteJid;
527
539
  }
528
- innerMessage[key].contextInfo = contextInfo;
540
+ if (contextInfo && innerMessage[key]) {
541
+ /* @ts-ignore */
542
+ innerMessage[key].contextInfo = contextInfo;
543
+ }
529
544
  }
530
545
  if (
531
546
  // if we want to send a disappearing message
532
- !!(options === null || options === void 0 ? void 0 : options.ephemeralExpiration) &&
547
+ !!options?.ephemeralExpiration &&
533
548
  // and it's not a protocol message -- delete, toggle disappear message
534
549
  key !== 'protocolMessage' &&
535
550
  // already not converted to disappearing message
536
551
  key !== 'ephemeralMessage' &&
537
- // newsletter not accept disappearing messages
538
- !(0, WABinary_1.isJidNewsLetter)(jid)) {
552
+ // newsletters don't support ephemeral messages
553
+ !(0, WABinary_1.isJidNewsletter)(jid)) {
554
+ /* @ts-ignore */
539
555
  innerMessage[key].contextInfo = {
540
556
  ...(innerMessage[key].contextInfo || {}),
541
- expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
557
+ expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL
542
558
  //ephemeralSettingTimestamp: options.ephemeralOptions.eph_setting_ts?.toString()
543
559
  };
544
560
  }
545
- message = Types_1.WAProto.Message.fromObject(message);
561
+ message = Types_1.WAProto.Message.create(message);
546
562
  const messageJSON = {
547
563
  key: {
548
564
  remoteJid: jid,
549
565
  fromMe: true,
550
- id: (options === null || options === void 0 ? void 0 : options.messageId) || (0, generics_1.generateMessageID)(),
566
+ id: options?.messageId || (0, generics_1.generateMessageIDV2)()
551
567
  },
552
568
  message: message,
553
569
  messageTimestamp: timestamp,
@@ -555,14 +571,14 @@ const generateWAMessageFromContent = (jid, message, options) => {
555
571
  participant: (0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidStatusBroadcast)(jid) ? userJid : undefined,
556
572
  status: Types_1.WAMessageStatus.PENDING
557
573
  };
558
- return Types_1.WAProto.WebMessageInfo.fromObject(messageJSON);
574
+ return Types_1.WAProto.WebMessageInfo.create(messageJSON);
559
575
  };
560
576
  exports.generateWAMessageFromContent = generateWAMessageFromContent;
561
577
  const generateWAMessage = async (jid, content, options) => {
562
- var _a;
563
578
  // ensure msg ID is with every log
564
- options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
565
- return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsLetter)(jid), ...options }), options);
579
+ options.logger = options?.logger?.child({ msgId: options.messageId });
580
+ // Pass jid in the options to generateWAMessageContent
581
+ return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { ...options, jid }), options);
566
582
  };
567
583
  exports.generateWAMessage = generateWAMessage;
568
584
  /** Get the key to access the true type of content */
@@ -594,12 +610,12 @@ const normalizeMessageContent = (content) => {
594
610
  }
595
611
  return content;
596
612
  function getFutureProofMessage(message) {
597
- return ((message === null || message === void 0 ? void 0 : message.ephemeralMessage)
598
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessage)
599
- || (message === null || message === void 0 ? void 0 : message.documentWithCaptionMessage)
600
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2)
601
- || (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension)
602
- || (message === null || message === void 0 ? void 0 : message.editedMessage));
613
+ return (message?.ephemeralMessage ||
614
+ message?.viewOnceMessage ||
615
+ message?.documentWithCaptionMessage ||
616
+ message?.viewOnceMessageV2 ||
617
+ message?.viewOnceMessageV2Extension ||
618
+ message?.editedMessage);
603
619
  }
604
620
  };
605
621
  exports.normalizeMessageContent = normalizeMessageContent;
@@ -608,7 +624,6 @@ exports.normalizeMessageContent = normalizeMessageContent;
608
624
  * Eg. extracts the inner message from a disappearing message/view once message
609
625
  */
610
626
  const extractMessageContent = (content) => {
611
- var _a, _b, _c, _d, _e, _f;
612
627
  const extractFromTemplateMessage = (msg) => {
613
628
  if (msg.imageMessage) {
614
629
  return { imageMessage: msg.imageMessage };
@@ -624,24 +639,22 @@ const extractMessageContent = (content) => {
624
639
  }
625
640
  else {
626
641
  return {
627
- conversation: 'contentText' in msg
628
- ? msg.contentText
629
- : ('hydratedContentText' in msg ? msg.hydratedContentText : '')
642
+ conversation: 'contentText' in msg ? msg.contentText : 'hydratedContentText' in msg ? msg.hydratedContentText : ''
630
643
  };
631
644
  }
632
645
  };
633
646
  content = (0, exports.normalizeMessageContent)(content);
634
- if (content === null || content === void 0 ? void 0 : content.buttonsMessage) {
647
+ if (content?.buttonsMessage) {
635
648
  return extractFromTemplateMessage(content.buttonsMessage);
636
649
  }
637
- if ((_a = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _a === void 0 ? void 0 : _a.hydratedFourRowTemplate) {
638
- return extractFromTemplateMessage((_b = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _b === void 0 ? void 0 : _b.hydratedFourRowTemplate);
650
+ if (content?.templateMessage?.hydratedFourRowTemplate) {
651
+ return extractFromTemplateMessage(content?.templateMessage?.hydratedFourRowTemplate);
639
652
  }
640
- if ((_c = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _c === void 0 ? void 0 : _c.hydratedTemplate) {
641
- return extractFromTemplateMessage((_d = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _d === void 0 ? void 0 : _d.hydratedTemplate);
653
+ if (content?.templateMessage?.hydratedTemplate) {
654
+ return extractFromTemplateMessage(content?.templateMessage?.hydratedTemplate);
642
655
  }
643
- if ((_e = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _e === void 0 ? void 0 : _e.fourRowTemplate) {
644
- return extractFromTemplateMessage((_f = content === null || content === void 0 ? void 0 : content.templateMessage) === null || _f === void 0 ? void 0 : _f.fourRowTemplate);
656
+ if (content?.templateMessage?.fourRowTemplate) {
657
+ return extractFromTemplateMessage(content?.templateMessage?.fourRowTemplate);
645
658
  }
646
659
  return content;
647
660
  };
@@ -649,7 +662,15 @@ exports.extractMessageContent = extractMessageContent;
649
662
  /**
650
663
  * Returns the device predicted by message ID
651
664
  */
652
- const getDevice = (id) => /^3A.{18}$/.test(id) ? 'ios' : /^3E.{20}$/.test(id) ? 'web' : /^(.{21}|.{32})$/.test(id) ? 'android' : /^.{18}$/.test(id) ? 'desktop' : 'unknown';
665
+ const getDevice = (id) => /^3A.{18}$/.test(id)
666
+ ? 'ios'
667
+ : /^3E.{20}$/.test(id)
668
+ ? 'web'
669
+ : /^(.{21}|.{32})$/.test(id)
670
+ ? 'android'
671
+ : /^(3F|.{18}$)/.test(id)
672
+ ? 'desktop'
673
+ : 'unknown';
653
674
  exports.getDevice = getDevice;
654
675
  /** Upserts a receipt in the message */
655
676
  const updateMessageWithReceipt = (msg, receipt) => {
@@ -666,21 +687,17 @@ exports.updateMessageWithReceipt = updateMessageWithReceipt;
666
687
  /** Update the message with a new reaction */
667
688
  const updateMessageWithReaction = (msg, reaction) => {
668
689
  const authorID = (0, generics_1.getKeyAuthor)(reaction.key);
669
- const reactions = (msg.reactions || [])
670
- .filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
671
- if (reaction.text) {
672
- reactions.push(reaction);
673
- }
690
+ const reactions = (msg.reactions || []).filter(r => (0, generics_1.getKeyAuthor)(r.key) !== authorID);
691
+ reaction.text = reaction.text || '';
692
+ reactions.push(reaction);
674
693
  msg.reactions = reactions;
675
694
  };
676
695
  exports.updateMessageWithReaction = updateMessageWithReaction;
677
696
  /** Update the message with a new poll update */
678
697
  const updateMessageWithPollUpdate = (msg, update) => {
679
- var _a, _b;
680
698
  const authorID = (0, generics_1.getKeyAuthor)(update.pollUpdateMessageKey);
681
- const reactions = (msg.pollUpdates || [])
682
- .filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
683
- if ((_b = (_a = update.vote) === null || _a === void 0 ? void 0 : _a.selectedOptions) === null || _b === void 0 ? void 0 : _b.length) {
699
+ const reactions = (msg.pollUpdates || []).filter(r => (0, generics_1.getKeyAuthor)(r.pollUpdateMessageKey) !== authorID);
700
+ if (update.vote?.selectedOptions?.length) {
684
701
  reactions.push(update);
685
702
  }
686
703
  msg.pollUpdates = reactions;
@@ -693,8 +710,10 @@ exports.updateMessageWithPollUpdate = updateMessageWithPollUpdate;
693
710
  * @returns A list of options & their voters
694
711
  */
695
712
  function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
696
- var _a, _b, _c;
697
- 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) || [];
713
+ const opts = message?.pollCreationMessage?.options ||
714
+ message?.pollCreationMessageV2?.options ||
715
+ message?.pollCreationMessageV3?.options ||
716
+ [];
698
717
  const voteHashMap = opts.reduce((acc, opt) => {
699
718
  const hash = (0, crypto_2.sha256)(Buffer.from(opt.optionName || '')).toString();
700
719
  acc[hash] = {
@@ -723,7 +742,6 @@ function getAggregateVotesInPollMessage({ message, pollUpdates }, meId) {
723
742
  }
724
743
  return Object.values(voteHashMap);
725
744
  }
726
- exports.getAggregateVotesInPollMessage = getAggregateVotesInPollMessage;
727
745
  /** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
728
746
  const aggregateMessageKeysNotFromMe = (keys) => {
729
747
  const keyMap = {};
@@ -748,20 +766,15 @@ const REUPLOAD_REQUIRED_STATUS = [410, 404];
748
766
  * Downloads the given message. Throws an error if it's not a media message
749
767
  */
750
768
  const downloadMediaMessage = async (message, type, options, ctx) => {
751
- const result = await downloadMsg()
752
- .catch(async (error) => {
753
- var _a;
754
- if (ctx) {
755
- if (axios_1.default.isAxiosError(error)) {
756
- // check if the message requires a reupload
757
- if (REUPLOAD_REQUIRED_STATUS.includes((_a = error.response) === null || _a === void 0 ? void 0 : _a.status)) {
758
- ctx.logger.info({ key: message.key }, 'sending reupload media request...');
759
- // request reupload
760
- message = await ctx.reuploadRequest(message);
761
- const result = await downloadMsg();
762
- return result;
763
- }
764
- }
769
+ const result = await downloadMsg().catch(async (error) => {
770
+ if (ctx &&
771
+ axios_1.default.isAxiosError(error) && // check if the message requires a reupload
772
+ REUPLOAD_REQUIRED_STATUS.includes(error.response?.status)) {
773
+ ctx.logger.info({ key: message.key }, 'sending reupload media request...');
774
+ // request reupload
775
+ message = await ctx.reuploadRequest(message);
776
+ const result = await downloadMsg();
777
+ return result;
765
778
  }
766
779
  throw error;
767
780
  });
@@ -772,7 +785,7 @@ const downloadMediaMessage = async (message, type, options, ctx) => {
772
785
  throw new boom_1.Boom('No message present', { statusCode: 400, data: message });
773
786
  }
774
787
  const contentType = (0, exports.getContentType)(mContent);
775
- let mediaType = contentType === null || contentType === void 0 ? void 0 : contentType.replace('Message', '');
788
+ let mediaType = contentType?.replace('Message', '');
776
789
  const media = mContent[contentType];
777
790
  if (!media || typeof media !== 'object' || (!('url' in media) && !('thumbnailDirectPath' in media))) {
778
791
  throw new boom_1.Boom(`"${contentType}" message is not a media message`);
@@ -803,11 +816,11 @@ exports.downloadMediaMessage = downloadMediaMessage;
803
816
  /** Checks whether the given message is a media message; if it is returns the inner content */
804
817
  const assertMediaContent = (content) => {
805
818
  content = (0, exports.extractMessageContent)(content);
806
- const mediaContent = (content === null || content === void 0 ? void 0 : content.documentMessage)
807
- || (content === null || content === void 0 ? void 0 : content.imageMessage)
808
- || (content === null || content === void 0 ? void 0 : content.videoMessage)
809
- || (content === null || content === void 0 ? void 0 : content.audioMessage)
810
- || (content === null || content === void 0 ? void 0 : content.stickerMessage);
819
+ const mediaContent = content?.documentMessage ||
820
+ content?.imageMessage ||
821
+ content?.videoMessage ||
822
+ content?.audioMessage ||
823
+ content?.stickerMessage;
811
824
  if (!mediaContent) {
812
825
  throw new boom_1.Boom('given message is not a media message', { statusCode: 400, data: content });
813
826
  }