| |
| import os |
| import json |
| import time |
| import random |
| import threading |
| import re |
| import requests |
| from fastapi import FastAPI |
| from fastapi.responses import HTMLResponse, JSONResponse |
|
|
| app = FastAPI() |
| db_lock = threading.Lock() |
|
|
| HF_TOKEN = os.getenv("HF_TOKEN", "") |
| MODEL_NAME = "Qwen/Qwen2.5-Coder-7B-Instruct" |
| GAMES_FILE = "games_database.json" |
| API_URL = f"https://api-inference.huggingface.co/models/{MODEL_NAME}" |
|
|
| |
| system_logs = ["[النظام] تم تشغيل السيرفر بنجاح وجاهز للمراقبة."] |
|
|
| def add_log(message): |
| global system_logs |
| timestamp = time.strftime("%H:%M:%S") |
| log_entry = f"[{timestamp}] {message}" |
| print(log_entry) |
| system_logs.append(log_entry) |
| if len(system_logs) > 40: |
| system_logs.pop(0) |
|
|
| |
| CORE_MECHANICS = [ |
| "تفادي عقبات ليزرية متساقطة بسرعة متزايدة بالنقر لليمين واليسار", |
| "تقطيع عناصر نيون مشعة تتطاير من الأسفل عبر سحب الإصبع على الشاشة", |
| "النقر السريع لتوليد طاقة وحماية النواة من الانفجار قبل انتهاء الوقت", |
| "إطلاق قذائف ضوئية من الأسفل لتدمير كتل هندسية تهبط تدريجياً", |
| "تجميع بلورات ملونة متساقطة وتجنب القنابل الليزرية السوداء" |
| ] |
|
|
| VISUAL_THEMES = [ |
| "سايبربانك مستقبلي نيون غامق وجذاب Cyberpunk Night", |
| "سينثويف ريترو Synthwave خطوط متحركة مع إضاءة الثمانينات", |
| "فضاء كوني عميق مليء بالنجوم المتوهجة والسدم المضيئة", |
| "واجهة زجاجية معتمة فائقة الأناقة بنمط Glassmorphism UI" |
| ] |
|
|
| COLOR_PALETTES = [ |
| "الوردي النيوني (#ff007f) والأزرق السيبراني (#00f0ff) مع توهج شديد", |
| "الأخضر الفسفوري الفاقع والبنفسجي الليزري المضيء", |
| "الذهبي الرقمي البراق والأبيض الكهربائي المشع" |
| ] |
|
|
| |
| F_1 = """<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Dodge</title><style>body{margin:0;background:#050510;color:#fff;text-align:center;overflow:hidden;height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center;}canvas{background:#0a0a20;border:2px solid #00f0ff;}</style></head><body><div>النقاط: <span id="s">0</span></div><canvas id="g" width="320" height="440"></canvas><script>const c=document.getElementById('g'),ctx=c.getContext('2d');let p={x:140,y:400,w:40,h:15},obs=[],score=0;function spawn(){obs.push({x:Math.random()*290,y:-20,w:25,h:25,s:4});setTimeout(spawn,900);}function loop(){ctx.clearRect(0,0,320,440);ctx.fillStyle='#00f0ff';ctx.fillRect(p.x,p.y,p.w,p.h);ctx.fillStyle='#ff007f';obs.forEach((o,i)=>{o.y+=o.s;ctx.fillRect(o.x,o.y,o.w,o.h);if(o.y>440){obs.splice(i,1);score++;document.getElementById('s').innerText=score;}});requestAnimationFrame(loop);}c.addEventListener('touchmove',(e)=>{p.x=Math.max(0,Math.min(280,e.touches[0].clientX-c.getBoundingClientRect().left-20));});spawn();loop();</script></body></html>""" |
| F_2 = """<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Clicker</title><style>body{margin:0;background:#06020f;color:#fff;display:flex;flex-direction:column;justify-content:center;align-items:center;height:100vh;}.core{width:100px;height:100px;background:#00f0ff;border-radius:50%;box-shadow:0 0 20px #00f0ff;cursor:pointer;}</style></head><body><h1 id="s">0</h1><div class="core" onclick="s++;document.getElementById('s').innerText=s"></div></body></html>""" |
|
|
| def load_games(): |
| with db_lock: |
| if os.path.exists(GAMES_FILE): |
| try: |
| with open(GAMES_FILE, "r", encoding="utf-8") as f: return json.load(f) |
| except: return [] |
| return [] |
|
|
| def save_games(games): |
| with db_lock: |
| try: |
| with open(GAMES_FILE, "w", encoding="utf-8") as f: json.dump(games, f, ensure_ascii=False, indent=4) |
| except Exception as e: print(f"Failed to save database: {e}") |
|
|
| def initialize_database_if_empty(): |
| games = load_games() |
| if len(games) < 2: |
| add_log("زراعة ألعاب الطوارئ الأولى لتأمين الواجهة حالاً...") |
| games = [ |
| {"id": 1, "title": "مفاعل النيون السريع", "genre": "Neon Clicker", "code": F_2, "likes": 12, "shares": 2, "timestamp": time.time()}, |
| {"id": 2, "title": "عقبات السيبر ليزر", "genre": "Cyber Dodge", "code": F_1, "likes": 24, "shares": 5, "timestamp": time.time()} |
| ] |
| save_games(games) |
|
|
| def extract_clean_html(raw_text): |
| match = re.search(r"(<!DOCTYPE html>.*?</html>)", raw_text, re.DOTALL | re.IGNORECASE) |
| if match: return match.group(1).strip() |
| return raw_text.strip() |
|
|
| def generate_new_game(): |
| if not HF_TOKEN: |
| add_log("⚠️ تحذير: الـ HF_TOKEN غير مضاف في إعدادات المنصة (Variables)! لن يعمل التوليد.") |
| return False |
| |
| m = random.choice(CORE_MECHANICS) |
| t = random.choice(VISUAL_THEMES) |
| c = random.choice(COLOR_PALETTES) |
| generated_title = f"أركيد {random.choice(['النيون', 'الليزر', 'السيبراني', 'المستقبل'])}" |
| |
| add_log(f"🤖 جاري الاتصال بموديل الذكاء الاصطناعي ({MODEL_NAME})...") |
| |
| headers = {"Authorization": f"Bearer {HF_TOKEN}", "Content-Type": "application/json"} |
| system_prompt = "You are an elite HTML5 game developer. Output ONLY valid executable HTML code starting with <!DOCTYPE html> and ending with </html>. No explanations." |
| user_prompt = f"صمم لعبة إركيد متكاملة وممتعة جداً للموبايل باللغة العربية. فكرة اللعب: {m}. المظهر: {t}. الألوان: {c}." |
| |
| payload = { |
| "inputs": f"<|system|>\n{system_prompt}\n<|user|>\n{user_prompt}\n<|assistant|>\n", |
| "parameters": {"max_new_tokens": 1500, "temperature": 0.8, "return_full_text": False} |
| } |
| |
| try: |
| response = requests.post(API_URL, headers=headers, json=payload, timeout=40) |
| |
| if response.status_code == 200: |
| res_json = response.json() |
| raw_text = res_json[0].get("generated_text", "") if isinstance(res_json, list) else res_json.get("generated_text", "") |
| clean_code = extract_clean_html(raw_text) |
| |
| if "html" in clean_code.lower() and "script" in clean_code.lower(): |
| games = load_games() |
| game_id = max([g["id"] for g in games]) + 1 if games else 1 |
| |
| new_entry = { |
| "id": game_id, "title": f"{generated_title} #{game_id}", "genre": "AI Live", |
| "code": clean_code, "likes": random.randint(5, 20), "shares": random.randint(1, 4), "timestamp": time.time() |
| } |
| games.insert(0, new_entry) |
| save_games(games) |
| add_log(f"✅ [نجاح باهر] الذكاء الاصطناعي صنع اللعبة بنجاح! رقم اللعبة الجديد: {game_id}") |
| return True |
| else: |
| add_log("⚠️ رد الذكاء الاصطناعي لم يكن كود HTML كاملاً أو ينقصه السكريبت.") |
| elif response.status_code == 503: |
| add_log("⏳ السيرفر الخارجي للذكاء الاصطناعي جاري تحميله (Loading). سيعود للعمل تلقائياً...") |
| else: |
| add_log(f"❌ فشل الاتصال. رمز الخطأ من السيرفر: {response.status_code}") |
| except Exception as e: |
| add_log(f"❌ حدث خطأ أثناء إرسال الطلب: {e}") |
| return False |
|
|
| def game_generator_cron(): |
| while True: |
| try: generate_new_game() |
| except: pass |
| time.sleep(90) |
|
|
| @app.on_event("startup") |
| def on_startup(): |
| initialize_database_if_empty() |
| threading.Thread(target=game_generator_cron, daemon=True).start() |
|
|
| |
| |
| |
| @app.get("/debug", response_class=HTMLResponse) |
| def render_debug_panel(): |
| games = load_games() |
| |
| logs_text = "\n".join(system_logs[::-1]) |
| |
| return f"""<!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="UTF-8"> |
| <title>لوحة مراقبة مصنع الألعاب 🕵️♂️</title> |
| <style> |
| body {{ font-family: sans-serif; background: #0a0a14; color: #fff; padding: 20px; direction: rtl; }} |
| .card {{ background: #121225; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 1px solid #1f1f3d; }} |
| .btn {{ padding: 12px 24px; background: #00f0ff; border: none; color: #000; font-weight: bold; border-radius: 5px; cursor: pointer; }} |
| .log-box {{ background: #000; color: #00ff00; padding: 15px; font-family: monospace; height: 250px; overflow-y: auto; border-radius: 5px; white-space: pre-wrap; }} |
| h2 {{ color: #ff007f; }} |
| </style> |
| <script> |
| async function triggerGeneration() {{ |
| document.getElementById('status-text').innerText = 'جاري التوليد الفوري الآن... انتظر 20 ثانية وتفقد السجلات بالأسفل'; |
| await fetch('/debug/force-generate', {{ method: 'POST' }}); |
| }} |
| setInterval(() => {{ location.reload(); }}, 7000); |
| </script> |
| </head> |
| <body> |
| <h1>🕵️♂️ لوحة فحص ومراقبة الروبوت الحية</h1> |
| <p>هذه الصفحة تحدث نفسها تلقائياً كل 7 ثواني لمراقبة السجلات.</p> |
| |
| <div class="card"> |
| <h2>📊 حالة قاعدة البيانات الحالية</h2> |
| <p>🔋 <b>إجمالي الألعاب المتوفرة داخل المنصة الآن:</b> <span style="font-size: 1.5rem; color: #00f0ff;">{len(games)} ألعاب</span></p> |
| <p>ℹ️ (إذا كان العدد أكثر من 2، فهذا يعني أن الذكاء الاصطناعي يشتغل ويولد بنجاح تام والموقع يسحب منه!)</p> |
| <button class="btn" onclick="triggerGeneration()">⚡ اضغط هنا لإجبار الذكاء الاصطناعي على توليد لعبة حالاً</button> |
| <p id="status-text" style="color: #ffaa00; font-weight: bold;"></p> |
| </div> |
| |
| <div class="card"> |
| <h2>📜 سجلات حركة الروبوت الحية (Logs)</h2> |
| <div class="log-box">{logs_text}</div> |
| </div> |
| </body> |
| </html>""" |
|
|
| @app.post("/debug/force-generate") |
| def force_generate(): |
| threading.Thread(target=generate_new_game).start() |
| return {"status": "triggered"} |
|
|
| |
| |
| |
| @app.get("/api/games") |
| def get_games(): |
| games = load_games() |
| return JSONResponse(content=[{k: v for k, v in g.items() if k != "code"} for g in games]) |
|
|
| @app.get("/api/game_code/{game_id}") |
| def get_game_code(game_id: int): |
| for g in load_games(): |
| if g["id"] == game_id: return HTMLResponse(content=g["code"]) |
| return HTMLResponse(content="<h1>اللعبة غير موجودة</h1>", status_code=404) |
|
|
| @app.get("/", response_class=HTMLResponse) |
| def render_ui(): |
| return """<!DOCTYPE html> |
| <html lang="ar" dir="rtl"> |
| <head> |
| <meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Arcade Reels AI</title> |
| <style> |
| body, html { margin: 0; padding: 0; width: 100%; height: 100%; background-color: #020205; overflow: hidden; font-family: sans-serif; color: #fff; } |
| .feed-container { width: 100%; max-width: 450px; height: 100vh; margin: 0 auto; overflow-y: scroll; scroll-snap-type: y mandatory; scrollbar-width: none; position: relative; background: #000; } |
| .feed-container::-webkit-scrollbar { display: none; } |
| .game-slide { width: 100%; height: 100vh; scroll-snap-align: start; position: relative; } |
| iframe { width: 100%; height: 100%; border: none; background: #000; } |
| .ui-overlay { position: absolute; bottom: 30px; right: 20px; left: 90px; z-index: 5; pointer-events: none; } |
| .ui-overlay h3 { margin: 0; color: #00f0ff; font-size: 1.2rem; } |
| </style> |
| </head> |
| <body> |
| <div class="feed-container" id="feed"></div> |
| <script> |
| let allGames = []; |
| async function initFeed() { |
| try { |
| const res = await fetch('/api/games'); |
| allGames = await res.json(); |
| const container = document.getElementById('feed'); |
| container.innerHTML = ''; |
| allGames.forEach((game) => { |
| const slide = document.createElement('div'); |
| slide.className = 'game-slide'; |
| slide.innerHTML = `<iframe data-src="/api/game_code/${game.id}"></iframe> |
| <div class="ui-overlay"><h3>${game.title}</h3><p>مصنع الألعاب اللانهائي 24/7</p></div>`; |
| container.appendChild(slide); |
| }); |
| setupObserver(); |
| } catch (err) {} |
| } |
| function setupObserver() { |
| const observer = new IntersectionObserver((entries) => { |
| entries.forEach(entry => { |
| const iframe = entry.target.querySelector('iframe'); |
| if (entry.isIntersecting && iframe && !iframe.src) iframe.src = iframe.getAttribute('data-src'); |
| }); |
| }, { threshold: 0.4 }); |
| document.querySelectorAll('.game-slide').forEach(s => observer.observe(s)); |
| } |
| window.onload = initFeed; |
| </script> |
| </body> |
| </html>""" |
|
|