Robert ist der WhatsApp-Bot von Blockbuster. Diese Seite erklärt im Detail,
aus welchen Teilen das System besteht, wie Daten flieĂźen und was wo verarbeitet wird.
Alle vier Container laufen per Docker Compose auf einem Raspberry Pi. Der Bot spricht mit dem
Backend ausschlieĂźlich ĂĽber das interne Docker-Netz und authentifiziert sich bei jedem Request mit
einem gemeinsamen Geheimnis (X-Bot-Secret-Header). Von auĂźen ist nur der
Cloudflare-Tunnel erreichbar; der QR-Code zum Koppeln des WhatsApp-Kontos ist nur lokal auf dem
Pi abrufbar.
2. Eingehende Nachrichten: Roberts Entscheidungs-Pipeline
Jede Nachricht in einer Gruppe oder per DM durchläuft dieselbe Kette von Prüfungen, bevor
Robert antwortet:
Nachricht„Robert, wann ist Training?“
→
FilterBefehl (!hilfe, !absagen)? Gruppe stummgeschaltet? „Nur wenn getaggt“?
→
Kontext bauenWissen + Gedächtnis zusammensetzen
→
OpenAIgpt-4o-mini (Responses API)
→
AntwortText in den Chat, Austausch merken
Befehle zuerst: Nachrichten mit ! werden direkt verarbeitet und gehen nie an die KI.
!absagen und !plan sind Team-Admins vorbehalten (im Admin-Bereich unter „🛡️ Robert-Admins“ eingestellt).
Im Privatchat zeigt !absagen eine nummerierte Liste aller anstehenden Termine
(!absagen 2 sagt Nr. 2 ab), und !plan liefert den zuletzt generierten
Trainingsplan.
Pro Gruppe steuerbar: Im Admin-Bereich lässt sich je Gruppe einstellen, ob Robert frei antwortet,
nur wenn er mit @ erwähnt wird, oder gar nicht. Die Erwähnung erkennt er sowohl über seine
Telefonnummer-ID als auch ĂĽber seine WhatsApp-Lid.
Absagen per Sprache: Sagt ein Admin z. B. „Robert, sag das Training ab“, darf das Modell ein
Absage-Werkzeug aufrufen. Der Bot prüft serverseitig noch einmal, dass die Person wirklich Admin ist —
egal, was das Modell behauptet.
Schutz vor Schleifen: Pro Chat gilt eine kurze Abklingzeit zwischen Antworten, und Nachrichten
werden auf 1000 Zeichen gekĂĽrzt, bevor sie an die KI gehen.
3. Roberts Wissen: was er weiĂź und woher
Robert „weiß“ nichts von sich aus — vor jeder Antwort bekommt er einen frischen Kontextblock
mit Daten aus drei Quellen:
Quelle
Inhalt
Aktualisierung
Backend
Gruppen & Trainingstage, anstehende Termine und Spiele (inkl. Zu-/Absagen), heutiges Datum
Der Bot holt die Konfiguration alle 15–30 Sekunden vom Backend
Open-Meteo
Wettervorhersage je Termin („🌧️ Schauer 8–23 °C, 30 % Regen“)
Backend cached 3 h pro Ort; nur für Termine in den nächsten 16 Tagen
mixedvolleyball.net
Tabellenplatz, Punkte, Bilanz, letztes Ergebnis und nächstes Spiel von Blockbuster
Backend cached 6 h (SportsPress-API der Liga)
FĂĽr alles, was darĂĽber hinausgeht (aktuelle Fragen, Ergebnisse, Allgemeinwissen), darf Robert
eine Websuche über OpenAIs eingebautes Such-Werkzeug starten. Damit eine gesprächige
Gruppe keine Kosten produziert, ist die Suche auf eine Tagesobergrenze pro Chat gedeckelt
(Standard: 25). Schlägt die Suche fehl, antwortet er ohne sie, statt zu schweigen.
Gesprächletzte ≤ 12 Wortmeldungen pro Chat (30 min gültig)
→
Verdichtungab 12 Einträgen fasst die KI ältere zu einem Merkzettel zusammen
→
Backend-APIjede Änderung wird sofort durchgeschrieben
→
bot_memoryMerkzettel + letzte Wortmeldungen je Chat
Kurzzeitgedächtnis: die letzten Wortmeldungen wörtlich, in Gruppen mit Absender-Namen
(„Lena: wann spielen wir?“). Nach 30 Minuten Ruhe wird es fallen gelassen.
Langzeitgedächtnis: ein laufend verdichteter Merkzettel (max. 1500 Zeichen) pro Chat —
Fakten wie Spitznamen, Positionen oder Running Gags ĂĽberleben so beliebig lange.
Neustart-fest: beim Start lädt Robert alle Gedächtnisse aus der Datenbank zurück;
Chats, die länger als 30 Tage inaktiv waren, bleiben archiviert und belegen keinen Arbeitsspeicher.
5. Ausgehende Posts: die Outbox
Robert postet nie „von selbst“ — das Backend stellt Aufträge in Warteschlangen, die der Bot
zyklisch abarbeitet und quittiert. Erst nach erfolgreicher Zustellung wird ein Auftrag als
erledigt markiert; schlägt etwas fehl, bleibt er liegen und wird beim nächsten Durchlauf erneut
versucht.
WarteschlangenTermine · Spiele · Nachrichten (pending bis zur Quittung)
→
GET /api/bot/configBot fragt alle 15–30 s an
→
SendenTermin-Karten, Spiel-Posts, DMs mit 4 s Abstand
→
Quittung„posted“ / „sent“ mit WhatsApp-Message-ID
Termin-Karten: Termine werden als native WhatsApp-Termine gepostet (mit Titel, Zeit, Ort,
Beschreibung). Zu- und Absagen passieren direkt in WhatsApp („Teilnehmen / Vielleicht /
Absagen“) — Robert liest sie etwa einmal pro Minute mit und spiegelt sie ins Backend, damit der
Admin-Bereich sie anzeigt und Robert Fragen wie „Wer kommt morgen?“ beantworten kann.
Liga-Ergebnisse: Taucht im Liga-Feed ein neues Endergebnis von Blockbuster auf,
postet Robert Spielstand, Sätze und Tabellenplatz automatisch in die Spiel-Gruppen — pro Ergebnis
genau einmal (in der Datenbank vermerkt) und nur, solange es jĂĽnger als eine Woche ist.
Drosselung: Direktnachrichten (z. B. Abstimmungs-Links) gehen mit 4 Sekunden Abstand raus,
damit WhatsApp den Account nicht als Spam einstuft.
Absagen: Bei einer Absage editiert Robert die ursprüngliche Termin-Karte auf „abgesagt“
(ausgegraut) und postet zusätzlich eine Nachricht in die Gruppe.
Mitglieder-Abgleich: Alle 2 Minuten meldet der Bot die Mitglieder seiner Gruppen
(außer als „Archiv“ markierten) ans Backend, damit Telefonnummern den Spieler-Profilen zugeordnet
werden können.
6. Trainingsplanung mit KI: vom Wunsch zum Plan
1 · UmfrageAdmin startet Wunsch-Umfrage mit Frist
→
2 · Link in die GruppeRobert postet den Wunsch-Link
→
3 · Wünsche sammelnTeam trägt Wünsche ein und upvotet (ohne Login)
→
4 · Plan bauenzur Frist: gpt-5 entwirft den Trainingsplan
→
5 · Link postenRobert postet einen Link zum fertigen Plan
24 Stunden vor der Frist erinnert Robert die Gruppe einmalig an die Umfrage.
Der Planer (ein stärkeres Modell als im Chat, konfigurierbar über OPENAI_PLAN_MODEL)
bekommt Dauer, reservierte Spielzeit und die Wünsche sortiert nach Stimmen — und muss mit dem
Material auskommen, das die Halle hergibt: Netz und Bälle.
Statt einer Textwand postet Robert nur einen Link auf die Planseite. Der Admin kann den Plan
danach jederzeit im Tool neu generieren oder mit Zusatz-Anweisungen (z. B. „erste Stunde nur
2 Übungen") anpassen — der Link in der Gruppe zeigt immer den aktuellen Stand.
Ein Versuch pro Viertelstunde: schlägt die Generierung fehl, probiert es der Zeitplaner später
erneut, statt Kosten zu produzieren.
Wiederkehrende Trainings (Mo/Mi) postet der Zeitplaner automatisch ab 06:00 am Trainingstag —
ganz ohne KI, aus den hinterlegten Trainingszeiten.
7. Spiele & Aufstellung: die Abstimmung
1 · Spiel anlegenAdmin plant Spiel mit Positionen
→
2 · Links verteilenpersönliche Abstimmungs-Links per DM / in die Gruppe
→
3 · AbstimmenTeam wählt je Position; Passwort schützt den Link
→
4 · Aufstellungbeim Schließen wird die Aufstellung berechnet
→
5 · VerkündenRobert postet die Aufstellung in die Gruppe
Jede Stimme wird in einer Datenbank-Transaktion mit Zeilensperre gezählt — zwei gleichzeitige
Stimmen können sich nicht gegenseitig überschreiben.
Die Abstimmungs-Links enthalten ein zufälliges Token; zusätzlich schützt ein persönliches
Passwort davor, dass jemand fremde Links aus dem Gruppenchat benutzt.
Spieler sehen Namen, aber keine Telefonnummern anderer — die vollständigen Daten sieht nur
der Admin.
8. Was an OpenAI geht — und was nicht
Geht an OpenAI
Bleibt im System
Der Nachrichtentext (max. 1000 Zeichen), Absender-Vorname in Gruppen, der Kontextblock
(Termine, Trainingszeiten, Wetter, Liga), das Chat-Gedächtnis und — für Trainingspläne —
die gesammelten WĂĽnsche.
Telefonnummern, Abstimmungs-Tokens und Passwörter, Gruppen-IDs, API-Schlüssel,
sowie sämtliche Datenbank-Inhalte, die nicht ausdrücklich Teil des Kontextblocks sind.
Es gibt zwei getrennte API-SchlĂĽssel: einen fĂĽr Roberts Chat-Antworten
(OPENAI_API_KEY, Modell gpt-4o-mini) und optional einen eigenen fĂĽr die
Trainingsplan-Generierung (OPENAI_PLAN_API_KEY, Modell gpt-5). Alle
Schlüssel und Passwörter liegen ausschließlich in GitHub-Secrets bzw. der .env auf dem
Pi — nie im Code.
Alle Aufrufe laufen mit store: false — OpenAI speichert die Anfragen und
Antworten nicht auf seiner Plattform (keine Logs im OpenAI-Dashboard). Die Unterhaltungen
liegen ausschließlich in Roberts eigenem Gedächtnis (bot_memory), das jede Person per
!delete löschen kann.
9. Betrieb: Deploy, Gesundheit, Wiederanlauf
CI/CD: Jeder Push baut und testet Backend (JUnit + Testcontainers) und Bot
(Lint + Tests) auf GitHub Actions; erst danach deployt ein Runner auf dem Pi die neuen Images.
Schlägt der Health-Check fehl, werden automatisch die vorherigen Images wiederhergestellt.
Healthchecks: Docker prĂĽft Backend (/api/me) und Bot
(/health) laufend; das Backend startet erst, wenn die Datenbank bereit ist.
Heartbeat: Der Bot meldet alle 30 s seinen Verbindungsstatus ans Backend —
die Web-App zeigt einen Banner, wenn Robert getrennt ist oder einen neuen QR-Scan braucht.
Selbstheilung: Bei Verbindungsabriss verbindet sich der Bot mit wachsenden
Wartezeiten neu; klappt das sechsmal nicht, beendet er sich und Docker startet den Container
frisch. Die WhatsApp-Sitzung ĂĽberlebt in einem Docker-Volume, ebenso die Datenbank.
Schema-Migrationen: Flyway führt nummerierte SQL-Migrationen beim Start aus —
die Datenbank passt damit immer zur laufenden Code-Version.
10. Deine Daten: was gespeichert wird – und wie du sie löschst
Robert speichert nur, was er zum Organisieren von Training und Spielen braucht. Alle Daten liegen
in der PostgreSQL-Datenbank auf dem Raspberry Pi (siehe Abschnitt 1); von auĂźen ist nur der
Cloudflare-Tunnel erreichbar.
Daten
Wozu
Aufbewahrung
Telefonnummer & WhatsApp-Name der Mitglieder seiner Gruppen
Zuordnung zu Spielerprofilen, SchlĂĽssel- und Abstimmungs-Funktionen
solange du mit Robert in einer Gruppe bist (laufend abgeglichen)
Gesprächsverlauf mit Robert (Gedächtnis pro Chat)
damit er sich im Chat an den Verlauf erinnert
Kurzzeit ~30 min, Merkzettel dauerhaft – per !delete löschbar
Spielerprofil (interner Name, Nummer, Positionen)
Aufstellung & Voting
bis ein Admin es löscht
Zu-/Absagen & abgegebene Stimmen
Teilnahme & Aufstellung
am Termin/Spiel; Stimmen werden nur anonym aggregiert gespeichert
bis ein Admin annimmt/ablehnt – per !delete löschbar
🗑️ Deine Daten löschen: !delete
Schreib Robert im Privatchat die Nachricht !delete. Er löscht dann
sofort alles, was er ĂĽber dich gespeichert hat:
euren Gesprächsverlauf (sein Gedächtnis für diesen Chat),
einen eventuellen Interessenten-Eintrag zu deiner Nummer und
seine Kopie des WhatsApp-Chats – Robert löscht die Unterhaltung auf seiner Seite.
Die Bestätigung kommt noch, bevor der Chat verschwindet. Den Chat auf deinem Handy kann
Robert nicht löschen – das geht nur bei dir selbst. Im Kader hinterlegte Spielerdaten (Name, Nummer,
Positionen) verwaltet ein Admin – sag einem Admin Bescheid, wenn auch diese gelöscht werden sollen.
In einer Gruppe fĂĽhrt !delete nichts aus, sondern verweist auf den Privatchat.
An OpenAI gehen nur die in Abschnitt 8 genannten Inhalte; Telefonnummern, Tokens und
Passwörter bleiben im System. Weitergehende Auskunfts- oder Löschwünsche richtest du an die im
Impressum genannte Kontaktadresse.