import os import uuid import tempfile import threading from flask import Flask, render_template_string, request, jsonify, send_file import yt_dlp app = Flask(__name__) TEMP_DIR = os.path.join(tempfile.gettempdir(), 'termux_dl_final') if not os.path.exists(TEMP_DIR): os.makedirs(TEMP_DIR) progress_db = {} HTML_TEMPLATE = """ Deepu Downloader

Deepu Downloader

YouTube Video & MP3 Downloader

Made by Deepu ❤️

""" def hook(d, uid): if uid not in progress_db: return if d['status'] == 'downloading': raw = d.get('_percent_str', '0%').replace('%', '').replace('\x1b[0;94m', '').replace('\x1b[0m', '').strip() try: p = float(raw) except: p = 0 progress_db[uid].update({ 'p': p, 's': d.get('_speed_str', 'N/A'), 'e': d.get('_eta_str', 'N/A'), 'status': 'dl' }) @app.route('/') def home(): return render_template_string(HTML_TEMPLATE) @app.route('/api/analyze', methods=['POST']) def api_analyze(): url = request.json.get('url', '').strip() if not url: return jsonify({'success': False, 'message': 'URL daalo bhai!'}) opts = { 'quiet': True, 'noplaylist': True, 'skip_download': True, } try: with yt_dlp.YoutubeDL(opts) as ydl: info = ydl.extract_info(url, download=False) fmts = [] seen = set() for f in info.get('formats', []): h = f.get('height') if h and f.get('vcodec', 'none') != 'none' and h not in seen: seen.add(h) fmts.append({'id': f['format_id'], 'h': h}) # Sort by height descending, take top 8 fmts = sorted(fmts, key=lambda x: x['h'], reverse=True)[:8] return jsonify({ 'success': True, 'title': info.get('title', 'Unknown'), 'thumbnail': info.get('thumbnail', ''), 'formats': fmts, 'url': url }) except yt_dlp.utils.DownloadError as e: return jsonify({'success': False, 'message': str(e)[:200]}) except Exception as e: return jsonify({'success': False, 'message': f'Error: {str(e)[:200]}'}) @app.route('/api/download', methods=['POST']) def api_download(): data = request.json uid = str(uuid.uuid4()) progress_db[uid] = {'p': 0, 's': '', 'e': '', 'status': 'start'} def dl(): path = os.path.join(TEMP_DIR, f"{uid}.%(ext)s") opts = { 'outtmpl': path, 'progress_hooks': [lambda d: hook(d, uid)], 'quiet': True, 'noplaylist': True, } if data.get('format') == 'mp3': opts.update({ 'format': 'bestaudio/best', 'postprocessors': [{'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192'}] }) else: fmt_id = data.get('format', 'best') opts.update({ 'format': f"{fmt_id}+bestaudio/best", 'merge_output_format': 'mp4' }) try: with yt_dlp.YoutubeDL(opts) as ydl: info = ydl.extract_info(data['url'], download=True) fname = ydl.prepare_filename(info) if data.get('format') == 'mp3': fname = os.path.splitext(fname)[0] + '.mp3' elif not fname.endswith('.mp4'): fname = os.path.splitext(fname)[0] + '.mp4' progress_db[uid].update({'status': 'done', 'file': os.path.basename(fname)}) except Exception as e: progress_db[uid]['status'] = 'error' print(f"Download error: {e}") threading.Thread(target=dl, daemon=True).start() return jsonify({'id': uid}) @app.route('/api/status/') def api_status(uid): return jsonify(progress_db.get(uid, {'status': 'none'})) @app.route('/api/file/') def api_file(name): fpath = os.path.join(TEMP_DIR, name) if not os.path.exists(fpath): return jsonify({'error': 'File nahi mili'}), 404 return send_file(fpath, as_attachment=True) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, threaded=True)