Update bot.py
Browse files
bot.py
CHANGED
|
@@ -5,13 +5,13 @@ import aiosqlite
|
|
| 5 |
import time
|
| 6 |
import shutil
|
| 7 |
import urllib.request
|
| 8 |
-
import random
|
| 9 |
from threading import Thread
|
| 10 |
from http.server import BaseHTTPRequestHandler, HTTPServer
|
| 11 |
from pyrogram import Client, filters, idle
|
| 12 |
from pyrogram.errors import FloodWait
|
| 13 |
from pyrogram.types import InputMediaPhoto, InputMediaVideo, InputMediaDocument, InputMediaAudio
|
| 14 |
-
from pyrogram.enums import ChatAction
|
| 15 |
|
| 16 |
# --- 1. الإعدادات الأساسية ---
|
| 17 |
DATA_DIR = "./data"
|
|
@@ -21,7 +21,7 @@ os.makedirs(DOWNLOAD_DIR, exist_ok=True)
|
|
| 21 |
|
| 22 |
HEALTHCHECK_URL = os.environ.get("HEALTHCHECK_URL", "")
|
| 23 |
MAX_FILE_SIZE = 2000 * 1024 * 1024 # 2GB
|
| 24 |
-
BASE_UPLOAD_DELAY =
|
| 25 |
|
| 26 |
download_queue = asyncio.Queue()
|
| 27 |
|
|
@@ -30,12 +30,12 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|
| 30 |
def do_GET(self):
|
| 31 |
self.send_response(200)
|
| 32 |
self.end_headers()
|
| 33 |
-
self.wfile.write(b"
|
| 34 |
def log_message(self, format, *args): pass
|
| 35 |
|
| 36 |
Thread(target=lambda: HTTPServer(('0.0.0.0', 7860), RequestHandler).serve_forever(), daemon=True).start()
|
| 37 |
|
| 38 |
-
# --- 3. إعدادات الحساب (تمويه
|
| 39 |
API_ID = int(os.environ.get("API_ID", 0))
|
| 40 |
API_HASH = os.environ.get("API_HASH", "")
|
| 41 |
SESSION_STRING = os.environ.get("SESSION_STRING", "")
|
|
@@ -47,10 +47,11 @@ app = Client(
|
|
| 47 |
api_hash=API_HASH,
|
| 48 |
session_string=SESSION_STRING,
|
| 49 |
in_memory=True,
|
| 50 |
-
device_model="Samsung Galaxy S23 Ultra",
|
| 51 |
-
system_version="Android 14.0",
|
| 52 |
-
app_version="10.14.1",
|
| 53 |
-
lang_code="ar"
|
|
|
|
| 54 |
)
|
| 55 |
|
| 56 |
# --- 4. أدوات النظام وقاعدة البيانات ---
|
|
@@ -128,7 +129,7 @@ async def download_worker_task(worker_id):
|
|
| 128 |
(message.chat.id, message.id, unique_id, group_id, m_type, final_caption, file_path, file_size, time.time())
|
| 129 |
)
|
| 130 |
await db.commit()
|
| 131 |
-
print(f"⚡ [Worker-{worker_id}] تم تنزيل رسالة: {message.id}")
|
| 132 |
break
|
| 133 |
else:
|
| 134 |
if file_path and os.path.exists(file_path): os.remove(file_path)
|
|
@@ -158,28 +159,28 @@ async def status_command(client, message):
|
|
| 158 |
free_mb = round(free / (1024 * 1024), 2)
|
| 159 |
|
| 160 |
report = (
|
| 161 |
-
f"👑 **حالة رادار الأرشفة:**\n\n"
|
| 162 |
-
f"📥 جاهز للرفع
|
| 163 |
-
f"📤 تم رفعه: `{uploaded}`\n"
|
| 164 |
-
f"🔄 قيد التنزيل
|
| 165 |
f"💾 المساحة المتاحة: `{free_mb} MB`"
|
| 166 |
)
|
| 167 |
await message.reply_text(report)
|
| 168 |
|
| 169 |
-
# --- 8. محرك الرفع الذكي
|
| 170 |
async def upload_worker():
|
| 171 |
global BASE_UPLOAD_DELAY
|
| 172 |
while True:
|
| 173 |
try:
|
| 174 |
async with aiosqlite.connect(DB_PATH) as db:
|
| 175 |
-
async with db.execute("SELECT id, chat_id, msg_id, media_group_id, media_type, caption, file_path, timestamp FROM queue WHERE status='DOWNLOADED' ORDER BY id ASC LIMIT 1") as cursor:
|
| 176 |
row = await cursor.fetchone()
|
| 177 |
|
| 178 |
if not row:
|
| 179 |
await asyncio.sleep(2)
|
| 180 |
continue
|
| 181 |
|
| 182 |
-
q_id, chat_id, msg_id, group_id, m_type, caption, file_path, ts = row
|
| 183 |
|
| 184 |
if not os.path.exists(file_path):
|
| 185 |
async with aiosqlite.connect(DB_PATH) as db:
|
|
@@ -187,18 +188,18 @@ async def upload_worker():
|
|
| 187 |
await db.commit()
|
| 188 |
continue
|
| 189 |
|
| 190 |
-
#
|
| 191 |
try:
|
| 192 |
if m_type == "photo": await app.send_chat_action(TARGET_CHAT, ChatAction.UPLOAD_PHOTO)
|
| 193 |
-
elif m_type
|
| 194 |
elif m_type == "doc": await app.send_chat_action(TARGET_CHAT, ChatAction.UPLOAD_DOCUMENT)
|
| 195 |
-
elif m_type
|
| 196 |
-
await asyncio.sleep(random.uniform(
|
| 197 |
-
except: pass
|
| 198 |
|
| 199 |
if group_id:
|
| 200 |
time_passed = time.time() - ts
|
| 201 |
-
if time_passed <
|
| 202 |
|
| 203 |
async with aiosqlite.connect(DB_PATH) as db:
|
| 204 |
async with db.execute(
|
|
@@ -235,11 +236,10 @@ async def upload_worker():
|
|
| 235 |
if os.path.exists(f_path): os.remove(f_path)
|
| 236 |
|
| 237 |
gc.collect()
|
| 238 |
-
|
| 239 |
-
human_delay = BASE_UPLOAD_DELAY + random.uniform(1.0, 3.5)
|
| 240 |
-
await asyncio.sleep(human_delay)
|
| 241 |
continue
|
| 242 |
|
|
|
|
| 243 |
if m_type == "photo": await app.send_photo(TARGET_CHAT, photo=file_path, caption=caption)
|
| 244 |
elif m_type == "video": await app.send_video(TARGET_CHAT, video=file_path, caption=caption, supports_streaming=True)
|
| 245 |
elif m_type == "doc": await app.send_document(TARGET_CHAT, document=file_path, caption=caption)
|
|
@@ -254,24 +254,24 @@ async def upload_worker():
|
|
| 254 |
|
| 255 |
if os.path.exists(file_path): os.remove(file_path)
|
| 256 |
|
| 257 |
-
|
| 258 |
-
|
|
|
|
| 259 |
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
await asyncio.sleep(human_delay)
|
| 263 |
|
| 264 |
except FloodWait as e:
|
| 265 |
-
print(f"⚠️ تليجرام
|
| 266 |
-
BASE_UPLOAD_DELAY +=
|
| 267 |
-
await asyncio.sleep(e.value + random.uniform(
|
| 268 |
except Exception as e:
|
| 269 |
-
print(f"⚠️ خطأ
|
| 270 |
async with aiosqlite.connect(DB_PATH) as db:
|
| 271 |
await db.execute("UPDATE queue SET status='FAILED' WHERE id=?", (q_id,))
|
| 272 |
await db.commit()
|
| 273 |
if os.path.exists(file_path): os.remove(file_path)
|
| 274 |
-
await asyncio.sleep(
|
| 275 |
|
| 276 |
async def healthcheck_ping():
|
| 277 |
while True:
|
|
@@ -284,17 +284,18 @@ async def main():
|
|
| 284 |
await init_db()
|
| 285 |
await app.start()
|
| 286 |
|
| 287 |
-
print("🔄 جاري
|
| 288 |
try:
|
| 289 |
-
|
|
|
|
|
|
|
| 290 |
pass
|
| 291 |
-
print("✅ تم تنشيط الذاكرة بنجاح وتخزين المعرفات!")
|
| 292 |
except Exception as e:
|
| 293 |
-
|
| 294 |
|
| 295 |
-
print("🚀 تم تشغيل
|
| 296 |
|
| 297 |
-
for i in range(
|
| 298 |
asyncio.create_task(download_worker_task(i + 1))
|
| 299 |
|
| 300 |
asyncio.create_task(upload_worker())
|
|
@@ -309,4 +310,4 @@ if __name__ == "__main__":
|
|
| 309 |
app.run(main())
|
| 310 |
except Exception as crash_error:
|
| 311 |
print(f"⚠️ إعادة تشغيل ذكية: {crash_error}")
|
| 312 |
-
time.sleep(
|
|
|
|
| 5 |
import time
|
| 6 |
import shutil
|
| 7 |
import urllib.request
|
| 8 |
+
import random
|
| 9 |
from threading import Thread
|
| 10 |
from http.server import BaseHTTPRequestHandler, HTTPServer
|
| 11 |
from pyrogram import Client, filters, idle
|
| 12 |
from pyrogram.errors import FloodWait
|
| 13 |
from pyrogram.types import InputMediaPhoto, InputMediaVideo, InputMediaDocument, InputMediaAudio
|
| 14 |
+
from pyrogram.enums import ChatAction
|
| 15 |
|
| 16 |
# --- 1. الإعدادات الأساسية ---
|
| 17 |
DATA_DIR = "./data"
|
|
|
|
| 21 |
|
| 22 |
HEALTHCHECK_URL = os.environ.get("HEALTHCHECK_URL", "")
|
| 23 |
MAX_FILE_SIZE = 2000 * 1024 * 1024 # 2GB
|
| 24 |
+
BASE_UPLOAD_DELAY = 4 # زيادة الأمان الافتراضي للرفع
|
| 25 |
|
| 26 |
download_queue = asyncio.Queue()
|
| 27 |
|
|
|
|
| 30 |
def do_GET(self):
|
| 31 |
self.send_response(200)
|
| 32 |
self.end_headers()
|
| 33 |
+
self.wfile.write(b"Ultimate Radar Archiver Engine Active!")
|
| 34 |
def log_message(self, format, *args): pass
|
| 35 |
|
| 36 |
Thread(target=lambda: HTTPServer(('0.0.0.0', 7860), RequestHandler).serve_forever(), daemon=True).start()
|
| 37 |
|
| 38 |
+
# --- 3. إعدادات الحساب (أعلى مستوى تمويه هاتف ذكي وبصمة حقيقية) ---
|
| 39 |
API_ID = int(os.environ.get("API_ID", 0))
|
| 40 |
API_HASH = os.environ.get("API_HASH", "")
|
| 41 |
SESSION_STRING = os.environ.get("SESSION_STRING", "")
|
|
|
|
| 47 |
api_hash=API_HASH,
|
| 48 |
session_string=SESSION_STRING,
|
| 49 |
in_memory=True,
|
| 50 |
+
device_model="Samsung Galaxy S23 Ultra",
|
| 51 |
+
system_version="Android 14.0",
|
| 52 |
+
app_version="10.14.1",
|
| 53 |
+
lang_code="ar",
|
| 54 |
+
system_lang_code="ar-SA"
|
| 55 |
)
|
| 56 |
|
| 57 |
# --- 4. أدوات النظام وقاعدة البيانات ---
|
|
|
|
| 129 |
(message.chat.id, message.id, unique_id, group_id, m_type, final_caption, file_path, file_size, time.time())
|
| 130 |
)
|
| 131 |
await db.commit()
|
| 132 |
+
print(f"⚡ [Worker-{worker_id}] تم تنزيل رسالة بنجاح: {message.id}")
|
| 133 |
break
|
| 134 |
else:
|
| 135 |
if file_path and os.path.exists(file_path): os.remove(file_path)
|
|
|
|
| 159 |
free_mb = round(free / (1024 * 1024), 2)
|
| 160 |
|
| 161 |
report = (
|
| 162 |
+
f"👑 **حالة رادار الأرشفة المحترف:**\n\n"
|
| 163 |
+
f"📥 جاهز للرفع: `{pending}`\n"
|
| 164 |
+
f"📤 تم رفعه بأمان: `{uploaded}`\n"
|
| 165 |
+
f"🔄 قيد التنزيل: `{download_queue.qsize()}`\n"
|
| 166 |
f"💾 المساحة المتاحة: `{free_mb} MB`"
|
| 167 |
)
|
| 168 |
await message.reply_text(report)
|
| 169 |
|
| 170 |
+
# --- 8. محرك الرفع الذكي العالي الأمان ---
|
| 171 |
async def upload_worker():
|
| 172 |
global BASE_UPLOAD_DELAY
|
| 173 |
while True:
|
| 174 |
try:
|
| 175 |
async with aiosqlite.connect(DB_PATH) as db:
|
| 176 |
+
async with db.execute("SELECT id, chat_id, msg_id, media_group_id, media_type, caption, file_path, file_size, timestamp FROM queue WHERE status='DOWNLOADED' ORDER BY id ASC LIMIT 1") as cursor:
|
| 177 |
row = await cursor.fetchone()
|
| 178 |
|
| 179 |
if not row:
|
| 180 |
await asyncio.sleep(2)
|
| 181 |
continue
|
| 182 |
|
| 183 |
+
q_id, chat_id, msg_id, group_id, m_type, caption, file_path, file_size, ts = row
|
| 184 |
|
| 185 |
if not os.path.exists(file_path):
|
| 186 |
async with aiosqlite.connect(DB_PATH) as db:
|
|
|
|
| 188 |
await db.commit()
|
| 189 |
continue
|
| 190 |
|
| 191 |
+
# محاكاة إرسال حالة الكتابة أو الرفع الحقيقية
|
| 192 |
try:
|
| 193 |
if m_type == "photo": await app.send_chat_action(TARGET_CHAT, ChatAction.UPLOAD_PHOTO)
|
| 194 |
+
elif m_type in ["video", "animation"]: await app.send_chat_action(TARGET_CHAT, ChatAction.UPLOAD_VIDEO)
|
| 195 |
elif m_type == "doc": await app.send_chat_action(TARGET_CHAT, ChatAction.UPLOAD_DOCUMENT)
|
| 196 |
+
elif m_type in ["audio", "voice"]: await app.send_chat_action(TARGET_CHAT, ChatAction.UPLOAD_AUDIO)
|
| 197 |
+
await asyncio.sleep(random.uniform(1.0, 2.0))
|
| 198 |
+
except: pass
|
| 199 |
|
| 200 |
if group_id:
|
| 201 |
time_passed = time.time() - ts
|
| 202 |
+
if time_passed < 10: await asyncio.sleep(10 - time_passed)
|
| 203 |
|
| 204 |
async with aiosqlite.connect(DB_PATH) as db:
|
| 205 |
async with db.execute(
|
|
|
|
| 236 |
if os.path.exists(f_path): os.remove(f_path)
|
| 237 |
|
| 238 |
gc.collect()
|
| 239 |
+
await asyncio.sleep(BASE_UPLOAD_DELAY + random.uniform(2.0, 4.0))
|
|
|
|
|
|
|
| 240 |
continue
|
| 241 |
|
| 242 |
+
# رفع الملف المفرد مع ضبط الحجم الذكي (الملفات الكبيرة تأخذ وقتاً أطول للراحة)
|
| 243 |
if m_type == "photo": await app.send_photo(TARGET_CHAT, photo=file_path, caption=caption)
|
| 244 |
elif m_type == "video": await app.send_video(TARGET_CHAT, video=file_path, caption=caption, supports_streaming=True)
|
| 245 |
elif m_type == "doc": await app.send_document(TARGET_CHAT, document=file_path, caption=caption)
|
|
|
|
| 254 |
|
| 255 |
if os.path.exists(file_path): os.remove(file_path)
|
| 256 |
|
| 257 |
+
# زيادة زمن الانتظار ديناميكياً إذا كان الملف كبيراً (أكثر من 50 ميجابايت) لحماية الحساب تماماً
|
| 258 |
+
size_factor = min(file_size / (10 * 1024 * 1024), 10) # حد أقصى للإضافات
|
| 259 |
+
safe_sleep = BASE_UPLOAD_DELAY + size_factor + random.uniform(1.0, 3.0)
|
| 260 |
|
| 261 |
+
gc.collect()
|
| 262 |
+
await asyncio.sleep(safe_sleep)
|
|
|
|
| 263 |
|
| 264 |
except FloodWait as e:
|
| 265 |
+
print(f"⚠️ تليجرام فرض حماية FloodWait لمدة {e.value} ثانية. جاري التهدئة...")
|
| 266 |
+
BASE_UPLOAD_DELAY += 5 # رفع معدل الأمان للأساس
|
| 267 |
+
await asyncio.sleep(e.value + random.uniform(10, 20))
|
| 268 |
except Exception as e:
|
| 269 |
+
print(f"⚠️ خطأ غير متوقع، تجاوز الملف: {e}")
|
| 270 |
async with aiosqlite.connect(DB_PATH) as db:
|
| 271 |
await db.execute("UPDATE queue SET status='FAILED' WHERE id=?", (q_id,))
|
| 272 |
await db.commit()
|
| 273 |
if os.path.exists(file_path): os.remove(file_path)
|
| 274 |
+
await asyncio.sleep(5)
|
| 275 |
|
| 276 |
async def healthcheck_ping():
|
| 277 |
while True:
|
|
|
|
| 284 |
await init_db()
|
| 285 |
await app.start()
|
| 286 |
|
| 287 |
+
print("🔄 جاري مزامنة بصمة الهاتف مع مراكز بيانات تليجرام...")
|
| 288 |
try:
|
| 289 |
+
me = await app.get_me()
|
| 290 |
+
print(f"✅ تم الاتصال بنجاح بالحساب: {me.first_name} (معرف الجلسة مستقر)")
|
| 291 |
+
async for _ in app.get_dialogs(limit=150):
|
| 292 |
pass
|
|
|
|
| 293 |
except Exception as e:
|
| 294 |
+
print(f"⚠️ تحذير الاتصال: {e}")
|
| 295 |
|
| 296 |
+
print("🚀 تم تشغيل الرادار الحي بنسخة الأمان القصوى والمحاكاة التامة!")
|
| 297 |
|
| 298 |
+
for i in range(2): # تقليل عدد العمال لضمان عدم حدوث زحمة طلبات (Rate Limit)
|
| 299 |
asyncio.create_task(download_worker_task(i + 1))
|
| 300 |
|
| 301 |
asyncio.create_task(upload_worker())
|
|
|
|
| 310 |
app.run(main())
|
| 311 |
except Exception as crash_error:
|
| 312 |
print(f"⚠️ إعادة تشغيل ذكية: {crash_error}")
|
| 313 |
+
time.sleep(10)
|