mirror of
https://github.com/skoelle/calender_sync.git
synced 2026-09-17 18:20:24 +00:00
docs: add README.md and AGENTS.md
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
Richtlinien für AI-Agenten die mit dem calender_sync Projekt arbeiten.
|
||||||
|
|
||||||
|
## Projektübersicht
|
||||||
|
|
||||||
|
Python-basierter Google Calendar → MariaDB Synchronizer. Läuft als Docker Container im Homelab und pollt periodisch einen ICS-Feed.
|
||||||
|
|
||||||
|
## Technologie-Stack
|
||||||
|
|
||||||
|
- **Sprache**: Python 3.12
|
||||||
|
- **Datenbank**: MariaDB (mysql-connector-python)
|
||||||
|
- **Docker**: Multi-Stage Build nicht verwendet, simples Slim-Image
|
||||||
|
- **Dependencies**: requests, icalendar, recurring-ical-events, mysql-connector-python
|
||||||
|
|
||||||
|
## Projektstruktur
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── sync.py # Hauptskript (alles in einer Datei)
|
||||||
|
├── requirements.txt # Python Dependencies
|
||||||
|
├── Dockerfile # Docker Image Definition
|
||||||
|
├── docker-compose.yml # Docker Compose Konfiguration
|
||||||
|
├── mariadb-setup.sql # Manuelles DB-Setup Script
|
||||||
|
├── .env.example # Beispiel-Umgebungsvariablen
|
||||||
|
└── .github/workflows/ # CI/CD (Docker Build + Push)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Wichtige Hinweise
|
||||||
|
|
||||||
|
### Kein Framework
|
||||||
|
Das Projekt verwendet kein Web-Framework. `sync.py` ist ein eigenständiges Python-Skript mit einer Endlosschleife (`main()` → `time.sleep()`).
|
||||||
|
|
||||||
|
### Datenbank-Schema
|
||||||
|
Schema wird in `ensure_schema()` per `CREATE TABLE IF NOT EXISTS` erstellt. Bei Schema-Änderungen:
|
||||||
|
- `ensure_schema()` in `sync.py:91` anpassen
|
||||||
|
- MariaDB-kompatibles SQL verwenden (kein PostgreSQL-Specific)
|
||||||
|
- Indexe für Performance bedenken
|
||||||
|
|
||||||
|
### Event-Expansion
|
||||||
|
Verwendet `recurring_ical_events` Bibliothek für RRULE/EXDATE/RECURRENCE-ID Expansion. Fenster wird über `WINDOW_PAST_DAYS`/`WINDOW_FUTURE_DAYS` gesteuert.
|
||||||
|
|
||||||
|
### UTC-Normalisierung
|
||||||
|
Alle Zeiten werden in naive UTC datetime konvertiert (`to_naive_utc()`). Bei Datumsänderungen sicherstellen, dass Zeitzone korrekt处理 wird.
|
||||||
|
|
||||||
|
### Soft-Delete
|
||||||
|
Events werden nicht gelöscht, sondern mit `deleted=1` markiert (`mark_missing_as_deleted()`).
|
||||||
|
|
||||||
|
## Entwicklung
|
||||||
|
|
||||||
|
### Lokaler Test
|
||||||
|
```bash
|
||||||
|
# Dependencies installieren
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# .env anlegen (aus .env.example kopieren)
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Direkt ausführen
|
||||||
|
python sync.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linting & Type Checking
|
||||||
|
Keine Linting/Type-Checking Tools konfiguriert. Bei Bedarf hinzufügen:
|
||||||
|
- `ruff` für Linting
|
||||||
|
- `mypy` für Type Checking
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
Keine Tests vorhanden. Bei Bedarf:
|
||||||
|
- `pytest` als Test-Framework verwenden
|
||||||
|
- Mock für `requests.get()` und `mysql.connector` erstellen
|
||||||
|
- Unit Tests für `to_naive_utc()`, `instance_key_for()`, `expand_events()`
|
||||||
|
|
||||||
|
## Code-Style
|
||||||
|
|
||||||
|
- Kein Docstring-Standard definiert
|
||||||
|
- Logging über `logging` Modul mit configurable Level
|
||||||
|
- Error Handling: Exceptions fangen, loggen, aber nicht verschlucken
|
||||||
|
- Keine externen Config-Libraries (nur `os.environ`)
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
- Image basiert auf `python:3.12-slim`
|
||||||
|
- Kein Multi-Stage Build nötig (einfaches Projekt)
|
||||||
|
- `PYTHONUNBUFFERED=1` für Logging im Container
|
||||||
|
- Watchtower Label für Auto-Updates
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
GitHub Actions Workflow:
|
||||||
|
- Baut Docker Image bei Push zu `main`
|
||||||
|
- Published nach `ghcr.io/skoelle/calender_sync:latest`
|
||||||
|
- Keine Tests im Workflow (derzeit)
|
||||||
@@ -1 +1,105 @@
|
|||||||
# calender_sync
|
# calender_sync
|
||||||
|
|
||||||
|
Google Calendar (ICS-Feed) → MariaDB Sync fürs Homelab.
|
||||||
|
|
||||||
|
Läuft als Docker Container, pollt periodisch einen privaten Google Calendar ICS-Feed, expandiert RRULE/EXDATE/RECURRENCE-ID und schreibt einzelne Instanzen in eine MariaDB-Datenbank.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Automatische Synchronisation alle 15 Minuten (konfigurierbar)
|
||||||
|
- Expandiert wiederkehrende Events (RRULE) und Serien-Exceptions (EXDATE, RECURRENCE-ID)
|
||||||
|
- Soft-Delete: Entfernte Events werden als `deleted=1` markiert, nicht gelöscht
|
||||||
|
- Optionales Database-Bootstrap: Erstellt DB und User automatisch bei `DB_BOOTSTRAP=true`
|
||||||
|
- Zeitfenster-konfiguration für Vergangenheit/Future (standardmäßig -90 Tage / +365 Tage)
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- Docker & Docker Compose
|
||||||
|
- MariaDB Instanz (z.B. als Proxmox LXC)
|
||||||
|
- Google Calendar mit privatem ICS-Feed
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **MariaDB Setup**
|
||||||
|
|
||||||
|
Entweder manuell ausführen:
|
||||||
|
```bash
|
||||||
|
mysql -u root -p < mariadb-setup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
Oder automatisch beim Start (in `.env` setzen):
|
||||||
|
```
|
||||||
|
DB_BOOTSTRAP=true
|
||||||
|
DB_ROOT_USER=root
|
||||||
|
DB_ROOT_PASSWORD=dein_root_passwort
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **.env anlegen**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Variablen anpassen, insbesondere:
|
||||||
|
- `ICS_URL`: Privater ICS-Link aus den Google Calendar Einstellungen
|
||||||
|
- `DB_PASSWORD`: Sicheres Passwort für den calendar_sync User
|
||||||
|
|
||||||
|
3. **Starten**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
| Variable | Default | Beschreibung |
|
||||||
|
|----------|---------|--------------|
|
||||||
|
| `ICS_URL` | *required* | Privater ICS-Feed aus Google Calendar |
|
||||||
|
| `CALENDAR_LABEL` | `default` | Label für den Kalender (für Multi-Kalender) |
|
||||||
|
| `DB_HOST` | `mariadb.fritz.box` | MariaDB Host |
|
||||||
|
| `DB_PORT` | `3306` | MariaDB Port |
|
||||||
|
| `DB_NAME` | `calendar_sync` | Datenbank-Name |
|
||||||
|
| `DB_USER` | *required* | Datenbank-User |
|
||||||
|
| `DB_PASSWORD` | *required* | Datenbank-Passwort |
|
||||||
|
| `SYNC_INTERVAL_MINUTES` | `15` | Sync-Intervall in Minuten |
|
||||||
|
| `WINDOW_PAST_DAYS` | `90` | Wie viele Tage in die Vergangenheit synchronisieren |
|
||||||
|
| `WINDOW_FUTURE_DAYS` | `365` | Wie viele Tage in die Zukunft synchronisieren |
|
||||||
|
| `LOG_LEVEL` | `INFO` | Python Logging Level |
|
||||||
|
| `DB_BOOTSTRAP` | `false` | DB + User beim Start erstellen |
|
||||||
|
| `DB_ROOT_USER` | - | Root-User fürs Bootstrap |
|
||||||
|
| `DB_ROOT_PASSWORD` | - | Root-Passwort fürs Bootstrap |
|
||||||
|
|
||||||
|
## Datenbank-Schema
|
||||||
|
|
||||||
|
Tabelle `calendar_events`:
|
||||||
|
|
||||||
|
| Spalte | Typ | Beschreibung |
|
||||||
|
|--------|-----|--------------|
|
||||||
|
| `id` | BIGINT PK | Auto-Increment |
|
||||||
|
| `calendar_label` | VARCHAR(64) | Kalender-Label |
|
||||||
|
| `instance_key` | VARCHAR(255) | SHA1-basierte eindeutige Instanz-ID |
|
||||||
|
| `uid` | VARCHAR(255) | ICS UID |
|
||||||
|
| `recurrence_id` | VARCHAR(64) | RECURRENCE-ID bei Serien-Exceptions |
|
||||||
|
| `summary` | VARCHAR(512) | Titel |
|
||||||
|
| `description` | TEXT | Beschreibung |
|
||||||
|
| `location` | VARCHAR(512) | Ort |
|
||||||
|
| `start_at` | DATETIME | Startzeit (UTC) |
|
||||||
|
| `end_at` | DATETIME | Endzeit (UTC) |
|
||||||
|
| `all_day` | TINYINT(1) | Ganz-tagig Flag |
|
||||||
|
| `status` | VARCHAR(32) | Event-Status |
|
||||||
|
| `deleted` | TINYINT(1) | Soft-Delete Flag |
|
||||||
|
| `last_seen_at` | DATETIME | Letzte Synchronisation |
|
||||||
|
| `created_at` | DATETIME | Erstellungszeitpunkt |
|
||||||
|
| `updated_at` | DATETIME | Letzte Änderung |
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
GitHub Actions Workflow (`docker-publish.yml`) baut und published das Docker Image automatisch nach GitHub Container Registry:
|
||||||
|
|
||||||
|
```
|
||||||
|
ghcr.io/skoelle/calender_sync:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lizenz
|
||||||
|
|
||||||
|
Keine Lizenz angegeben.
|
||||||
|
|||||||
Reference in New Issue
Block a user