Fix bot polling, downloads, and file delivery
This commit is contained in:
commit
8a21cbe18a
16 changed files with 1712 additions and 0 deletions
195
youtube_mp3_telegram_service_TZ.md
Normal file
195
youtube_mp3_telegram_service_TZ.md
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
# ТЗ: Telegram-сервис “YouTube → MP3” + Admin bot (Docker Compose, Ubuntu 24.04, Python)
|
||||
|
||||
## 0. Цель
|
||||
Нужно реализовать сервис на Python, который состоит из **двух Telegram-ботов**:
|
||||
1) **User-bot** — принимает от пользователя ссылку на YouTube-видео и возвращает аудио-дорожку в **MP3**. Имя файла должно быть **идентично названию видео на YouTube**.
|
||||
2) **Admin-bot** — получает **все MP3**, которые были выданы пользователям user-bot, вместе с метаданными:
|
||||
- название файла (title)
|
||||
- Telegram username пользователя (кто запросил)
|
||||
- исходная ссылка на видео
|
||||
|
||||
Сервис разворачивается в Docker через docker-compose на хосте **Ubuntu 24.04**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Общие требования
|
||||
- Язык: **Python**.
|
||||
- Сервис работает в Docker.
|
||||
- Используется **docker compose** (актуальная версия).
|
||||
- В репозитории должен быть файл `.env.example`. Реальный `.env` хранится на сервере и находится в `.gitignore`.
|
||||
- При `isProd=true` используются **продовые** токены ботов, при `isProd=false` — **тестовые**.
|
||||
- В обоих режимах всегда запускаются **оба бота** (user + admin), меняются только токены.
|
||||
|
||||
---
|
||||
|
||||
## 2. Переменные окружения
|
||||
Файл `.env.example` должен содержать:
|
||||
|
||||
- `IS_PROD=false` (строка `true/false`)
|
||||
|
||||
Токены 4 ботов:
|
||||
- `TG_USER_BOT_TOKEN_PROD=...`
|
||||
- `TG_ADMIN_BOT_TOKEN_PROD=...`
|
||||
- `TG_USER_BOT_TOKEN_TEST=...`
|
||||
- `TG_ADMIN_BOT_TOKEN_TEST=...`
|
||||
|
||||
Дополнительно (можно включить, если нужно для реализации):
|
||||
- `ADMIN_CHAT_ID=` (если admin-bot должен отправлять файлы в конкретный чат/пользователю; если не задан — отправлять **все админам admin-бота, которые ему написали /start** и тем самым зарегистрировались)
|
||||
- `WORKDIR=/data` (папка для временных файлов внутри контейнера)
|
||||
- `LOG_LEVEL=INFO`
|
||||
|
||||
> Важно: логика выбора токенов:
|
||||
- если `IS_PROD=true` → берём `*_PROD`
|
||||
- иначе (`false`) → берём `*_TEST`
|
||||
|
||||
---
|
||||
|
||||
## 3. Docker / Compose требования
|
||||
### 3.1 Контейнер
|
||||
В контейнере должны быть установлены:
|
||||
- `yt-dlp`
|
||||
- `ffmpeg`
|
||||
- **опционально** `nodejs` (т.к. YouTube иногда требует JS runtime; установка допускается)
|
||||
|
||||
### 3.2 Временное хранение файлов
|
||||
- Все промежуточные файлы (скачанное аудио/MP3) должны храниться во **временной папке**, смонтированной как **volume** на хост.
|
||||
- После успешной отправки MP3 **и пользователю, и в admin-bot** файл должен быть **удалён**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Очередь и конкурентность
|
||||
- Все запросы на скачивание должны обрабатываться **строго последовательно** (FIFO очередь).
|
||||
- В один момент времени выполняется **только 1 активная загрузка/конвертация** (однопоточно, один worker).
|
||||
- Если несколько пользователей отправляют ссылки одновременно — они “встают в очередь”.
|
||||
- Пользователь должен получать сообщения о статусе:
|
||||
- “Принято в очередь, позиция: N”
|
||||
- “Начинаю обработку”
|
||||
- “Готово, отправляю файл”
|
||||
- “Ошибка: …”
|
||||
|
||||
---
|
||||
|
||||
## 5. Функционал user-bot
|
||||
### 5.1 Вход
|
||||
Пользователь отправляет сообщение, содержащее ссылку на YouTube-видео.
|
||||
|
||||
Поддерживаемые ссылки:
|
||||
- `https://www.youtube.com/...`
|
||||
- `https://youtu.be/...` (это короткий домен YouTube, его тоже нужно поддержать)
|
||||
|
||||
Если ссылка не похожа на YouTube — отвечаем пользователю:
|
||||
“Пришли ссылку на YouTube-видео.”
|
||||
|
||||
### 5.2 Получение названия видео
|
||||
- Бот пытается получить `title` через `yt-dlp` метаданными.
|
||||
- Если **название получить не удалось** (пустое/ошибка/не распарсилось), включается интерактивный шаг:
|
||||
1) Бот пишет: “Не смог определить название. Введи имя файла (без расширения .mp3).”
|
||||
2) Бот ждёт ответ пользователя текстом.
|
||||
3) Полученное имя используется как название выходного mp3.
|
||||
|
||||
### 5.3 Формирование корректного имени файла
|
||||
- Название файла должно быть безопасным для файловой системы:
|
||||
- запрещённые символы заменять на `_`
|
||||
- ограничить длину (например, до 150 символов)
|
||||
- итоговый файл: `<title>.mp3`
|
||||
|
||||
### 5.4 Скачивание и конвертация
|
||||
Команда yt-dlp должна:
|
||||
- извлечь аудио и сконвертировать в mp3
|
||||
- использовать ffmpeg
|
||||
|
||||
Рекомендуемый шаблон:
|
||||
- `yt-dlp -x --audio-format mp3 --audio-quality 0 -o "<path>/%(title)s.%(ext)s" "<URL>"`
|
||||
Но с учётом того, что название может быть задано вручную, реализация может:
|
||||
- скачать во временный файл,
|
||||
- затем переименовать,
|
||||
- либо подставить имя в `-o`.
|
||||
|
||||
### 5.5 Выход
|
||||
- User-bot отправляет пользователю MP3 как документ/аудио файл.
|
||||
- Имя файла (filename) в Telegram должно быть `<title>.mp3`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Функционал admin-bot
|
||||
### 6.1 Что отправлять
|
||||
На каждый успешный запрос user-bot admin-bot должен получить:
|
||||
- сообщение (текст) с полями:
|
||||
- `title: ...`
|
||||
- `requested_by: @username` (если username отсутствует — использовать user_id)
|
||||
- `url: ...`
|
||||
- затем **сам mp3 файл** (один файл = одно событие)
|
||||
|
||||
### 6.2 Куда отправлять
|
||||
Варианты (выбрать и реализовать):
|
||||
- Если задан `ADMIN_CHAT_ID` → отправлять туда.
|
||||
- Иначе: admin-bot должен иметь механизм регистрации администраторов:
|
||||
- любой, кто написал admin-bot `/start`, добавляется в список получателей
|
||||
- всем зарегистрированным администраторам отправлять уведомления и mp3
|
||||
|
||||
Список администраторов хранить в простом виде:
|
||||
- JSON файл в volume (`/data/admins.json`) **или**
|
||||
- SQLite в volume
|
||||
|
||||
---
|
||||
|
||||
## 7. Логирование и наблюдаемость
|
||||
- Логи писать в stdout/stderr (чтобы смотреть через `docker logs`).
|
||||
- Логировать:
|
||||
- входящие запросы (user_id, username, url)
|
||||
- постановку в очередь (позиция)
|
||||
- старт/успех/ошибку обработки
|
||||
- ошибки `yt-dlp` и `ffmpeg` (кратко, но информативно)
|
||||
- Уровень логов через `LOG_LEVEL`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Обработка ошибок
|
||||
Нужно аккуратно обрабатывать:
|
||||
- yt-dlp не смог скачать (403/geo/timeout и т.п.)
|
||||
- ffmpeg упал
|
||||
- Telegram API ошибка отправки файла
|
||||
- пользователь прислал мусор вместо ссылки
|
||||
- пользователь не ответил на запрос имени файла (можно таймаут, например 5 минут → отмена)
|
||||
|
||||
Поведение при ошибке:
|
||||
- пользователю отправить сообщение с ошибкой (без гигантского трейсбека, но с причиной)
|
||||
- задачу удалить из очереди и перейти к следующей
|
||||
- временные файлы удалить
|
||||
|
||||
---
|
||||
|
||||
## 9. Структура проекта (ожидание)
|
||||
В репозитории должны быть:
|
||||
- `docker-compose.yml`
|
||||
- `Dockerfile`
|
||||
- `.env.example`
|
||||
- `.gitignore` (включает `.env` и временные файлы)
|
||||
- `app/` (код)
|
||||
- `README.md` с командами запуска
|
||||
|
||||
---
|
||||
|
||||
## 10. Команды запуска (описать в README)
|
||||
- `docker compose up -d --build`
|
||||
- просмотр логов: `docker compose logs -f`
|
||||
|
||||
---
|
||||
|
||||
## 11. Ограничения (сознательно НЕ делаем сейчас)
|
||||
Пока **не вводим**:
|
||||
- лимиты по длительности видео
|
||||
- лимиты по размеру файла
|
||||
- поддержку плейлистов
|
||||
- сложные ACL/авторизации, кроме механизма получателей admin-bot (см. 6.2)
|
||||
|
||||
---
|
||||
|
||||
## 12. Критерии приёмки
|
||||
1) Пользователь отправляет YouTube-ссылку → получает mp3 с названием как у видео.
|
||||
2) Одновременно 5 пользователей отправляют ссылки → задачи встают в очередь, скачивание идёт строго по одной.
|
||||
3) На каждый успешно выданный mp3 admin-bot получает:
|
||||
- текст с title/username/url
|
||||
- затем mp3 файл
|
||||
4) После отправки пользователю и в admin-bot временный файл удаляется.
|
||||
5) Переключение `IS_PROD` меняет только токены, оба бота всегда работают.
|
||||
Loading…
Add table
Add a link
Reference in a new issue