Opera8 commited on
Commit
804d1b4
·
verified ·
1 Parent(s): d5ea59e

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +117 -70
main.py CHANGED
@@ -11,13 +11,13 @@ from flask import Flask
11
  from rubpy.bot import BotClient, filters
12
 
13
  # ==============================================================================
14
- # 🟢 تنظیمات
15
  # ==============================================================================
16
  app = Flask(__name__)
17
 
18
  @app.route('/')
19
  def home():
20
- return "🚀 ربات کلاستر گیت‌هاب (هماهنگ با گوشی) فعال است!"
21
 
22
  def run_flask():
23
  app.run(host="0.0.0.0", port=7860, threaded=True)
@@ -26,18 +26,18 @@ bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
26
  GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "").strip()
27
  GITHUB_REPO = "Hamed744/internet-melli"
28
 
 
 
 
 
29
  bot = BotClient(bot_token)
30
- git_lock = asyncio.Lock()
31
 
32
- # ==============================================================================
33
- # 🟢 تابع کمکی محاسبه حجم
34
- # ==============================================================================
35
- def get_size_format(file_path):
36
- size_bytes = os.path.getsize(file_path)
37
- return f"{size_bytes / (1024 * 1024):.2f} MB"
38
 
39
  # ==============================================================================
40
- # 🟢 دانلود فایل
41
  # ==============================================================================
42
  async def download_large_file(url, chat_id, message_id, client):
43
  if "dropbox.com" in url:
@@ -50,114 +50,161 @@ async def download_large_file(url, chat_id, message_id, client):
50
  parsed_url = urllib.parse.urlparse(url)
51
  filename = os.path.basename(parsed_url.path)
52
  if not filename or '.' not in filename: filename = f"file_{uuid.uuid4().hex[:8]}.dat"
 
53
  file_path = os.path.join(temp_dir, f"{uuid.uuid4().hex[:6]}_{filename}")
54
-
55
  status_msg_id = None
 
56
  try:
57
- status_msg = await client.send_message(chat_id, "⏳ شروع دانلود از اینترنت آزاد...", reply_to_message_id=message_id)
58
- status_msg_id = getattr(status_msg, 'message_id', None) or status_msg.get('message_id')
59
- except: pass
 
 
60
 
61
  try:
62
- headers = {"User-Agent": "Mozilla/5.0"}
63
  async with aiohttp.ClientSession(headers=headers) as session:
64
  async with session.get(url, timeout=0) as response:
65
- if response.status != 200: return None, None, status_msg_id
 
66
  with open(file_path, 'wb') as f:
67
- async for chunk in response.content.iter_chunked(1024 * 1024):
68
  if chunk: f.write(chunk)
69
  return file_path, filename, status_msg_id
70
- except: return None, None, status_msg_id
71
 
72
  # ==============================================================================
73
- # 🟢 خرد کردن استاندارد فایل برای اپلیکیشن‌های گوشی (با 7z)
74
  # ==============================================================================
75
- def split_file_with_7z(file_path, dest_dir, base_filename):
76
- os.makedirs(dest_dir, exist_ok=True)
77
- archive_path = os.path.join(dest_dir, f"{base_filename}.7z")
78
- source_dir = os.path.dirname(file_path)
79
- source_file = os.path.basename(file_path)
80
 
81
- # -v95m: حجم هر پارت ۹۵ مگابایت
82
- # -mx=0: سطح فشرده‌سازی صفر (فقط خرد می‌کند تا سرعت سرور پایین نیاید)
83
- cmd = ['7z', 'a', '-v95m', '-mx=0', archive_path, source_file]
84
 
