Opera8 commited on
Commit
cf73621
·
verified ·
1 Parent(s): b1ac9c6

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +160 -95
main.py CHANGED
@@ -21,11 +21,12 @@ app = Flask(__name__)
21
 
22
  @app.route('/')
23
  def home():
24
- return "🚀 ربات هوشمند انتقال فایل (YouTube, Instagram, Telegram, Web) روشن است!"
25
 
26
  def run_flask():
27
  app.run(host="0.0.0.0", port=7860, threaded=True)
28
 
 
29
  bot_token = os.environ.get("RUBIKA_AUTH", "توکن_روبیکا").strip()
30
  GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "توکن_گیت‌هاب").strip()
31
  TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "توکن_تلگرام").strip()
@@ -37,7 +38,7 @@ TG_API_ID = 6
37
  TG_API_HASH = "eb06d4abfb49dc3eeb1aeb98ae0f581e"
38
 
39
  if bot_token == "توکن_روبیکا" or GITHUB_TOKEN == "توکن_گیت‌هاب":
40
- print("❌ تنظیمات ناقص است! توکن روبیکا یا گیت‌هاب را وارد کنید.")
41
  exit()
42
 
43
  bot = BotClient(bot_token)
@@ -45,13 +46,19 @@ BOT_GUID = None
45
  git_lock = asyncio.Lock()
46
 
47
  # ==============================================================================
48
- # 🟢 کلاینت تلگرام
49
  # ==============================================================================
50
  tg_client = None
51
  is_tg_started = False
52
 
53
  if TG_BOT_TOKEN and TG_BOT_TOKEN != "توکن_تلگرام":
54
- tg_client = Client("tg_bot_session", api_id=TG_API_ID, api_hash=TG_API_HASH, bot_token=TG_BOT_TOKEN, in_memory=True)
 
 
 
 
 
 
55
 
56
  async def ensure_tg_started():
57
  global is_tg_started
@@ -60,10 +67,10 @@ async def ensure_tg_started():
60
  is_tg_started = True
61
 
62
  # ==============================================================================
63
- # 🟢 توابع دانلود حرفه‌ای
64
  # ==============================================================================
65
 
66
- # 1. دانلود از یوتیوب، اینستاگرام و سایر شبکههای اجتماعی
67
  def sync_download_ytdlp(url, temp_dir):
