Webanwendung, die die ICS-Kurskalender der DHBW Lörrach als HTML-Kalender darstellt — mit Wochen-, Monats- und Listenansicht, Kursauswahl und teilbaren URLs.
Die Datei courses.example.json kopieren nach public/courses.json und
dort die gewünschten Kurs-Codes eintragen.
python3 server.py # Port 8000
python3 server.py 9000 # anderer PortDann http://localhost:8000/ öffnen. Es ist nur Python 3 (Standardbibliothek) nötig, kein Build-Schritt, keine Abhängigkeiten.
server.py liefert die statischen Dateien aus und proxyt GET /ics/<kurs>
zum DHBW-Server (webmail.dhbw-loerrach.de), weil dieser keine CORS-Header
sendet. Antworten werden zehn Minuten im Speicher gecacht — gleich
lange wie im Browser, sodass Stundenplanänderungen nach spätestens
~20 Minuten sichtbar sind. Das gilt auch für einen geöffneten Tab ohne
Interaktion: Der Client lädt abgelaufene Feeds selbsttätig nach.
http://localhost:8000/?kurs=TIF25A&ansicht=woche&datum=2026-06-08
| Parameter | Werte | Default |
|---|---|---|
kurs |
Kurskürzel, z. B. TIF25A, WWI24B |
- |
ansicht |
woche, monat, liste |
woche |
datum |
ISO-Datum als Anker der Ansicht | heute |
datum wird beim Navigieren nur in die URL geschrieben, wenn es nicht
„heute" ist — ein Bookmark ohne datum zeigt also immer die aktuelle Woche.
Die Auswahlliste kommt aus courses.json (flaches Array von Kürzeln).
Neue Kurse einfach ergänzen; die Gruppierung im Dropdown wird aus dem
Kürzel abgeleitet. Kurse, die nicht in der Liste stehen, sind über das
Freitextfeld oder direkt per URL erreichbar — der Kalender existiert,
sobald die DHBW unter
https://stash.dhbw-loerrach.de/calendar/kal-<kurs>@dhbw-loerrach.de.ics
eine Datei bereitstellt.
Der Python-Code in server.py definiert einen Statischer Server und ICS-Proxy (Python-Stdlib).
Im Verzeichnis public befinden sich Dateien mit dem Code für die Webapp:
| Datei | Aufgabe |
|---|---|
index.html |
Seitengerüst |
style.css |
Gestaltung |
app.js |
Zustand, URL-Synchronisation, Steuerung |
ics.js |
Minimaler ICS-Parser |
views.js |
Renderer der drei Ansichten |
dhbw-logo.svg |
Logo der DHBW als SVG |
courses.json |
Gepflegte Kursliste (muss erstellt werden, siehe courses.example.json) |
Das Docker-Image wird über GitHub Actions gebaut und in die GitHub Container Registry veröffentlicht. Der VPS lädt die aktuelle Version aus GHCR und startet den Container über Docker Compose neu.
Ablauf:
- Änderungen nach GitHub pushen.
- GitHub Actions baut das Docker-Image (nur wenn sich relevante Dateien ändern, siehe
.github/workflows/docker.yml). - Das Image wird bei GitHub in die GHCR gepusht.
- Auf dem VPS wird das neue Image gepullt.
- Docker Compose startet den Container mit dem aktualisierten Image neu.
Auf dem VPS deployen:
docker compose pull dhbw-calendar
docker compose up -d dhbw-calendarDer Container läuft auf dem VPS hinter Traefik. Traefik übernimmt TLS,
Rate-Limiting und den Passwortschutz per HTTP Basic Auth. Benutzername und
Passwort-Hash werden aus der in .env gesetzten Variablen DHBW_AUTH gelesen.
Unter macOS lässt sich ein neuer bcrypt-Hash mit dem vorinstallierten
htpasswd erzeugen. Das Passwort wird dabei interaktiv abgefragt und nicht
in die Shell-History geschrieben:
htpasswd -nB -C 10 BENUTZERNAMEDie vollständige Ausgabe unverändert und mit einfachen Anführungszeichen in
.env eintragen:
DHBW_AUTH='BENUTZERNAME:$2y$10$REST_DES_HASHES'