85
- # اجرا در پوشه سورس تا مسیرهای تو در تو داخل فایل زیپ ایجاد نشود
86
- subprocess.run(cmd, cwd=source_dir, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  # ==============================================================================
89
- # 🟢 عملیات اصلی گیت‌هاب
90
  # ==============================================================================
91
- async def process_and_commit(client, chat_id, message_id, url):
92
  file_path, filename, status_msg_id = await download_large_file(url, chat_id, message_id, client)
93
 
94
  if not file_path or not os.path.exists(file_path):
95
- if status_msg_id: await client.edit_message_text(chat_id, status_msg_id, "❌ خطای دانلود.")
 
 
96
  return
97
 
98
- file_size_str = get_size_format(file_path)
99
-
100
  try:
101
  if status_msg_id:
102
- await client.edit_message_text(chat_id, status_msg_id, f"✅ دانلود شد ({file_size_str})\n✂️ در حال ساخت پارت‌های استاندارد گوشی و Push به گیت‌هاب...")
 
103
 
 
104
  async with git_lock:
105
  tag_name = f"DL-{uuid.uuid4().hex[:6]}"
106
  repo_url = f"https://oauth2:{GITHUB_TOKEN}@github.com/{GITHUB_REPO}.git"
107
  work_dir = "/app/git_workspace"
108
 
109
- if os.path.exists(work_dir): shutil.rmtree(work_dir)
 
 
 
 
 
110
 
111
- # کلون کردن
112
- subprocess.run(["git", "clone", "--depth", "1", repo_url, work_dir], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
113
- subprocess.run(["git", "config", "user.email", "bot@alpha.com"], cwd=work_dir)
114
- subprocess.run(["git", "config", "user.name", "Bot"], cwd=work_dir)
115
 
116
- # خرد کردن استاندارد
117
- target_folder = os.path.join(work_dir, tag_name)
118
- split_file_with_7z(file_path, target_folder, filename)
119
 
120
- # ارسال به گیت‌هاب
121
  subprocess.run(["git", "add", "."], cwd=work_dir, check=True)
122
- subprocess.run(["git", "commit", "-m", f"Upload {filename} ({file_size_str})"], cwd=work_dir, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
 
123
  subprocess.run(["git", "tag", tag_name], cwd=work_dir, check=True)
124
- subprocess.run(["git", "push", "origin", "main", "--tags"], cwd=work_dir, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
125
 
126
- link = f"https://github.com/{GITHUB_REPO}/archive/refs/tags/{tag_name}.zip"
 
127
 
128
- final_text = (
129
- f"🎉 انتقال با موفقیت انجام شد!\n\n"
130
- f"📦 نام فایل: {filename}\n"
131
- f"📊 حجم کل: {file_size_str}\n"
132
- f"🔗 لینک دانلود (اینترنت ملی):\n{link}\n\n"
133
- f"📱 راهنمای استخراج در گوشی:\n"
134
- f"۱. فایل Zip را دانلود و استخراج کنید.\n"
135
- f"۲. وارد پوشه شوید و روی پارت اول (`001.`) با برنامه RAR یا ZArchiver ضربه بزنید تا به صورت خودکار فایل کامل را به شما بدهد."
136
  )
137
- if status_msg_id: await client.edit_message_text(chat_id, status_msg_id, final_text)
 
 
 
 
 
138
 
139
  except Exception as e:
140
- err = str(e)[:150]
141
- if status_msg_id: await client.edit_message_text(chat_id, status_msg_id, f"❌ خطای عملیات:\n{err}")
 
 
142
  finally:
143
- if os.path.exists(file_path): os.remove(file_path)
144
- if os.path.exists("/app/git_workspace"): shutil.rmtree("/app/git_workspace")
 
 
 
145
 
146
  # ==============================================================================
147
- # 🟢 اجرا
148
  # ==============================================================================
149
  @bot.on_update(filters.private)
150
  async def main_handler(client, update):
151
- msg = getattr(update, "message", None) or getattr(update, "new_message", None)
152
- if not msg: return
153
-
154
- text = str(msg.get("text", "")).strip()
155
- chat_id = msg.get("author_object_guid")
156
- msg_id = msg.get("message_id")
157
-
158
- if text.lower().startswith("http"):
159
- asyncio.create_task(process_and_commit(client, chat_id, msg_id, text))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  if __name__ == "__main__":
162
  threading.Thread(target=run_flask, daemon=True).start()
 
163
  bot.run()
 
11
  from rubpy.bot import BotClient, filters
12
 
13
  # ==============================================================================
14
+ # 🟢 تنظیمات و متغیرهای محیطی
15
  # ==============================================================================
16
  app = Flask(__name__)
17
 
18
  @app.route('/')
19
  def home():
20
+ return "🚀 ربات انتقال پارت‌بندی شده به گیت‌هاب (اینترنت ملی) روشن است!"
21
 
22
  def run_flask():
23
  app.run(host="0.0.0.0", port=7860, threaded=True)
 
26
  GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "").strip()
27
  GITHUB_REPO = "Hamed744/internet-melli"
28
 
29
+ if not bot_token or not GITHUB_TOKEN:
30
+ print("❌ توکن روبیکا یا گیت‌هاب وارد نشده است!")
31
+ exit()
32
+
33
  bot = BotClient(bot_token)
34
+ BOT_GUID = None
35
 
36
+ # قفل برای جلوگیری از تداخل کامیت‌های همزمان گیت
37
+ git_lock = asyncio.Lock()
 
 
 
 
38
 
39
  # ==============================================================================
40
+ # 🟢 تابع دانلود (تغییری نکرده است)
41
  # ==============================================================================
42
  async def download_large_file(url, chat_id, message_id, client):
43
  if "dropbox.com" in url:
 
50
  parsed_url = urllib.parse.urlparse(url)
51
  filename = os.path.basename(parsed_url.path)
52
  if not filename or '.' not in filename: filename = f"file_{uuid.uuid4().hex[:8]}.dat"
53
+
54
  file_path = os.path.join(temp_dir, f"{uuid.uuid4().hex[:6]}_{filename}")
 
55
  status_msg_id = None
56
+
57
  try:
58
+ status_msg = await client.send_message(chat_id, "⏳ در حال دانلود فایل در سرور واسط...", reply_to_message_id=message_id)
59
+ status_msg_id = getattr(status_msg, 'message_id', None)
60
+ if not status_msg_id and isinstance(status_msg, dict):
61
+ status_msg_id = status_msg.get('message_update', {}).get('message_id') or status_msg.get('message_id')
62
+ except Exception: pass
63
 
64
  try:
65
+ headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
66
  async with aiohttp.ClientSession(headers=headers) as session:
67
  async with session.get(url, timeout=0) as response:
68
+ if response.status != 200:
69
+ return None, None, status_msg_id
70
  with open(file_path, 'wb') as f:
71
+ async for chunk in response.content.iter_chunked(2 * 1024 * 1024):
72
  if chunk: f.write(chunk)
73
  return file_path, filename, status_msg_id
74
+ except Exception: return None, None, status_msg_id
75
 
76
  # ==============================================================================
77
+ # 🟢 تابع خرد کردن فایل برای WinRAR (.001, .002, ...)
78
  # ==============================================================================
79
+ def split_file_for_winrar(file_path, dest_dir, base_filename):
80
+ chunk_size = 95 * 1024 * 1024 # محدودیت 95 مگابایتی برای گیت‌هاب
81
+ part_num = 1
 
 
82
 
83
+ os.makedirs(dest_dir, exist_ok=True)
 
 
84
 
85
+ with open(file_path, 'rb') as f:
86
+ while True:
87
+ chunk = f.read(chunk_size)
88
+ if not chunk: break
89
+
90
+ # تولید نام پارت به سبک WinRAR (مثال: video.mp4.001)
91
+ part_name = f"{base_filename}.{part_num:03d}"
92
+ part_path = os.path.join(dest_dir, part_name)
93
+
94
+ with open(part_path, 'wb') as p:
95
+ p.write(chunk)
96
+
97
+ part_num += 1
98
 
99
  # ==============================================================================
100
+ # 🟢 پردازش و کامیت مستقیم در گیت‌هاب
101
  # ==============================================================================
102
+ async def process_and_commit_to_github(client, chat_id, message_id, url):
103
  file_path, filename, status_msg_id = await download_large_file(url, chat_id, message_id, client)
104
 
105
  if not file_path or not os.path.exists(file_path):
106
+ if status_msg_id:
107
+ try: await client.edit_message_text(chat_id, status_msg_id, "❌ خطا در دانلود فایل اصلی.")
108
+ except: pass
109
  return
110
 
 
 
111
  try:
112
  if status_msg_id:
113
+ try: await client.edit_message_text(chat_id, status_msg_id, "✅ دانلود تکمیل شد.\n✂️ در حال پارت‌بندی و انتقال به مخزن گیت‌هاب (این مرحله زمان‌بر است)...")
114
+ except: pass
115
 
116
+ # استفاده از قفل تا عملیات گیت برای لینک‌های مختلف تداخل پیدا نکند
117
  async with git_lock:
118
  tag_name = f"DL-{uuid.uuid4().hex[:6]}"
119
  repo_url = f"https://oauth2:{GITHUB_TOKEN}@github.com/{GITHUB_REPO}.git"
120
  work_dir = "/app/git_workspace"
121
 
122
+ # ۱. پاکسازی محیط کاری قبلی
123
+ if os.path.exists(work_dir):
124
+ shutil.rmtree(work_dir)
125
+
126
+ # ۲. کلون کردن مخزن
127
+ subprocess.run(["git", "clone", repo_url, work_dir], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
128
 
129
+ # تنظیمات اولیه کاربر گیت برای کامیت
130
+ subprocess.run(["git", "config", "user.email", "bot@aialpha.local"], cwd=work_dir)
131
+ subprocess.run(["git", "config", "user.name", "AI Alpha Bot"], cwd=work_dir)
 
132
 
133
+ # ۳. ساخت یک پوشه مخصوص این فایل در مخزن و خرد کردن فایل داخل آن
134
+ file_folder = os.path.join(work_dir, tag_name)
135
+ split_file_for_winrar(file_path, file_folder, filename)
136
 
137
+ # ۴. کامیت کردن و پوش کردن فایل‌ها
138
  subprocess.run(["git", "add", "."], cwd=work_dir, check=True)
139
+ subprocess.run(["git", "commit", "-m", f"Add parts for {filename}"], cwd=work_dir, check=True)
140
+
141
+ # ۵. ساخت تگ و پوش کردن آن به سرور گیت‌هاب
142
  subprocess.run(["git", "tag", tag_name], cwd=work_dir, check=True)
143
+ subprocess.run(["git", "push", "origin", "main"], cwd=work_dir, check=True)
144
+ subprocess.run(["git", "push", "origin", tag_name], cwd=work_dir, check=True)
145
 
146
+ # ۶. آماده‌سازی لینک نهایی اینترنت ملی
147
+ zip_download_link = f"https://github.com/{GITHUB_REPO}/archive/refs/tags/{tag_name}.zip"
148
 
149
+ success_text = (
150
+ f"🎉 فایل با موفقیت در گیت‌هاب ذخیره شد!\n\n"
151
+ f"📁 نام: {filename}\n"
152
+ f"🔗 لینک دانلود مستقیم (با اینترنت ملی):\n{zip_download_link}\n\n"
153
+ f"💡 راهنما: فایل Zip بالا را دانلود کنید. داخل آن پارت‌هایی با پسوند 001 و 002 وجود دارد. روی پارت 001 کلیک راست کرده و با WinRAR گزینه Extract را بزنید تا فایل اصلی به صورت کامل استخراج شود."
 
 
 
154
  )
155
+
156
+ if status_msg_id:
157
+ try: await client.edit_message_text(chat_id, status_msg_id, success_text)
158
+ except: await client.send_message(chat_id, success_text)
159
+ else:
160
+ await client.send_message(chat_id, success_text)
161
 
162
  except Exception as e:
163
+ error_txt = f"❌ خطای گیت‌هاب:\n{str(e)[:150]}"
164
+ if status_msg_id:
165
+ try: await client.edit_message_text(chat_id, status_msg_id, error_txt)
166
+ except: await client.send_message(chat_id, error_txt)
167
  finally:
168
+ try: os.remove(file_path)
169
+ except: pass
170
+ if os.path.exists("/app/git_workspace"):
171
+ try: shutil.rmtree("/app/git_workspace")
172
+ except: pass
173
 
174
  # ==============================================================================
175
+ # 🟢 هندلر روبیکا
176
  # ==============================================================================
177
  @bot.on_update(filters.private)
178
  async def main_handler(client, update):
179
+ global BOT_GUID
180
+ try:
181
+ if not BOT_GUID:
182
+ me = await client.get_me()
183
+ if me and hasattr(me, 'user'): BOT_GUID = getattr(me.user, 'user_guid', None)
184
+
185
+ msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
186
+ author_id = getattr(update, 'author_guid', None)
187
+ 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)
188
+ if BOT_GUID and author_id == BOT_GUID: return
189
+
190
+ chat_id = getattr(update, 'object_guid', None) or getattr(update, 'author_guid', None) or getattr(update, "chat_id", None)
191
+ if not chat_id: return
192
+ msg_id = getattr(update, "message_id", None)
193
+
194
+ user_text = getattr(update, "text", "") or getattr(msg_obj, "text", "")
195
+ user_text_str = str(user_text).strip()
196
+ if not user_text_str: return
197
+
198
+ if user_text_str.lower() in ["/start", "سلام"]:
199
+ await client.send_message(chat_id, "👋 سلام! لینک مستقیم هر فایلی رو بفرست تا برات خرد کنم و بفرستم روی گیت‌هاب (قابل دانلود با اینترنت ملی).")
200
+ return
201
+
202
+ if user_text_str.lower().startswith("http"):
203
+ asyncio.create_task(process_and_commit_to_github(client, chat_id, msg_id, user_text_str))
204
+
205
+ except Exception: traceback.print_exc()
206
 
207
  if __name__ == "__main__":
208
  threading.Thread(target=run_flask, daemon=True).start()
209
+ print("🚀 ربات کلاستر گیت‌هاب روشن شد...")
210
  bot.run()