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.
- package/lib/Utils/messages-media.js +79 -13
- package/lib/Utils/messages.js +7 -1
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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(), {
|
|
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 =
|
|
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
|
-
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
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
|
-
|
|
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
|
-
|
|
548
|
-
|
|
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)) {
|
package/lib/Utils/messages.js
CHANGED
|
@@ -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
|
|