alipclutch-baileys 8.5.3 → 8.5.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 (112) hide show
  1. package/engine-requirements.js +10 -0
  2. package/lib/Defaults/baileys-version.json +2 -2
  3. package/lib/Defaults/index.d.ts +7 -16
  4. package/lib/Defaults/index.js +119 -90
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Socket/Client/abstract-socket-client.d.ts +17 -0
  7. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  8. package/lib/Socket/Client/index.d.ts +3 -2
  9. package/lib/Socket/Client/index.js +3 -2
  10. package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
  11. package/lib/Socket/Client/mobile-socket-client.js +65 -0
  12. package/lib/Socket/Client/web-socket-client.d.ts +12 -0
  13. package/lib/Socket/Client/web-socket-client.js +62 -0
  14. package/lib/Socket/business.d.ts +58 -59
  15. package/lib/Socket/chats.d.ts +230 -45
  16. package/lib/Socket/chats.js +238 -139
  17. package/lib/Socket/groups.d.ts +32 -41
  18. package/lib/Socket/groups.js +23 -38
  19. package/lib/Socket/index.d.ts +64 -63
  20. package/lib/Socket/index.js +3 -2
  21. package/lib/Socket/messages-recv.js +65 -9
  22. package/lib/Socket/messages-send.d.ts +47 -49
  23. package/lib/Socket/messages-send.js +395 -543
  24. package/lib/Socket/newsletter.d.ts +37 -39
  25. package/lib/Socket/newsletter.js +123 -88
  26. package/lib/Socket/registration.d.ts +267 -0
  27. package/lib/Socket/registration.js +166 -0
  28. package/lib/Socket/setup.d.ts +253 -0
  29. package/lib/Socket/setup.js +4 -5
  30. package/lib/Socket/socket.d.ts +43 -270
  31. package/lib/Socket/socket.js +19 -8
  32. package/lib/Socket/usync.d.ts +3 -3
  33. package/lib/Store/index.d.ts +2 -1
  34. package/lib/Store/index.js +3 -1
  35. package/lib/Store/make-cache-manager-store.d.ts +13 -0
  36. package/lib/Store/make-cache-manager-store.js +83 -0
  37. package/lib/Store/make-in-memory-store.d.ts +24 -24
  38. package/lib/Store/make-in-memory-store.js +14 -26
  39. package/lib/Store/make-ordered-dictionary.d.ts +1 -1
  40. package/lib/Store/make-ordered-dictionary.js +2 -2
  41. package/lib/Types/Auth.d.ts +7 -0
  42. package/lib/Types/Call.d.ts +1 -1
  43. package/lib/Types/Chat.d.ts +7 -14
  44. package/lib/Types/Contact.d.ts +1 -5
  45. package/lib/Types/Events.d.ts +2 -44
  46. package/lib/Types/GroupMetadata.d.ts +2 -11
  47. package/lib/Types/Label.js +1 -1
  48. package/lib/Types/LabelAssociation.js +1 -1
  49. package/lib/Types/Message.d.ts +21 -148
  50. package/lib/Types/Message.js +2 -0
  51. package/lib/Types/Newsletter.d.ts +97 -73
  52. package/lib/Types/Newsletter.js +38 -18
  53. package/lib/Types/Socket.d.ts +9 -17
  54. package/lib/Types/index.d.ts +1 -8
  55. package/lib/Types/index.js +2 -2
  56. package/lib/Utils/auth-utils.d.ts +3 -3
  57. package/lib/Utils/auth-utils.js +13 -6
  58. package/lib/Utils/business.js +2 -2
  59. package/lib/Utils/chat-utils.d.ts +16 -15
  60. package/lib/Utils/chat-utils.js +35 -36
  61. package/lib/Utils/crypto.d.ts +16 -15
  62. package/lib/Utils/crypto.js +29 -71
  63. package/lib/Utils/decode-wa-message.d.ts +6 -22
  64. package/lib/Utils/decode-wa-message.js +56 -65
  65. package/lib/Utils/event-buffer.d.ts +2 -2
  66. package/lib/Utils/event-buffer.js +7 -11
  67. package/lib/Utils/generics.d.ts +20 -17
  68. package/lib/Utils/generics.js +75 -95
  69. package/lib/Utils/history.d.ts +0 -4
  70. package/lib/Utils/history.js +6 -4
  71. package/lib/Utils/link-preview.d.ts +2 -2
  72. package/lib/Utils/link-preview.js +1 -34
  73. package/lib/Utils/logger.d.ts +3 -10
  74. package/lib/Utils/lt-hash.d.ts +2 -2
  75. package/lib/Utils/lt-hash.js +6 -6
  76. package/lib/Utils/make-mutex.d.ts +2 -2
  77. package/lib/Utils/messages-media.d.ts +24 -28
  78. package/lib/Utils/messages-media.js +111 -272
  79. package/lib/Utils/messages.d.ts +10 -13
  80. package/lib/Utils/messages.js +51 -336
  81. package/lib/Utils/noise-handler.d.ts +12 -10
  82. package/lib/Utils/noise-handler.js +23 -18
  83. package/lib/Utils/process-message.d.ts +4 -5
  84. package/lib/Utils/process-message.js +25 -108
  85. package/lib/Utils/signal.d.ts +1 -2
  86. package/lib/Utils/signal.js +26 -26
  87. package/lib/Utils/use-multi-file-auth-state.d.ts +1 -0
  88. package/lib/Utils/use-multi-file-auth-state.js +0 -6
  89. package/lib/Utils/validate-connection.d.ts +4 -3
  90. package/lib/Utils/validate-connection.js +1 -1
  91. package/lib/WABinary/constants.d.ts +27 -24
  92. package/lib/WABinary/constants.js +13 -1276
  93. package/lib/WABinary/decode.d.ts +4 -3
  94. package/lib/WABinary/decode.js +13 -26
  95. package/lib/WABinary/encode.d.ts +2 -1
  96. package/lib/WABinary/encode.js +152 -137
  97. package/lib/WABinary/generic-utils.d.ts +4 -1
  98. package/lib/WABinary/generic-utils.js +125 -37
  99. package/lib/WABinary/jid-utils.d.ts +5 -11
  100. package/lib/WABinary/jid-utils.js +5 -28
  101. package/lib/WAM/BinaryInfo.d.ts +11 -2
  102. package/lib/WAM/encode.d.ts +2 -1
  103. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -1
  104. package/lib/index.d.ts +1 -0
  105. package/lib/index.js +15 -27
  106. package/package.json +31 -18
  107. package/WAProto/GenerateStatics.sh +0 -4
  108. package/WAProto/WAProto.proto +0 -4775
  109. package/WAProto/index.d.ts +0 -55057
  110. package/WAProto/index.ts.ts +0 -53473
  111. package/lib/Socket/setup.ts +0 -623
  112. package/lib/WABinary/jid-utils.js.bak +0 -83