68
  ydl_opts = {
69
  'outtmpl': f'{temp_dir}/{uuid.uuid4().hex[:6]}_%(title)s.%(ext)s',
@@ -75,24 +82,23 @@ def sync_download_ytdlp(url, temp_dir):
75
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
76
  info = ydl.extract_info(url, download=True)
77
  file_path = ydl.prepare_filename(info)
78
- # اگر فایل mkv بود یا فرمت دیگری، yt-dlp ممکن است پسوند را تغییر دهد
79
- if not os.path.exists(file_path):
80
- base_path = os.path.splitext(file_path)[0]
81
- for ext in ['.mp4', '.mkv', '.webm', '.flv']:
82
- if os.path.exists(base_path + ext):
83
- file_path = base_path + ext
84
- break
85
-
86
  filename = os.path.basename(file_path)
87
- clean_filename = re.sub(r'[\\/*?:"<>|]', "", filename).replace(" ", "_")
88
- clean_path = os.path.join(temp_dir, clean_filename)
89
- os.rename(file_path, clean_path)
90
- return clean_path, clean_filename
 
 
 
91
 
92
- async def download_social_media(url, chat_id, message_id, client, platform_name):
93
  status_msg_id = None
 
 
 
 
94
  try:
95
- status_msg = await client.send_message(chat_id, f"⏳ در حال پردازش لینک {platform_name} و دانلود با بالاترین کیفیت...", reply_to_message_id=message_id)
96
  status_msg_id = getattr(status_msg, 'message_id', None)
97
  if not status_msg_id and isinstance(status_msg, dict):
98
  status_msg_id = status_msg.get('message_update', {}).get('message_id') or status_msg.get('message_id')
@@ -101,173 +107,232 @@ async def download_social_media(url, chat_id, message_id, client, platform_name)
101
  try:
102
  temp_dir = "/app/downloads"
103
  os.makedirs(temp_dir, exist_ok=True)
 
 
104
  file_path, filename = await asyncio.to_thread(sync_download_ytdlp, url, temp_dir)
105
  return file_path, filename, status_msg_id
106
  except Exception as e:
107
- error_msg = f"❌ خطا در دانلود از {platform_name}:\nاحتمالاً محتوا حذف شده یا محدودیت جغرافیایی دارد."
108
  if status_msg_id:
109
  try: await client.edit_message_text(chat_id, status_msg_id, error_msg)
110
  except: pass
111
  return None, None, status_msg_id
112
 
113
- # 2. دانلود از تلگرام (کانال‌های عمومی)
114
  async def download_from_telegram(url, chat_id, message_id, client):
115
  status_msg_id = None
116
  try:
117
- status_msg = await client.send_message(chat_id, "⏳ در حال اتصال به تلگرام...", reply_to_message_id=message_id)
118
  status_msg_id = getattr(status_msg, 'message_id', None)
 
 
119
  except: pass
120
 
121
  try:
122
  if not tg_client: raise Exception("توکن تلگرام تنظیم نشده است.")
123
  await ensure_tg_started()
 
124
  match = re.search(r"t\.me/([^/]+)/(\d+)", url)
125
- if not match: raise Exception("لینک نامعتبر.")
126
 
127
- channel, m_id = match.group(1), int(match.group(2))
128
- msg = await tg_client.get_messages(channel, m_id)
129
 
 
 
 
 
 
130
  if not msg or not msg.media: raise Exception("فایلی یافت نشد.")
131
 
132
- filename = (getattr(msg.document, 'file_name', None) or
133
- getattr(msg.video, 'file_name', None) or
134
- getattr(msg.audio, 'file_name', None) or
135
- f"photo_{uuid.uuid4().hex[:5]}.jpg")
 
 
 
136
 
137
  temp_dir = "/app/downloads"
138
  os.makedirs(temp_dir, exist_ok=True)
139
  file_path = os.path.join(temp_dir, f"{uuid.uuid4().hex[:6]}_{filename}")
140
 
141
  if status_msg_id:
142
- try: await client.edit_message_text(chat_id, status_msg_id, "📥 در حال دریافت فایل از تلگرام...")
143
  except: pass
144
-
145
  await tg_client.download_media(msg, file_name=file_path)
146
  return file_path, filename, status_msg_id
147
  except Exception as e:
148
- if status_msg_id: await client.edit_message_text(chat_id, status_msg_id, f"❌ خطا: {str(e)[:100]}")
 
 
149
  return None, None, status_msg_id
150
 
151
- # 3. دانلود فایل وب (لینک مستقیم)
152
  async def download_large_file(url, chat_id, message_id, client):
 
 
 
153
  temp_dir = "/app/downloads"
154
  os.makedirs(temp_dir, exist_ok=True)
155
- filename = os.path.basename(urllib.parse.urlparse(url).path) or f"file_{uuid.uuid4().hex[:6]}.dat"
 
 
156
  file_path = os.path.join(temp_dir, f"{uuid.uuid4().hex[:6]}_{filename}")
 
157
  status_msg_id = None
158
  try:
159
- status_msg = await client.send_message(chat_id, "⏳ در حال دانلود فایل مستقیم...", reply_to_message_id=message_id)
160
  status_msg_id = getattr(status_msg, 'message_id', None)
161
- async with aiohttp.ClientSession() as session:
 
 
 
 
162
  async with session.get(url, timeout=0) as resp:
163
  if resp.status != 200: return None, None, status_msg_id
164
  with open(file_path, 'wb') as f:
165
- async for chunk in resp.content.iter_chunked(2*1024*1024): f.write(chunk)
 
166
  return file_path, filename, status_msg_id
167
  except: return None, None, status_msg_id
168
 
169
  # ==============================================================================
170
- # 🟢 عملیات گیت‌هاب و پارت‌بندی
171
  # ==============================================================================
172
- def split_file(file_path, dest_dir, base_filename):
173
- chunk_size = 94 * 1024 * 1024
174
  part_num = 1
175
  os.makedirs(dest_dir, exist_ok=True)
176
  with open(file_path, 'rb') as f:
177
  while True:
178
  chunk = f.read(chunk_size)
179
  if not chunk: break
180
- with open(os.path.join(dest_dir, f"{base_filename}.{part_num:03d}"), 'wb') as p: p.write(chunk)
 
181
  part_num += 1
182
 
183
  async def process_and_commit_to_github(client, chat_id, message_id, url):
184
  url_l = url.lower()
185
- # تشخیص پلتفرم
186
- if any(x in url_l for x in ["youtube.com", "youtu.be"]):
187
- file_path, filename, status_msg_id = await download_social_media(url, chat_id, message_id, client, "یوتیوب")
188
- elif "instagram.com" in url_l:
189
- file_path, filename, status_msg_id = await download_social_media(url, chat_id, message_id, client, "اینستاگرام")
190
- elif any(x in url_l for x in ["tiktok.com", "twitter.com", "x.com"]):
191
- file_path, filename, status_msg_id = await download_social_media(url, chat_id, message_id, client, "شبکه‌های اجتماعی")
192
  elif "t.me/" in url_l:
193
  file_path, filename, status_msg_id = await download_from_telegram(url, chat_id, message_id, client)
194
  else:
195
  file_path, filename, status_msg_id = await download_large_file(url, chat_id, message_id, client)
196
 
197
- if not file_path or not os.path.exists(file_path): return
 
 
 
 
198
 
199
  try:
 
 
 
 
200
  async with git_lock:
201
- ts = int(time.time())
202
- branch = f"DL-{ts}-{uuid.uuid4().hex[:5]}"
203
  repo_url = f"https://oauth2:{GITHUB_TOKEN}@github.com/{GITHUB_REPO}.git"
204
  work_dir = "/app/git_workspace"
205
 
206
  if os.path.exists(work_dir): shutil.rmtree(work_dir)
207
  subprocess.run(["git", "clone", repo_url, work_dir], check=True, capture_output=True)
208
- subprocess.run(["git", "config", "user.email", "bot@ai.com"], cwd=work_dir)
209
- subprocess.run(["git", "config", "user.name", "Bot"], cwd=work_dir)
210
- subprocess.run(["git", "checkout", "--orphan", branch], cwd=work_dir, check=True)
211
  subprocess.run(["git", "rm", "-rf", "."], cwd=work_dir, capture_output=True)
212
 
213
- split_file(file_path, os.path.join(work_dir, filename), filename)
 
214
 
215
  subprocess.run(["git", "add", "."], cwd=work_dir, check=True)
216
- subprocess.run(["git", "commit", "-m", "add file"], cwd=work_dir, check=True)
217
- subprocess.run(["git", "push", "origin", branch], cwd=work_dir, check=True)
218
 
219
- link = f"https://github.com/{GITHUB_REPO}/archive/refs/heads/{branch}.zip"
220
- msg = (f"🎉 **فایل شما آماده دانلود است!**\n\n📁 نام: {filename}\n🔗 لینک دانلود (اینترنت ملی):\n{link}\n\n"
221
- f"⏳ این لینک **۲ ساعت دیگر** به طور خودکار حذف می‌شود.")
222
- await client.edit_message_text(chat_id, status_msg_id, msg)
 
 
 
 
 
 
 
 
 
223
  except Exception as e:
224
- if status_msg_id: await client.send_message(chat_id, f"❌ خطای گیت: {str(e)[:100]}")
 
 
225
  finally:
226
  if file_path and os.path.exists(file_path): os.remove(file_path)
 
227
 
228
  # ==============================================================================
229
- # 🟢 سیستم حذف خودکار
230
  # ==============================================================================
231
- async def cleanup_loop():
232
  while True:
233
  try:
234
  api_url = f"https://api.github.com/repos/{GITHUB_REPO}/git/refs/heads"
235
- headers = {"Authorization": f"token {GITHUB_TOKEN}"}
236
- async with aiohttp.ClientSession() as sess:
237
- async with sess.get(api_url, headers=headers) as r:
238
- if r.status == 200:
239
- for ref in await r.json():
240
- name = ref["ref"].split("/")[-1]
241
- if name.startswith("DL-"):
242
- try:
243
- creation_ts = int(name.split("-")[1])
244
- if int(time.time()) - creation_ts > 7200:
245
- await sess.delete(f"{api_url}/{name}", headers=headers)
246
- print(f"Deleted {name}")
247
- except: pass
 
 
 
248
  except: pass
249
  await asyncio.sleep(1800)
250
 
251
- # ==============================================================================
252
- # 🟢 شروع به کار
253
- # ==============================================================================
254
  @bot.on_update(filters.private)
255
- async def handler(client, update):
256
  global BOT_GUID
257
- if not BOT_GUID:
258
- me = await client.get_me()
259
- BOT_GUID = me.user.user_guid
260
-
261
- msg = getattr(update, "message", update)
262
- if not msg or msg.get('author_object_guid') == BOT_GUID: return
263
-
264
- text = msg.get("text", "").strip()
265
- if text.lower().startswith("http"):
266
- asyncio.create_task(process_and_commit_to_github(client, msg.get("author_object_guid"), msg.get("message_id"), text))
267
- elif text == "/start":
268
- await client.send_message(msg.get("author_object_guid"), "🚀 لینک یوتیوب، اینستاگرام، تلگرام یا لینک مستقیم بفرست تا برات آماده کنم!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  if __name__ == "__main__":
271
  threading.Thread(target=run_flask, daemon=True).start()
272
- threading.Thread(target=lambda: asyncio.run(cleanup_loop()), daemon=True).start()
 
273
  bot.run()
 
21
 
22
  @app.route('/')
23
  def home():
24
+ return "🚀 ربات هوشمند انتقال به گیت‌هاب (وب، تلگرام، یوتیوب و اینستاگرام) فعال است!"
25
 
26
  def run_flask():
27
  app.run(host="0.0.0.0", port=7860, threaded=True)
28
 
29
+ # توکن‌های خود را در بخش زیر جایگذاری کنید
30
  bot_token = os.environ.get("RUBIKA_AUTH", "توکن_روبیکا").strip()
31
  GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "توکن_گیت‌هاب").strip()
32
  TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "توکن_تلگرام").strip()
 
