#!/usr/bin/env python3 """Fehler-Melde-Server fuer brettspiel-news.de Mini-HTTP-Server auf Port 8888. Nur das Formular + API. Isoliert von allen anderen Diensten. Kein Flask, nur stdlib.""" import http.server import json import sqlite3 import os import urllib.parse import urllib.request from datetime import datetime PORT = 8888 HOST = "127.0.0.1" DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fehler.db") TOKEN = os.environ.get("FEHLER_TOKEN", "br3ttsp1el-f3hl3r-2026") TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "") TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "") # ═══════════════════════════════════════════════════ # SQLite # ═══════════════════════════════════════════════════ def init_db(): conn = sqlite3.connect(DB_PATH) conn.execute(""" CREATE TABLE IF NOT EXISTS fehler ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id TEXT NOT NULL, melder_name TEXT NOT NULL, melder_email TEXT DEFAULT '', fehler_text TEXT NOT NULL, status TEXT DEFAULT 'offen', loesung TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now','localtime')), updated_at TEXT DEFAULT (datetime('now','localtime')) ) """) conn.commit() conn.close() def save_report(article_id, name, email, text): conn = sqlite3.connect(DB_PATH) conn.execute( "INSERT INTO fehler (article_id, melder_name, melder_email, fehler_text) VALUES (?,?,?,?)", (str(article_id), name, email, text) ) rid = conn.execute("SELECT last_insert_rowid()").fetchone()[0] conn.commit() conn.close() return rid def get_stats(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row total = conn.execute("SELECT COUNT(*) as c FROM fehler").fetchone()["c"] offen = conn.execute("SELECT COUNT(*) as c FROM fehler WHERE status='offen'").fetchone()["c"] behoben = conn.execute("SELECT COUNT(*) as c FROM fehler WHERE status='behoben'").fetchone()["c"] verworfen = conn.execute("SELECT COUNT(*) as c FROM fehler WHERE status='verworfen'").fetchone()["c"] conn.close() return {"total": total, "offen": offen, "behoben": behoben, "verworfen": verworfen} def get_meldungen(status_filter=None, limit=100): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row if status_filter: rows = conn.execute( "SELECT * FROM fehler WHERE status=? ORDER BY created_at DESC LIMIT ?", (status_filter, limit) ).fetchall() else: rows = conn.execute( "SELECT * FROM fehler ORDER BY created_at DESC LIMIT ?", (limit,) ).fetchall() conn.close() return [dict(r) for r in rows] def update_status(rid, status, loesung): conn = sqlite3.connect(DB_PATH) conn.execute( "UPDATE fehler SET status=?, loesung=?, updated_at=datetime('now','localtime') WHERE id=?", (status, loesung, rid) ) conn.commit() conn.close() # ═══════════════════════════════════════════════════ # Basti-Benachrichtigung (Datei-basiert) # ═══════════════════════════════════════════════════ FEHLER_EINGANG = os.path.join(os.path.dirname(os.path.abspath(__file__)), "eingang") def notify_basti(report_id, article_id, name, text): """Schreibt Fehlermeldung als .md-Datei für Basti.""" os.makedirs(FEHLER_EINGANG, exist_ok=True) ts = datetime.now().strftime("%Y%m%d-%H%M%S") fname = f"{ts}_{report_id}.md" fpath = os.path.join(FEHLER_EINGANG, fname) url = f"https://www.brettspiel-news.de/index.php/de/component/content/article/{article_id}" content = f"""# 🐛 Fehlermeldung #{report_id} **Artikel:** [#{article_id}]({url}) **Gemeldet von:** {name} **Datum:** {datetime.now().strftime('%d.%m.%Y %H:%M')} ## Fehlerbeschreibung {text} --- *Status: offen | Bearbeiter: Basti* """ with open(fpath, "w") as f: f.write(content) print(f"[OK] Basti benachrichtigt → {fname}") return fpath # ═══════════════════════════════════════════════════ # HTML-Formular (inline, self-contained) # ═══════════════════════════════════════════════════ FORM_HTML = r"""