При обновлении календаря (раз в 13 минут) старая выгрузка сравнивается с новой по UID события. Бот присылает одно сообщение со списком изменений: новое событие, удалено, перенесено (было/стало). Учитываются и отдельные вхождения повторяющихся событий — перенос (RECURRENCE-ID) и удаление (EXDATE). Прошедшие события пропускаются: Яндекс выгружает всю историю календаря. В сообщении — не больше 10 изменений, остальные одной строкой «…и ещё N». Команда /changes включает и выключает эти уведомления; по умолчанию включены у всех, колонка alarms.changes добавляется при запуске. При подписке и замене ссылки сравнения нет. Closes #2
6 KiB
Я.Календаркин
Русский · English
Telegram-бот, который присылает уведомления о событиях из Яндекс.Календаря: утреннюю сводку на день, два напоминания перед событием и сообщение в момент начала. Достаточно прислать ссылку экспорта календаря.
Статус: личный проект, поддерживается · бот @calendarkin_ybot
Стек: Python 3.12 · aiogram 3 · aiohttp · icalendar · python-dateutil · pytz · PostgreSQL · Docker
Возможности
- Подписка по ссылке экспорта iCal; часовой пояс берётся из ссылки
- Повторяющиеся события (
RRULE) разворачиваются на сегодняшний день - Сводка на день в 8:00 по часовому поясу календаря (
/daily) - Два напоминания перед событием: по умолчанию за 15 и 5 минут, меняются в
/edit_alarm - Сообщение в момент начала события (
/moment) - Уведомление, если в календаре появилось новое событие, а предстоящее удалили или перенесли (
/changes) - Календарь обновляется раз в 13 минут; если обновление не удалось, остаётся прошлая версия
Пример уведомления:
Напоминаю!
Через 15 минут будет событие:
Созвон по проекту
Организатор: boss@example.com
10:00 — 11:00
Команды
| Команда | Что делает |
|---|---|
/link |
как получить ссылку на календарь |
/list |
события на сегодня |
/daily |
включить или выключить утреннюю сводку |
/moment |
включить или выключить сообщение в момент начала |
/changes |
включить или выключить уведомления о новых, удалённых и перенесённых событиях |
/get_alarm, /edit_alarm |
посмотреть и изменить время напоминаний |
/stop_alarm |
включить или выключить второе напоминание |
/notif |
приостановить или возобновить все уведомления |
/unsubscribe |
удалить подписку на календарь |
Запуск
git clone https://github.com/EDeev/y.calendarkin.git && cd y.calendarkin
cp .env.example .env # BOT_TOKEN от @BotFather
docker compose up -d
Готовый образ: docker pull ghcr.io/edeev/y.calendarkin или docker pull git.deev.su/edeev/y.calendarkin.
Таблицы в PostgreSQL создаются при первом запуске. Данные старой версии (SQLite users.db и clock.db)
переносит python scripts/migrate_sqlite.py --sqlite-dir путь/к/db --dsn postgresql://….
Без Docker: Python 3.10+, PostgreSQL, pip install -r requirements.txt, затем
cd code && BOT_TOKEN=… DATABASE_URL=postgresql://… python bot.py.
Как устроено
code/bot.py запуск и два фоновых цикла: проверка событий раз в минуту, обновление календарей
code/changes.py сравнение старой и новой выгрузки: новые, удалённые и перенесённые события
code/handlers.py команды и приём ссылки
code/script.py проверка ссылки, скачивание, разбор iCal и повторений, текст уведомления
code/sql.py пользователи, подписки и настройки напоминаний (PostgreSQL)
scripts/ перенос данных из SQLite
Принимаются только ссылки https://calendar.yandex.*: бот не скачивает файлы по произвольным адресам.
Ошибка у одного пользователя — битый календарь или заблокированный бот — не останавливает рассылку
остальным.
Разработка
pip install -r requirements-dev.txt
ruff check --select E9,F code tests && pytest
Тесты (хранилище — на PostgreSQL из TEST_DATABASE_URL) проверяют разбор календаря: события на сегодня, повторения, UNTIL в разных форматах, проверку
ссылки, текст уведомления и поиск изменений между выгрузками. Docker-образ собирается по тегу v* и публикуется в GitHub Packages и
git.deev.su.
Лицензия
MIT — см. LICENSE.
Автор
Деев Егор Викторович — GitHub · Telegram · egor@deev.space
Сделано с ❤️ — deev.space