Co-authored-by: Cursor <cursoragent@cursor.com>
Kantine BHZ Kiel-Wik – Speiseplan zu iCal
Liest die PDF-Speisepläne von kantine-bhz.de aus und erzeugt eine iCal-Datei (.ics) für den Import in Google Kalender. Jeder Termin enthält alle Tagesgerichte (I. bis V.) und ist auf 12:00 Uhr mittags gesetzt.
Voraussetzungen
- Python 3.9+ (für
zoneinfo) - Bestehendes venv unter
.venv
Installation
-
Virtuelle Umgebung aktivieren:
Windows (PowerShell):
.venv\Scripts\Activate.ps1Windows (CMD):
.venv\Scripts\activate.bat -
Abhängigkeiten installieren:
pip install -r requirements.txt
Nutzung
python kantine2ical.py
Erzeugt standardmäßig die Datei kantine_speiseplan.ics im aktuellen Verzeichnis.
Optionen:
-o DATEI/--output DATEI– Ausgabedatei (Standard:kantine_speiseplan.ics)--url URL– Basis-URL der Kantine (Standard:http://kantine-bhz.de)
Beispiel:
python kantine2ical.py -o mein_speiseplan.ics
Google Kalender Import
- Google Kalender öffnen
- Neben „Meine Kalender“ auf das Drei-Punkte-Menü klicken → Import
- Die erzeugte
.ics-Datei auswählen und dem gewünschten Kalender zuordnen
Die Termine erscheinen mit der Zeitzone Europe/Berlin um 12:00 Uhr mit allen fünf Tagesgerichten in der Beschreibung.
Server-Modus (abonnierbare URL)
Der Speiseplan kann als externer Kalender per URL angeboten werden. Ein Flask-Server liefert die iCal-Daten; Google Kalender und andere Clients können die URL direkt abonnieren. Im Hintergrund wird täglich nach neuen Speiseplan-PDFs gesucht und der Kalender aktualisiert.
Startseite: Unter der Stamm-URL (/) liefert der Server eine Startseite mit:
- der Abo-URL zum Kopieren (inkl. „Kopieren“-Button),
- einer Anleitung zur Einbettung in Google Kalender (Schritt für Schritt),
- Kurzhinweisen für andere Kalender-Apps (Outlook, Apple Kalender, Thunderbird, Android/iOS),
- der Angabe, wann die Speisepläne zuletzt aktualisiert wurden.
Die eigentliche iCal-Datei für Abos und direkten Download ist unter /calendar.ics erreichbar.
Voraussetzung: Für „Von URL hinzufügen“ in Google Kalender muss die Server-URL von außen erreichbar sein (öffentliche IP, Reverse-Proxy oder z. B. ngrok für Tests).
- Abhängigkeiten installieren (inkl. Flask):
pip install -r requirements.txt - Server starten:
Oder mit Flask-CLI:
python app.pyflask --app app run --host 0.0.0.0 --port 5000 - Im Browser die Startseite aufrufen:
http://<host>:5000/– dort die Abo-URL kopieren und die Anleitung nutzen. - Direkte Abo-URL:
http://<host>:5000/calendar.ics(bzw. Port durch Ihren Host ersetzen). - In Google Kalender: „Andere Kalender hinzufügen“ → „Von URL“ → Abo-URL eintragen.
Konfiguration (optional, Umgebungsvariablen):
KANTINE_BASE_URL– Basis-URL der Kantine (Standard:http://kantine-bhz.de)REFRESH_INTERVAL_SECONDS– Sekunden zwischen Aktualisierungen (Standard: 43200 = 12 h)PUBLIC_URL– Öffentliche Basis-URL (z. B.https://kantine.elpatron.me). Wenn gesetzt, wird diese URL für die Kalender-Abo-URL auf der Startseite verwendet. Empfohlen hinter HTTPS-Proxy, falls der Proxy keineX-Forwarded-Proto/X-Forwarded-Host-Header sendet – sonst erscheint dort weiterhinhttp://.
Docker (Production)
Für den Betrieb als Container (z. B. auf einem Server):
Build und Run:
docker build -t kantine2ical .
docker run -p 8000:8000 -e PUBLIC_URL=https://kantine.elpatron.me kantine2ical
(Ersetzen Sie https://kantine.elpatron.me durch Ihre öffentliche HTTPS-URL. Dann zeigt die Startseite die Kalender-URL mit https://.)
- Startseite (Anleitung + Abo-URL):
http://<host>:8000/bzw. Ihre HTTPS-URL - iCal-Abo:
http://<host>:8000/calendar.icsbzw.https://<host>/calendar.ics - Manueller Refresh:
GET /refresh(z. B.https://<host>/refresh) – löst sofort einen Abruf der Speiseplan-PDFs aus. Nützlich, wenn auf kantine-bhz.de ein neuer Plan liegt und der 24h-Refresh noch nicht gelaufen ist. Nach dem Aufruf enthält der Kalender die aktuellen Daten.
Kalender wird nicht aktualisiert? Container-Logs prüfen (docker logs <container>): Dort erscheinen gefundene PDFs und Fehler beim Laden/Parsen. Bei fehlgeschlagenem PDF wird die URL und die Exception geloggt.
Mit Docker Compose:
docker compose up -d
Deploy-Ablauf (Update auf dem Server): Nach git pull und docker build muss der Container neu gestartet werden, damit das neue Image genutzt wird – der laufende Container verwendet sonst weiter das alte Image.
git pull
docker compose build --no-cache # oder: docker build -t kantine2ical . --no-cache
docker compose up -d --force-recreate
Ohne Compose (einzelner Container):
git pull
docker build -t kantine2ical . --no-cache
docker stop <container-name> # laufenden Container stoppen
docker rm <container-name> # optional
docker run -d -p 8000:8000 -e PUBLIC_URL=https://kantine.elpatron.me --name kantine2ical kantine2ical
Der Container läuft auf Port 8000 und startet bei Bedarf neu (restart: unless-stopped).
Hinweis: Für den Einsatz in Production wird ein Reverse-Proxy mit HTTPS (z. B. Traefik, Caddy oder nginx) vor dem Container empfohlen, damit Google die Kalender-URL zuverlässig abrufen kann.