@@ -15,47 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
37
24
  };
38
25
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.getStream = exports.toBuffer = exports.toReadable = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.extractVideoThumb = exports.hkdfInfoKey = void 0;
40
- exports.getMediaKeys = getMediaKeys;
41
- exports.uploadFile = uploadFile;
42
- exports.vid2jpg = vid2jpg;
43
- exports.getAudioDuration = getAudioDuration;
44
- exports.getAudioWaveform = getAudioWaveform;
45
- exports.generateThumbnail = generateThumbnail;
46
- exports.extensionForMediaMessage = extensionForMediaMessage;
26
+ exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
47
27
  const boom_1 = require("@hapi/boom");
48
- const axios_1 = __importDefault(require("axios"));
49
- const form_data_1 = __importDefault(require("form-data"));
50
- const cheerio = __importStar(require("cheerio"));
28
+ const child_process_1 = require("child_process");
51
29
  const Crypto = __importStar(require("crypto"));
52
30
  const events_1 = require("events");
53
31
  const fs_1 = require("fs");
54
32
  const os_1 = require("os");
55
33
  const path_1 = require("path");
56
- const jimp_1 = __importDefault(require("jimp"));
57
34
  const stream_1 = require("stream");
58
- const child_process_1 = require("child_process");
59
35
  const WAProto_1 = require("../../WAProto");
60
36
  const Defaults_1 = require("../Defaults");
61
37
  const WABinary_1 = require("../WABinary");
