A self-hosted Docker service that fetches your ICS calendars and sends a formatted daily summary to a Telegram bot every morning.
- Docker + Docker Compose
- A Telegram bot token from @BotFather
- Your Telegram chat ID (get it from
https://api.telegram.org/bot<TOKEN>/getUpdates) after sending an email to your bot - ICS URLs for each calendar (secret iCal address from Google Calendar settings, or any ICS feed URL)
1. Clone and configure
git clone https://github.com/UseLess289/calendar-digest
cd calendar-digest2. Create and edit .env
TELEGRAM_TOKEN=123456:ABC-...
TELEGRAM_CHAT_ID=123456789
ICS_DOMICILE=https://calendar.google.com/calendar/ical/XXXXX/private-XXXXX/basic.ics
ICS_TRAVAIL=https://calendar.google.com/calendar/ical/XXXXX/private-XXXXX/basic.ics
ICS_UNIVERSITE=...You should add each ICS_ variable on the table at the top of digest.py.
3. Build
docker compose build4. Test
docker compose run --rm calendar-digestYou should receive a Telegram message within seconds.
Add to your crontab (crontab -e) to run every morning at 7am.
If your server is set to UTC, adjust for your timezone (e.g. UTC+2 in summer for Paris):
0 5 * * * cd /path/to/calendar-digest && docker compose run --rm calendar-digest
- Fetches each configured ICS URL at runtime
- Expands recurring events (RRULE) for the current day using
recurring-ical-events - Handles both timed events and all-day events, sorted chronologically
- Formats and sends a digest to your Telegram chat with HTML formatting
1. Add the new calendar to CALENDARS in digest.py:
CALENDARS = {
...
"Sport": os.getenv("ICS_SPORT"),
}2. Add its emoji to CAL_EMOJI:
CAL_EMOJI = {
...
"Sport": "🏃",
}3. Add the variable to .env:
ICS_SPORT=https://...Calendars with no URL set in .env are silently skipped.