@ubedsockets/baileys 1.6.3 → 1.6.5

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