audio_from_youtube/youtube_mp3_telegram_service_TZ.md

195 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ТЗ: 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` меняет только токены, оба бота всегда работают.