97 lines
5.4 KiB
Markdown
97 lines
5.4 KiB
Markdown
# Favorite stickers Telegram bot
|
||
|
||
Максимально простой бот для личных стикерпаков «Избранное»: пользователь отправляет медиа или стикер, бот сразу добавляет его в персональный набор. Повторная отправка того же стикера удаляет его.
|
||
|
||
## Возможности
|
||
|
||
- Принимает фотографии, видео/видеосообщения до 3 секунд, GIF/анимации, документы с медиа и обычные или видео-стикеры.
|
||
- Преобразует всё через `ffmpeg` в Telegram Video Sticker: WEBM/VP9, без звука, до 512 px и 256 КиБ.
|
||
- Ограничивает входной файл по фактическому размеру и отклоняет разрешение выше 33,5 Мп; конвертации имеют таймаут и общий лимит параллельности.
|
||
- Передаёт вход в `ffmpeg`/`ffprobe` через отдельный файловый дескриптор и запрещает вложенные файловые и сетевые протоколы.
|
||
- Поэтому картинки и видео могут находиться в одном наборе.
|
||
- Первый набор называется `<bot username> - Favorites <user id>`.
|
||
- После лимита в 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.
|