from flask import Flask, render_template, request, send_file, jsonify from yt_dlp import YoutubeDL import instaloader import os import uuid import shutil from waitress import serve import ssl import certifi # Disable SSL verification warnings ssl._create_default_https_context = ssl._create_unverified_context app = Flask(__name__) # Create downloads directory os.makedirs('downloads', exist_ok=True) @app.route('/') def home(): return render_template('index.html') @app.route('/download', methods=['POST']) def download(): url = request.form.get('url') if not url: return jsonify({'error': 'No URL provided'}), 400 try: if 'youtube.com' in url or 'youtu.be' in url: return download_youtube(url) elif 'instagram.com' in url: return download_instagram(url) elif 'tiktok.com' in url: return download_tiktok(url) else: return jsonify({'error': 'Please enter a valid YouTube, Instagram, or TikTok URL'}), 400 except Exception as e: return jsonify({'error': str(e)}), 500 def download_youtube(url): try: filename = f"youtube_{uuid.uuid4().hex}.mp4" filepath = os.path.join('downloads', filename) ydl_opts = { 'format': 'best', 'outtmpl': filepath, 'nocheckcertificate': True, 'no_check_certificates': True, 'quiet': True, 'no_warnings': True, 'ignoreerrors': True, 'extract_flat': True, 'force_generic_extractor': True, 'http_headers': { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } } with YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=True) if info: return send_file( filepath, as_attachment=True, download_name=f"{info.get('title', 'video')}.mp4" ) else: raise Exception("Failed to extract video information") except Exception as e: return jsonify({'error': f'YouTube download failed: {str(e)}'}), 500 finally: if os.path.exists(filepath): try: os.remove(filepath) except: pass def download_instagram(url): try: L = instaloader.Instaloader() temp_dir = f"downloads/insta_{uuid.uuid4().hex}" os.makedirs(temp_dir, exist_ok=True) try: if "/reel/" in url: shortcode = url.split("/reel/")[1].split("/")[0] elif "/p/" in url: shortcode = url.split("/p/")[1].split("/")[0] else: raise ValueError("Invalid Instagram URL") post = instaloader.Post.from_shortcode(L.context, shortcode) L.download_post(post, target=temp_dir) for file in os.listdir(temp_dir): if file.endswith('.mp4'): filepath = os.path.join(temp_dir, file) return send_file( filepath, as_attachment=True, download_name=f"instagram_{shortcode}.mp4" ) raise Exception("No video found in this post") finally: if os.path.exists(temp_dir): shutil.rmtree(temp_dir, ignore_errors=True) except Exception as e: return jsonify({'error': f'Instagram download failed: {str(e)}'}), 500 def download_tiktok(url): try: filename = f"tiktok_{uuid.uuid4().hex}.mp4" filepath = os.path.join('downloads', filename) ydl_opts = { 'format': 'best', 'outtmpl': filepath, 'quiet': True, 'no_warnings': True, 'nocheckcertificate': True } with YoutubeDL(ydl_opts) as ydl: ydl.download([url]) if os.path.exists(filepath): return send_file( filepath, as_attachment=True, download_name=f"tiktok_video.mp4" ) else: raise Exception("Failed to download video") except Exception as e: return jsonify({'error': f'TikTok download failed: {str(e)}'}), 500 finally: if os.path.exists(filepath): try: os.remove(filepath) except: pass @app.after_request def cleanup(response): try: for file in os.listdir('downloads'): filepath = os.path.join('downloads', file) if os.path.isfile(filepath): os.remove(filepath) except: pass return response if __name__ == "__main__": port = int(os.environ.get("PORT", 7860)) serve(app, host="0.0.0.0", port=port)