Compare commits
2 Commits
4863d5f139
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6896798561 | |||
| 4607f2b497 |
121
README.md
121
README.md
@@ -1,11 +1,24 @@
|
|||||||
# IGMG Gebetszeiten -> ICS (Traefik File Provider)
|
# IGMG Gebetszeiten → iCalendar (.ics) Feed (Docker + Traefik)
|
||||||
|
|
||||||
## Start
|
Dieses Projekt erzeugt aus dem IGMG-Gebetskalender (AJAX-Quelle) einen **abonnierbaren iCalendar-Feed (.ics)** und stellt ihn über einen Webserver bereit.
|
||||||
```bash
|
Ein separater Updater-Container aktualisiert den Feed **automatisch** (Standard: **monatlich**).
|
||||||
cp .env.example .env
|
|
||||||
nano .env
|
Ziel: Du kannst den Link in Google Calendar / iOS Kalender / Outlook etc. als **Kalender-Abo** hinzufügen und bekommst immer die aktuellen Gebetszeiten.
|
||||||
docker compose up -d --build
|
|
||||||
```
|
---
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
|
||||||
|
- **Updater-Container** (Python + Cron)
|
||||||
|
- ruft die IGMG-AJAX-Quelle ab
|
||||||
|
- parst die HTML-Antwort
|
||||||
|
- schreibt atomar eine `.ics` Datei und eine `index.html` in ein Docker-Volume
|
||||||
|
|
||||||
|
- **Web-Container** (nginx)
|
||||||
|
- liefert das Volume `/data` via HTTP aus
|
||||||
|
- Traefik routet von außen auf nginx
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Container bauen und pushen
|
## Container bauen und pushen
|
||||||
```bash
|
```bash
|
||||||
@@ -25,3 +38,97 @@ docker buildx build \
|
|||||||
-f ./web/Dockerfile \
|
-f ./web/Dockerfile \
|
||||||
.
|
.
|
||||||
```
|
```
|
||||||
|
---
|
||||||
|
## Architektur
|
||||||
|
```
|
||||||
|
Internet
|
||||||
|
|
|
||||||
|
| https://gebetszeiten.musaberdem.de/igmg-20020.ics
|
||||||
|
v
|
||||||
|
Traefik (File Provider Routing)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
igmg-ics-web (nginx) ---> liest /data (read-only)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Docker Volume "igmg_ics_data" <--- igmg-ics-updater schreibt /data
|
||||||
|
^
|
||||||
|
|
|
||||||
|
igmg-ics-updater (cron + python)
|
||||||
|
```
|
||||||
|
|
||||||
|
Warum zwei Container?
|
||||||
|
|
||||||
|
- nginx bleibt minimal und sicher (nur statische Dateien)
|
||||||
|
- Updater hat Schreibrechte und macht die HTTP-Requests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dateistruktur
|
||||||
|
|
||||||
|
Beispiel-Struktur des Projekts:
|
||||||
|
```
|
||||||
|
igmg-ics/
|
||||||
|
docker-compose.yml
|
||||||
|
nginx.conf
|
||||||
|
.env.example
|
||||||
|
traefik/
|
||||||
|
dynamic/
|
||||||
|
igmg-ics.yml
|
||||||
|
updater/
|
||||||
|
Dockerfile
|
||||||
|
entrypoint.sh
|
||||||
|
crontab
|
||||||
|
update.py
|
||||||
|
README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Im Volume `igmg_ics_data` landen:
|
||||||
|
|
||||||
|
- `/data/<ICS_FILENAME>` → abonnierbarer Kalenderfeed
|
||||||
|
- `/data/index.html` → Landing-Page (Link + letzte Aktualisierung)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
Konfiguration erfolgt über eine `.env` Datei im Projektordner.
|
||||||
|
|
||||||
|
### Beispiel `.env`
|
||||||
|
|
||||||
|
```env
|
||||||
|
TZ=Europe/Berlin
|
||||||
|
PUID=1000
|
||||||
|
PGID=1000
|
||||||
|
|
||||||
|
CITY_ID=20020
|
||||||
|
CITY_SLUG=Blumberg_(DE)
|
||||||
|
LANG=de
|
||||||
|
|
||||||
|
ICS_FILENAME=igmg-20020.ics
|
||||||
|
```
|
||||||
|
|
||||||
|
Erklärung
|
||||||
|
|
||||||
|
- `TZ`: Zeitzone. Wichtig für korrekte Event-Zeiten.
|
||||||
|
- `CITY_ID`: ID aus der IGMG-URL (id=...)
|
||||||
|
- `CITY_SLUG`: stadt=... Teil der URL (wird nur als Quell-Link genutzt)
|
||||||
|
- `LANG`: de oder tr
|
||||||
|
- `ICS_FILENAME`: Dateiname, unter dem der Feed ausgeliefert wird
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kalender abonnieren
|
||||||
|
|
||||||
|
Der Feed ist erreichbar unter: https://gebetszeiten.musaberdem.de/igmg-20020.ics
|
||||||
|
|
||||||
|
Optional (einige Clients bevorzugen webcal): webcal://gebetszeiten.musaberdem.de/igmg-20020.ics
|
||||||
|
|
||||||
|
### Hinweise zu Kalendern
|
||||||
|
|
||||||
|
- Google Calendar: “Andere Kalender” → “Per URL” → HTTPS-Link einfügen
|
||||||
|
- iOS / macOS: Kalender → “Kalender hinzufügen” → “Kalenderabonnement”
|
||||||
|
- Outlook: “Kalender hinzufügen” → “Aus dem Internet” / “Abonnieren”
|
||||||
|
|
||||||
|
Hinweis: Kalender-Abos refreshen oft nur alle paar Stunden oder 1× täglich.
|
||||||
@@ -149,13 +149,20 @@ def month_add(year: int, month: int, delta: int) -> tuple[int, int]:
|
|||||||
m = (m % 12) + 1
|
m = (m % 12) + 1
|
||||||
return y, m
|
return y, m
|
||||||
|
|
||||||
def atomic_write(path: str, content: str):
|
def atomic_write(path: str, content: str, mode: int = 0o644):
|
||||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
fd, tmp_path = tempfile.mkstemp(prefix=os.path.basename(path) + ".", dir=os.path.dirname(path))
|
|
||||||
|
fd, tmp_path = tempfile.mkstemp(
|
||||||
|
prefix=os.path.basename(path) + ".",
|
||||||
|
dir=os.path.dirname(path),
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
with os.fdopen(fd, "w", encoding="utf-8", newline="") as f:
|
with os.fdopen(fd, "w", encoding="utf-8", newline="") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
|
os.chmod(tmp_path, mode)
|
||||||
os.replace(tmp_path, path)
|
os.replace(tmp_path, path)
|
||||||
|
os.chmod(path, mode)
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
if os.path.exists(tmp_path):
|
if os.path.exists(tmp_path):
|
||||||
|
|||||||
Reference in New Issue
Block a user