import os import aiohttp import asyncio import logging from flask import Flask, render_template, request, jsonify app = Flask(__name__) # إعداد السجلات (Logging) logging.basicConfig(level=logging.INFO) logger = logging.getLogger("web_app") # جلب الإعدادات الحساسة BASE_URL = os.getenv("BASE_URL") MANGA_PATH = os.getenv("MANGA_API_PATH") CHAPTER_PATH = os.getenv("CHAPTER_API_PATH") PORT = int(os.getenv("PORT", 7860)) # الهيدرز المحسنة لتخطي الحماية HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", "Accept": "application/json, text/plain, */*", "Accept-Language": "ar,en-US;q=0.9,en;q=0.8", "Referer": "https://utoon.net/", "Origin": "https://utoon.net", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", } async def get_chapters(manga_url): slug = manga_url.strip().rstrip("/").split("/")[-1] try: api_url = f"{BASE_URL}{MANGA_PATH.format(slug=slug)}" logger.info(f"🔍 Fetching Manga: {api_url}") # استخدام كوكيز وهمية قد يساعد أحياناً async with aiohttp.ClientSession(headers=HEADERS) as session: async with session.get(api_url, timeout=15) as resp: logger.info(f"📡 API Response Status: {resp.status}") if resp.status == 403: logger.error("🚫 Access Denied (403). Site is blocking Hugging Face.") return None if resp.status != 200: return None data = await resp.json() mangas = data.get("mangas", []) if not mangas: return None m = mangas[0] return { "title": m.get("post_title", slug), "thumbnail": m.get("thumbnail", ""), "chapters": [ {"id": c["id_capitulo"], "title": c["nombre"], "slug": c["slug"]} for c in m.get("capitulos", []) ] } except Exception as e: logger.error(f"💥 Scraper Error: {str(e)}") return None async def get_images(chapter_id): try: api_url = f"{BASE_URL}{CHAPTER_PATH.format(id=chapter_id)}" async with aiohttp.ClientSession(headers=HEADERS) as session: async with session.get(api_url, timeout=15) as resp: if resp.status != 200: return [] data = await resp.json() imgs = data.get("imagenes") or [] return [i["src"] if isinstance(i, dict) else i for i in imgs] except Exception as e: return [] @app.route("/") def index(): return render_template("index.html") @app.route("/api/manga") def api_manga(): url = request.args.get("url") if not url: return jsonify({"error": "Missing URL"}), 400 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) data = loop.run_until_complete(get_chapters(url)) if not data: return jsonify({"error": "Access Denied by Site or Manga not found"}), 404 return jsonify(data) @app.route("/api/chapter/") def api_chapter(chapter_id): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) images = loop.run_until_complete(get_images(chapter_id)) return jsonify({"images": images}) if __name__ == "__main__": app.run(host="0.0.0.0", port=PORT)