Перейти к содержимому
← Все проекты

// личный проект

GitNotifyBot

Telegram-бот, который следит за публичными GitHub-репозиториями и присылает в чат короткие сводки об их обновлениях. Сводки готовит LLM на выбранном языке - как только выходит новый релиз или меняется отслеживаемый файл. Не нужно листать ленту релизов или подписываться на watcher: добавил репо командой в чате и читаешь только то, что тебе важно.

Стек Python 3.13, aiogram 3, PostgreSQL, OpenAI
Тип Личный инструмент, open-source

// зачем

Что приходит в чат

У GitHub есть свой watcher на релизы, но он шлёт в почту голый changelog. Хотелось получать короткую сводку, по делу, прямо в Telegram - и чтобы можно было задать стиль и язык под себя. Бот делает это: парсит обновление, прогоняет его через LLM с настройками чата и шлёт уведомление.

✨ Обновился репозиторий cli/cli (v2.45.0)

Релиз cli/cli v2.45.0

Что нового:
• Добавлена команда `gh repo lock` для блокировки новых issues.
• Исправлен сбой при отправке PR review через JSON pipe.

🔗 https://github.com/cli/cli/releases/tag/v2.45.0
Постоянное меню GitNotifyBot в Telegram

Постоянное меню: пять основных действий, всегда внизу чата

Подписка на репозиторий в режиме File

Подписка добавлена: репозиторий, режим, ветка, файл, baseline sha

// как работает

От подписки до уведомления

01

Подписка

Пользователь добавляет репозиторий прямо в чате через меню. Выбирает режим (релизы или файл), язык и стиль сводки. Подписка пишется в PostgreSQL.

02

Опрос GitHub

Воркер циклом обходит подписки, у которых наступило время проверки, и дёргает GitHub REST API. Для релизов сравнивает id, для файлов - blob sha.

03

Сводка от LLM

Если что-то изменилось, изменение уходит в OpenAI Responses API. Промт подставляет язык, стиль и пожелания чата. Ответ возвращается строгим json_schema.

04

Уведомление

Готовая сводка публикуется через бот-токен в чат. Параллельно она кэшируется в БД - чтобы не звать LLM повторно для других чатов с теми же настройками.

// режимы

Два режима отслеживания

Releases

Опрашивает GET /releases/latest, фиксирует baseline по id текущего релиза и шлёт уведомление только при появлении нового. Тело релиза идёт в LLM как есть.

File

Следит за одним файлом на default-ветке. Сравнивает blob sha, и если он изменился - забирает у GitHub патч последнего коммита, затронувшего этот путь. Хорошо подходит для CHANGELOG.md.

// возможности

Что ещё умеет

Настройки на чат

Свой язык сводки (ru/en), стиль (кратко/подробно) и свободные пожелания: например, «выделяй изменения CLI и API». Для каждого чата отдельно.

Кэш LLM-ответов

Один и тот же апдейт с одинаковыми настройками - один вызов OpenAI, шерится между чатами. Ключ кэша: id обновления + язык + стиль + хеш пожеланий + версия промта.

Постоянное меню

Reply-клавиатура с пятью основными действиями всегда внизу чата: добавить, список, проверить сейчас, настройки, помощь. Подфлоу - через инлайн-клавиатуры с FSM.

Ручная проверка

Кнопка «Проверить сейчас» сбрасывает next_check_at у подписок чата. Воркер подхватывает их на ближайшем цикле, без ожидания интервала.

// под капотом

Технические детали

Два процесса, одна БД

Бот и воркер - отдельные процессы, делят PostgreSQL. Бот отвечает за Telegram-трафик. Воркер опрашивает GitHub, зовёт OpenAI и шлёт уведомления через тот же бот-токен.

OpenAI Responses API

Использую новый Responses API с reasoning и строгим json_schema на выходе. Промты лежат в YAML с версионированием через prompt_version и подстановкой переменных.

SQLAlchemy 2 async + Alembic

Полный async-стек: asyncpg как драйвер, SQLAlchemy 2.0 ORM в async-режиме, Alembic для миграций. Никаких блокирующих вызовов в основном цикле.

aiogram 3 c FSM

Все диалоги добавления и настроек - через FSM aiogram 3. Reply-меню всегда снизу чата, инлайн-клавиатуры на подшаги. Команды и обработчики разделены по роутерам.

Pydantic 2

Конфигурация, схемы LLM-ответов и шаблоны промтов - всё на Pydantic 2 с валидацией на старте. Если в .env что-то не так, процесс падает сразу с понятной ошибкой.

Тесты и линт

pytest с фейками для GitHub и OpenAI - пайплайны прогоняются без сети. Линт через ruff, зависимости через uv. Структура слоёв: bot / worker / application / domain / integrations / storage.