10 KiB
ТЗ: Telegram-сервис “YouTube → MP3” + Admin bot (Docker Compose, Ubuntu 24.04, Python)
0. Цель
Нужно реализовать сервис на Python, который состоит из двух Telegram-ботов:
- User-bot — принимает от пользователя ссылку на YouTube-видео и возвращает аудио-дорожку в MP3. Имя файла должно быть идентично названию видео на YouTube.
- 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-dlpffmpeg- опционально
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метаданными. - Если название получить не удалось (пустое/ошибка/не распарсилось), включается интерактивный шаг:
- Бот пишет: “Не смог определить название. Введи имя файла (без расширения .mp3).”
- Бот ждёт ответ пользователя текстом.
- Полученное имя используется как название выходного 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
- любой, кто написал admin-bot
Список администраторов хранить в простом виде:
- 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.ymlDockerfile.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. Критерии приёмки
- Пользователь отправляет YouTube-ссылку → получает mp3 с названием как у видео.
- Одновременно 5 пользователей отправляют ссылки → задачи встают в очередь, скачивание идёт строго по одной.
- На каждый успешно выданный mp3 admin-bot получает:
- текст с title/username/url
- затем mp3 файл
- После отправки пользователю и в admin-bot временный файл удаляется.
- Переключение
IS_PRODменяет только токены, оба бота всегда работают.