audio_from_youtube/youtube_mp3_telegram_service_TZ.md

10 KiB
Raw Blame History

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