@@ -65,11 +41,13 @@ const getTmpFilesDirectory = () => (0, os_1.tmpdir)();
65
41
  const getImageProcessingLibrary = async () => {
66
42
  const [_jimp, sharp] = await Promise.all([
67
43
  (async () => {
68
- const jimp = await (Promise.resolve().then(() => __importStar(require('jimp'))).catch(() => { }));
44
+ const jimp = await (import('jimp')
45
+ .catch(() => { }));
69
46
  return jimp;
70
47
  })(),
71
48
  (async () => {
72
- const sharp = await (Promise.resolve().then(() => __importStar(require('sharp'))).catch(() => { }));
49
+ const sharp = await (import('sharp')
50
+ .catch(() => { }));
73
51
  return sharp;
74
52
  })()
75
53
  ]);
@@ -88,7 +66,7 @@ const hkdfInfoKey = (type) => {
88
66
  };
89
67
  exports.hkdfInfoKey = hkdfInfoKey;
90
68
  /** generates all the keys required to encrypt/decrypt & sign a media message */
91
- async function getMediaKeys(buffer, mediaType) {
69
+ function getMediaKeys(buffer, mediaType) {
92
70
  if (!buffer) {
93
71
  throw new boom_1.Boom('Cannot derive from empty media key');
94
72
  }
@@ -96,183 +74,26 @@ async function getMediaKeys(buffer, mediaType) {
96
74
  buffer = Buffer.from(buffer.replace('data:;base64,', ''), 'base64');
97
75
  }
98
76
  // expand using HKDF to 112 bytes, also pass in the relevant app info
99
- const expandedMediaKey = await (0, crypto_1.hkdf)(buffer, 112, { info: (0, exports.hkdfInfoKey)(mediaType) });
77
+ const expandedMediaKey = (0, crypto_1.hkdf)(buffer, 112, { info: (0, exports.hkdfInfoKey)(mediaType) });
100
78
  return {
101
79
  iv: expandedMediaKey.slice(0, 16),
102
80
  cipherKey: expandedMediaKey.slice(16, 48),
103
81
  macKey: expandedMediaKey.slice(48, 80),
104
82
  };
105
83
  }
106
- async function uploadFile(buffer, logger) {
107
- const { fromBuffer } = await Promise.resolve().then(() => __importStar(require('file-type')));
108
- const fileType = await fromBuffer(buffer);
109
- if (!fileType)
110
- throw new Error("Failed to detect file type.");
111
- const { ext, mime } = fileType;
112
- const services = [
113
- {
114
- name: "catbox",
115
- url: "https://catbox.moe/user/api.php",
116
- buildForm: () => {
117
- const form = new form_data_1.default();
118
- form.append("fileToUpload", buffer, {
119
- filename: `file.${ext}`,
120
- contentType: mime || "application/octet-stream"
121
- });
122
- form.append("reqtype", "fileupload");
123
- return form;
124
- },
125
- parseResponse: res => res.data
126
- },
127
- {
128
- name: "pdi.moe",
129
- url: "https://scdn.pdi.moe/upload",
130
- buildForm: () => {
131
- const form = new form_data_1.default();
132
- form.append("file", buffer, {
133
- filename: `file.${ext}`,
134
- contentType: mime
135
- });
136
- return form;
137
- },
138
- parseResponse: res => res.data.result.url
139
- },
140
- {
141
- name: "qu.ax",
142
- url: "https://qu.ax/upload.php",
143
- buildForm: () => {
144
- const form = new form_data_1.default();
145
- form.append("files[]", buffer, {
146
- filename: `file.${ext}`,
147
- contentType: mime || "application/octet-stream"
148
- });
149
- return form;
150
- },
151
- parseResponse: res => {
152
- var _a, _b, _c;
153
- if (!((_c = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.url))
154
- throw new Error("Failed to get URL from qu.ax");
155
- return res.data.files[0].url;
156
- }
157
- },
158
- {
159
- name: "uguu.se",
160
- url: "https://uguu.se/upload.php",
161
- buildForm: () => {
162
- const form = new form_data_1.default();
163
- form.append("files[]", buffer, {
164
- filename: `file.${ext}`,
165
- contentType: mime || "application/octet-stream"
166
- });
167
- return form;
168
- },
169
- parseResponse: res => {
170
- var _a, _b, _c;
171
- if (!((_c = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.url))
172
- throw new Error("Failed to get URL from uguu.se");
173
- return res.data.files[0].url;
174
- }
175
- },
176
- {
177
- name: "tmpfiles",
178
- url: "https://tmpfiles.org/api/v1/upload",
179
- buildForm: () => {
180
- const form = new form_data_1.default();
181
- form.append("file", buffer, {
182
- filename: `file.${ext}`,
183
- contentType: mime
184
- });
185
- return form;
186
- },
187
- parseResponse: res => {
188
- const match = res.data.data.url.match(/https:\/\/tmpfiles\.org\/(.*)/);
189
- if (!match)
190
- throw new Error("Failed to parse tmpfiles URL.");
191
- return `https://tmpfiles.org/dl/${match[1]}`;
192
- }
193
- }
194
- ];
195
- for (const service of services) {
196
- try {
197
- const form = service.buildForm();
198
- const res = await axios_1.default.post(service.url, form, {
199
- headers: form.getHeaders()
200
- });
201
- const url = service.parseResponse(res);
202
- return url;
203
- }
204
- catch (error) {
205
- logger === null || logger === void 0 ? void 0 : logger.debug(`[${service.name}] eror:`, (error === null || error === void 0 ? void 0 : error.message) || error);
206
- }
207
- }
208
- throw new Error("All upload services failed.");
209
- }
210
- async function vid2jpg(videoUrl) {
211
- try {
212
- const { data } = await axios_1.default.get(`https://ezgif.com/video-to-jpg?url=${encodeURIComponent(videoUrl)}`);
213
- const $ = cheerio.load(data);
214
- const fileToken = $('input[name="file"]').attr("value");
215
- if (!fileToken) {
216
- throw new Error("Failed to retrieve file token. The video URL may be invalid or inaccessible.");
217
- }
218
- const formData = new URLSearchParams();
219
- formData.append("file", fileToken);
220
- formData.append("end", "1");
221
- formData.append("video-to-jpg", "Convert to JPG!");
222
- const convert = await axios_1.default.post(`https://ezgif.com/video-to-jpg/${fileToken}`, formData);
223
- const $2 = cheerio.load(convert.data);
224
- let imageUrl = $2("#output img").first().attr("src");
225
- if (!imageUrl) {
226
- throw new Error("Could not locate the converted image output.");
227
- }
228
- if (imageUrl.startsWith("//")) {
229
- imageUrl = "https:" + imageUrl;
84
+ exports.getMediaKeys = getMediaKeys;
85
+ /** Extracts video thumb using FFMPEG */
86
+ const extractVideoThumb = async (path, destPath, time, size) => new Promise((resolve, reject) => {
87
+ const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}`;
88
+ (0, child_process_1.exec)(cmd, (err) => {
89
+ if (err) {
90
+ reject(err);
230
91
  }
231
- else if (imageUrl.startsWith("/")) {
232
- const cdnMatch = imageUrl.match(/\/(s\d+\..+?)\/.*/);
233
- if (cdnMatch) {
234
- imageUrl = "https://" + imageUrl.slice(2);
235
- }
236
- else {
237
- imageUrl = "https://ezgif.com" + imageUrl;
238
- }
92
+ else {
93
+ resolve();
239
94
  }
240
- return imageUrl;
241
- }
242
- catch (error) {
243
- throw new Error("Failed to convert video to JPG: " + error.message);
244
- }
245
- }
246
- /**
247
- * Extracts video thumbnail using FFmpeg
248
- */
249
- const extractVideoThumb = async (videoPath, time = '00:00:00', size = { width: 256 }) => {
250
- return new Promise((resolve, reject) => {
251
- const args = [
252
- '-ss', time,
253
- '-i', videoPath,
254
- '-y',
255
- '-vf', `scale=${size.width}:-1`,
256
- '-vframes', '1',
257
- '-f', 'image2',
258
- '-vcodec', 'mjpeg',
259
- 'pipe:1'
260
- ];
261
- const ffmpeg = (0, child_process_1.spawn)('ffmpeg', args);
262
- const chunks = [];
263
- let errorOutput = '';
264
- ffmpeg.stdout.on('data', chunk => chunks.push(chunk));
265
- ffmpeg.stderr.on('data', data => {
266
- errorOutput += data.toString();
267
- });
268
- ffmpeg.on('error', reject);
269
- ffmpeg.on('close', code => {
270
- if (code === 0) return resolve(Buffer.concat(chunks));
271
- reject(new Error(`ffmpeg exited with code ${code}\n${errorOutput}`));
272
- });
273
95
  });
274
- };
275
- exports.extractVideoThumb = extractVideoThumb;
96
+ });
276
97
  const extractImageThumb = async (bufferOrFilePath, width = 32) => {
277
98
  var _a, _b;
278
99
  if (bufferOrFilePath instanceof stream_1.Readable) {
@@ -321,8 +142,8 @@ const encodeBase64EncodedStringForUpload = (b64) => (encodeURIComponent(b64
321
142
  .replace(/\=+$/, '')));
322
143
  exports.encodeBase64EncodedStringForUpload = encodeBase64EncodedStringForUpload;
323
144
  const generateProfilePicture = async (mediaUpload) => {
145
+ var _a, _b;
324
146
  let bufferOrFilePath;
325
- let img;
326
147
  if (Buffer.isBuffer(mediaUpload)) {
327
148
  bufferOrFilePath = mediaUpload;
328
149
  }
@@ -332,11 +153,29 @@ const generateProfilePicture = async (mediaUpload) => {
332
153
  else {
333
154
  bufferOrFilePath = await (0, exports.toBuffer)(mediaUpload.stream);
334
155
  }
335
- const jimp = await jimp_1.default.read(bufferOrFilePath);
336
- const cropped = jimp.getWidth() > jimp.getHeight() ? jimp.resize(550, -1) : jimp.resize(-1, 650);
337
- img = cropped
338
- .quality(100)
339
- .getBufferAsync(jimp_1.default.MIME_JPEG);
156
+ const lib = await getImageProcessingLibrary();
157
+ let img;
158
+ if ('sharp' in lib && typeof ((_a = lib.sharp) === null || _a === void 0 ? void 0 : _a.default) === 'function') {
159
+ img = lib.sharp.default(bufferOrFilePath)
160
+ .resize(640, 640)
161
+ .jpeg({
162
+ quality: 50,
163
+ })
164
+ .toBuffer();
165
+ }
166
+ else if ('jimp' in lib && typeof ((_b = lib.jimp) === null || _b === void 0 ? void 0 : _b.read) === 'function') {
167
+ const { read, MIME_JPEG, RESIZE_BILINEAR } = lib.jimp;
168
+ const jimp = await read(bufferOrFilePath);
169
+ const min = Math.min(jimp.getWidth(), jimp.getHeight());
170
+ const cropped = jimp.crop(0, 0, min, min);
171
+ img = cropped
172
+ .quality(50)
173
+ .resize(640, 640, RESIZE_BILINEAR)
174
+ .getBufferAsync(MIME_JPEG);
175
+ }
176
+ else {
177
+ throw new boom_1.Boom('No image processing library available');
178
+ }
340
179
  return {
341
180
  img: await img,
342
181
  };
@@ -526,28 +365,12 @@ async function generateThumbnail(file, mediaType, options) {
526
365
  }
527
366
  }
528
367
  else if (mediaType === 'video') {
368
+ const imgFilename = (0, path_1.join)(getTmpFilesDirectory(), (0, generics_1.generateMessageID)() + '.jpg');
529
369
  try {
530
- let videoPath = file;
531
- if (Buffer.isBuffer(file) || file instanceof stream_1.Readable) {
532
- videoPath = (0, path_1.join)(getTmpFilesDirectory(), (0, generics_1.generateMessageIDV2)() + '.mp4');
533
- const buffer = Buffer.isBuffer(file) ? file : await (0, exports.toBuffer)(file);
534
- await fs_1.promises.writeFile(videoPath, buffer);
535
- }
536
- const thumbnailBuffer = await (0, exports.extractVideoThumb)(videoPath);
537
- const imgFilename = (0, path_1.join)(getTmpFilesDirectory(), (0, generics_1.generateMessageIDV2)() + '.jpg');
538
- await fs_1.promises.writeFile(imgFilename, thumbnailBuffer);
539
- const { buffer: processedThumbnailBuffer, original } = await (0, exports.extractImageThumb)(imgFilename);
540
- thumbnail = processedThumbnailBuffer.toString('base64');
541
- if (original.width && original.height) {
542
- originalImageDimensions = {
543
- width: original.width,
544
- height: original.height,
545
- };
546
- }
370
+ await extractVideoThumb(file, imgFilename, '00:00:00', { width: 32, height: 32 });
371
+ const buff = await fs_1.promises.readFile(imgFilename);
372
+ thumbnail = buff.toString('base64');
547
373
  await fs_1.promises.unlink(imgFilename);
548
- if (videoPath !== file) {
549
- await fs_1.promises.unlink(videoPath);
550
- }
551
374
  }
552
375
  catch (err) {
553
376
  (_a = options.logger) === null || _a === void 0 ? void 0 : _a.debug('could not generate video thumb: ' + err);
@@ -558,8 +381,10 @@ async function generateThumbnail(file, mediaType, options) {
558
381
  originalImageDimensions
559
382
  };
560
383
  }
384
+ exports.generateThumbnail = generateThumbnail;
561
385
  const getHttpStream = async (url, options = {}) => {
562
- const fetched = await axios_1.default.get(url.toString(), { ...options, responseType: 'stream' });
386
+ const { default: axios } = await import('axios');
387
+ const fetched = await axios.get(url.toString(), { ...options, responseType: 'stream' });
563
388
  return fetched.data;
564
389
  };
565
390
  exports.getHttpStream = getHttpStream;
@@ -574,7 +399,7 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
574
399
  bodyPath = media.url;
575
400
  }
576
401
  else if (saveOriginalFileIfRequired) {
577
- bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageIDV2)());
402
+ bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
578
403
  (0, fs_1.writeFileSync)(bodyPath, buffer);
579
404
  didSaveToTmpPath = true;
580
405
  }
@@ -593,6 +418,7 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
593
418
  };
594
419
  }
595
420
  catch (error) {
421
+ // destroy all streams with error
596
422
  stream.destroy();
597
423
  if (didSaveToTmpPath) {
598
424
  try {
@@ -608,53 +434,52 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
608
434
  exports.prepareStream = prepareStream;
609
435
  const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts, isPtt, forceOpus } = {}) => {
610
436
  const { stream, type } = await (0, exports.getStream)(media, opts);
611
- logger?.debug('fetched media stream');
612
-
613
- let finalStream = stream;
614
-
615
- // Tambahan untuk konversi audio jadi Opus (PTT)
437
+
438
+ let finalStream = stream;
616
439
  if (mediaType === 'audio' && (isPtt === true || forceOpus === true)) {
617
440
  try {
618
441
  const buffer = await (0, exports.toBuffer)(stream);
619
442
  const opusBuffer = await exports.convertToOpusBuffer(buffer, logger);
620
443
  finalStream = (0, exports.toReadable)(opusBuffer);
621
- logger?.debug('converted audio to Opus');
622
444
  } catch (error) {
623
- logger?.error('failed to convert audio to Opus, fallback to original stream');
624
445
  const { stream: newStream } = await (0, exports.getStream)(media, opts);
625
446
  finalStream = newStream;
626
447
  }
627
448
  }
628
449
 
629
450
  const mediaKey = Crypto.randomBytes(32);
630
- const { cipherKey, iv, macKey } = await getMediaKeys(mediaKey, mediaType);
451
+ const { cipherKey, iv, macKey } = getMediaKeys(mediaKey, mediaType);
631
452
  const encWriteStream = new stream_1.Readable({ read: () => { } });
632
453
  let bodyPath;
633
454
  let writeStream;
634
455
  let didSaveToTmpPath = false;
635
-
456
+
636
457
  if (type === 'file') {
637
458
  bodyPath = media.url;
638
- } else if (saveOriginalFileIfRequired) {
639
- bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageIDV2)());
459
+ }
460
+ else if (saveOriginalFileIfRequired) {
461
+ bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
640
462
  writeStream = (0, fs_1.createWriteStream)(bodyPath);
641
463
  didSaveToTmpPath = true;
642
464
  }
643
-
465
+
644
466
  let fileLength = 0;
645
467
  const aes = Crypto.createCipheriv('aes-256-cbc', cipherKey, iv);
646
468
  let hmac = Crypto.createHmac('sha256', macKey).update(iv);
647
469
  let sha256Plain = Crypto.createHash('sha256');
648
470
  let sha256Enc = Crypto.createHash('sha256');
649
-
471
+
650
472
  try {
651
473
  for await (const data of finalStream) {
652
474
  fileLength += data.length;
653
- if (type === 'remote' && (opts?.maxContentLength) && fileLength + data.length > opts.maxContentLength) {
475
+ if (type === 'remote'
476
+ && (opts === null || opts === void 0 ? void 0 : opts.maxContentLength)
477
+ && fileLength + data.length > opts.maxContentLength) {
654
478
  throw new boom_1.Boom(`content length exceeded when encrypting "${type}"`, {
655
479
  data: { media, type }
656
480
  });
657
481
  }
482
+
658
483
  sha256Plain = sha256Plain.update(data);
659
484
  if (writeStream) {
660
485
  if (!writeStream.write(data)) {
@@ -663,20 +488,18 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
663
488
  }
664
489
  onChunk(aes.update(data));
665
490
  }
666
-
491
+
667
492
  onChunk(aes.final());
668
493
  const mac = hmac.digest().slice(0, 10);
669
494
  sha256Enc = sha256Enc.update(mac);
670
495
  const fileSha256 = sha256Plain.digest();
671
496
  const fileEncSha256 = sha256Enc.digest();
672
-
497
+
673
498
  encWriteStream.push(mac);
674
499
  encWriteStream.push(null);
675
- writeStream?.end();
500
+ writeStream === null || writeStream === void 0 ? void 0 : writeStream.end();
676
501
  finalStream.destroy();
677
-
678
- logger?.debug('encrypted data successfully');
679
-
502
+
680
503
  return {
681
504
  mediaKey,
682
505
  encWriteStream,
@@ -687,25 +510,26 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
687
510
  fileLength,
688
511
  didSaveToTmpPath
689
512
  };
690
- } catch (error) {
513
+ }
514
+ catch (error) {
691
515
  encWriteStream.destroy();
692
- writeStream?.destroy();
516
+ writeStream === null || writeStream === void 0 ? void 0 : writeStream.destroy();
693
517
  aes.destroy();
694
518
  hmac.destroy();
695
519
  sha256Plain.destroy();
696
520
  sha256Enc.destroy();
697
521
  finalStream.destroy();
698
-
522
+
699
523
  if (didSaveToTmpPath) {
700
524
  try {
701
525
  await fs_1.promises.unlink(bodyPath);
702
- } catch (err) {
703
- logger?.error({ err }, 'failed to save to tmp path');
526
+ }
527
+ catch (err) {
704
528
  }
705
529
  }
706
530
  throw error;
707
531
  }
708
-
532
+
709
533
  function onChunk(buff) {
710
534
  sha256Enc = sha256Enc.update(buff);
711
535
  hmac = hmac.update(buff);
@@ -720,20 +544,21 @@ const toSmallestChunkSize = (num) => {
720
544
  };
721
545
  const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
722
546
  exports.getUrlFromDirectPath = getUrlFromDirectPath;
723
- const downloadContentFromMessage = async ({ mediaKey, directPath, url }, type, opts = {}) => {
724
- const isValidMediaUrl = url === null || url === void 0 ? void 0 : url.startsWith('https://mmg.whatsapp.net/');
725
- const downloadUrl = isValidMediaUrl ? url : (0, exports.getUrlFromDirectPath)(directPath);
726
- if (!downloadUrl) {
727
- throw new boom_1.Boom('No valid media URL or directPath present in message', { statusCode: 400 });
728
- }
729
- const keys = await getMediaKeys(mediaKey, type);
547
+ const downloadContentFromMessage = ({ mediaKey, directPath, url }, type, opts = {}) => {
548
+ const downloadUrl = url || (0, exports.getUrlFromDirectPath)(directPath);
549
+ const keys = getMediaKeys(mediaKey, type);
730
550
  return (0, exports.downloadEncryptedContent)(downloadUrl, keys, opts);
731
551
  };
732
552
  exports.downloadContentFromMessage = downloadContentFromMessage;
553
+ /**
554
+ * Decrypts and downloads an AES256-CBC encrypted file given the keys.
555
+ * Assumes the SHA256 of the plaintext is appended to the end of the ciphertext
556
+ * */
733
557
  const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startByte, endByte, options } = {}) => {
734
558
  let bytesFetched = 0;
735
559
  let startChunk = 0;
736
560
  let firstBlockIsIV = false;
561
+ // if a start byte is specified -- then we need to fetch the previous chunk as that will form the IV
737
562
  if (startByte) {
738
563
  const chunk = toSmallestChunkSize(startByte || 0);
739
564
  if (chunk) {
@@ -753,6 +578,7 @@ const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startB
753
578
  headers.Range += endChunk;
754
579
  }
755
580
  }
581
+ // download the message
756
582
  const fetched = await (0, exports.getHttpStream)(downloadUrl, {
757
583
  ...options || {},
758
584
  headers,
@@ -785,6 +611,8 @@ const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startB
785
611
  data = data.slice(AES_CHUNK_SIZE);
786
612
  }
787
613
  aes = Crypto.createDecipheriv('aes-256-cbc', cipherKey, ivValue);
614
+ // if an end byte that is not EOF is specified
615
+ // stop auto padding (PKCS7) -- otherwise throws an error for decryption
788
616
  if (endByte) {
789
617
  aes.setAutoPadding(false);
790
618
  }
@@ -825,9 +653,12 @@ function extensionForMediaMessage(message) {
825
653
  }
826
654
  return extension;
827
655
  }
656
+ exports.extensionForMediaMessage = extensionForMediaMessage;
828
657
  const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
829
658
  return async (stream, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
830
659
  var _a, _b;
660
+ const { default: axios } = await import('axios');
661
+ // send a query JSON to obtain the url & auth token to upload our media
831
662
  let uploadInfo = await refreshMediaConn(false);
832
663
  let urls;
833
664
  const hosts = [...customUploadHosts, ...uploadInfo.hosts];
@@ -845,14 +676,14 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
845
676
  }
846
677
  for (const { hostname, maxContentLengthBytes } of hosts) {
847
678
  logger.debug(`uploading to "${hostname}"`);
848
- const auth = encodeURIComponent(uploadInfo.auth);
679
+ const auth = encodeURIComponent(uploadInfo.auth); // the auth token
849
680
  const url = `https://${hostname}${media}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
850
681
  let result;
851
682
  try {
852
683
  if (maxContentLengthBytes && reqBody.length > maxContentLengthBytes) {
853
684
  throw new boom_1.Boom(`Body too large for "${hostname}"`, { statusCode: 413 });
854
685
  }
855
- const body = await axios_1.default.post(url, reqBody, {
686
+ const body = await axios.post(url, reqBody, {
856
687
  ...options,
857
688
  headers: {
858
689
  ...options.headers || {},
@@ -880,7 +711,7 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
880
711
  }
881
712
  }
882
713
  catch (error) {
883
- if (axios_1.default.isAxiosError(error)) {
714
+ if (axios.isAxiosError(error)) {
884
715
  result = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data;
885
716
  }
886
717
  const isLast = hostname === ((_b = hosts[uploadInfo.hosts.length - 1]) === null || _b === void 0 ? void 0 : _b.hostname);
@@ -897,11 +728,14 @@ exports.getWAUploadToServer = getWAUploadToServer;
897
728
  const getMediaRetryKey = (mediaKey) => {
898
729
  return (0, crypto_1.hkdf)(mediaKey, 32, { info: 'WhatsApp Media Retry Notification' });
899
730
  };
900
- const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
731
+ /**
732
+ * Generate a binary node that will request the phone to re-upload the media & return the newly uploaded URL
733
+ */
734
+ const encryptMediaRetryRequest = (key, mediaKey, meId) => {
901
735
  const recp = { stanzaId: key.id };
902
736
  const recpBuffer = WAProto_1.proto.ServerErrorReceipt.encode(recp).finish();
903
737
  const iv = Crypto.randomBytes(12);
904
- const retryKey = await getMediaRetryKey(mediaKey);
738
+ const retryKey = getMediaRetryKey(mediaKey);
905
739
  const ciphertext = (0, crypto_1.aesEncryptGCM)(recpBuffer, retryKey, iv, Buffer.from(key.id));
906
740
  const req = {
907
741
  tag: 'receipt',
@@ -911,6 +745,9 @@ const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
911
745
  type: 'server-error'
912
746
  },
913
747
  content: [
748
+ // this encrypt node is actually pretty useless
749
+ // the media is returned even without this node
750
+ // keeping it here to maintain parity with WA Web
914
751
  {
915
752
  tag: 'encrypt',
916
753
  attrs: {},
@@ -924,6 +761,7 @@ const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
924
761
  attrs: {
925
762
  jid: key.remoteJid,
926
763
  'from_me': (!!key.fromMe).toString(),
764
+ // @ts-ignore
927
765
  participant: key.participant || undefined
928
766
  }
929
767
  }
@@ -961,8 +799,8 @@ const decodeMediaRetryNode = (node) => {
961
799
  return event;
962
800
  };
963
801
  exports.decodeMediaRetryNode = decodeMediaRetryNode;
964
- const decryptMediaRetryData = async ({ ciphertext, iv }, mediaKey, msgId) => {
965
- const retryKey = await getMediaRetryKey(mediaKey);
802
+ const decryptMediaRetryData = ({ ciphertext, iv }, mediaKey, msgId) => {
803
+ const retryKey = getMediaRetryKey(mediaKey);
966
804
  const plaintext = (0, crypto_1.aesDecryptGCM)(ciphertext, retryKey, iv, Buffer.from(msgId));
967
805
  return WAProto_1.proto.MediaRetryNotification.decode(plaintext);
968
806
  };
@@ -975,6 +813,7 @@ const MEDIA_RETRY_STATUS_MAP = {
975
813
  [WAProto_1.proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
976
814
  [WAProto_1.proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418,
977
815
  };
816
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
978
817
  function __importStar(arg0) {
979
818
  throw new Error('Function not implemented.');
980
- }
819
+ }