#!/usr/bin/env node /** * Downloads the standalone yt-dlp binary into ./bin so the app never depends on * a system-wide install. The Linux/macOS builds are self-contained (no Python * required). Run automatically on `npm install`, or manually with `npm run setup`. */ const fs = require('fs'); const path = require('path'); const https = require('https'); const BIN_DIR = path.join(__dirname, '..', 'bin'); const force = process.argv.includes('--force'); function assetForPlatform() { switch (process.platform) { case 'win32': return { asset: 'yt-dlp.exe', out: 'yt-dlp.exe' }; case 'darwin': return { asset: 'yt-dlp_macos', out: 'yt-dlp' }; default: // Linux (incl. WSL). yt-dlp_linux is a self-contained build. return { asset: 'yt-dlp_linux', out: 'yt-dlp' }; } } function download(url, dest) { return new Promise((resolve, reject) => { const file = fs.createWriteStream(dest); const get = (u, redirects = 0) => { if (redirects > 10) return reject(new Error('Too many redirects')); https .get(u, { headers: { 'User-Agent': 'ytplayer-setup' } }, (res) => { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { res.resume(); return get(res.headers.location, redirects + 1); } if (res.statusCode !== 200) { res.resume(); return reject(new Error(`HTTP ${res.statusCode} for ${u}`)); } const total = parseInt(res.headers['content-length'] || '0', 10); let received = 0; res.on('data', (chunk) => { received += chunk.length; if (total) { const pct = ((received / total) * 100).toFixed(0); process.stdout.write(`\r downloading yt-dlp… ${pct}%`); } }); res.pipe(file); file.on('finish', () => file.close(() => { process.stdout.write('\r downloading yt-dlp… done \n'); resolve(); })); }) .on('error', (err) => { fs.unlink(dest, () => reject(err)); }); }; get(url); }); } async function main() { const { asset, out } = assetForPlatform(); const dest = path.join(BIN_DIR, out); if (!fs.existsSync(BIN_DIR)) fs.mkdirSync(BIN_DIR, { recursive: true }); if (fs.existsSync(dest) && !force) { console.log(`yt-dlp already present at ${dest} (use "npm run update-ytdlp" to refresh).`); return; } const url = `https://github.com/yt-dlp/yt-dlp/releases/latest/download/${asset}`; console.log(`Fetching ${asset} from latest yt-dlp release…`); try { await download(url, dest); if (process.platform !== 'win32') fs.chmodSync(dest, 0o755); console.log(`yt-dlp installed at ${dest}`); } catch (err) { console.error('\nFailed to download yt-dlp automatically:', err.message); console.error('You can place a yt-dlp binary manually in the ./bin folder, or ensure'); console.error('yt-dlp is on your PATH — the app will fall back to PATH if ./bin is empty.'); process.exitCode = 1; } } main();