Update 2025-04-13_16:49:18

This commit is contained in:
root
2025-04-13 16:49:20 +02:00
commit 06fb52f574
2398 changed files with 435653 additions and 0 deletions

139
main.py Normal file
View File

@ -0,0 +1,139 @@
from fastapi import FastAPI, Request, Body
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
import requests, random, logging, json
from logging.handlers import RotatingFileHandler
from fastapi.responses import HTMLResponse
from pathlib import Path
log_path = "/var/log/games/WordCraze.log"
logger = logging.getLogger("WordCraze")
logger.setLevel(logging.INFO)
handler = RotatingFileHandler(log_path, maxBytes=1_000_000, backupCount=3)
formatter = logging.Formatter('%(asctime)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
app = FastAPI()
app.mount("/static", StaticFiles(directory="static", html=True), name="static")
@app.get("/", response_class=HTMLResponse)
async def root():
return Path("static/index.html").read_text(encoding="utf-8")
class GameState:
def __init__(self, word: str):
self.word = word
self.guessed = ["_"] * len(word)
self.attempts = 8
self.status = "playing"
self.correct_total = 0
state = None
def getWordsFromOllama():
try:
url = "https://at1.dynproxy.net/api/chat/completions"
headers = {"Authorization": "Bearer sk-d0e3a491b19c435a975b234969298cd0"}
body = {
"model": "gemma3:1b",
"messages": [
{
"role": "system",
"content": "Gib ein zufälliges Thema an (z.B. Tiere, Essen, Möbel) und dann ein Array mit 5 Wörtern dieses Themas mit 3 bis 6 Buchstaben im JSON-Format. Nur das Array, keine Einleitung."
},
{
"role": "user",
"content": "Einfaches Thema und 5 passende Wörter mit 36 Buchstaben im JSON-Array."
}
],
"stream": False
}
r = requests.post(url, json=body, headers=headers, timeout=5)
r.raise_for_status()
content = r.json().get("choices", [{}])[0].get("message", {}).get("content", "[]")
clean = content.strip()
if clean.startswith("```json"):
clean = clean.removeprefix("```json").strip()
if clean.endswith("```"):
clean = clean.removesuffix("```").strip()
logger.info(f"Ollama-Rohantwort:\n{clean}")
return json.loads(clean)
except Exception as e:
logger.warning(f"Fallback Ollama getWordsFromOllama(): {e}")
return []
@app.post("/api/start")
def start_game():
global state
words = getWordsFromOllama()
if not words:
return JSONResponse({"error": "No words found"}, status_code=500)
word = random.choice(words)
state = GameState(word)
try:
desc_req = requests.post(
"https://at1.dynproxy.net/api/chat/completions",
headers={"Authorization": "Bearer sk-d0e3a491b19c435a975b234969298cd0"},
json={
"model": "gemma3:1b",
"messages": [
{"role": "user", "content": f"Nenne ein Oberthema (wie Möbel, Tiere, Sport), zu dem das Wort {word} gehört. Antworte nur mit einem allgemeinen Wort. Nenne niemals das Wort selbst."}
],
"stream": False
},
timeout=5
)
desc_req.raise_for_status()
desc = desc_req.json().get("choices", [{}])[0].get("message", {}).get("content", "(unbekannt)").strip()
except Exception as e:
logger.warning(f"Beschreibung für '{word}' fehlgeschlagen: {e}")
desc = "(unbekannt)"
logger.info(f"Zufallsstart mit Wort: {word}")
return {"word": state.guessed, "attempts": state.attempts, "source": "ollama", "topic": desc}
@app.post("/api/guess/{letter}")
def guess_letter(letter: str):
global state
if not state or state.status != "playing":
return {"status": "not_started"}
letter = letter.lower()
correct_this_turn = 0
for i, char in enumerate(state.word.lower()):
if char == letter and state.guessed[i] == "_":
state.guessed[i] = state.word[i]
correct_this_turn += 1
state.correct_total += correct_this_turn
if "_" not in state.guessed:
state.status = "won"
elif correct_this_turn == 0:
state.attempts -= 1
if state.attempts <= 0:
state.status = "lost"
response = {
"word": state.guessed,
"attempts": state.attempts,
"correct_this_turn": correct_this_turn,
"total_correct": state.correct_total,
"status": state.status
}
if state.status != "playing":
response["target"] = state.word
return response
@app.post("/api/moderate")
async def moderate(request: Request):
data = await request.json()
text = data.get("text", "")
bad = any(w in text.lower() for w in ["shit", "fuck", "spam"])
logger.info(f"Moderation checked: '{text}'{'REJECTED' if bad else 'OK'}")
return {"is_ok": not bad}
@app.get("/api/ping")
def ping():
return {"status": "ok"}