Gttfhuss's picture
Update app.py
2646f1b verified
Raw
History Blame Contribute Delete
14.6 kB
# -*- coding: utf-8 -*-
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()
# ----------------------------------------------------------------
# صفحة لوحة التحكم الحية الخالية من أخطاء الـ Backslash
# ----------------------------------------------------------------
@app.get("/debug", response_class=HTMLResponse)
def render_debug_panel():
games = load_games()
# فصل عملية الـ join المسببة للمشكلة خارج الـ f-string لحلها جذرياً
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"}
# ----------------------------------------------------------------
# باقي منافذ الواجهة وAPI المنصة
# ----------------------------------------------------------------
@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>"""