Move files from lara-chess folder to root directory
This commit is contained in:
168
server.py
Normal file
168
server.py
Normal file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Lokal Proxy-Server für Lara's Schachturnier
|
||||
Lädt die PGN-Datei und stellt sie mit CORS-Headern bereit.
|
||||
"""
|
||||
|
||||
import http.server
|
||||
import socketserver
|
||||
import urllib.request
|
||||
import sys
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
PGN_URL = "https://www.deutsche-schachjugend.de/2026/odjm-d/partien/gesamt-utf8.pgn"
|
||||
PORT = 8111
|
||||
CACHE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cache")
|
||||
CACHE_FILE = os.path.join(CACHE_DIR, "gesamt-utf8.pgn")
|
||||
CACHE_TTL = 30 # Sekunden
|
||||
|
||||
os.makedirs(CACHE_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def fetch_pgn():
|
||||
"""Lädt die PGN-Datei von der URL als Bytes."""
|
||||
try:
|
||||
req = urllib.request.Request(PGN_URL, headers={"User-Agent": "Mozilla/5.0"})
|
||||
with urllib.request.urlopen(req, timeout=30) as response:
|
||||
return response.read()
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Fehler beim Laden: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_pgn_content():
|
||||
"""Gibt PGN-Inhalt als Bytes zurück, nutzt Cache wenn möglich."""
|
||||
now = time.time()
|
||||
|
||||
# Prüfe Cache
|
||||
if os.path.exists(CACHE_FILE):
|
||||
age = now - os.path.getmtime(CACHE_FILE)
|
||||
if age < CACHE_TTL:
|
||||
with open(CACHE_FILE, "rb") as f:
|
||||
return f.read()
|
||||
|
||||
# Cache verfallen oder nicht vorhanden -> neu laden
|
||||
content = fetch_pgn()
|
||||
if content:
|
||||
with open(CACHE_FILE, "wb") as f:
|
||||
f.write(content)
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] PGN aktualisiert ({len(content)} Bytes)")
|
||||
return content
|
||||
|
||||
# Fallback: alter Cache
|
||||
if os.path.exists(CACHE_FILE):
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Verwende alten Cache")
|
||||
with open(CACHE_FILE, "rb") as f:
|
||||
return f.read()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class PGNHandler(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
if self.path == "/pgn":
|
||||
content = get_pgn_content()
|
||||
if content:
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/plain; charset=utf-8")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.send_header("Cache-Control", "no-cache")
|
||||
self.end_headers()
|
||||
self.wfile.write(content)
|
||||
else:
|
||||
self.send_response(502)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(b'{"error": "Konnte PGN nicht laden"}')
|
||||
|
||||
elif self.path == "/status":
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(b'{"status": "ok"}')
|
||||
|
||||
else:
|
||||
# Statische Dateien aus dem Verzeichnis
|
||||
if self.path == "/":
|
||||
self.path = "/index.html"
|
||||
|
||||
filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), self.path.lstrip("/"))
|
||||
if os.path.isfile(filepath):
|
||||
content_types = {
|
||||
".html": "text/html",
|
||||
".css": "text/css",
|
||||
".js": "application/javascript",
|
||||
".json": "application/json",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".svg": "image/svg+xml",
|
||||
}
|
||||
ext = os.path.splitext(filepath)[1]
|
||||
content_type = content_types.get(ext, "application/octet-stream")
|
||||
|
||||
with open(filepath, "rb") as f:
|
||||
content = f.read()
|
||||
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", f"{content_type}; charset=utf-8")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(content)
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
|
||||
def log_message(self, format, *args):
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] {args[0]}")
|
||||
|
||||
|
||||
def background_refresh():
|
||||
"""Aktualisiert den Cache im Hintergrund."""
|
||||
while True:
|
||||
time.sleep(CACHE_TTL)
|
||||
try:
|
||||
content = fetch_pgn()
|
||||
if content:
|
||||
with open(CACHE_FILE, "wb") as f:
|
||||
f.write(content)
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Hintergrund-Refresh Fehler: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 50)
|
||||
print(" [TROPHY] Lara Kiesewetter – Live Schachturnier")
|
||||
print("=" * 50)
|
||||
print(f" Server läuft auf: http://localhost:{PORT}")
|
||||
print(f" Drücke Ctrl+C zum Beenden")
|
||||
print("=" * 50)
|
||||
|
||||
# Initialer Ladeversuch
|
||||
content = fetch_pgn()
|
||||
if content:
|
||||
with open(CACHE_FILE, "wb") as f:
|
||||
f.write(content)
|
||||
print(f"[OK] PGN geladen ({len(content)} Bytes)")
|
||||
else:
|
||||
print("[WARN] Initialer Ladeversuch fehlgeschlagen, wird wiederholt...")
|
||||
|
||||
# Hintergrund-Refresh Thread starten
|
||||
refresh_thread = threading.Thread(target=background_refresh, daemon=True)
|
||||
refresh_thread.start()
|
||||
|
||||
# Server starten
|
||||
with socketserver.TCPServer(("", PORT), PGNHandler) as httpd:
|
||||
print(f"\n[SERVER] Server gestartet: http://localhost:{PORT}\n")
|
||||
try:
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("\n[BYE] Server gestoppt.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user