media-dl 2.2.2 → 2.3.0
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/bin/cli.js +98 -20
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -9,11 +9,14 @@ const { C, printHeader, renderProgressBar, askQuestion, rl } = require('./ui');
|
|
|
9
9
|
// --- KONFIGURASI VISUAL (ANSI COLORS) ---
|
|
10
10
|
|
|
11
11
|
const TOOLS_DIR = path.join(os.homedir(), '.media-dl');
|
|
12
|
+
|
|
12
13
|
const isWindows = process.platform === 'win32';
|
|
13
14
|
const isMac = process.platform === 'darwin';
|
|
15
|
+
const isTermux =
|
|
16
|
+
process.env.PREFIX && process.env.PREFIX.includes('com.termux');
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
let YTDLP_PATH = path.join(TOOLS_DIR, isWindows ? 'yt-dlp.exe' : 'yt-dlp');
|
|
19
|
+
let FFMPEG_PATH = path.join(TOOLS_DIR, isWindows ? 'ffmpeg.exe' : 'ffmpeg');
|
|
17
20
|
|
|
18
21
|
// State Aplikasi
|
|
19
22
|
let safeMode = true;
|
|
@@ -21,10 +24,40 @@ let safeMode = true;
|
|
|
21
24
|
if (!fs.existsSync(TOOLS_DIR)) fs.mkdirSync(TOOLS_DIR, { recursive: true });
|
|
22
25
|
|
|
23
26
|
function checkTools() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
let ytExists = fs.existsSync(YTDLP_PATH);
|
|
28
|
+
let ffExists = fs.existsSync(FFMPEG_PATH);
|
|
29
|
+
|
|
30
|
+
// Cek Global yt-dlp
|
|
31
|
+
if (!ytExists) {
|
|
32
|
+
try {
|
|
33
|
+
const cmd = isWindows ? 'where yt-dlp' : 'which yt-dlp';
|
|
34
|
+
const pathFound = execSync(cmd, { stdio: ['ignore', 'pipe', 'ignore'] })
|
|
35
|
+
.toString()
|
|
36
|
+
.trim()
|
|
37
|
+
.split('\n')[0];
|
|
38
|
+
if (pathFound) {
|
|
39
|
+
YTDLP_PATH = pathFound; // UPDATE PATH KE GLOBAL
|
|
40
|
+
ytExists = true;
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Cek Global ffmpeg
|
|
46
|
+
if (!ffExists) {
|
|
47
|
+
try {
|
|
48
|
+
const cmd = isWindows ? 'where ffmpeg' : 'which ffmpeg';
|
|
49
|
+
const globalPath = execSync(cmd, { stdio: ['ignore', 'pipe', 'ignore'] })
|
|
50
|
+
.toString()
|
|
51
|
+
.trim()
|
|
52
|
+
.split('\n')[0];
|
|
53
|
+
if (globalPath) {
|
|
54
|
+
FFMPEG_PATH = globalPath; // UPDATE PATH KE GLOBAL
|
|
55
|
+
ffExists = true;
|
|
56
|
+
}
|
|
57
|
+
} catch (e) {}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { ytExists, ffExists, allReady: ytExists && ffExists };
|
|
28
61
|
}
|
|
29
62
|
|
|
30
63
|
// --- INSTALLERS ---
|
|
@@ -36,17 +69,31 @@ async function installYtdlp() {
|
|
|
36
69
|
const url = isWindows
|
|
37
70
|
? 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe'
|
|
38
71
|
: 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp';
|
|
72
|
+
|
|
39
73
|
try {
|
|
40
|
-
if (
|
|
74
|
+
if (isTermux) {
|
|
75
|
+
// Di Termux, lebih disarankan menggunakan python/pip untuk stabilitas
|
|
76
|
+
console.log(`${C.dim}Menginstall yt-dlp via python...${C.reset}`);
|
|
77
|
+
execSync('pkg update && pkg install python ffmpeg -y', {
|
|
78
|
+
stdio: 'inherit',
|
|
79
|
+
});
|
|
80
|
+
execSync('pip install -U "yt-dlp[default]"', { stdio: 'inherit' });
|
|
81
|
+
console.log(
|
|
82
|
+
`\n${C.green}✅ yt-dlp berhasil diinstal di Termux!${C.reset}`,
|
|
83
|
+
);
|
|
84
|
+
} else if (isWindows) {
|
|
41
85
|
execSync(
|
|
42
86
|
`powershell -Command "Invoke-WebRequest -Uri ${url} -OutFile '${YTDLP_PATH}'"`,
|
|
43
87
|
{ stdio: 'inherit' },
|
|
44
88
|
);
|
|
45
89
|
} else {
|
|
90
|
+
// Linux (Ubuntu) & macOS
|
|
46
91
|
execSync(`curl -L -# "${url}" -o "${YTDLP_PATH}"`, { stdio: 'inherit' });
|
|
47
92
|
execSync(`chmod a+rx "${YTDLP_PATH}"`);
|
|
48
93
|
}
|
|
49
|
-
|
|
94
|
+
if (!isTermux) {
|
|
95
|
+
console.log(`\n${C.green}✅ yt-dlp berhasil dikonfigurasi!${C.reset}`);
|
|
96
|
+
}
|
|
50
97
|
} catch (e) {
|
|
51
98
|
console.error(
|
|
52
99
|
`\n${C.red}❌ Gagal mengunduh. Periksa koneksi internet Anda.${C.reset}`,
|
|
@@ -61,7 +108,15 @@ async function installFfmpeg() {
|
|
|
61
108
|
);
|
|
62
109
|
|
|
63
110
|
try {
|
|
64
|
-
if (
|
|
111
|
+
if (isTermux) {
|
|
112
|
+
console.log(
|
|
113
|
+
`${C.blue}⏳ Mendeteksi Termux: Menginstall via pkg...${C.reset}`,
|
|
114
|
+
);
|
|
115
|
+
execSync('pkg update && pkg install ffmpeg -y', { stdio: 'inherit' });
|
|
116
|
+
console.log(
|
|
117
|
+
`\n${C.green}✅ FFmpeg berhasil diinstal di Termux!${C.reset}`,
|
|
118
|
+
);
|
|
119
|
+
} else if (isMac) {
|
|
65
120
|
// ... (Kode macOS Anda sudah benar)
|
|
66
121
|
console.log(`${C.blue}⏳ Mengunduh FFmpeg untuk macOS...${C.reset}`);
|
|
67
122
|
const zipPath = path.join(TOOLS_DIR, 'ffmpeg.zip');
|
|
@@ -104,6 +159,18 @@ async function installFfmpeg() {
|
|
|
104
159
|
console.log(
|
|
105
160
|
`\n${C.green}✅ FFmpeg berhasil diinstal di Windows!${C.reset}`,
|
|
106
161
|
);
|
|
162
|
+
} else {
|
|
163
|
+
// Asumsi Linux (Ubuntu/Debian)
|
|
164
|
+
console.log(
|
|
165
|
+
`${C.blue}⏳ Mendeteksi Linux: Menginstall via apt...${C.reset}`,
|
|
166
|
+
);
|
|
167
|
+
console.log(`${C.dim}Mungkin memerlukan password sudo.${C.reset}`);
|
|
168
|
+
execSync('sudo apt update && sudo apt install ffmpeg -y', {
|
|
169
|
+
stdio: 'inherit',
|
|
170
|
+
});
|
|
171
|
+
console.log(
|
|
172
|
+
`\n${C.green}✅ FFmpeg berhasil diinstal di Linux!${C.reset}`,
|
|
173
|
+
);
|
|
107
174
|
}
|
|
108
175
|
} catch (e) {
|
|
109
176
|
console.error(
|
|
@@ -178,8 +245,12 @@ async function startDownload(videoURLFromArgs = null) {
|
|
|
178
245
|
|
|
179
246
|
try {
|
|
180
247
|
const rawInfo = execSync(
|
|
181
|
-
`"${YTDLP_PATH}" --flat-playlist --print "%(playlist_title)s|%(title)s" "${videoURL}"`,
|
|
182
|
-
{
|
|
248
|
+
`"${YTDLP_PATH}" --flat-playlist --no-warnings --print "%(playlist_title)s|%(title)s" "${videoURL}"`,
|
|
249
|
+
{
|
|
250
|
+
encoding: 'utf-8',
|
|
251
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
252
|
+
timeout: 20000,
|
|
253
|
+
},
|
|
183
254
|
);
|
|
184
255
|
const lines = rawInfo.trim().split('\n');
|
|
185
256
|
if (lines.length > 1 || videoURL.includes('playlist?list=')) {
|
|
@@ -187,7 +258,22 @@ async function startDownload(videoURLFromArgs = null) {
|
|
|
187
258
|
playlistInfo.title = lines[0].split('|')[0] || 'Unduhan Playlist';
|
|
188
259
|
playlistInfo.items = lines.map((l) => l.split('|')[1]).filter(Boolean);
|
|
189
260
|
}
|
|
190
|
-
} catch (e) {
|
|
261
|
+
} catch (e) {
|
|
262
|
+
console.log(`\n${C.red}❌ Gagal menganalisa tautan.${C.reset}`);
|
|
263
|
+
|
|
264
|
+
if (e.message.includes('ETIMEDOUT')) {
|
|
265
|
+
console.log(
|
|
266
|
+
`${C.yellow}⚠️ Waktu analisa habis. Periksa koneksi internet Anda.${C.reset}`,
|
|
267
|
+
);
|
|
268
|
+
} else {
|
|
269
|
+
console.log(
|
|
270
|
+
`${C.yellow}⚠️ Pastikan link valid atau tidak diprivat/dihapus.${C.reset}`,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
await askQuestion('\nTekan Enter untuk kembali ke menu...');
|
|
275
|
+
return mainMenu(); // Keluar dari fungsi dan balik ke menu utama
|
|
276
|
+
}
|
|
191
277
|
|
|
192
278
|
let playlistSelection = null;
|
|
193
279
|
if (playlistInfo.isPlaylist) {
|
|
@@ -470,14 +556,6 @@ async function cleanUp() {
|
|
|
470
556
|
fs.rmSync(TOOLS_DIR, { recursive: true, force: true });
|
|
471
557
|
}
|
|
472
558
|
|
|
473
|
-
function checkTools() {
|
|
474
|
-
return {
|
|
475
|
-
ytExists: fs.existsSync(YTDLP_PATH),
|
|
476
|
-
ffExists: fs.existsSync(FFMPEG_PATH),
|
|
477
|
-
allReady: fs.existsSync(YTDLP_PATH) && fs.existsSync(FFMPEG_PATH),
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
|
|
481
559
|
async function firstTimeSetup() {
|
|
482
560
|
while (true) {
|
|
483
561
|
const { ytExists, ffExists } = checkTools();
|