38
  TG_API_HASH = "eb06d4abfb49dc3eeb1aeb98ae0f581e"
39
 
40
  if bot_token == "توکن_روبیکا" or GITHUB_TOKEN == "توکن_گیت‌هاب":
41
+ print("❌ خطا: توکن‌های اصلی تنظیم نشده‌اند!")
42
  exit()
43
 
44
  bot = BotClient(bot_token)
 
46
  git_lock = asyncio.Lock()
47
 
48
  # ==============================================================================
49
+ # 🟢 تنظیمات کلاینت تلگرام (Pyrogram)
50
  # ==============================================================================
51
  tg_client = None
52
  is_tg_started = False
53
 
54
  if TG_BOT_TOKEN and TG_BOT_TOKEN != "توکن_تلگرام":
55
+ tg_client = Client(
56
+ "tg_bot_session",
57
+ api_id=TG_API_ID,
58
+ api_hash=TG_API_HASH,
59
+ bot_token=TG_BOT_TOKEN,
60
+ in_memory=True
61
+ )
62
 
63
  async def ensure_tg_started():
64
  global is_tg_started
 
67
  is_tg_started = True
68
 
69
  # ==============================================================================
70
+ # 🟢 توابع دانلود پیشرفته
71
  # ==============================================================================
72
 
