frostpv 1.0.21 → 1.0.22
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/index.js +54 -12
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -4,25 +4,27 @@ const path = require("path");
|
|
|
4
4
|
const os = require("os");
|
|
5
5
|
const FormData = require("form-data");
|
|
6
6
|
const crypto = require("crypto");
|
|
7
|
-
const { igdl, ttdl, fbdown, mediafire, capcut, gdrive, pinterest, twitter } = require("btch-downloader");
|
|
8
|
-
const { TwitterDL } = require("twitter-downloader");
|
|
9
|
-
const instagramCustom = require('./instagramcustom');
|
|
10
|
-
const tiktokCustom = require('./tiktokcustom');
|
|
11
|
-
const btch = require("btch-downloader");
|
|
12
|
-
const btchOld = require("btch-downloader-old");
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const Tiktok = require("@tobyg74/tiktok-api-dl");
|
|
16
|
-
const ab = require("ab-downloader");
|
|
17
|
-
const ffmpegPath = require('ffmpeg-ffprobe-static').ffmpegPath;
|
|
18
7
|
const { v4: uuidv4 } = require('uuid');
|
|
19
|
-
|
|
20
8
|
const pathToFfmpeg = require("ffmpeg-ffprobe-static");
|
|
21
9
|
const ffmpeg = require("fluent-ffmpeg");
|
|
22
10
|
ffmpeg.setFfmpegPath(pathToFfmpeg.ffmpegPath);
|
|
23
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Aciona a coleta de lixo se o Node for iniciado com --expose-gc
|
|
14
|
+
*/
|
|
15
|
+
function triggerGC() {
|
|
16
|
+
if (global.gc) {
|
|
17
|
+
try {
|
|
18
|
+
global.gc();
|
|
19
|
+
} catch (e) {
|
|
20
|
+
// Ignora silenciosamente se falhar
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
24
25
|
const OUTPUT_DIR = process.cwd();
|
|
25
26
|
try { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } catch (_) { }
|
|
27
|
+
|
|
26
28
|
const TEMP_DIR = path.join(os.tmpdir(), "downloader-dl-bot");
|
|
27
29
|
try { fs.mkdirSync(TEMP_DIR, { recursive: true }); } catch (_) { }
|
|
28
30
|
const OUTPUT_RETENTION_MIN = Number(process.env.OUTPUT_RETENTION_MIN || 5);
|
|
@@ -288,6 +290,17 @@ function getPlatformType(url) {
|
|
|
288
290
|
async function tryFallbackDownload(url, maxRetries = 3) {
|
|
289
291
|
const platform = getPlatformType(url);
|
|
290
292
|
|
|
293
|
+
// Importações dinâmicas para economizar RAM
|
|
294
|
+
const btch = require("btch-downloader");
|
|
295
|
+
const { igdl, ttdl, fbdown, mediafire, pinterest } = btch;
|
|
296
|
+
const { TwitterDL } = require("twitter-downloader");
|
|
297
|
+
const btchOld = require("btch-downloader-old");
|
|
298
|
+
const Tiktok = require("@tobyg74/tiktok-api-dl");
|
|
299
|
+
const ab = require("ab-downloader");
|
|
300
|
+
const instagramCustom = require('./instagramcustom');
|
|
301
|
+
const tiktokCustom = require('./tiktokcustom');
|
|
302
|
+
|
|
303
|
+
|
|
291
304
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
292
305
|
try {
|
|
293
306
|
let videoUrl = null;
|
|
@@ -852,8 +865,13 @@ async function downloadSmartVideo(url, config) {
|
|
|
852
865
|
let videoUrl = null;
|
|
853
866
|
let platform = getPlatformType(url);
|
|
854
867
|
|
|
868
|
+
// Importações dinâmicas por plataforma para economizar RAM
|
|
869
|
+
let downloader = null;
|
|
870
|
+
|
|
871
|
+
|
|
855
872
|
switch (platform) {
|
|
856
873
|
case "instagram": {
|
|
874
|
+
const { igdl } = require("btch-downloader");
|
|
857
875
|
let data = null;
|
|
858
876
|
let attempts = 0;
|
|
859
877
|
const maxAttempts = 3;
|
|
@@ -874,6 +892,7 @@ async function downloadSmartVideo(url, config) {
|
|
|
874
892
|
await new Promise(resolve => setTimeout(resolve, 1000 * attempts));
|
|
875
893
|
}
|
|
876
894
|
}
|
|
895
|
+
|
|
877
896
|
if (!videoUrl) {
|
|
878
897
|
throw new Error("Video unavailable or invalid link for Instagram.");
|
|
879
898
|
}
|
|
@@ -882,6 +901,8 @@ async function downloadSmartVideo(url, config) {
|
|
|
882
901
|
case "tiktok": {
|
|
883
902
|
let data = null;
|
|
884
903
|
let fallbackError = null;
|
|
904
|
+
const { ttdl } = require("btch-downloader");
|
|
905
|
+
const Tiktok = require("@tobyg74/tiktok-api-dl");
|
|
885
906
|
try {
|
|
886
907
|
data = await ttdl(url);
|
|
887
908
|
if (!data || !data.video || !data.video[0]) {
|
|
@@ -925,7 +946,10 @@ async function downloadSmartVideo(url, config) {
|
|
|
925
946
|
}
|
|
926
947
|
break;
|
|
927
948
|
}
|
|
949
|
+
|
|
950
|
+
|
|
928
951
|
case "facebook": {
|
|
952
|
+
const { fbdown } = require("btch-downloader");
|
|
929
953
|
try {
|
|
930
954
|
const data = await fbdown(url);
|
|
931
955
|
if (!data || (!data.Normal_video && !data.HD)) {
|
|
@@ -949,7 +973,9 @@ async function downloadSmartVideo(url, config) {
|
|
|
949
973
|
}
|
|
950
974
|
break;
|
|
951
975
|
}
|
|
976
|
+
|
|
952
977
|
case "mediafire": {
|
|
978
|
+
const { mediafire } = require("btch-downloader");
|
|
953
979
|
try {
|
|
954
980
|
const data = await mediafire(url);
|
|
955
981
|
if (!data || !data.url) {
|
|
@@ -961,7 +987,9 @@ async function downloadSmartVideo(url, config) {
|
|
|
961
987
|
}
|
|
962
988
|
break;
|
|
963
989
|
}
|
|
990
|
+
|
|
964
991
|
case "pinterest": {
|
|
992
|
+
const { pinterest } = require("btch-downloader");
|
|
965
993
|
try {
|
|
966
994
|
const data = await pinterest(url);
|
|
967
995
|
let directUrl = null;
|
|
@@ -1004,7 +1032,9 @@ async function downloadSmartVideo(url, config) {
|
|
|
1004
1032
|
}
|
|
1005
1033
|
break;
|
|
1006
1034
|
}
|
|
1035
|
+
|
|
1007
1036
|
case "twitter": {
|
|
1037
|
+
const { twitter } = require("btch-downloader");
|
|
1008
1038
|
try {
|
|
1009
1039
|
const data = await twitter(url);
|
|
1010
1040
|
if (data && data.url) {
|
|
@@ -1049,6 +1079,7 @@ async function downloadSmartVideo(url, config) {
|
|
|
1049
1079
|
}
|
|
1050
1080
|
break;
|
|
1051
1081
|
}
|
|
1082
|
+
|
|
1052
1083
|
default:
|
|
1053
1084
|
throw new Error("Platform not supported or invalid link.");
|
|
1054
1085
|
}
|
|
@@ -1078,7 +1109,9 @@ async function downloadSmartVideo(url, config) {
|
|
|
1078
1109
|
videoWriter.on("finish", async () => {
|
|
1079
1110
|
try {
|
|
1080
1111
|
const finalFilePath = await processDownloadedFile(fileName, config, platform);
|
|
1112
|
+
triggerGC(); // Limpar memória após processamento pesado
|
|
1081
1113
|
resolve(finalFilePath);
|
|
1114
|
+
|
|
1082
1115
|
} catch (error) {
|
|
1083
1116
|
reject(new Error(`Error processing downloaded video: ${error.message}`));
|
|
1084
1117
|
}
|
|
@@ -1092,6 +1125,7 @@ async function downloadSmartVideo(url, config) {
|
|
|
1092
1125
|
}
|
|
1093
1126
|
}
|
|
1094
1127
|
|
|
1128
|
+
|
|
1095
1129
|
// Function for direct video download
|
|
1096
1130
|
async function downloadDirectVideo(url, config) {
|
|
1097
1131
|
try {
|
|
@@ -1231,7 +1265,9 @@ async function cleanupTempFiles() {
|
|
|
1231
1265
|
for (const file of tempFiles) {
|
|
1232
1266
|
await safeUnlinkWithRetry(path.join(TEMP_DIR, file));
|
|
1233
1267
|
}
|
|
1268
|
+
triggerGC();
|
|
1234
1269
|
} catch (error) {
|
|
1270
|
+
|
|
1235
1271
|
if (error && error.code !== 'ENOENT') {
|
|
1236
1272
|
console.error(`Error during temp file cleanup: ${error.message}`);
|
|
1237
1273
|
}
|
|
@@ -1256,9 +1292,11 @@ async function cleanupOutputFiles() {
|
|
|
1256
1292
|
}
|
|
1257
1293
|
} catch (_) { }
|
|
1258
1294
|
}
|
|
1295
|
+
triggerGC();
|
|
1259
1296
|
} catch (_) { }
|
|
1260
1297
|
}
|
|
1261
1298
|
|
|
1299
|
+
|
|
1262
1300
|
// Schedule periodic cleanup (every 10 minutes)
|
|
1263
1301
|
setInterval(() => {
|
|
1264
1302
|
cleanupTempFiles();
|
|
@@ -1500,7 +1538,9 @@ const AudioDownloader = async (url, options = {}) => {
|
|
|
1500
1538
|
await safeUnlinkWithRetry(downloadedFilePath);
|
|
1501
1539
|
|
|
1502
1540
|
const result = await uploadToGoFileIfNeeded(audioFilePath);
|
|
1541
|
+
triggerGC();
|
|
1503
1542
|
return result;
|
|
1543
|
+
|
|
1504
1544
|
} else {
|
|
1505
1545
|
throw new Error("Failed to obtain downloaded file path.");
|
|
1506
1546
|
}
|
|
@@ -1522,8 +1562,10 @@ async function extractAudioMp3(videoPath) {
|
|
|
1522
1562
|
.format('mp3')
|
|
1523
1563
|
.save(audioPath)
|
|
1524
1564
|
.on('end', () => {
|
|
1565
|
+
triggerGC();
|
|
1525
1566
|
resolve(audioPath);
|
|
1526
1567
|
})
|
|
1568
|
+
|
|
1527
1569
|
.on('error', (err) => {
|
|
1528
1570
|
reject(new Error(`Error extracting audio: ${err.message}`));
|
|
1529
1571
|
});
|