|
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 52s
Реальный инцидент: cookies "протухли" за пару дней вместо ~года. Причина —
не срок годности, а сам yt-dlp: --cookies FILE читает И дописывает cookie
jar обратно в файл после каждого запуска (--help: "read cookies from and
dump cookie jar in"), а когда Instagram-экстрактор решает, что сессия
невалидна, он явно чистит sessionid из jar'а — и это тут же сохраняется на
диск через YoutubeDL.close(). Наш собственный health-check (каждые 30 мин)
и обычные скачивания медленно, но верно стирали себе рабочие cookies.
Фикс: yt-dlp больше никогда не видит мастер-файл, только одноразовую копию
в фиксированном /tmp-пути (безопасно — оба сервиса --workers=1, гонок нет).
Проверено: md5sum/mtime мастер-файлов не меняются ни после серии
/cookies/check, ни после реального /download/stream.
Заодно в bot.py: notify_admin_cookie_alert больше не заявляет "это НЕ
cookies" для extraction_failed — на практике это оказалось не всегда
верно (анонимный rate-limit тоже "не cookies" по факту, но валидная
сессия могла бы его обойти). В алерты добавлена проверяемая ссылка
(test_url из /cookies/check), чтобы сразу было видно, что это health-check
дёргает тестовый ролик, а не реальная ссылка пользователя. Новый статус
cookies_incomplete детектирует "файл есть, но sessionid нет" ещё до
сетевых проверок — ловит именно тот случай, что привёл к инциденту.
Отдельно: пользователю теперь показывается понятное сообщение, когда
Instagram сам блокирует контент как возрастной/чувствительный
("can't be seen by certain audiences") — вместо общего "Something went
wrong", раз повторная попытка всё равно не поможет. Админ по-прежнему
получает полный технический текст без изменений.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|---|---|---|
| .forgejo/workflows | ||
| cookies | ||
| instagram-downloader | ||
| tiktok-downloader | ||
| vk-downloader | ||
| yapfiles-downloader | ||
| youtube-downloader | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| admin_bot.py | ||
| ARCHITECTURE.md | ||
| bot.py | ||
| broadcast.py | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
| smoke_test.py | ||
Telegram Video Download Bot
Telegram бот для скачивания видео с YouTube, Instagram, TikTok, VK и Yapfiles. Микросервисная архитектура с раздельными сервисами для каждого источника.
Архитектура
Проект разделен на микросервисы:
- Основной бот (в корне проекта) - Telegram бот, обрабатывает сообщения и оркестрирует запросы к сервисам
- youtube-downloader - сервис для скачивания с YouTube (порт 5557)
- instagram-downloader - сервис для скачивания с Instagram (порт 5556)
- vk-downloader - сервис для скачивания с VK (порт 5555)
- yapfiles-downloader - сервис для скачивания с Yapfiles (порт 5558)
- tiktok-downloader - сервис для скачивания с TikTok (порт 5559)
Каждый сервис работает в отдельном Docker контейнере и может быть развернут независимо.
Возможности
- 📹 Скачивание видео с YouTube
- 📸 Скачивание видео с Instagram (требуются cookies)
- 🎵 Скачивание видео с TikTok
- 🎬 Скачивание видео с VK
- 📁 Скачивание видео с Yapfiles
- 🌍 Локализация интерфейса (русский/английский) на основе языка пользователя
- 📊 Статистика скачанных видео и пользователей
- 🔄 Автоматическое сохранение статистики в базу данных
- 👥 Работа в группах с автоматическим обнаружением ссылок
- 📢 Рассылка сообщений всем пользователям (
broadcast.py)
Команды бота
/start— начало работы с ботом/stat— статистика: количество пользователей и скачанных видео/support— информация о боте и контакт автора
Требования
- Docker и Docker Compose
- Telegram Bot Token (получить у @BotFather)
- Для Instagram: файл с cookies (см. раздел Instagram ниже)
Быстрый старт
1. Клонирование репозитория
git clone <repository_url>
cd videoDownloadBot
2. Настройка переменных окружения
Скопируйте .env.example в .env в корне проекта и заполните:
cp .env.example .env
nano .env # или используйте любой редактор
Необходимые переменные:
TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
TELEGRAM_BOT_USERNAME=your_bot_username
# Downloader Services URLs
YOUTUBE_DOWNLOADER_URL=http://localhost:5557
INSTAGRAM_DOWNLOADER_URL=http://localhost:5556
VK_DOWNLOADER_URL=http://localhost:5555
YAPFILES_DOWNLOADER_URL=http://localhost:5558
TIKTOK_DOWNLOADER_URL=http://localhost:5559
3. Настройка Instagram (опционально)
Если планируете скачивать видео с Instagram:
- Экспортируйте cookies из браузера расширением для
cookies.txt— процедура вcookies/README.md - Сохраните файл как
instagram_cookies.txtв папкеinstagram-downloader/
4. Запуск сервисов
Все 7 сервисов (бот, admin-бот, 5 загрузчиков) собираются и запускаются одной командой из корня проекта — единый docker-compose.yml уже содержит build-контексты для всех подпапок:
docker compose up -d --build
Перезапустить/пересобрать только один сервис (например, при правке youtube-downloader/app.py):
docker compose up -d --build youtube-downloader
5. Проверка статуса
# Проверка всех сервисов
docker ps | grep -E "(video_download_bot|youtube|instagram|vk|yapfiles|tiktok)"
Порты сервисов
| Сервис | Порт |
|---|---|
| VK Downloader | 5555 |
| Instagram Downloader | 5556 |
| YouTube Downloader | 5557 |
| Yapfiles Downloader | 5558 |
| TikTok Downloader | 5559 |
Рассылка сообщений
Скрипт broadcast.py позволяет отправить сообщение всем пользователям бота:
# Простое сообщение
./broadcast.py -y "Текст сообщения"
# С HTML-разметкой
./broadcast.py -y --html '<b>Важно!</b> Новая функция добавлена.'
# Из файла
./broadcast.py -y --file announcement.txt --html
# Посмотреть список пользователей
./broadcast.py --list
Структура проекта
videoDownloadBot/
├── bot.py # Код основного Telegram бота
├── broadcast.py # Скрипт для рассылки сообщений
├── requirements.txt # Python зависимости бота
├── Dockerfile # Образ для бота
├── docker-compose.yml # Конфигурация бота
├── .env.example # Пример конфигурации
├── data/ # База данных (bot.db)
├── video/ # Скачанные видео
├── youtube-downloader/ # Сервис для YouTube
├── instagram-downloader/ # Сервис для Instagram
├── vk-downloader/ # Сервис для VK
├── yapfiles-downloader/ # Сервис для Yapfiles
├── tiktok-downloader/ # Сервис для TikTok
├── README.md # Этот файл
└── ARCHITECTURE.md # Описание архитектуры
API Endpoints
Все сервисы загрузчиков предоставляют одинаковый API:
GET /health- проверка здоровья сервисаPOST /download/stream- скачивание видео (возвращает бинарные данные)
POST /download/stream
Content-Type: application/json
{
"url": "https://youtube.com/watch?v=..."
}
Cookies на проде (YouTube/Instagram)
В проде youtube_cookies.txt/instagram_cookies.txt монтируются в контейнеры с хоста (docker-compose.prod.yml), а не запекаются в образ — это позволяет обновлять их без пересборки/передеплоя. yt-dlp/app.py читают файл с диска при каждом запросе — рестарт контейнера не требуется.
Куки обновляются вручную и редко — по алерту 🍪⚠️ COOKIES ПРОТУХЛИ из админ-бота, а не по расписанию. Ключевые куки живут около года, поэтому регулярный экспорт не нужен; за состоянием следит фоновая проверка в bot.py (check_cookies_health, раз в 30 минут дёргает POST /cookies/check у youtube- и instagram-downloader).
Экспорт делается с машины с браузером (на проде нет GUI) и требует точной процедуры — для YouTube только через приватное окно, иначе сессия ротируется и куки протухают. Пошаговая инструкция и скрипт доставки — в cookies/.
Смоук-тест
После любой правки, до коммита, на поднятом тестовом контуре:
python3 smoke_test.py
Гоняет реальные ссылки через запущенные сервисы и печатает таблицу: /cookies/check обоих загрузчиков, /formats на возрастном YouTube-видео (ловит отсутствие рабочего JS-рантайма) и реальные скачивания YouTube и Instagram. Код возврата 0 — всё прошло, 1 — есть падения. Адреса переопределяются через YOUTUBE_DOWNLOADER_URL/INSTAGRAM_DOWNLOADER_URL.
Если сервисы пересобирались — поднимать их через docker compose up -d --force-recreate <service>: без флага up -d просто стартует старый контейнер, и правка в проверку не попадёт.
Обновление
Деплой на прод выполняется автоматически через Forgejo CI/CD (.forgejo/workflows/deploy.yml) при пуше в main: сборка всех 7 образов → push в registry → docker save/ssh/docker load на прод-хост (registry не доступен с внешнего VPS напрямую) → docker compose up -d --remove-orphans.
Для ручного локального обновления:
git pull
docker compose up -d --build
Локализация
Бот автоматически определяет язык пользователя из настроек Telegram:
- Если язык начинается с
ru— интерфейс на русском - Иначе — интерфейс на английском
Язык сохраняется в базе данных для каждого пользователя.
Troubleshooting
Бот не отвечает
- Проверьте логи:
docker compose logs bot - Убедитесь, что токен правильный в
.env - Проверьте, что все сервисы запущены и доступны
Сервис не работает
- Проверьте логи сервиса:
docker compose logs -f <service>-downloader - Проверьте URL в
.env - Для Instagram: проверьте валидность cookies
База данных не сохраняется
- Проверьте права на папку
data/ - Убедитесь, что volume смонтирован в
docker-compose.yml
Лицензия
MIT
Поддержка
При возникновении проблем создайте issue в репозитории или свяжитесь с автором: @rvrubel