Spaces:
Paused
Paused
| import os | |
| import time | |
| import subprocess | |
| import threading | |
| import random | |
| import shutil | |
| import logging | |
| import requests | |
| import gc | |
| from flask import Flask, request, jsonify | |
| from huggingface_hub import HfApi | |
| app = Flask(__name__) | |
| logging.basicConfig(level=logging.INFO) | |
| DATASET_REPO = os.environ.get("DATASET_REPO") | |
| HF_TOKEN = os.environ.get("HF_TOKEN") | |
| RENDER_URL = os.environ.get("RENDER_URL") | |
| ACCOUNTS_FILE = "accounts.txt" | |
| # Hugging Face token varsa API'yi başlat | |
| api = HfApi(token=HF_TOKEN) if HF_TOKEN else None | |
| # --- YARDIMCI FONKSİYONLAR --- | |
| def get_accounts(): | |
| if not os.path.exists(ACCOUNTS_FILE): return [] | |
| with open(ACCOUNTS_FILE, 'r') as f: | |
| return [line.strip() for line in f if ':' in line] | |
| def report_to_render(status, message, task_id, download_url=None): | |
| print(f"📡 Rapor: {status} - {message}", flush=True) | |
| if not RENDER_URL: return | |
| try: | |
| requests.post(f"{RENDER_URL}/webhook", json={ | |
| 'status': status, 'message': message, 'task_id': task_id, 'download_url': download_url | |
| }, timeout=10) | |
| except: pass | |
| # --- TOR VE GİZLİLİK YÖNETİMİ (Ücretsiz Sınırsız IP) --- | |
| def rotate_warp_ip(): | |
| """Tor ağını yeniden başlatarak yepyeni bir IP (Çıkış Düğümü) alır""" | |
| print("\n🧅 TOR AĞI: Yeni IP aranıyor...", flush=True) | |
| try: | |
| os.system("pkill tor") | |
| time.sleep(2) | |
| subprocess.Popen(["tor"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| print("⏳ Tor devresinin kurulması bekleniyor (15 sn)...", flush=True) | |
| time.sleep(15) | |
| print("🚀 TOR Tüneli Hazır! Yeni Kimlik Aktif.", flush=True) | |
| return True | |
| except Exception as e: | |
| print(f"❌ Tor Başlatma Hatası: {e}", flush=True) | |
| return False | |
| def safe_mega_reset(): | |
| """MegaCMD'yi güvenli sıfırlar""" | |
| try: | |
| os.system("pkill mega-cmd") | |
| time.sleep(2) | |
| subprocess.Popen(["nohup", "mega-cmd-server"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| time.sleep(5) | |
| except: pass | |
| def login_with_proxy(account_str): | |
| try: | |
| email, password = account_str.split(":", 1) | |
| proxy_url = "socks5://127.0.0.1:9050" | |
| subprocess.run(["mega-proxy", proxy_url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| # 🔥 İŞTE SİSTEMİ ÇÖKERTEN YER BURASIYDI, DÜZELTİLDİ! | |
| subprocess.run(["mega-logout"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
| time.sleep(2) | |
| print(f"🔑 Giriş Deneniyor: {email[:3]}***", flush=True) | |
| res = subprocess.run(["mega-login", email, password], capture_output=True, text=True, timeout=45) | |
| if res.returncode == 0: | |
| print("✅ Giriş Başarılı.", flush=True) | |
| return True | |
| else: | |
| print(f"❌ Giriş Başarısız: {res.stderr}", flush=True) | |
| return False | |
| except Exception as e: | |
| # Kod bir daha sessizce çökerse diye buraya uyarıcı ekledim | |
| print(f"🔥 KOD İÇİNDE SİSTEM HATASI: {e}", flush=True) | |
| return False | |
| def get_mega_details(): | |
| try: | |
| res = subprocess.run(["mega-transfers"], capture_output=True, text=True) | |
| return res.stdout.strip() | |
| except: return "" | |
| # --- ANA İNDİRME MOTORU --- | |
| def download_engine(link, task_id): | |
| try: | |
| print(f"\n⚙️ WORKER BAŞLADI: {task_id}", flush=True) | |
| base_dir = "downloads" | |
| abs_base = os.path.abspath(base_dir) | |
| download_folder = f"{abs_base}/{task_id}" | |
| zip_file = f"{abs_base}/{task_id}.zip" | |
| os.makedirs(download_folder, exist_ok=True) | |
| accounts = get_accounts() | |
| random.shuffle(accounts) | |
| if not accounts: | |
| print("❌ HATA: accounts.txt boş veya bulunamadı!", flush=True) | |
| return | |
| is_completed = False | |
| safe_mega_reset() | |
| rotate_warp_ip() | |
| for i, account in enumerate(accounts): | |
| if is_completed: break | |
| print(f"\n🔄 --- HESAP {i+1} / {len(accounts)} ---", flush=True) | |
| if not login_with_proxy(account): | |
| rotate_warp_ip() | |
| safe_mega_reset() | |
| if not login_with_proxy(account): continue | |
| print(f"📥 İNDİRME BAŞLATILIYOR...", flush=True) | |
| cmd = f'nohup mega-get "{link}" "{download_folder}" > /dev/null 2>&1 &' | |
| os.system(cmd) | |
| no_transfer_count = 0 | |
| loop_counter = 0 | |
| previous_active_transfers = [] | |
| stuck_counter = 0 | |
| while True: | |
| time.sleep(5) | |
| output = get_mega_details() | |
| lower_output = output.lower() | |
| lines = output.split('\n') | |
| # 1. Kota ve Ban Kontrolü | |
| if "bandwidth quota exceeded" in lower_output or "paused" in lower_output or "retrying" in lower_output: | |
| print("\n🚨 KOTA TESPİT EDİLDİ! Tor Kimliği Değiştiriliyor...", flush=True) | |
| os.system("pkill mega-get") | |
| if rotate_warp_ip(): | |
| safe_mega_reset() | |
| else: | |
| time.sleep(60) | |
| break | |
| # 2. V3 Zombi ve Hız Koruması (Acımasız Mod) | |
| current_active_transfers = [line for line in lines if "ACTIVE" in line] | |
| if current_active_transfers: | |
| if current_active_transfers == previous_active_transfers: | |
| stuck_counter += 1 | |
| print(f"⚠️ HIZ SIFIR VEYA ZOMBİ BUG! (Tor'u patlatmaya son {6 - stuck_counter} adım)", flush=True) | |
| if stuck_counter >= 6: | |
| print("\n💥 SİSTEM TIKANDI! Mega'nın kafasına sıkılıp yeni Tor IP alınıyor...", flush=True) | |
| os.system("pkill mega-get") | |
| rotate_warp_ip() | |
| safe_mega_reset() | |
| stuck_counter = 0 | |
| break | |
| else: | |
| stuck_counter = 0 | |
| previous_active_transfers = current_active_transfers | |
| else: | |
| stuck_counter = 0 | |
| # 3. Bitiş Kontrolü | |
| if "no active transfers" in lower_output: | |
| loop_counter += 1 | |
| if loop_counter > 3: | |
| no_transfer_count += 1 | |
| if no_transfer_count >= 2: | |
| if len(os.listdir(download_folder)) > 0: | |
| print("\n✅ İNDİRME TAMAMLANDI!", flush=True) | |
| is_completed = True | |
| break | |
| else: | |
| break | |
| else: | |
| no_transfer_count = 0 | |
| # Log Basma | |
| for line in lines: | |
| if "TRANSFERRING" in line or "%" in line: | |
| print(f"📊 {line.strip()}", flush=True) | |
| loop_counter += 1 | |
| if is_completed: break | |
| time.sleep(2) | |
| if not is_completed: return | |
| print("📦 ZİPLENİYOR...", flush=True) | |
| shutil.make_archive(f"{abs_base}/{task_id}", 'zip', download_folder) | |
| print("📤 YÜKLENİYOR...", flush=True) | |
| if api: | |
| try: | |
| api.upload_file( | |
| path_or_fileobj=zip_file, repo_id=DATASET_REPO, repo_type="dataset", path_in_repo=f"uploads/{task_id}.zip" | |
| ) | |
| print("✅ HUGGING FACE YÜKLEMESİ BAŞARILI!") | |
| except Exception as e: | |
| print(f"❌ Upload Hatası: {e}", flush=True) | |
| else: | |
| print("⚠️ HF_TOKEN bulunamadı, Hugging Face yüklemesi atlandı.") | |
| try: | |
| shutil.rmtree(download_folder, ignore_errors=True) | |
| os.remove(zip_file) | |
| except: pass | |
| gc.collect() | |
| except Exception as e: | |
| print(f"🔥 KRİTİK HATA: {e}", flush=True) | |
| # --- WEB ARAYÜZÜ (PANEL) --- | |
| def process(): | |
| data = request.json | |
| threading.Thread(target=download_engine, args=(data['link'], data.get('task_id', 'mega_task'))).start() | |
| return jsonify({'status': 'started'}) | |
| def ui(): | |
| return """ | |
| <html> | |
| <body style="background-color: #1e1e1e; color: white; font-family: sans-serif; text-align: center; padding-top: 50px;"> | |
| <h2>Yael Mega-Worker (Tor Edition) 🚀</h2> | |
| <div style="margin: 20px;"> | |
| <input id="mega_link" type="text" placeholder="Mega.nz Linkini Buraya Yapıştır..." style="width: 80%; max-width: 500px; padding: 15px; border-radius: 8px; border: none; margin-bottom: 10px;"/><br> | |
| <input id="task_id" type="text" placeholder="Görev Adı (Örn: arsiv_1 - Boşluk Bırakma)" style="width: 80%; max-width: 500px; padding: 15px; border-radius: 8px; border: none; margin-bottom: 20px;"/><br> | |
| <button onclick="tetikle()" style="background-color: #ff9900; color: #1e1e1e; font-weight: bold; padding: 15px 30px; border: none; border-radius: 8px; cursor: pointer; font-size: 16px;">İndirmeyi Başlat</button> | |
| </div> | |
| <p id="sonuc" style="color: #00ff00; font-size: 18px; margin-top: 20px;"></p> | |
| <script> | |
| function tetikle() { | |
| let link = document.getElementById('mega_link').value; | |
| let task = document.getElementById('task_id').value; | |
| let sonucText = document.getElementById('sonuc'); | |
| if(!link || !task) { | |
| sonucText.innerText = "⚠️ Hata: Link ve Görev Adı boş olamaz!"; | |
| sonucText.style.color = "red"; | |
| return; | |
| } | |
| sonucText.innerText = "⏳ İstek sunucuya iletiliyor, bekle..."; | |
| sonucText.style.color = "yellow"; | |
| fetch('/process', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/json'}, | |
| body: JSON.stringify({link: link, task_id: task}) | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| sonucText.innerText = "✅ İndirme motoru ateşlendi! Hugging Face loglarından takip edebilirsin."; | |
| sonucText.style.color = "#00ff00"; | |
| }) | |
| .catch(err => { | |
| sonucText.innerText = "❌ Bir hata oluştu: " + err; | |
| sonucText.style.color = "red"; | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| if __name__ == '__main__': | |
| app.run(host='0.0.0.0', port=7860) |