import os, time, threading, zipfile, io, re, telebot, requests from flask import Flask, render_template_string from playwright.sync_api import sync_playwright from PIL import Image import img2pdf from telebot import types # --- الإعدادات --- BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") ADMIN_HANDLE = "@svipfast" bot = telebot.TeleBot(BOT_TOKEN, threaded=False) app = Flask(__name__) # مخزن مؤقت لحالات المستخدمين user_states = {} @app.route('/') def home(): return "

Manga Engine Professional is Running

" # --- محرك السحب (Playwright) --- def fetch_images_engine(url): with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") page = context.new_page() try: page.goto(url, wait_until="networkidle", timeout=60000) # التمرير لضمان تحميل الصور بالكامل for _ in range(5): page.mouse.wheel(0, 1200) time.sleep(0.8) images = page.query_selector_all("img") img_list = [] for img in images: src = img.get_attribute("src") or img.get_attribute("data-src") or img.get_attribute("data-lazy-src") if src and any(ext in src.lower() for ext in ['.jpg', '.jpeg', '.png', '.webp', '.avif']): if "logo" in src.lower() or "banner" in src.lower(): continue try: res = page.request.get(src) if res.status == 200 and len(res.body()) > 25000: img_list.append(Image.open(io.BytesIO(res.body())).convert('RGB')) except: continue browser.close() return img_list except: browser.close() return [] # --- لوحة التحكم والترحيب --- @bot.message_handler(commands=['start']) def welcome(message): user_states[message.chat.id] = {} # تصفير حالة المستخدم markup = types.InlineKeyboardMarkup(row_width=1) btn_start = types.InlineKeyboardButton("📥 إرسال رابط جديد", callback_data="new_order") btn_help = types.InlineKeyboardButton("💡 كيف أحصل على الرابط؟", callback_data="help_link") btn_admin = types.InlineKeyboardButton("👨‍💻 المطور", url=f"https://t.me/{ADMIN_HANDLE.replace('@','')}") markup.add(btn_start, btn_help, btn_admin) bot.send_message(message.chat.id, f"مرحباً بك في بوت سحب المانجا الإحترافي 🚀\n\n" f"النظام يعمل بمحرك محاكاة لتجاوز الحمايات.\n" f"المطور المسؤول: {ADMIN_HANDLE}", parse_mode="HTML", reply_markup=markup) # --- معالجة الضغط على الأزرار --- @bot.callback_query_handler(func=lambda call: True) def handle_query(call): chat_id = call.message.chat.id if call.data == "new_order": msg = bot.send_message(chat_id, "الآن، أرسل رابط المانجا (رابط أي فصل):", parse_mode="HTML") bot.register_next_step_handler(msg, process_url_step) elif call.data == "help_link": help_txt = ( "طريقة إرسال الرابط الصحيحة:\n\n" "انسخ رابط الفصل من الموقع مباشرة، مثال:\n" "https://olympustaff.com/series/manga-name/1" ) bot.send_message(chat_id, help_txt, parse_mode="HTML") # أزرار خيارات التحميل elif call.data.startswith("mode_"): mode = call.data.split("_")[1] user_states[chat_id]['mode'] = mode if mode == "single": msg = bot.send_message(chat_id, "🔢 أرسل رقم الفصل فقط:") elif mode == "range": msg = bot.send_message(chat_id, "🔢 أرسل المدى (مثال: 1-10):") elif mode == "auto10": msg = bot.send_message(chat_id, "🔢 أرسل رقم الفصل الذي سنبدأ التحميل منه:") bot.register_next_step_handler(msg, final_execution_step) bot.answer_callback_query(call.id) # --- الخطوة الثانية: استلام الرابط --- def process_url_step(message): url = message.text.strip() if not url.startswith("http"): bot.send_message(message.chat.id, "❌ الرابط غير صحيح، أرسل رابط يبدأ بـ http") return user_states[message.chat.id] = {'url': url} # إظهار خيارات التحميل كأزرار markup = types.InlineKeyboardMarkup(row_width=2) markup.add( types.InlineKeyboardButton("🎯 فصل واحد", callback_data="mode_single"), types.InlineKeyboardButton("📦 حزمة فصول", callback_data="mode_range"), types.InlineKeyboardButton("⏩ تحميل 10 فصول", callback_data="mode_auto10") ) bot.send_message(message.chat.id, "ممتاز! اختر الآن طريقة التحميل:", parse_mode="HTML", reply_markup=markup) # --- الخطوة الأخيرة: التنفيذ --- def final_execution_step(message): chat_id = message.chat.id state = user_states.get(chat_id) if not state or 'url' not in state: bot.send_message(chat_id, "⚠️ حدث خطأ، يرجى البدء من جديد عبر /start") return text = message.text.strip() mode = state['mode'] url = state['url'] try: if mode == "single": start, end = int(text), int(text) elif mode == "range": start, end = map(int, text.split('-')) elif mode == "auto10": start = int(text) end = start + 9 status_msg = bot.send_message(chat_id, f"🔄 جاري تشغيل المحرك الذكي...\n📦 سحب الفصول: {start} ⬅️ {end}", parse_mode="HTML") # تشغيل السحب zip_path = run_manga_engine(url, start, end) if zip_path: with open(zip_path, 'rb') as f: caption = ( f"✅ اكتملت عملية السحب بنجاح\n\n" f"📂 النطاق: {start} إلى {end}\n" f"👨‍💻 بواسطة: {ADMIN_HANDLE}" ) bot.send_document(chat_id, f, caption=caption, parse_mode="HTML") os.remove(zip_path) bot.delete_message(chat_id, status_msg.message_id) else: bot.edit_message_text(f"❌ لم ينجح المحرك في سحب الصور.\nتواصل مع الإدارة: {ADMIN_HANDLE}", chat_id, status_msg.message_id) except Exception as e: bot.send_message(chat_id, "⚠️ خطأ في إدخال الأرقام. يرجى التأكد من كتابتها بشكل صحيح (مثال: 1-5).") # --- منطق بناء الروابط وضغط الملفات --- def run_manga_engine(sample_url, start, end): base_part = re.sub(r'/(?:chapter-)?\d+$', '', sample_url.strip().rstrip('/')) is_azora = "azoramoon" in sample_url pdf_files = [] for i in range(start, end + 1): target_url = f"{base_part}/chapter-{i}" if is_azora else f"{base_part}/{i}" imgs = fetch_images_engine(target_url) if imgs: fname = f"Chapter_{i}.pdf" imgs[0].save(fname, save_all=True, append_images=imgs[1:], format='PDF') pdf_files.append(fname) if not pdf_files: return None zip_name = f"Manga_Pack_{int(time.time())}.zip" with zipfile.ZipFile(zip_name, 'w') as zipf: for f in pdf_files: zipf.write(f) os.remove(f) return zip_name # --- التشغيل --- if __name__ == "__main__": # تنصيب متصفح Playwright os.system("playwright install chromium") threading.Thread(target=lambda: bot.infinity_polling(), daemon=True).start() app.run(host="0.0.0.0", port=7860)