Spaces:
Sleeping
Sleeping
Update main.py
Browse files
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 |
-
|
| 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, "⏳
|
| 58 |
-
status_msg_id = getattr(status_msg, 'message_id', None)
|
| 59 |
-
|
|
|
|
|
|
|
| 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:
|
|
|
|
| 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 |
-
# 🟢 خرد کردن
|
| 74 |
# ==============================================================================
|
| 75 |
-
def
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
source_dir = os.path.dirname(file_path)
|
| 79 |
-
source_file = os.path.basename(file_path)
|
| 80 |
|
| 81 |
-
|
| 82 |
-
# -mx=0: سطح فشردهسازی صفر (فقط خرد میکند تا سرعت سرور پایین نیاید)
|
| 83 |
-
cmd = ['7z', 'a', '-v95m', '-mx=0', archive_path, source_file]
|
| 84 |
|
| 85 |
-
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
# ==============================================================================
|
| 89 |
-
# 🟢
|
| 90 |
# ==============================================================================
|
| 91 |
-
async def
|
| 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:
|
|
|
|
|
|
|
| 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,
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
-
#
|
| 112 |
-
subprocess.run(["git", "
|
| 113 |
-
subprocess.run(["git", "config", "user.
|
| 114 |
-
subprocess.run(["git", "config", "user.name", "Bot"], cwd=work_dir)
|
| 115 |
|
| 116 |
-
# خرد کردن ا
|
| 117 |
-
|
| 118 |
-
|
| 119 |
|
| 120 |
-
# ار
|
| 121 |
subprocess.run(["git", "add", "."], cwd=work_dir, check=True)
|
| 122 |
-
subprocess.run(["git", "commit", "-m", f"
|
|
|
|
|
|
|
| 123 |
subprocess.run(["git", "tag", tag_name], cwd=work_dir, check=True)
|
| 124 |
-
subprocess.run(["git", "push", "origin", "main"
|
|
|
|
| 125 |
|
| 126 |
-
|
|
|
|
| 127 |
|
| 128 |
-
|
| 129 |
-
f"🎉 ا
|
| 130 |
-
f"
|
| 131 |
-
f"
|
| 132 |
-
f"
|
| 133 |
-
f"📱 راهنمای استخراج در گوشی:\n"
|
| 134 |
-
f"۱. فایل Zip را دانلود و استخراج کنید.\n"
|
| 135 |
-
f"۲. وارد پوشه شوید و روی پارت اول (`001.`) با برنامه RAR یا ZArchiver ضربه بزنید تا به صورت خودکار فایل کامل را به شما بدهد."
|
| 136 |
)
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
except Exception as e:
|
| 140 |
-
|
| 141 |
-
if status_msg_id:
|
|
|
|
|
|
|
| 142 |
finally:
|
| 143 |
-
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
# ==============================================================================
|
| 147 |
-
# 🟢
|
| 148 |
# ==============================================================================
|
| 149 |
@bot.on_update(filters.private)
|
| 150 |
async def main_handler(client, update):
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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()
|