amiudmodz 5.0.8 → 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' };
@@ -479,15 +501,25 @@ const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequi
479
501
  };
480
502
  exports.prepareStream = prepareStream;
481
503
  const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts, isPtt, forceOpus } = {}) => {
482
- const { stream, type } = await (0, exports.getStream)(media, opts);
504
+ const { stream, type, spilledPath } = await (0, exports.getStream)(media, opts);
483
505
  let finalStream = stream;
484
506
  let opusConverted = false;
507
+ // Track temp files created for spill-to-disk of audio opus conversion
508
+ let opusSpillPath;
485
509
  if (mediaType === 'audio' && (isPtt === true || forceOpus === true)) {
486
510
  try {
487
- const buffer = await (0, exports.toBuffer)(stream);
488
- const opusBuffer = await exports.convertToOpusBuffer(buffer, logger);
489
- finalStream = (0, exports.toReadable)(opusBuffer);
490
- 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
+ }
491
523
  }
492
524
  catch (error) {
493
525
  const { stream: newStream } = await (0, exports.getStream)(media, opts);
@@ -497,15 +529,16 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
497
529
  const mediaKey = Crypto.randomBytes(32);
498
530
  const { cipherKey, iv, macKey } = getMediaKeys(mediaKey, mediaType);
499
531
 
500
-
501
532
  const encPath = (0, path_1.join)(getTmpFilesDirectory(), `enc-${mediaType}-${(0, generics_1.generateMessageID)()}`);
502
533
  const encTempWriteStream = (0, fs_1.createWriteStream)(encPath);
503
534
 
504
535
  let bodyPath;
505
536
  let writeStream;
506
537
  let didSaveToTmpPath = false;
538
+ // For 'file' type (includes our spill-to-disk buffers), use the path directly
507
539
  if (type === 'file') {
508
- 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);
509
542
  }
510
543
  else if (saveOriginalFileIfRequired) {
511
544
  bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
@@ -556,15 +589,32 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
556
589
  const fileSha256 = sha256Plain.digest();
557
590
  const fileEncSha256 = sha256Enc.digest();
558
591
 
559
- encTempWriteStream.end();
560
- 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
+ }
561
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.
562
611
 
563
612
  return {
564
613
  mediaKey,
565
614
  encWriteStream: (0, fs_1.createReadStream)(encPath),
566
615
  bodyPath,
567
616
  streamPath: encPath,
617
+ spilledPath, // expose so caller can clean up the buffer spill file
568
618
  mac,
569
619
  fileEncSha256,
570
620
  fileSha256,
@@ -581,6 +631,9 @@ const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfReq
581
631
  sha256Plain.destroy();
582
632
  sha256Enc.destroy();
583
633
  finalStream.destroy();
634
+ if (opusSpillPath) {
635
+ await fs_1.promises.unlink(opusSpillPath).catch(() => {});
636
+ }
584
637
  try {
585
638
  await fs_1.promises.unlink(encPath);
586
639
  } catch { }
@@ -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.8",
3
+ "version": "5.0.9",
4
4
  "description": "WhatsApp Baileys mod Powered by UDMODZ",
5
5
  "keywords": [
6
6
  "whatsapp",