diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ab593a5 --- /dev/null +++ b/.env.example @@ -0,0 +1,17 @@ +# --- Calendar sources (comma-separated iCal URLs) --- +CALENDAR_URLS=https://todo.zenkit.com/api/v1/lists/e33c3349-7c35-4c7b-b16f-c74fa6c17d2e/ical/2e5a8b0a-8f95-471e-82bd-1ebd4df191b7,https://todo.zenkit.com/api/v1/lists/8208ce8f-dd5e-4539-8b9e-e3d1ab6d1fe6/ical/59ce4a5c-59e1-4d7f-b421-94883d3f9bec + +# --- Refresh interval in seconds (900 = 15 minutes) --- +FETCH_INTERVAL_SECONDS=900 + +# --- HTTP server --- +PORT=8080 +CALENDAR_PATH=/calendar.ics +HTTP_TIMEOUT_SECONDS=30 + +# --- Optional RFC5545 PRODID --- +# PRODID=-//beging.de//Cal-Funnel 1.0//EN + +# --- Traefik (used by docker-compose labels) --- +TRAEFIK_HOST=cal.example.com +TRAEFIK_CERT_RESOLVER=letsencrypt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a85a596 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.env +.env.local +docker-compose.override.yml +.cursor/ +__pycache__/ +*.py[cod] +.venv/ +venv/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..a45c57f --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Cal-Funnel + +Merge multiple iCalendar feeds into one and serve the result over HTTP. Built with [mergecal](https://pypi.org/project/mergecal/) and designed to run behind Traefik. + +## Quick start + +1. Copy the environment template: + + ```bash + cp .env.example .env + ``` + +2. Edit `.env` and set your calendar URLs and Traefik host. + +3. Start behind Traefik (requires external `proxy` network): + + ```bash + docker compose up -d + ``` + +4. Subscribe your calendar client to: + + ``` + https:///calendar.ics + ``` + +## Local testing (without Traefik) + +Create `docker-compose.override.yml` (gitignored) with a port mapping: + +```yaml +services: + cal-funnel: + ports: + - "8080:8080" +``` + +Then run: + +```bash +docker compose up -d +curl http://localhost:8080/health +curl http://localhost:8080/calendar.ics +``` + +## Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `CALENDAR_URLS` | *(required)* | Comma-separated iCal feed URLs | +| `FETCH_INTERVAL_SECONDS` | `900` | How often feeds are re-fetched | +| `PORT` | `8080` | HTTP listen port | +| `CALENDAR_PATH` | `/calendar.ics` | Path served to calendar clients | +| `HTTP_TIMEOUT_SECONDS` | `30` | Per-feed fetch timeout | +| `PRODID` | *(optional)* | RFC5545 PRODID for merged calendar | +| `TRAEFIK_HOST` | *(compose only)* | Hostname for Traefik routing | +| `TRAEFIK_CERT_RESOLVER` | *(compose only)* | Traefik cert resolver name | + +## Endpoints + +| Path | Description | +|------|-------------| +| `/calendar.ics` | Merged iCalendar feed | +| `/health` | Health check (`200` when ready) | +| `/` | Short HTML page with subscription link | + +## Build image + +```bash +docker build -t cal-funnel:latest . +``` + +## License note + +mergecal is licensed under GPL-3.0. This project uses it as a self-hosted calendar merge tool. diff --git a/project.prompt.md b/project.prompt.md new file mode 100644 index 0000000..57154fb --- /dev/null +++ b/project.prompt.md @@ -0,0 +1 @@ +Create a Docker environment with a minimal base OS. The container should use the 'mergecal' library to fetch multiple iCalendar feeds from URLs provided via environment variables, merge them into a single feed, and update this at regular intervals. The fetch interval should also be configurable via the .env file. \ No newline at end of file