73
+ # 1. تابع دانلود جهانی با yt-dlp (یوتیوب، اینستاگرام، توییتر، تیک‌تاک)
74
  def sync_download_ytdlp(url, temp_dir):
75
  ydl_opts = {
76
  'outtmpl': f'{temp_dir}/{uuid.uuid4().hex[:6]}_%(title)s.%(ext)s',
 
82
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
83
  info = ydl.extract_info(url, download=True)
84
  file_path = ydl.prepare_filename(info)
 
 
 
 
 
 
 
 
85
  filename = os.path.basename(file_path)
86
+ # پاکسازی نام فایل برای جلوگیری از خطای سیستم فایل گیت‌هاب
87
+ clean_filename = re.sub(r'[\\/*?:"<>|]', "", filename)
88
+ if clean_filename != filename:
89
+ clean_path = os.path.join(temp_dir, clean_filename)
90
+ os.rename(file_path, clean_path)
91
+ return clean_path, clean_filename
92
+ return file_path, filename
93
 
94
+ async def download_via_ytdlp(url, chat_id, message_id, client):
95
  status_msg_id = None
96
+ source_name = "شبکه‌های اجتماعی"
97
+ if "youtube" in url or "youtu.be" in url: source_name = "یوتیوب"
98
+ elif "instagram" in url: source_name = "اینستاگرام"
99
+
100
  try:
101
+ status_msg = await client.send_message(chat_id, f"⏳ در حال استخراج و دانلود از {source_name}...\n(ممکن است برای ویدیوهای حجیم کمی طول بکشد)", reply_to_message_id=message_id)
102
  status_msg_id = getattr(status_msg, 'message_id', None)
103
  if not status_msg_id and isinstance(status_msg, dict):
104
  status_msg_id = status_msg.get('message_update', {}).get('message_id') or status_msg.get('message_id')
 
107
  try:
108
  temp_dir = "/app/downloads"
109
  os.makedirs(temp_dir, exist_ok=True)
110
+
111
+ # اجرای دانلود در ترد مجزا برای جلوگیری از فریز شدن ربات روبیکا
112
  file_path, filename = await asyncio.to_thread(sync_download_ytdlp, url, temp_dir)
113
  return file_path, filename, status_msg_id
114
  except Exception as e:
115
+ error_msg = f"❌ خطا در دانلود از {source_name}:\n{str(e)[:150]}"
116
  if status_msg_id:
117
  try: await client.edit_message_text(chat_id, status_msg_id, error_msg)
118
  except: pass
119
  return None, None, status_msg_id
120
 
121
+ # 2. تابع دانلود از تلگرام
122
  async def download_from_telegram(url, chat_id, message_id, client):
123
  status_msg_id = None
124
  try:
125
+ status_msg = await client.send_message(chat_id, "⏳ در حال برقراری ارتباط با سرورهای تلگرام...", reply_to_message_id=message_id)
126
  status_msg_id = getattr(status_msg, 'message_id', None)
127
+ if not status_msg_id and isinstance(status_msg, dict):
128
+ status_msg_id = status_msg.get('message_update', {}).get('message_id') or status_msg.get('message_id')
129
  except: pass
130
 
131
  try:
132
  if not tg_client: raise Exception("توکن تلگرام تنظیم نشده است.")
133
  await ensure_tg_started()
134
+
135
  match = re.search(r"t\.me/([^/]+)/(\d+)", url)
136
+ if not match: raise Exception("لینک تلگرام نامعتبر است.")
137
 
138
+ channel_username, msg_id = match.group(1), int(match.group(2))
 
139
 
140
+ if status_msg_id:
141
+ try: await client.edit_message_text(chat_id, status_msg_id, "⏳ در حال دریافت اطلاعات فایل از تلگرام...")
142
+ except: pass
143
+
144
+ msg = await tg_client.get_messages(channel_username, msg_id)
145
  if not msg or not msg.media: raise Exception("فایلی یافت نشد.")
146
 
147
+ filename = None
148
+ if getattr(msg, 'document', None): filename = msg.document.file_name
149
+ elif getattr(msg, 'video', None): filename = msg.video.file_name
150
+ elif getattr(msg, 'audio', None): filename = msg.audio.file_name
151
+ elif getattr(msg, 'photo', None): filename = f"photo_{uuid.uuid4().hex[:6]}.jpg"
152
+
153
+ if not filename: filename = f"tg_file_{uuid.uuid4().hex[:6]}.dat"
154
 
155
  temp_dir = "/app/downloads"
156
  os.makedirs(temp_dir, exist_ok=True)
157
  file_path = os.path.join(temp_dir, f"{uuid.uuid4().hex[:6]}_{filename}")
158
 
159
  if status_msg_id:
160
+ try: await client.edit_message_text(chat_id, status_msg_id, "📥 در حال انتقال فایل از تلگرام به سرور...")
161
  except: pass
162
+
163
  await tg_client.download_media(msg, file_name=file_path)
164
  return file_path, filename, status_msg_id
165
  except Exception as e:
166
+ if status_msg_id:
167
+ try: await client.edit_message_text(chat_id, status_msg_id, f"❌ خطای تلگرام: {str(e)[:100]}")
168
+ except: pass
169
  return None, None, status_msg_id
170
 
171
+ # 3. تابع دانلود وب (لینک مستقیم)
172
  async def download_large_file(url, chat_id, message_id, client):
173
+ if "dropbox.com" in url:
174
+ url = url.replace("dl=0", "dl=1") if "dl=0" in url else (url + ("&dl=1" if "?" in url else "?dl=1"))
175
+
176
  temp_dir = "/app/downloads"
177
  os.makedirs(temp_dir, exist_ok=True)
178
+ parsed_url = urllib.parse.urlparse(url)
179
+ filename = os.path.basename(parsed_url.path)
180
+ if not filename or '.' not in filename: filename = f"file_{uuid.uuid4().hex[:8]}.dat"
181
  file_path = os.path.join(temp_dir, f"{uuid.uuid4().hex[:6]}_{filename}")
182
+
183
  status_msg_id = None
184
  try:
185
+ status_msg = await client.send_message(chat_id, "⏳ در حال دانلود لینک مستقیم در سرور...", reply_to_message_id=message_id)
186
  status_msg_id = getattr(status_msg, 'message_id', None)
187
+ except: pass
188
+
189
+ try:
190
+ headers = {"User-Agent": "Mozilla/5.0"}
191
+ async with aiohttp.ClientSession(headers=headers) as session:
192
  async with session.get(url, timeout=0) as resp:
193
  if resp.status != 200: return None, None, status_msg_id
194
  with open(file_path, 'wb') as f:
195
+ async for chunk in resp.content.iter_chunked(2 * 1024 * 1024):
196
+ if chunk: f.write(chunk)
197
  return file_path, filename, status_msg_id
198
  except: return None, None, status_msg_id
199
 
200
  # ==============================================================================
201
+ # 🟢 توابع گیت‌هاب و پردازش نهایی
202
  # ==============================================================================
203
+ def split_file_for_winrar(file_path, dest_dir, base_filename):
204
+ chunk_size = 95 * 1024 * 1024
205
  part_num = 1
206
  os.makedirs(dest_dir, exist_ok=True)
207
  with open(file_path, 'rb') as f:
208
  while True:
209
  chunk = f.read(chunk_size)
210
  if not chunk: break
211
+ part_path = os.path.join(dest_dir, f"{base_filename}.{part_num:03d}")
212
+ with open(part_path, 'wb') as p: p.write(chunk)
213
  part_num += 1
214
 
215
  async def process_and_commit_to_github(client, chat_id, message_id, url):
216
  url_l = url.lower()
217
+
218
+ # تشخیص هوشمند منبع لینک
219
+ if any(x in url_l for x in ["youtube.com", "youtu.be", "instagram.com", "twitter.com", "x.com", "tiktok.com"]):
220
+ file_path, filename, status_msg_id = await download_via_ytdlp(url, chat_id, message_id, client)
 
 
 
221
  elif "t.me/" in url_l:
222
  file_path, filename, status_msg_id = await download_from_telegram(url, chat_id, message_id, client)
223
  else:
224
  file_path, filename, status_msg_id = await download_large_file(url, chat_id, message_id, client)
225
 
226
+ if not file_path or not os.path.exists(file_path):
227
+ if status_msg_id:
228
+ try: await client.edit_message_text(chat_id, status_msg_id, "❌ پردازش لینک با خطا مواجه شد.")
229
+ except: pass
230
+ return
231
 
232
  try:
233
+ if status_msg_id:
234
+ try: await client.edit_message_text(chat_id, status_msg_id, "✅ فایل با موفقیت دریافت شد.\n✂️ در حال پارت‌بندی و انتقال به گیت‌هاب...")
235
+ except: pass
236
+
237
  async with git_lock:
238
+ current_timestamp = int(time.time())
239
+ branch_name = f"DL-{current_timestamp}-{uuid.uuid4().hex[:4]}"
240
  repo_url = f"https://oauth2:{GITHUB_TOKEN}@github.com/{GITHUB_REPO}.git"
241
  work_dir = "/app/git_workspace"
242
 
243
  if os.path.exists(work_dir): shutil.rmtree(work_dir)
244
  subprocess.run(["git", "clone", repo_url, work_dir], check=True, capture_output=True)
245
+ subprocess.run(["git", "config", "user.email", "bot@alpha.io"], cwd=work_dir)
246
+ subprocess.run(["git", "config", "user.name", "AI Alpha Bot"], cwd=work_dir)
247
+ subprocess.run(["git", "checkout", "--orphan", branch_name], cwd=work_dir, check=True)
248
  subprocess.run(["git", "rm", "-rf", "."], cwd=work_dir, capture_output=True)
249
 
250
+ file_folder = os.path.join(work_dir, filename)
251
+ split_file_for_winrar(file_path, file_folder, filename)
252
 
253
  subprocess.run(["git", "add", "."], cwd=work_dir, check=True)
254
+ subprocess.run(["git", "commit", "-m", f"Upload: {filename}"], cwd=work_dir, check=True)
255
+ subprocess.run(["git", "push", "origin", branch_name], cwd=work_dir, check=True)
256
 
257
+ zip_link = f"https://github.com/{GITHUB_REPO}/archive/refs/heads/{branch_name}.zip"
258
+
259
+ success_text = (
260
+ f"🎉 فایل شما آماده دانلود است!\n\n"
261
+ f"📁 **نام:** {filename}\n"
262
+ f"🔗 **لینک دانلود مستقیم (اینترنت ملی):**\n{zip_link}\n\n"
263
+ f"⏳ **مهلت دانلود:** این لینک دقیقاً ۲ ساعت دیگر برای همیشه حذف می‌شود."
264
+ )
265
+ if status_msg_id:
266
+ try: await client.edit_message_text(chat_id, status_msg_id, success_text)
267
+ except: await client.send_message(chat_id, success_text)
268
+ else: await client.send_message(chat_id, success_text)
269
+
270
  except Exception as e:
271
+ if status_msg_id:
272
+ try: await client.edit_message_text(chat_id, status_msg_id, f"❌ خطای گیت‌هاب:\n{str(e)[:150]}")
273
+ except: pass
274
  finally:
275
  if file_path and os.path.exists(file_path): os.remove(file_path)
276
+ if os.path.exists("/app/git_workspace"): shutil.rmtree("/app/git_workspace")
277
 
278
  # ==============================================================================
279
+ # 🟢 پاکسازی و اجرا
280
  # ==============================================================================
281
+ async def cleanup_expired_branches():
282
  while True:
283
  try:
284
  api_url = f"https://api.github.com/repos/{GITHUB_REPO}/git/refs/heads"
285
+ headers = {"Authorization": f"token {GITHUB_TOKEN}", "Accept": "application/vnd.github.v3+json"}
286
+ async with aiohttp.ClientSession() as session:
287
+ async with session.get(api_url, headers=headers) as resp:
288
+ if resp.status == 200:
289
+ refs = await resp.json()
290
+ current_time = int(time.time())
291
+ for ref in refs:
292
+ ref_name = ref.get("ref", "")
293
+ if "refs/heads/DL-" in ref_name:
294
+ branch_name = ref_name.split("/")[-1]
295
+ parts = branch_name.split("-")
296
+ if len(parts) >= 2 and parts[1].isdigit():
297
+ if current_time - int(parts[1]) > 7200:
298
+ del_url = f"https://api.github.com/repos/{GITHUB_REPO}/git/refs/heads/{branch_name}"
299
+ await session.delete(del_url, headers=headers)
300
+ print(f"🗑 Deleted expired branch: {branch_name}")
301
  except: pass
302
  await asyncio.sleep(1800)
303
 
 
 
 
304
  @bot.on_update(filters.private)
305
+ async def main_handler(client, update):
306
  global BOT_GUID
307
+ try:
308
+ if not BOT_GUID:
309
+ me = await client.get_me()
310
+ if me and hasattr(me, 'user'): BOT_GUID = getattr(me.user, 'user_guid', None)
311
+
312
+ msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
313
+ author_id = getattr(update, 'author_guid', None)
314
+ if not author_id and msg_obj: author_id = msg_obj.get('author_object_guid') if isinstance(msg_obj, dict) else getattr(msg_obj, 'author_object_guid', None)
315
+ if BOT_GUID and author_id == BOT_GUID: return
316
+
317
+ chat_id = getattr(update, 'object_guid', None) or getattr(update, 'author_guid', None) or getattr(update, "chat_id", None)
318
+ if not chat_id: return
319
+ msg_id = getattr(update, "message_id", None)
320
+
321
+ user_text = getattr(update, "text", "") or getattr(msg_obj, "text", "")
322
+ user_text_str = str(user_text).strip()
323
+ if not user_text_str: return
324
+
325
+ if user_text_str.lower() in ["/start", "سلام"]:
326
+ await client.send_message(chat_id, "👋 سلام! لینک مورد نظرت رو بفرست:\n\n🎥 **یوتیوب / اینستاگرام / تیک‌تاک**\n✈️ **تلگرام (کانال عمومی)**\n🌐 **لینک مستقیم وب**\n\nفایل‌ها پارت‌بندی شده و روی گیت‌هاب (اینترنت ملی) آپلود میشن و ۲ ساعت بعد خودکار حذف میشن.")
327
+ return
328
+
329
+ if user_text_str.lower().startswith("http"):
330
+ asyncio.create_task(process_and_commit_to_github(client, chat_id, msg_id, user_text_str))
331
+
332
+ except Exception: traceback.print_exc()
333
 
334
  if __name__ == "__main__":
335
  threading.Thread(target=run_flask, daemon=True).start()
336
+ threading.Thread(target=lambda: asyncio.run(cleanup_expired_branches()), daemon=True).start()
337
+ print("🚀 ربات با پشتیبانی کامل از یوتیوب و اینستاگرام روشن شد...")
338
  bot.run()