Brettspiel News Logo in Header + Projekt-Briefing für Wolfi
- Logo (993x217) als Base64 in public_frontend() und public_detail()
- Ersetzt 🎲 BSN Community Text-Logo durch Brettspiel News Bild-Logo
- PROJEKT-BRIEFING.md: Vollständige Projektdokumentation für AGB/Datenschutz
- Architektur, Datenflüsse, DSGVO-Relevanz, Feature-Stand
This commit is contained in:
@@ -0,0 +1,290 @@
|
|||||||
|
# BSN-Chatsystem — Projekt-Briefing
|
||||||
|
|
||||||
|
> **Stand:** 17. Juni 2026
|
||||||
|
> **Betreiber:** Daniel Krause, brettspiel-news.de
|
||||||
|
> **Zweck dieses Dokuments:** Vollständige Übersicht für die Erstellung von AGB, Datenschutzerklärung und rechtlichen Dokumenten durch Wolfi.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Projektüberblick
|
||||||
|
|
||||||
|
Das **BSN-Chatsystem** („BSN Community — Stimmen aus der Szene“) ist ein **Multi-Channel-Intake-System** für die Brettspiel-Community. Besucher können über verschiedene Kanäle (WhatsApp, Web-Formular) Texte, Fotos, Videos und Sprachnachrichten einreichen — rund um Brettspiele, insbesondere zur SPIEL Essen.
|
||||||
|
|
||||||
|
Die Redaktion (brettspiel-news.de) sichtet die Einreichungen, reichert sie mit KI-Unterstützung an (Zusammenfassung, Hallen-Erkennung, Spieltitel-Erkennung) und veröffentlicht ausgewählte Beiträge auf einer öffentlichen Frontend-Seite.
|
||||||
|
|
||||||
|
Zusätzlich gibt es einen **KI-Chat-Assistenten**, der Besucherfragen auf Basis der veröffentlichten Inhalte beantwortet.
|
||||||
|
|
||||||
|
**URLs:**
|
||||||
|
- Öffentliches Frontend: `https://chat.datenhimmel.work/`
|
||||||
|
- Admin-Dashboard: `https://chat.datenhimmel.work/admin`
|
||||||
|
- WhatsApp-Kontakt: +1 (555) 238-5591 (Meta-Testnummer)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Architektur
|
||||||
|
|
||||||
|
```
|
||||||
|
WhatsApp ──→ Meta Cloud API ──→ cloudflared Tunnel ──→ Flask :5002 ──→ SQLite
|
||||||
|
Web-Formular ─────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌──────┴──────┐
|
||||||
|
│ Admin │ /admin
|
||||||
|
│ Frontend │ /
|
||||||
|
│ Detail │ /beitrag/<id>
|
||||||
|
│ Chat-API │ /api/chat
|
||||||
|
│ Submit-API │ /api/submit
|
||||||
|
└─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Technologie-Stack
|
||||||
|
|
||||||
|
| Komponente | Technologie |
|
||||||
|
|---|---|
|
||||||
|
| Webserver | Flask (Python), Port 5002 |
|
||||||
|
| Datenbank | SQLite (`bsn_intake.db`) |
|
||||||
|
| Tunnel | cloudflared (token-basiert, permanent) |
|
||||||
|
| KI-Modelle | DeepSeek V4 Flash (Zusammenfassung), faster-whisper (Transkription) |
|
||||||
|
| TTS | Piper TTS (de_DE-thorsten-medium) für WhatsApp-Sprachnachrichten |
|
||||||
|
| Frontend | Vanilla HTML/CSS/JS, Masonry-Layout, iOS-26-Design |
|
||||||
|
| Hosting | 4-Kern AMD EPYC, 8 GB RAM, 250 GB Disk, Linux |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Kanäle & Funktionen
|
||||||
|
|
||||||
|
### 3.1 WhatsApp-Intake
|
||||||
|
|
||||||
|
- **Webhook:** Meta Cloud API → `POST /whatsapp/webhook`
|
||||||
|
- **Unterstützte Formate:** Text, Bilder, Sprachnachrichten, Videos
|
||||||
|
- **Auto-Reply:**
|
||||||
|
- **Neuer Nutzer (erster Kontakt):** Ausführliche Willkommensnachricht mit Erklärung, DSGVO-Hinweis, TTS-Sprachnachricht (Piper Thorsten)
|
||||||
|
- **Bestehender Nutzer (neuer Thread):** Kurze Dankesnachricht
|
||||||
|
- **Thread-Fortsetzung (innerhalb 5 Min.):** Keine Antwort, Nachricht wird an bestehenden Thread angehängt
|
||||||
|
- **Transkription:** Sprachnachrichten und Videos werden automatisch mit faster-whisper transkribiert
|
||||||
|
- **KI-Anreicherung:** Nach Transkription automatische Zusammenfassung + Hallen/Stand-Erkennung via DeepSeek V4 Flash
|
||||||
|
- **Medien-Download:** Bilder, Audio, Video werden von Meta-Servern heruntergeladen und lokal gespeichert
|
||||||
|
|
||||||
|
### 3.2 Web-Submit-Formular
|
||||||
|
|
||||||
|
- **Zugang:** Floating „+“-Button auf dem öffentlichen Frontend
|
||||||
|
- **Eingabefelder:**
|
||||||
|
- Name (optional, Vorname/Spitzname)
|
||||||
|
- Nachricht (optional, max. 5.000 Zeichen)
|
||||||
|
- Medien-Upload: Foto (Kamera), Video (Kamera), Audio (Mikrofon), Galerie
|
||||||
|
- Halle/Stand (optional)
|
||||||
|
- Spieltitel (optional)
|
||||||
|
- **Capture-Buttons:** Mobile-First — direkter Kamera-/Mikrofon-Zugriff ohne Galerie-Umweg
|
||||||
|
- **Bestätigung:** Nach erfolgreicher Einreichung wird eine **Referenz-ID** angezeigt, die für spätere Löschanträge notiert werden soll
|
||||||
|
- **KI-Anreicherung:** Automatische LLM-Zusammenfassung + Hallen-Erkennung im Hintergrund
|
||||||
|
- **Speicherung:** `channel='web'`, `status='new'`
|
||||||
|
|
||||||
|
### 3.3 Admin-Dashboard (`/admin`)
|
||||||
|
|
||||||
|
- **Zugang:** Aktuell ungeschützt (lokal); auf dem Server über den cloudflared-Tunnel erreichbar
|
||||||
|
- **Funktionen:**
|
||||||
|
- Tabellarische Übersicht aller Einreichungen
|
||||||
|
- Filterung nach Status (Neu, Publiziert, Markiert) per Pill-Buttons
|
||||||
|
- Detailansicht pro Einreichung (`/submission/<id>`):
|
||||||
|
- Absender, Typ, Inhalt, Status, Kategorie
|
||||||
|
- Medien-Vorschau (Bilder, Videos, Audio)
|
||||||
|
- **Per-Media-Veröffentlichungs-Checkboxen** (Toggle-Switches)
|
||||||
|
- **Inline-Editing:** Spieltitel, Zusammenfassung, Halle, Veröffentlichungsname
|
||||||
|
- **LLM-Zusammenfassung-Button** (KI-generierte 2–3-Satz-Zusammenfassung)
|
||||||
|
- **Veröffentlichen-Button** (Status: `new` → `published`)
|
||||||
|
- **Veröffentlichung-zurücknehmen-Button** (Status: `published` → `new`)
|
||||||
|
- **Erledigt-Button** (Status: `new` → `done`)
|
||||||
|
- **Löschen-Button** (mit Bestätigungsdialog, löscht Medien + DB-Eintrag hart)
|
||||||
|
- iOS-26-Design: Dark/Light-Theme, Glass-Header, Pill-Buttons, Mobile-Bottom-Bar
|
||||||
|
- Auto-Refresh alle 30 Sekunden
|
||||||
|
- Theme-Toggle (🌓) mit localStorage-Persistenz
|
||||||
|
|
||||||
|
### 3.4 Öffentliches Frontend (`/`)
|
||||||
|
|
||||||
|
- **Design:** SPIEL Essen inspiriert, gelber Hintergrund (#FCE812), Masonry-Layout
|
||||||
|
- **Anzeige:** Nur veröffentlichte Beiträge (`status='published'`, `deleted_at IS NULL`)
|
||||||
|
- **Karten:**
|
||||||
|
- Bild/Video-Karten: Medien-Vorschau mit Frosted-Glass-Timestamp
|
||||||
|
- Text-Karten: Kompakt, 4-Zeilen-Preview
|
||||||
|
- Badges: 📍 Halle, 🚫 AUSVERKAUFT
|
||||||
|
- **Filter:** Dropdown-Filter für Halle (H1–H7) und Kategorie
|
||||||
|
- **Detailseite:** `/beitrag/<id>` — vollständiger Beitrag mit Medien, Metadaten, Beitrags-ID (für DSGVO-Löschanträge)
|
||||||
|
- **Floating Buttons:**
|
||||||
|
- 💬 Chat-Bubble (BSN Assistant)
|
||||||
|
- ➕ Submit-Button (Einreich-Formular)
|
||||||
|
|
||||||
|
### 3.5 Chat-Assistant (`/api/chat`)
|
||||||
|
|
||||||
|
- **Typ:** Read-Only — beantwortet Fragen nur auf Basis veröffentlichter Beiträge
|
||||||
|
- **Modell:** DeepSeek V4 Flash
|
||||||
|
- **Kontext:** Bis zu 60 aktuellste veröffentlichte Beiträge
|
||||||
|
- **Sicherheit:**
|
||||||
|
- Kein Zugriff auf Rohdaten
|
||||||
|
- Antwortet nur aus dem Kontext
|
||||||
|
- Ehrlichkeits-Prompt: „Dazu habe ich leider keine Informationen“ bei Unbekanntem
|
||||||
|
- **Frontend:** Chat-Overlay mit Nachrichten-Bubbles, TTS-Button (Web Speech API, Deutsch), Typing-Indikator
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Datenverarbeitung
|
||||||
|
|
||||||
|
### 4.1 Gespeicherte Daten pro Einreichung (`submissions`-Tabelle)
|
||||||
|
|
||||||
|
| Feld | Beschreibung | Personenbezug |
|
||||||
|
|---|---|---|
|
||||||
|
| `id` | Fortlaufende Nummer | Nein |
|
||||||
|
| `channel` | Kanal (`whatsapp`, `web`) | Nein |
|
||||||
|
| `sender_id` | WhatsApp-Nummer oder `web_<Name>` | **Ja** (Telefonnummer bei WhatsApp) |
|
||||||
|
| `sender_name` | WhatsApp-Profilname (automatisch) | **Ja** |
|
||||||
|
| `type` | `text`, `image`, `audio`, `video`, `document` | Nein |
|
||||||
|
| `content` | Nachrichtentext / Transkription | **Ja** (Inhalt) |
|
||||||
|
| `media_path` | Pfade zu gespeicherten Mediendateien | **Ja** (Bilder, Audio, Video) |
|
||||||
|
| `media_publish_flags` | Pro-Medium 0/1 (welche Medien öffentlich) | Nein |
|
||||||
|
| `status` | `new`, `done`, `published`, `flagged`, `gdpr_deleted` | Nein |
|
||||||
|
| `category` | KI-klassifizierte Kategorie | Nein |
|
||||||
|
| `summary` | KI-generierte Zusammenfassung | Nein |
|
||||||
|
| `publish_name` | Name zur Veröffentlichung (nur mit Einwilligung) | **Ja** |
|
||||||
|
| `halle` | Extrahierte Hallen/Stand-Info | Nein |
|
||||||
|
| `spiel_titel` | Extrahierter Spieltitel | Nein |
|
||||||
|
| `published_at` | Veröffentlichungszeitpunkt | Nein |
|
||||||
|
| `deleted_at` | Soft-Delete-Zeitpunkt | Nein |
|
||||||
|
| `created_at` | Erstellungszeitpunkt | Nein |
|
||||||
|
|
||||||
|
### 4.2 Einwilligung (Consent)
|
||||||
|
|
||||||
|
- **WhatsApp:** Der erste Kontakt erhält eine Nachricht, die erklärt, dass das Nennen des Vornamens die Einwilligung zur Namensnennung als Quelle darstellt. Ohne Name = „anonyme Quelle“.
|
||||||
|
- **Web-Formular:** Name ist optional. Wird ein Name angegeben, gilt dies als Einwilligung zur Nennung.
|
||||||
|
- **Keine Checkbox:** Die Einwilligung erfolgt konkludent durch die freiwillige Angabe des Namens.
|
||||||
|
|
||||||
|
### 4.3 DSGVO-Löschung
|
||||||
|
|
||||||
|
- **WhatsApp:** Nutzer sendet „Meine Daten löschen“ → Alle Einreichungen + Medien dieser Nummer werden sofort gelöscht. Ein anonymer DSGVO-Vermerk bleibt.
|
||||||
|
- **Web:** Nutzer notiert die bei Einreichung angezeigte **Referenz-ID**. Löschung aktuell nur durch Kontaktaufnahme mit der Redaktion (zukünftig: Selbstbedienungs-Löschformular).
|
||||||
|
- **Admin:** Beiträge können im Admin-Dashboard hart gelöscht werden (Medien + DB-Eintrag).
|
||||||
|
|
||||||
|
### 4.4 Speicherdauer
|
||||||
|
|
||||||
|
- Unveröffentlichte Einreichungen: Bis zur manuellen Löschung oder DSGVO-Anfrage
|
||||||
|
- Veröffentlichte Beiträge: Bis zur Zurücknahme oder Löschung
|
||||||
|
- DSGVO-Vermerke: Dauerhaft (Dokumentationspflicht)
|
||||||
|
- **Keine automatische Löschroutine** aktuell implementiert
|
||||||
|
|
||||||
|
### 4.5 Medien
|
||||||
|
|
||||||
|
- Gespeichert unter `./media/` auf dem Server
|
||||||
|
- WhatsApp: `whatsapp_<timestamp>.<ext>`
|
||||||
|
- Web: `web_<timestamp>.<ext>`
|
||||||
|
- Werden bei DSGVO-Löschung oder Admin-Löschung von der Platte entfernt
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Datenschutzrechtliche Relevanz
|
||||||
|
|
||||||
|
### 5.1 Personenbezogene Daten (Art. 4 DSGVO)
|
||||||
|
|
||||||
|
| Datenkategorie | Vorhanden | Quelle |
|
||||||
|
|---|---|---|
|
||||||
|
| Telefonnummer | ✅ | WhatsApp-Sender |
|
||||||
|
| Name (Vorname/Spitzname) | ✅ | WhatsApp-Profil + Nutzereingabe |
|
||||||
|
| Bildaufnahmen | ✅ | WhatsApp/Web-Upload (kann Personen zeigen) |
|
||||||
|
| Videoaufnahmen | ✅ | WhatsApp/Web-Upload (kann Personen zeigen) |
|
||||||
|
| Sprachaufnahmen | ✅ | WhatsApp/Web-Upload |
|
||||||
|
| Inhaltsdaten | ✅ | Nutzertexte |
|
||||||
|
| Standortdaten | ❌ | Nicht erfasst |
|
||||||
|
|
||||||
|
### 5.2 Erforderliche Dokumente
|
||||||
|
|
||||||
|
1. **Datenschutzerklärung** — für das öffentliche Frontend (`/`)
|
||||||
|
2. **AGB / Nutzungsbedingungen** — für die Nutzung des Einreich-Formulars und Chat-Assistenten
|
||||||
|
3. **Impressum** — mit Kontaktdaten des Verantwortlichen
|
||||||
|
4. **Cookie-Hinweis** — aktuell: nur localStorage für Theme (Dark/Light), kein Tracking
|
||||||
|
|
||||||
|
### 5.3 Navigation (Vorschlag)
|
||||||
|
|
||||||
|
```
|
||||||
|
/
|
||||||
|
├── Startseite (Community-Feed)
|
||||||
|
├── Impressum
|
||||||
|
├── Datenschutz
|
||||||
|
├── AGB / Nutzungsbedingungen
|
||||||
|
└── Fußzeile (Footer)
|
||||||
|
├── brettspiel-news.de
|
||||||
|
├── Impressum
|
||||||
|
├── Datenschutz
|
||||||
|
└── AGB
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Technische Details
|
||||||
|
|
||||||
|
### 6.1 Server
|
||||||
|
|
||||||
|
- **Host:** 4-Kern AMD EPYC, 8 GB RAM, 250 GB Disk
|
||||||
|
- **OS:** Linux (Debian)
|
||||||
|
- **Prozess:** Flask läuft als Hintergrundprozess mit Keepalive-Thread (gegen Inaktivitäts-Timeout)
|
||||||
|
- **Start:** `cd ~/workspace/bsn-chatbot && source .env && /home/hermes/venv/bin/python app.py`
|
||||||
|
- **Port:** 5002 (localhost only)
|
||||||
|
- **Tunnel:** cloudflared token-basiert → `chat.datenhimmel.work`
|
||||||
|
|
||||||
|
### 6.2 Meta / WhatsApp
|
||||||
|
|
||||||
|
- **App:** Brettspiel-News.de (App-ID: `1864231860438511`)
|
||||||
|
- **Token:** Permanent System User Token (läuft nie ab)
|
||||||
|
- **Phone Number ID:** `1152708791258718`
|
||||||
|
- **Test-Nummer:** `16315551181` (Meta-Testnummer)
|
||||||
|
|
||||||
|
### 6.3 KI-Dienste
|
||||||
|
|
||||||
|
- **DeepSeek V4 Flash:** via `https://ui.datenhimmel.work/api/chat/completions` (API-Key in `~/.hermes/config.yaml`)
|
||||||
|
- **faster-whisper:** Lokal unter `/home/hermes/.hermes/venvs/speech/`, Modell `base`
|
||||||
|
- **Piper TTS:** Lokal unter `~/.local/bin/piper`, Stimme `de_DE-thorsten-medium`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Aktueller Feature-Stand
|
||||||
|
|
||||||
|
| Feature | Status |
|
||||||
|
|---|---|
|
||||||
|
| WhatsApp Webhook (Text, Bild, Audio, Video) | ✅ Produktiv |
|
||||||
|
| WhatsApp Auto-Reply (Onboarding + Thread) | ✅ Produktiv |
|
||||||
|
| WhatsApp TTS-Onboarding (Thorsten) | ✅ Produktiv |
|
||||||
|
| Sprachnachrichten-Transkription | ✅ Produktiv |
|
||||||
|
| Video-Transkription | ✅ Produktiv |
|
||||||
|
| Auto-LLM-Zusammenfassung + Hallen-Erkennung | ✅ Produktiv |
|
||||||
|
| Web-Submit-Formular mit Capture-Buttons | ✅ Produktiv |
|
||||||
|
| Referenz-ID mit Kopier-Button nach Web-Submit | ✅ Produktiv |
|
||||||
|
| DSGVO-Löschung per WhatsApp („Meine Daten löschen“) | ✅ Produktiv |
|
||||||
|
| Admin-Dashboard mit iOS-26-Design | ✅ Produktiv |
|
||||||
|
| Admin-Detailview mit Medien-Toggles | ✅ Produktiv |
|
||||||
|
| Admin-Unpublish (Veröffentlichung zurücknehmen) | ✅ Produktiv |
|
||||||
|
| Admin-LLM-Zusammenfassung-Button | ✅ Produktiv |
|
||||||
|
| Admin-Delete mit Bestätigungsdialog | ✅ Produktiv |
|
||||||
|
| Admin-Theme-Toggle (Dark/Light) | ✅ Produktiv |
|
||||||
|
| Öffentliches Frontend (Masonry-Layout) | ✅ Produktiv |
|
||||||
|
| Frontend-Filter (Halle + Kategorie) | ✅ Produktiv |
|
||||||
|
| Beitrags-Detailseite mit ID-Footer | ✅ Produktiv |
|
||||||
|
| Chat-Assistant (Read-Only, RAG) | ✅ Produktiv |
|
||||||
|
| DSGVO-Löschung per Web-ID | ⏳ In Planung |
|
||||||
|
| AGB / Datenschutz / Impressum | ❌ Fehlt |
|
||||||
|
| Cookie-Consent-Banner | ❌ Nicht nötig (kein Tracking) |
|
||||||
|
| Zugangsschutz für /admin | ❌ Fehlt |
|
||||||
|
| Automatische Löschroutine | ❌ Fehlt |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Datei-Übersicht (Projektverzeichnis)
|
||||||
|
|
||||||
|
```
|
||||||
|
~/workspace/bsn-chatbot/
|
||||||
|
├── app.py # Flask-Hauptanwendung (2.700+ Zeilen)
|
||||||
|
├── bsn_intake.db # SQLite-Datenbank
|
||||||
|
├── .env # Secrets (Meta-Token etc., nicht in Git)
|
||||||
|
├── .env.bak # Backup (nicht in Git)
|
||||||
|
├── .gitignore # Schützt Secrets, DB, Medien vor Commit
|
||||||
|
├── media/ # Hochgeladene Mediendateien (nicht in Git)
|
||||||
|
└── bsn-chatbot/SKILL.md # Entwickler-Dokumentation (Skill)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Erstellt von Basti (Hermes Agent) am 17.06.2026 für Daniel Krause / brettspiel-news.de*
|
||||||
@@ -2672,8 +2672,7 @@ def public_detail(sub_id: int):
|
|||||||
<body>
|
<body>
|
||||||
<header class="site-header">
|
<header class="site-header">
|
||||||
<a href="/" class="site-logo">
|
<a href="/" class="site-logo">
|
||||||
<div class="logo-icon">🎲</div>
|
<img src="data:image/jpeg;base64,{LOGO_B64}" alt="Brettspiel News" style="height:30px;width:auto;display:block;">
|
||||||
<div class="logo-text">BSN Community</div>
|
|
||||||
</a>
|
</a>
|
||||||
</header>
|
</header>
|
||||||
<main class="detail-container">
|
<main class="detail-container">
|
||||||
|
|||||||
Reference in New Issue
Block a user