amiudmodz 5.0.7 → 5.0.9

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.
@@ -343,9 +343,31 @@ const toBuffer = async (stream) => {
343
343
  return Buffer.concat(chunks);
344
344
  };
345
345
  exports.toBuffer = toBuffer;
346
+ /**
347
+ * Spills a Buffer or Readable stream to a temp file on disk so it is not
348
+ * held entirely in RAM. Returns the temp-file path so the caller can clean
349
+ * it up when done.
350
+ */
351
+ const spillToDisk = async (source) => {
352
+ const tmpPath = (0, path_1.join)(getTmpFilesDirectory(), `spill-${(0, generics_1.generateMessageID)()}`);
353
+ const writeStream = (0, fs_1.createWriteStream)(tmpPath);
354
+ await new Promise((resolve, reject) => {
355
+ writeStream.on('error', reject);
356
+ writeStream.on('finish', resolve);
357
+ if (Buffer.isBuffer(source)) {
358
+ writeStream.end(source);
359
+ } else {
360
+ source.pipe(writeStream);
361
+ source.on('error', reject);
362
+ }
363
+ });
364
+ return tmpPath;
365
+ };
346
366
  const getStream = async (item, opts) => {
347
367
  if (Buffer.isBuffer(item)) {
348
- return { stream: (0, exports.toReadable)(item), type: 'buffer' };
368
+ // Write the Buffer to a temp file so it can be GC'd from RAM
369
+ const tmpPath = await spillToDisk(item);
370
+ return { stream: (0, fs_1.createReadStream)(tmpPath), type: 'file', spilledPath: tmpPath };
349
371
  }
350
372
  if ('stream' in item) {
351
373
  return { stream: item.stream, type: 'readable' };
@@ -391,7 +413,19 @@ async function generateThumbnail(file, mediaType, options) {
391
413
  exports.generateThumbnail = generateThumbnail;
392
414
  const getHttpStream = async (url, options = {}) => {
393
415
  const { default: axios } = await import('axios');
394
- const fetched = await axios.get(url.toString(), { ...options, responseType: 'stream' });
416
+ const fetched = await axios.get(url.toString(), {
417
+ ...options,
418
+ responseType: 'stream',
419
+ maxContentLength: Infinity,
420
+ maxBodyLength: Infinity,
421
+ decompress: false,
422
+ headers: {
423
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
424
+ 'Accept': '*/*',
425
+ 'Accept-Encoding': 'identity',
426
+ ...options.headers,
427
+ }
428
+ });
395
429
  return fetched.data;
396
430
  };
397
431
  exports.getHttpStream = getHttpStream;
@@ -414,7 +448,7 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
414
448
  didSaveToTmpPath = true;
415
449
  }
416
450
 
417
- const writeStream = bodyPath && !media.url ? (0, fs_1.createWriteStream)(bodyPath) : undefined;
451
+ const writeStream = didSaveToTmpPath ? (0, fs_1.createWriteStream)(bodyPath) : undefined;
418
452
 
419
453
  try {
420
454
  for await (const chunk of stream) {
@@ -467,15 +501,25 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
467
501
  };
468
502
  exports.prepareStream = prepareStream;
469
503
  const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts, isPtt, forceOpus } = {}) => {
470
- const { stream, type } = await (0, exports.getStream)(media, opts);
504
+ const { stream, type, spilledPath } = await (0, exports.getStream)(media, opts);
471
505
  let finalStream = stream;
472
506
  let opusConverted = false;
507
+ // Track temp files created for spill-to-disk of audio opus conversion
508
+ let opusSpillPath;
473
509
  if (mediaType === 'audio' && (isPtt === true || forceOpus === true)) {
474
510
  try {
475
- const buffer = await (0, exports.toBuffer)(stream);
476
- const opusBuffer = await exports.convertToOpusBuffer(buffer, logger);
477
- finalStream = (0, exports.toReadable)(opusBuffer);
478
- opusConverted = true;
511
+ // Write audio to temp file, convert via ffmpeg, write result to another temp file
512
+ const audioTmpPath = await spillToDisk(stream);
513
+ try {
514
+ const opusBuffer = await exports.convertToOpusBuffer(
515
+ await fs_1.promises.readFile(audioTmpPath), logger
516
+ );
517
+ opusSpillPath = await spillToDisk(opusBuffer);
518
+ finalStream = (0, fs_1.createReadStream)(opusSpillPath);
519
+ opusConverted = true;
520
+ } finally {
521
+ await fs_1.promises.unlink(audioTmpPath).catch(() => {});
522
+ }
479
523
  }
480
524
  catch (error) {
481
525
  const { stream: newStream } = await (0, exports.getStream)(media, opts);
@@ -485,15 +529,16 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
485
529
  const mediaKey = Crypto.randomBytes(32);
486
530
  const { cipherKey, iv, macKey } = getMediaKeys(mediaKey, mediaType);
487
531
 
488
-
489
532
  const encPath = (0, path_1.join)(getTmpFilesDirectory(), `enc-${mediaType}-${(0, generics_1.generateMessageID)()}`);
490
533
  const encTempWriteStream = (0, fs_1.createWriteStream)(encPath);
491
534
 
492
535
  let bodyPath;
493
536
  let writeStream;
494
537
  let didSaveToTmpPath = false;
538
+ // For 'file' type (includes our spill-to-disk buffers), use the path directly
495
539
  if (type === 'file') {
496
- bodyPath = media.url;
540
+ // If spilled from a Buffer, spilledPath IS the original; use it as bodyPath
541
+ bodyPath = spilledPath || (media && media.url ? media.url : undefined);
497
542
  }
498
543
  else if (saveOriginalFileIfRequired) {
499
544
  bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
@@ -544,15 +589,32 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
544
589
  const fileSha256 = sha256Plain.digest();
545
590
  const fileEncSha256 = sha256Enc.digest();
546
591
 
547
- encTempWriteStream.end();
548
- writeStream === null || writeStream === void 0 ? void 0 : writeStream.end();
592
+ await new Promise((resolve, reject) => {
593
+ encTempWriteStream.end(resolve);
594
+ encTempWriteStream.once('error', reject);
595
+ });
596
+ if (writeStream) {
597
+ await new Promise((resolve, reject) => {
598
+ writeStream.end(resolve);
599
+ writeStream.once('error', reject);
600
+ });
601
+ }
549
602
  finalStream.destroy();
603
+ // Clean up the opus spill temp file if used
604
+ if (opusSpillPath) {
605
+ await fs_1.promises.unlink(opusSpillPath).catch(() => {});
606
+ }
607
+ // Clean up the buffer-spill temp file — it's no longer needed once encrypted
608
+ // (the enc temp file is what gets uploaded; bodyPath/spilledPath is only
609
+ // needed for thumbnail/duration computation which happens in parallel)
610
+ // Caller (messages.js) handles cleanup of streamPath & bodyPath.
550
611
 
551
612
  return {
552
613
  mediaKey,
553
614
  encWriteStream: (0, fs_1.createReadStream)(encPath),
554
615
  bodyPath,
555
616
  streamPath: encPath,
617
+ spilledPath, // expose so caller can clean up the buffer spill file
556
618
  mac,
557
619
  fileEncSha256,
558
620
  fileSha256,
@@ -569,6 +631,9 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
569
631
  sha256Plain.destroy();
570
632
  sha256Enc.destroy();
571
633
  finalStream.destroy();
634
+ if (opusSpillPath) {
635
+ await fs_1.promises.unlink(opusSpillPath).catch(() => {});
636
+ }
572
637
  try {
573
638
  await fs_1.promises.unlink(encPath);
574
639
  } catch { }
@@ -737,10 +802,11 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
737
802
  'Origin': Defaults_1.DEFAULT_ORIGIN
738
803
  },
739
804
  httpsAgent: fetchAgent,
740
- timeout: timeoutMs,
805
+ timeout: timeoutMs || Defaults_1.UPLOAD_TIMEOUT,
741
806
  responseType: 'json',
742
807
  maxBodyLength: Infinity,
743
808
  maxContentLength: Infinity,
809
+ decompress: false
744
810
  });
745
811
  result = body.data;
746
812
  if ((result === null || result === void 0 ? void 0 : result.url) || (result === null || result === void 0 ? void 0 : result.directPath)) {
@@ -149,7 +149,7 @@ const prepareWAMessageMedia = async (message, options) => {
149
149
  const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
150
150
  const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
151
151
 
152
- const { mediaKey, encWriteStream, bodyPath, streamPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, opusConverted } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
152
+ const { mediaKey, encWriteStream, bodyPath, streamPath, spilledPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, opusConverted } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
153
153
  logger,
154
154
  saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
155
155
  opts: options.options,
@@ -210,6 +210,12 @@ const prepareWAMessageMedia = async (message, options) => {
210
210
  if (streamPath) {
211
211
  await fs_1.promises.unlink(streamPath).catch(() => { });
212
212
  }
213
+ // Clean up the buffer-spill temp file (if input was a Buffer, it was
214
+ // written to /tmp to avoid holding it in RAM; delete it now that we
215
+ // are done with thumbnail/duration computation)
216
+ if (spilledPath && spilledPath !== bodyPath) {
217
+ await fs_1.promises.unlink(spilledPath).catch(() => { });
218
+ }
213
219
  logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp files');
214
220
  });
215
221
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amiudmodz",
3
- "version": "5.0.7",
3
+ "version": "5.0.9",
4
4
  "description": "WhatsApp Baileys mod Powered by UDMODZ",
5
5
  "keywords": [
6
6
  "whatsapp",