Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -20,7 +20,7 @@ app = Flask(__name__)
|
|
| 20 |
|
| 21 |
@app.route('/')
|
| 22 |
def home():
|
| 23 |
-
return "🚀 ربات هوشمند انتقال به گیتهاب (مجهز به
|
| 24 |
|
| 25 |
def run_flask():
|
| 26 |
app.run(host="0.0.0.0", port=7860, threaded=True)
|
|
@@ -29,9 +29,6 @@ bot_token = os.environ.get("RUBIKA_AUTH", "توکن_روبیکا").strip()
|
|
| 29 |
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "توکن_گیتهاب").strip()
|
| 30 |
TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "توکن_تلگرام").strip()
|
| 31 |
|
| 32 |
-
# توکن مربوط به RapidAPI برای دانلود یوتیوب (مهم)
|
| 33 |
-
RAPIDAPI_KEY = os.environ.get("RAPIDAPI_KEY", "b448420296msh34bbdc459d62fa0p124de1jsn8778ca694e65").strip()
|
| 34 |
-
|
| 35 |
GITHUB_REPO = "hajiliker6-source/internet-melli"
|
| 36 |
|
| 37 |
TG_API_ID = 6
|
|
@@ -63,12 +60,12 @@ async def ensure_tg_started():
|
|
| 63 |
is_tg_started = True
|
| 64 |
|
| 65 |
# ==============================================================================
|
| 66 |
-
# 🟢 تابع اختصاصی دانلود یوتیوب از طریق
|
| 67 |
# ==============================================================================
|
| 68 |
-
async def
|
| 69 |
status_msg_id = None
|
| 70 |
try:
|
| 71 |
-
msg_text = "⏳ در حال ا
|
| 72 |
status_msg = await client.send_message(chat_id, msg_text, reply_to_message_id=message_id)
|
| 73 |
status_msg_id = getattr(status_msg, 'message_id', None)
|
| 74 |
if not status_msg_id and isinstance(status_msg, dict):
|
|
@@ -76,81 +73,42 @@ async def download_youtube_rapidapi(url, chat_id, message_id, client):
|
|
| 76 |
except: pass
|
| 77 |
|
| 78 |
try:
|
| 79 |
-
|
| 80 |
-
raise Exception("کلید RAPIDAPI_KEY تنظیم نشده است! بدون این کلید، API کار نخواهد کرد.")
|
| 81 |
-
|
| 82 |
-
API_BASE = "https://yt-video-audio-downloader-api.p.rapidapi.com"
|
| 83 |
headers = {
|
|
|
|
| 84 |
"Content-Type": "application/json",
|
| 85 |
-
"X-RapidAPI-Key": RAPIDAPI_KEY,
|
| 86 |
-
"X-RapidAPI-Host": "yt-video-audio-downloader-api.p.rapidapi.com",
|
| 87 |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
| 88 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
async with aiohttp.ClientSession(headers=headers) as session:
|
| 91 |
-
# مرحله
|
| 92 |
-
|
| 93 |
-
async with session.post(f"{API_BASE}/download", json=payload) as resp:
|
| 94 |
-
|
| 95 |
if resp.status != 200:
|
| 96 |
server_log = await resp.text()
|
| 97 |
error_message = (
|
| 98 |
-
f"خطا در ارتباط با سرور
|
| 99 |
f"کد ارور: {resp.status}\n\n"
|
| 100 |
-
f"📝 لاگ سرور
|
| 101 |
)
|
| 102 |
raise Exception(error_message)
|
| 103 |
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
download_url = None
|
| 107 |
-
if start_data.get("directDownload"):
|
| 108 |
-
download_url = start_data["downloadUrl"]
|
| 109 |
-
else:
|
| 110 |
-
job_id = start_data.get("jobId")
|
| 111 |
-
if not job_id:
|
| 112 |
-
raise Exception(f"سرور شناسه Job ID را برنگرداند. پاسخ سرور:\n{start_data}")
|
| 113 |
-
|
| 114 |
-
# خواندن داینامیک مسیر وضعیت
|
| 115 |
-
status_path = start_data.get("statusUrl")
|
| 116 |
-
if not status_path:
|
| 117 |
-
status_path = f"/status/{job_id}" # بکاپ اگر سرور لینک نداد
|
| 118 |
-
|
| 119 |
-
if status_path.startswith("/"):
|
| 120 |
-
status_url = API_BASE + status_path
|
| 121 |
-
else:
|
| 122 |
-
status_url = f"{API_BASE}/{status_path}"
|
| 123 |
|
| 124 |
-
|
| 125 |
-
try: await client.edit_message_text(chat_id, status_msg_id, "⏳ ویدیو در سرور رپید در حال پردازش است (در حال بررسی وضعیت...)")
|
| 126 |
-
except: pass
|
| 127 |
-
|
| 128 |
-
# مرحله 2: بررسی وضعیت پردازش
|
| 129 |
-
while True:
|
| 130 |
-
await asyncio.sleep(3)
|
| 131 |
-
async with session.get(status_url) as status_resp:
|
| 132 |
-
if status_resp.status != 200:
|
| 133 |
-
status_log = await status_resp.text()
|
| 134 |
-
raise Exception(f"خطا در بررسی وضعیت (کد {status_resp.status}).\nلاگ:\n{status_log}")
|
| 135 |
-
|
| 136 |
-
status_data = await status_resp.json()
|
| 137 |
-
if status_data.get("status") == "completed":
|
| 138 |
-
download_url = status_data["downloadUrl"]
|
| 139 |
-
break
|
| 140 |
-
elif status_data.get("status") == "error":
|
| 141 |
-
raise Exception("خطای پردازش داخلی سرور: " + status_data.get("error", "نامشخص"))
|
| 142 |
-
|
| 143 |
if not download_url:
|
| 144 |
-
raise Exception("
|
| 145 |
-
|
| 146 |
-
if download_url.startswith("/"):
|
| 147 |
-
download_url = API_BASE + download_url
|
| 148 |
|
| 149 |
if status_msg_id:
|
| 150 |
-
try: await client.edit_message_text(chat_id, status_msg_id, "📥
|
| 151 |
except: pass
|
| 152 |
|
| 153 |
-
# مرحله
|
| 154 |
temp_dir = "/app/downloads"
|
| 155 |
os.makedirs(temp_dir, exist_ok=True)
|
| 156 |
filename = f"youtube_{uuid.uuid4().hex[:6]}.mp4"
|
|
@@ -167,9 +125,9 @@ async def download_youtube_rapidapi(url, chat_id, message_id, client):
|
|
| 167 |
return file_path, filename, status_msg_id
|
| 168 |
|
| 169 |
except Exception as e:
|
| 170 |
-
error_msg = f"❌ خطای یوتیوب:\n{str(e)}"
|
| 171 |
if status_msg_id:
|
| 172 |
-
try: await client.edit_message_text(chat_id, status_msg_id, error_msg
|
| 173 |
except: pass
|
| 174 |
return None, None, status_msg_id
|
| 175 |
|
|
@@ -178,7 +136,6 @@ async def download_youtube_rapidapi(url, chat_id, message_id, client):
|
|
| 178 |
# ==============================================================================
|
| 179 |
async def get_direct_link_from_free_api(url):
|
| 180 |
is_ig = "instagram.com" in url.lower()
|
| 181 |
-
|
| 182 |
if not is_ig: return None
|
| 183 |
|
| 184 |
async with aiohttp.ClientSession() as session:
|
|
@@ -345,8 +302,9 @@ def split_file_for_winrar(file_path, dest_dir, base_filename):
|
|
| 345 |
async def process_and_commit_to_github(client, chat_id, message_id, url):
|
| 346 |
url_l = url.lower()
|
| 347 |
|
|
|
|
| 348 |
if any(x in url_l for x in ["youtube.com", "youtu.be"]):
|
| 349 |
-
file_path, filename, status_msg_id = await
|
| 350 |
elif "instagram.com" in url_l:
|
| 351 |
file_path, filename, status_msg_id = await download_via_free_api(url, chat_id, message_id, client)
|
| 352 |
elif "t.me/" in url_l:
|
|
@@ -461,5 +419,5 @@ async def main_handler(client, update):
|
|
| 461 |
if __name__ == "__main__":
|
| 462 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 463 |
threading.Thread(target=lambda: asyncio.run(cleanup_expired_branches()), daemon=True).start()
|
| 464 |
-
print("🚀 آماده به کار با APIهای جایگزین و
|
| 465 |
bot.run()
|
|
|
|
| 20 |
|
| 21 |
@app.route('/')
|
| 22 |
def home():
|
| 23 |
+
return "🚀 ربات هوشمند انتقال به گیتهاب (مجهز به کبالت و تلگرام) فعال است!"
|
| 24 |
|
| 25 |
def run_flask():
|
| 26 |
app.run(host="0.0.0.0", port=7860, threaded=True)
|
|
|
|
| 29 |
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "توکن_گیتهاب").strip()
|
| 30 |
TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "توکن_تلگرام").strip()
|
| 31 |
|
|
|
|
|
|
|
|
|
|
| 32 |
GITHUB_REPO = "hajiliker6-source/internet-melli"
|
| 33 |
|
| 34 |
TG_API_ID = 6
|
|
|
|
| 60 |
is_tg_started = True
|
| 61 |
|
| 62 |
# ==============================================================================
|
| 63 |
+
# 🟢 تابع اختصاصی دانلود یوتیوب از طریق Cobalt (کاملا رایگان و بدون کلید)
|
| 64 |
# ==============================================================================
|
| 65 |
+
async def download_youtube_cobalt(url, chat_id, message_id, client):
|
| 66 |
status_msg_id = None
|
| 67 |
try:
|
| 68 |
+
msg_text = "⏳ در حال استخراج لینک یوتیوب از سرورهای ضد-تحریم کبالت..."
|
| 69 |
status_msg = await client.send_message(chat_id, msg_text, reply_to_message_id=message_id)
|
| 70 |
status_msg_id = getattr(status_msg, 'message_id', None)
|
| 71 |
if not status_msg_id and isinstance(status_msg, dict):
|
|
|
|
| 73 |
except: pass
|
| 74 |
|
| 75 |
try:
|
| 76 |
+
api_url = "https://api.cobalt.tools/api/json"
|
|
|
|
|
|
|
|
|
|
| 77 |
headers = {
|
| 78 |
+
"Accept": "application/json",
|
| 79 |
"Content-Type": "application/json",
|
|
|
|
|
|
|
| 80 |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
| 81 |
}
|
| 82 |
+
payload = {
|
| 83 |
+
"url": url,
|
| 84 |
+
"vCodec": "h264",
|
| 85 |
+
"vQuality": "720",
|
| 86 |
+
"filenamePattern": "classic"
|
| 87 |
+
}
|
| 88 |
|
| 89 |
async with aiohttp.ClientSession(headers=headers) as session:
|
| 90 |
+
# مرحله ۱: ارسال درخواست به کبالت برای دور زدن محدودیتهای یوتیوب
|
| 91 |
+
async with session.post(api_url, json=payload) as resp:
|
|
|
|
|
|
|
| 92 |
if resp.status != 200:
|
| 93 |
server_log = await resp.text()
|
| 94 |
error_message = (
|
| 95 |
+
f"خطا در ارتباط با سرور کبالت.\n"
|
| 96 |
f"کد ارور: {resp.status}\n\n"
|
| 97 |
+
f"📝 لاگ سرور:\n{server_log}"
|
| 98 |
)
|
| 99 |
raise Exception(error_message)
|
| 100 |
|
| 101 |
+
data = await resp.json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
+
download_url = data.get("url")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
if not download_url:
|
| 105 |
+
raise Exception(f"سرور کبالت لینک دانلود را برنگرداند. پاسخ:\n{data}")
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
if status_msg_id:
|
| 108 |
+
try: await client.edit_message_text(chat_id, status_msg_id, "📥 لینک استخراج شد! در حال دانلود ویدیو روی سرور...")
|
| 109 |
except: pass
|
| 110 |
|
| 111 |
+
# مرحله ۲: دانلود فایل نهایی روی سرور
|
| 112 |
temp_dir = "/app/downloads"
|
| 113 |
os.makedirs(temp_dir, exist_ok=True)
|
| 114 |
filename = f"youtube_{uuid.uuid4().hex[:6]}.mp4"
|
|
|
|
| 125 |
return file_path, filename, status_msg_id
|
| 126 |
|
| 127 |
except Exception as e:
|
| 128 |
+
error_msg = f"❌ خطای یوتیوب (کبالت):\n{str(e)[:1000]}"
|
| 129 |
if status_msg_id:
|
| 130 |
+
try: await client.edit_message_text(chat_id, status_msg_id, error_msg)
|
| 131 |
except: pass
|
| 132 |
return None, None, status_msg_id
|
| 133 |
|
|
|
|
| 136 |
# ==============================================================================
|
| 137 |
async def get_direct_link_from_free_api(url):
|
| 138 |
is_ig = "instagram.com" in url.lower()
|
|
|
|
| 139 |
if not is_ig: return None
|
| 140 |
|
| 141 |
async with aiohttp.ClientSession() as session:
|
|
|
|
| 302 |
async def process_and_commit_to_github(client, chat_id, message_id, url):
|
| 303 |
url_l = url.lower()
|
| 304 |
|
| 305 |
+
# 🟢 هدایت لینکهای یوتیوب به سمت کبالت
|
| 306 |
if any(x in url_l for x in ["youtube.com", "youtu.be"]):
|
| 307 |
+
file_path, filename, status_msg_id = await download_youtube_cobalt(url, chat_id, message_id, client)
|
| 308 |
elif "instagram.com" in url_l:
|
| 309 |
file_path, filename, status_msg_id = await download_via_free_api(url, chat_id, message_id, client)
|
| 310 |
elif "t.me/" in url_l:
|
|
|
|
| 419 |
if __name__ == "__main__":
|
| 420 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 421 |
threading.Thread(target=lambda: asyncio.run(cleanup_expired_branches()), daemon=True).start()
|
| 422 |
+
print("🚀 آماده به کار با APIهای جایگزین و Cobalt...")
|
| 423 |
bot.run()
|