# Favorite stickers Telegram bot Максимально простой бот для личных стикерпаков «Избранное»: пользователь отправляет медиа или стикер, бот сразу добавляет его в персональный набор. Повторная отправка того же стикера удаляет его. ## Возможности - Принимает фотографии, видео/видеосообщения до 3 секунд, GIF/анимации, документы с медиа и обычные или видео-стикеры. - Преобразует всё через `ffmpeg` в Telegram Video Sticker: WEBM/VP9, без звука, до 512 px и 256 КиБ. - Ограничивает входной файл по фактическому размеру и отклоняет разрешение выше 33,5 Мп; конвертации имеют таймаут и общий лимит параллельности. - Передаёт вход в `ffmpeg`/`ffprobe` через отдельный файловый дескриптор и запрещает вложенные файловые и сетевые протоколы. - Поэтому картинки и видео могут находиться в одном наборе. - Первый набор называется ` - Favorites `. - После лимита в 120 стикеров автоматически создаётся набор `... [2]`, затем `[3]` и т. д. - Повторная отправка исходного стикера или стикера из созданного ботом набора удаляет его. - Ничего не переставляет и не задаёт дополнительных вопросов. - Связи пользователей, наборов и стикеров хранятся в SQLite. > TGS — векторный формат Telegram, который `ffmpeg` не декодирует. Для TGS-стикера бот сразу показывает понятную ошибку. Статические и WEBM-стикеры поддерживаются. ## Требования - Python 3.11+ - [uv](https://docs.astral.sh/uv/) - `ffmpeg` и `ffprobe` с кодеком `libvpx-vp9` - токен Telegram-бота от [@BotFather](https://t.me/BotFather) ## Запуск ```bash uv sync export BOT_TOKEN='123456:token-from-botfather' uv run tg-favorite-stickers --check uv run tg-favorite-stickers ``` Бот работает через long polling. Дополнительная настройка в BotFather не требуется. ### Переменные окружения - `BOT_TOKEN` — обязательный токен бота. - `DATABASE_PATH` — SQLite-файл, по умолчанию `data/favorites.sqlite3`. - `MAX_DOWNLOAD_MB` — максимальный размер входного файла, по умолчанию `20`. - `FFMPEG_TIMEOUT_SECONDS` — общий таймаут одной конвертации, по умолчанию `60`. - `MAX_CONVERSIONS` — максимальное число одновременных конвертаций, по умолчанию `2`. Пример: ```bash cp .env.example .env set -a source .env set +a uv run tg-favorite-stickers ``` SQLite-файл нужен не только для списка наборов, но и для распознавания повторно отправленных стикеров. Его следует сохранять при переносе бота. Незавершённые операции Telegram↔SQLite сохраняются в журнале и восстанавливаются при следующем сообщении пользователя. С одной базой одновременно запускается только один экземпляр бота. ## Контейнер Локальная сборка и запуск с постоянным Docker volume: ```bash docker build -t tg-favorite-stickers . docker volume create tg-favorite-stickers-data docker run --rm \ --name tg-favorite-stickers \ --env BOT_TOKEN='123456:token-from-botfather' \ --mount source=tg-favorite-stickers-data,target=/app/data \ tg-favorite-stickers ``` Готовый multi-arch образ для `linux/amd64` и `linux/arm64` публикуется в `ghcr.io/kr0sh512/tg-favorite-stickers`. Ветка `main` получает теги `main`, `latest` и `sha-…`, а Git-теги вида `v*` публикуются под своим именем: ```bash docker pull ghcr.io/kr0sh512/tg-favorite-stickers:latest ``` GitHub Actions проверяет тесты перед сборкой. Для pull request образ только собирается, но не публикуется в registry. ## Проверка ```bash uv sync --extra test uv run pytest ``` ## Структура - `src/favorite_stickers/bot.py` — обработчики Telegram и выбор медиа. - `src/favorite_stickers/media.py` — проверка и конвертация через ffmpeg. - `src/favorite_stickers/service.py` — добавление/удаление и переход к следующему набору. - `src/favorite_stickers/store.py` — SQLite. - `src/favorite_stickers/telegram.py` — операции Telegram Bot API.