UNPKG

mr-chamuwa-downloader

Version:

šŸ”„ MrChamuwa's Ultimate Facebook Video Downloader - The most powerful FB video downloading tool in Sri Lanka!

357 lines (308 loc) • 12.2 kB
const { Command } = require('commander'); const inquirer = require('inquirer'); const chalk = require('chalk'); const ora = require('ora'); const boxen = require('boxen'); const figlet = require('figlet'); const gradient = require('gradient-string'); const updateNotifier = require('update-notifier'); const pkg = require('../package.json'); const MrChamuwaFBDownloader = require('../src/index.js'); // Check for updates const notifier = updateNotifier({ pkg }); notifier.notify(); // MrChamuwa's signature banner const createBanner = () => { const title = figlet.textSync('MrChamuwa', { font: 'Slant', horizontalLayout: 'fitted' }); const subtitle = 'FB DOWNLOADER šŸ”„'; return boxen( gradient.pastel.multiline(title) + '\n' + chalk.yellow.bold(subtitle) + '\n' + chalk.cyan('The Ultimate Facebook Video Downloader šŸ‡±šŸ‡°') + '\n' + chalk.gray('Made with ā¤ļø by MrChamuwa'), { padding: 1, margin: 1, borderStyle: 'double', borderColor: 'cyan', backgroundColor: '#000040' } ); }; const program = new Command(); program .name('chamuwa-fb') .description(createBanner() + '\n\nšŸš€ Download Facebook videos like a pro!') .version(pkg.version); // Interactive download command program .command('download') .alias('dl') .description('šŸŽÆ Download Facebook video (Interactive Mode)') .action(async () => { console.log(createBanner()); try { const answers = await inquirer.prompt([ { type: 'input', name: 'url', message: chalk.yellow('šŸ”— Facebook Video URL ą¶‘ą¶š paste කරන්න:'), validate: (input) => { if (!input.trim()) return 'URL ą¶‘ą¶šą¶šą·Š enter කරන්න!'; if (!input.includes('facebook.com') && !input.includes('fb.watch')) { return 'Valid Facebook URL ą¶‘ą¶šą¶šą·Š enter කරන්න!'; } return true; } }, { type: 'list', name: 'quality', message: chalk.yellow('šŸŽ„ Video Quality:'), choices: [ { name: 'šŸ”„ HD Quality (High)', value: 'hd' }, { name: 'šŸ“± SD Quality (Standard)', value: 'sd' }, { name: 'šŸ¤– Auto Select', value: 'auto' } ], default: 'hd' }, { type: 'input', name: 'filename', message: chalk.yellow('šŸ“ Custom filename (optional):'), default: '' }, { type: 'list', name: 'language', message: chalk.yellow('šŸŒ Language / ą¶·ą·ą·‚ą·:'), choices: [ { name: 'šŸ‡±šŸ‡° Sinhala (ą·ƒą·’ą¶‚ą·„ą¶½)', value: 'si' }, { name: 'šŸ‡ŗšŸ‡ø English', value: 'en' } ], default: 'si' } ]); // Initialize downloader const downloader = new MrChamuwaFBDownloader({ quality: answers.quality, language: answers.language, saveMetadata: true, createSubfolders: true }); const spinner = ora({ text: answers.language === 'si' ? 'šŸ” Video ą¶‘ą¶š analyze ą¶šą¶»ą¶±ą·€ą·...' : 'šŸ” Analyzing video...', spinner: 'dots12' }).start(); // Set up progress tracking let progressSpinner = null; downloader.on('progress', (data) => { if (!progressSpinner) { spinner.stop(); progressSpinner = ora().start(); } const percent = data.progress.toFixed(1); const speed = (data.speed / 1024 / 1024).toFixed(2); const downloaded = (data.downloaded / 1024 / 1024).toFixed(2); const total = data.total > 0 ? (data.total / 1024 / 1024).toFixed(2) : '??'; progressSpinner.text = `ā¬‡ļø ${percent}% | ${downloaded}/${total} MB | ${speed} MB/s`; }); // Download the video const result = await downloader.downloadVideo( answers.url, answers.filename || null ); if (progressSpinner) progressSpinner.stop(); // Success message console.log('\n' + boxen( chalk.green.bold('āœ… DOWNLOAD COMPLETED! šŸŽ‰\n\n') + chalk.cyan(`šŸ“ File: ${result.fileName}\n`) + chalk.cyan(`šŸ“‚ Location: ${result.filePath}\n`) + chalk.cyan(`šŸ“Š Size: ${(result.size / 1024 / 1024).toFixed(2)} MB\n`) + chalk.cyan(`ā±ļø Time: ${(result.downloadTime / 1000).toFixed(1)}s\n`) + chalk.yellow('šŸ™ Thank you for using MrChamuwa FB Downloader!'), { padding: 1, borderStyle: 'round', borderColor: 'green' } )); // Show video info if available if (result.videoInfo.title) { console.log(chalk.blue(`šŸŽ¬ Title: ${result.videoInfo.title}`)); } } catch (error) { if (spinner && spinner.isSpinning) spinner.stop(); console.log('\n' + boxen( chalk.red.bold('āŒ DOWNLOAD FAILED!\n\n') + chalk.yellow(`Error: ${error.message}\n\n`) + chalk.cyan('šŸ’” Tips:\n') + chalk.white('• Make sure the Facebook video is public\n') + chalk.white('• Check your internet connection\n') + chalk.white('• Try with a different video URL'), { padding: 1, borderStyle: 'round', borderColor: 'red' } )); } }); // Quick download command program .command('quick <url>') .alias('q') .description('⚔ Quick download (no prompts)') .option('-q, --quality <quality>', 'Video quality (hd/sd)', 'hd') .option('-o, --output <filename>', 'Output filename') .option('-l, --lang <language>', 'Language (si/en)', 'si') .action(async (url, options) => { console.log(createBanner()); const spinner = ora('šŸš€ Starting quick download...').start(); try { const downloader = new MrChamuwaFBDownloader({ quality: options.quality, language: options.lang }); const result = await downloader.downloadVideo(url, options.output); spinner.succeed(chalk.green('āœ… Quick download completed!')); console.log(chalk.cyan(`šŸ“ Saved: ${result.filePath}`)); console.log(chalk.yellow(`šŸ“Š Size: ${(result.size / 1024 / 1024).toFixed(2)} MB`)); } catch (error) { spinner.fail(chalk.red(`āŒ Quick download failed: ${error.message}`)); } }); // Batch download command program .command('batch <file>') .alias('b') .description('šŸ“‹ Batch download from URL list file') .option('-c, --concurrent <number>', 'Concurrent downloads', '2') .action(async (file, options) => { console.log(createBanner()); const spinner = ora('šŸ“‹ Loading URL list...').start(); try { const fs = require('fs-extra'); const urls = (await fs.readFile(file, 'utf8')) .split('\n') .filter(url => url.trim()) .map(url => url.trim()); if (urls.length === 0) { throw new Error('No URLs found in file'); } spinner.text = `šŸš€ Starting batch download of ${urls.length} videos...`; const downloader = new MrChamuwaFBDownloader({ createSubfolders: true, saveMetadata: true }); let completed = 0; let failed = 0; // Process URLs with concurrency control const concurrency = parseInt(options.concurrent) || 2; for (let i = 0; i < urls.length; i += concurrency) { const batch = urls.slice(i, i + concurrency); const promises = batch.map(async (url, index) => { try { const result = await downloader.downloadVideo(url); completed++; spinner.text = `āœ… ${completed}/${urls.length} completed | Current: ${result.fileName}`; return { success: true, url, result }; } catch (error) { failed++; spinner.text = `āŒ ${failed} failed, ${completed}/${urls.length} completed`; return { success: false, url, error: error.message }; } }); await Promise.all(promises); } spinner.succeed(`šŸŽ‰ Batch download completed! ${completed} success, ${failed} failed`); } catch (error) { spinner.fail(chalk.red(`āŒ Batch download failed: ${error.message}`)); } }); // Info command program .command('info <url>') .alias('i') .description('ā„¹ļø Get video information without downloading') .action(async (url) => { console.log(createBanner()); const spinner = ora('šŸ” Getting video information...').start(); try { const downloader = new MrChamuwaFBDownloader(); const videoInfo = await downloader.extractVideoInfo(url); spinner.succeed('ā„¹ļø Video information extracted!'); console.log('\n' + boxen( chalk.blue.bold('šŸ“Š VIDEO INFORMATION\n\n') + chalk.cyan(`šŸŽ¬ Title: ${videoInfo.title || 'N/A'}\n`) + chalk.cyan(`šŸ‘¤ Uploader: ${videoInfo.uploader || 'N/A'}\n`) + chalk.cyan(`šŸŽ„ Quality: ${videoInfo.quality || 'N/A'}\n`) + chalk.cyan(`ā±ļø Duration: ${videoInfo.duration ? `${videoInfo.duration}s` : 'N/A'}\n`) + chalk.cyan(`šŸ“ Description: ${videoInfo.description ? videoInfo.description.substring(0, 100) + '...' : 'N/A'}\n`) + chalk.cyan(`šŸ”— Thumbnail: ${videoInfo.thumbnailUrl ? 'Available' : 'N/A'}\n`) + chalk.cyan(`šŸ“… Method: ${videoInfo.extractionMethod || 'N/A'}`), { padding: 1, borderStyle: 'round', borderColor: 'blue' } )); } catch (error) { spinner.fail(chalk.red(`āŒ Failed to get video info: ${error.message}`)); } }); // Stats command program .command('stats') .alias('s') .description('šŸ“ˆ Show download statistics') .action(() => { console.log(createBanner()); // This would typically read from a stats file console.log(boxen( chalk.green.bold('šŸ“ˆ DOWNLOAD STATISTICS\n\n') + chalk.cyan('šŸŽÆ Total Downloads: 0\n') + chalk.cyan('āŒ Failed Downloads: 0\n') + chalk.cyan('šŸ“Š Success Rate: 0%\n') + chalk.cyan('šŸ’¾ Total Size: 0 MB\n') + chalk.cyan('ā±ļø Total Time: 0s\n\n') + chalk.yellow('Start downloading to see stats!'), { padding: 1, borderStyle: 'round', borderColor: 'green' } )); }); // Help command with MrChamuwa style program .command('help-si') .description('šŸ‡±šŸ‡° Help in Sinhala (ą·ƒą·’ą¶‚ą·„ą¶½ ą¶‹ą¶Æą·€ą·Š)') .action(() => { console.log(createBanner()); console.log(boxen( chalk.yellow.bold('šŸ‡±šŸ‡° MrChamuwa FB Downloader - ą·ƒą·’ą¶‚ą·„ą¶½ ą¶‹ą¶Æą·€ą·Š\n\n') + chalk.cyan('šŸ“ Commands:\n\n') + chalk.white('chamuwa-fb download ') + chalk.gray('- Interactive download\n') + chalk.white('chamuwa-fb quick <url> ') + chalk.gray('- Quick download\n') + chalk.white('chamuwa-fb batch <file> ') + chalk.gray('- Batch download\n') + chalk.white('chamuwa-fb info <url> ') + chalk.gray('- Video info\n') + chalk.white('chamuwa-fb stats ') + chalk.gray('- Statistics\n\n') + chalk.green('šŸŽÆ Usage Example:\n') + chalk.white('chamuwa-fb download\n') + chalk.white('chamuwa-fb quick "https://facebook.com/video-url"\n\n') + chalk.red('āš ļø Important:\n') + chalk.yellow('• Video public විය යුතුයි\n') + chalk.yellow('• Internet connection ą·„ą·œą¶³ විය යුතුයි\n') + chalk.yellow('• Facebook URL ą¶‘ą¶š valid විය යුතුයි'), { padding: 1, borderStyle: 'round', borderColor: 'yellow' } )); }); program.parse();