Yaelcode commited on
Commit
d615b83
·
verified ·
1 Parent(s): 77fd563

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +278 -0
app.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import subprocess
4
+ import threading
5
+ import random
6
+ import shutil
7
+ import logging
8
+ import requests
9
+ import gc
10
+ import json
11
+ from flask import Flask, request, jsonify
12
+ from huggingface_hub import HfApi
13
+
14
+ app = Flask(__name__)
15
+ logging.basicConfig(level=logging.INFO)
16
+
17
+ DATASET_REPO = os.environ.get("DATASET_REPO")
18
+ HF_TOKEN = os.environ.get("HF_TOKEN")
19
+ RENDER_URL = os.environ.get("RENDER_URL")
20
+ ACCOUNTS_FILE = "accounts.txt"
21
+ WARP_PORT = 40000
22
+
23
+ api = HfApi(token=HF_TOKEN)
24
+
25
+ # --- YARDIMCI KOMUTLAR ---
26
+ def run_command(cmd):
27
+ try:
28
+ return subprocess.run(cmd, shell=True, capture_output=True, text=True)
29
+ except Exception as e:
30
+ print(f"⚠️ Komut Hatası: {e}", flush=True)
31
+ return None
32
+
33
+ def get_accounts():
34
+ if not os.path.exists(ACCOUNTS_FILE): return []
35
+ with open(ACCOUNTS_FILE, 'r') as f:
36
+ return [line.strip() for line in f if ':' in line]
37
+
38
+ def report_to_render(status, message, task_id, download_url=None):
39
+ print(f"📡 Rapor: {status} - {message}", flush=True)
40
+ if not RENDER_URL: return
41
+ try:
42
+ requests.post(f"{RENDER_URL}/webhook", json={
43
+ 'status': status, 'message': message, 'task_id': task_id, 'download_url': download_url
44
+ }, timeout=10)
45
+ except: pass
46
+
47
+ # --- GÜVENLİ WARP YÖNETİMİ ---
48
+ def rotate_warp_ip():
49
+ """WARP IP'sini güvenli bir şekilde değiştirir (Çökmeden)"""
50
+ print("\n♻️ IP ROTASYONU BAŞLATILIYOR...", flush=True)
51
+ try:
52
+ os.system("pkill wireproxy")
53
+ os.system("pkill wgcf")
54
+ time.sleep(2)
55
+
56
+ for f in ["wgcf-account.toml", "wgcf-profile.conf", "wireproxy.conf"]:
57
+ if os.path.exists(f):
58
+ try: os.remove(f)
59
+ except: pass
60
+
61
+ print("⚡ Cloudflare ile görüşülüyor...", flush=True)
62
+ subprocess.run(["wgcf", "register", "--accept-tos"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=30)
63
+ subprocess.run(["wgcf", "generate"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=30)
64
+
65
+ if not os.path.exists("wgcf-profile.conf"):
66
+ print("❌ WARP Config alınamadı!", flush=True)
67
+ return False
68
+
69
+ with open("wgcf-profile.conf", "r") as f:
70
+ content = f.read()
71
+
72
+ private_key = content.split("PrivateKey = ")[1].split("\n")[0].strip()
73
+ address = content.split("Address = ")[1].split("\n")[0].strip()
74
+
75
+ wp_conf = f"""[Interface]
76
+ PrivateKey = {private_key}
77
+ Address = {address}
78
+ DNS = 1.1.1.1
79
+ [Peer]
80
+ PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
81
+ AllowedIPs = 0.0.0.0/0
82
+ Endpoint = engage.cloudflareclient.com:2408
83
+ [Socks5]
84
+ BindAddress = 127.0.0.1:{WARP_PORT}"""
85
+
86
+ with open("wireproxy.conf", "w") as f:
87
+ f.write(wp_conf)
88
+
89
+ print(f"🚀 Tünel Açılıyor...", flush=True)
90
+ subprocess.Popen(["wireproxy", "-c", "wireproxy.conf"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
91
+ time.sleep(5)
92
+ return True
93
+ except Exception as e:
94
+ print(f"❌ IP Rotasyonunda Hata: {e}", flush=True)
95
+ return False
96
+
97
+ def safe_mega_reset():
98
+ """MegaCMD'yi güvenli sıfırlar"""
99
+ try:
100
+ os.system("pkill mega-cmd")
101
+ time.sleep(2)
102
+ subprocess.Popen(["nohup", "mega-cmd-server"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
103
+ time.sleep(5)
104
+ except: pass
105
+
106
+ def login_with_proxy(account_str):
107
+ try:
108
+ email, password = account_str.split(":", 1)
109
+ proxy_url = f"socks5://127.0.0.1:{WARP_PORT}"
110
+ subprocess.run(["mega-proxy", proxy_url], capture_output=True)
111
+
112
+ print(f"🔑 Giriş Deneniyor: {email[:3]}***", flush=True)
113
+ res = subprocess.run(["mega-login", email, password], capture_output=True, text=True, timeout=45)
114
+ if res.returncode == 0:
115
+ print("✅ Giriş Başarılı.", flush=True)
116
+ return True
117
+ else:
118
+ print(f"❌ Giriş Başarısız: {res.stderr}", flush=True)
119
+ return False
120
+ except Exception as e:
121
+ return False
122
+
123
+ def get_mega_details():
124
+ try:
125
+ res = subprocess.run(["mega-transfers"], capture_output=True, text=True)
126
+ return res.stdout.strip()
127
+ except: return ""
128
+
129
+ def download_engine(link, task_id):
130
+ try:
131
+ print(f"\n⚙️ WORKER BAŞLADI: {task_id}", flush=True)
132
+ base_dir = "downloads"
133
+ abs_base = os.path.abspath(base_dir)
134
+ download_folder = f"{abs_base}/{task_id}"
135
+ zip_file = f"{abs_base}/{task_id}.zip"
136
+
137
+ os.makedirs(download_folder, exist_ok=True)
138
+ accounts = get_accounts()
139
+ random.shuffle(accounts)
140
+
141
+ if not accounts: return
142
+ is_completed = False
143
+
144
+ safe_mega_reset()
145
+ rotate_warp_ip()
146
+
147
+ for i, account in enumerate(accounts):
148
+ if is_completed: break
149
+
150
+ print(f"\n🔄 --- HESAP {i+1} / {len(accounts)} ---", flush=True)
151
+ if not login_with_proxy(account):
152
+ rotate_warp_ip()
153
+ safe_mega_reset()
154
+ if not login_with_proxy(account): continue
155
+
156
+ print(f"📥 İNDİRME BAŞLATILIYOR...", flush=True)
157
+ cmd = f'nohup mega-get "{link}" "{download_folder}" > /dev/null 2>&1 &'
158
+ os.system(cmd)
159
+
160
+ no_transfer_count = 0
161
+ loop_counter = 0
162
+
163
+ while True:
164
+ time.sleep(5)
165
+ output = get_mega_details()
166
+ lower_output = output.lower()
167
+
168
+ if "bandwidth quota exceeded" in lower_output or "paused" in lower_output or "retrying" in lower_output:
169
+ print("\n🚨 KOTA/IP BAN TESPİT EDİLDİ! Değiştiriliyor...", flush=True)
170
+ os.system("pkill mega-get")
171
+ if rotate_warp_ip():
172
+ safe_mega_reset()
173
+ else:
174
+ time.sleep(60)
175
+ break
176
+
177
+ if "no active transfers" in lower_output:
178
+ loop_counter += 1
179
+ if loop_counter > 3:
180
+ no_transfer_count += 1
181
+ if no_transfer_count >= 2:
182
+ if len(os.listdir(download_folder)) > 0:
183
+ print("\n✅ İNDİRME TAMAMLANDI!", flush=True)
184
+ is_completed = True
185
+ break
186
+ else:
187
+ break
188
+ else:
189
+ no_transfer_count = 0
190
+
191
+ lines = output.split('\n')
192
+ for line in lines:
193
+ if "TRANSFERRING" in line or "%" in line:
194
+ print(f"📊 {line.strip()}", flush=True)
195
+ loop_counter += 1
196
+
197
+ if is_completed: break
198
+ time.sleep(2)
199
+
200
+ if not is_completed: return
201
+
202
+ print("📦 ZİPLENİYOR...", flush=True)
203
+ shutil.make_archive(f"{abs_base}/{task_id}", 'zip', download_folder)
204
+
205
+ print("📤 YÜKLENİYOR...", flush=True)
206
+ try:
207
+ api.upload_file(
208
+ path_or_fileobj=zip_file, repo_id=DATASET_REPO, repo_type="dataset", path_in_repo=f"uploads/{task_id}.zip"
209
+ )
210
+ print("✅ HUGGING FACE YÜKLEMESİ BAŞARILI!")
211
+ except Exception as e:
212
+ print(f"❌ Upload Hatası: {e}", flush=True)
213
+
214
+ try:
215
+ shutil.rmtree(download_folder, ignore_errors=True)
216
+ os.remove(zip_file)
217
+ except: pass
218
+ gc.collect()
219
+
220
+ except Exception as e:
221
+ print(f"🔥 KRİTİK HATA: {e}", flush=True)
222
+
223
+ @app.route('/process', methods=['POST'])
224
+ def process():
225
+ data = request.json
226
+ threading.Thread(target=download_engine, args=(data['link'], data.get('task_id', 'mega_task'))).start()
227
+ return jsonify({'status': 'started'})
228
+
229
+ @app.route('/')
230
+ def ui():
231
+ return """
232
+ <html>
233
+ <body style="background-color: #1e1e1e; color: white; font-family: sans-serif; text-align: center; padding-top: 50px;">
234
+ <h2>Yael Mega-Worker Paneli 🚀</h2>
235
+ <div style="margin: 20px;">
236
+ <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>
237
+ <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>
238
+ <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>
239
+ </div>
240
+ <p id="sonuc" style="color: #00ff00; font-size: 18px; margin-top: 20px;"></p>
241
+
242
+ <script>
243
+ function tetikle() {
244
+ let link = document.getElementById('mega_link').value;
245
+ let task = document.getElementById('task_id').value;
246
+ let sonucText = document.getElementById('sonuc');
247
+
248
+ if(!link || !task) {
249
+ sonucText.innerText = "⚠️ Hata: Link ve Görev Adı boş olamaz!";
250
+ sonucText.style.color = "red";
251
+ return;
252
+ }
253
+
254
+ sonucText.innerText = "⏳ İstek sunucuya iletiliyor, bekle...";
255
+ sonucText.style.color = "yellow";
256
+
257
+ fetch('/process', {
258
+ method: 'POST',
259
+ headers: {'Content-Type': 'application/json'},
260
+ body: JSON.stringify({link: link, task_id: task})
261
+ })
262
+ .then(res => res.json())
263
+ .then(data => {
264
+ sonucText.innerText = "✅ İndirme motoru ateşlendi! Hugging Face loglarından takip edebilirsin.";
265
+ sonucText.style.color = "#00ff00";
266
+ })
267
+ .catch(err => {
268
+ sonucText.innerText = "❌ Bir hata oluştu: " + err;
269
+ sonucText.style.color = "red";
270
+ });
271
+ }
272
+ </script>
273
+ </body>
274
+ </html>
275
+ """
276
+
277
+ if __name__ == '__main__':
278
+ app.run(host='0.0.0.0', port=7860)