import os
import time
import uuid
import threading
from flask import Flask, request, jsonify, send_file, render_template_string
from flask_cors import CORS
import yt_dlp
app = Flask(__name__)
CORS(app)
DOWNLOAD_FOLDER = 'downloads'
os.makedirs(DOWNLOAD_FOLDER, exist_ok=True)
# ==========================================
# سیستم پاکسازی خودکار فایلهای قدیمی
# ==========================================
def cleanup_old_files():
"""این تابع هر یک ساعت اجرا میشود و فایلهای قدیمیتر از 1 ساعت را پاک میکند تا حافظه پر نشود"""
while True:
try:
current_time = time.time()
for filename in os.listdir(DOWNLOAD_FOLDER):
file_path = os.path.join(DOWNLOAD_FOLDER, filename)
if os.path.isfile(file_path):
# اگر فایل قدیمیتر از 3600 ثانیه (1 ساعت) بود، حذف شود
if current_time - os.path.getctime(file_path) > 3600:
os.remove(file_path)
except Exception as e:
print(f"Cleanup error: {e}")
time.sleep(3600)
# راهاندازی نخ پاکسازی در پسزمینه
cleanup_thread = threading.Thread(target=cleanup_old_files, daemon=True)
cleanup_thread.start()
# ==========================================
# رابط کاربری ساده برای تست (رابط وب)
# ==========================================
HTML_TEMPLATE = """
دانلودر اختصاصی ویدیو
"""
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
# ==========================================
# API دانلود ویدیو
# ==========================================
@app.route('/api/download', methods=['POST'])
def download_video():
data = request.get_json()
if not data or 'url' not in data:
return jsonify({'error': 'URL is required'}), 400
url = data['url']
# شناسه یکتا برای فایل خروجی
file_id = str(uuid.uuid4())
output_template = os.path.join(DOWNLOAD_FOLDER, f"{file_id}.%(ext)s")
# تنظیمات yt-dlp همراه با سیستم بایپس یوتیوب
ydl_opts = {
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
'outtmpl': output_template,
'quiet': True,
'no_warnings': True,
'merge_output_format': 'mp4',
# 1. آدرس فایل کوکی که باید در کنار app.py آپلود شود
'cookiefile': 'cookies.txt',
# 2. تغییر کلاینت به موبایل/وب برای کاهش حساسیت رباتهای یوتیوب
'extractor_args': {'youtube': {'player_client': ['android', 'web']}},
}
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
# استخراج اطلاعات و دانلود
info_dict = ydl.extract_info(url, download=True)
downloaded_ext = info_dict.get('ext', 'mp4')
final_filename = f"{file_id}.{downloaded_ext}"
if not os.path.exists(os.path.join(DOWNLOAD_FOLDER, final_filename)):
final_filename = f"{file_id}.mp4"
final_path = os.path.join(DOWNLOAD_FOLDER, final_filename)
if os.path.exists(final_path):
return send_file(final_path, as_attachment=True, download_name=f"video_{int(time.time())}.mp4")
else:
return jsonify({'error': 'فایل پس از دانلود یافت نشد.'}), 500
except Exception as e:
error_msg = str(e)
if "Sign in to confirm" in error_msg or "Private video" in error_msg:
return jsonify({'error': 'آیپی سرور مسدود شده است. لطفا مطمئن شوید فایل cookies.txt را در روت پروژه آپلود کردهاید.'}), 403
return jsonify({'error': f'خطا در دانلود: {error_msg}'}), 500
if __name__ == '__main__':
port = int(os.environ.get('PORT', 7860))
app.run(host='0.0.0.0', port=port)