- Разделение на микросервисы: youtube-downloader, instagram-downloader, vk-downloader - Основной бот в корне проекта, работает через HTTP API с сервисами - Каждый сервис запускается отдельно в своей папке - Видео сохраняются в папке video/ и не удаляются - Обновлена документация и архитектура - Скрипты для Instagram cookies перенесены в instagram-downloader/
22 KiB
Архитектура системы
Документ описывает внутреннюю архитектуру и принципы работы Telegram Video Download Bot.
Общая архитектура
Система состоит из микросервисной архитектуры с раздельными сервисами для каждого источника видео:
- Основной бот (
bot.pyв корне проекта) — Telegram бот, обрабатывающий запросы пользователей и оркестрирующий запросы к сервисам - YouTube Downloader Service (
youtube-downloader/) — микросервис для скачивания видео с YouTube - Instagram Downloader Service (
instagram-downloader/) — микросервис для скачивания видео с Instagram - VK Downloader Service (
vk-downloader/) — микросервис для скачивания видео с VK
┌─────────────────┐
│ Telegram User │
└────────┬────────┘
│
▼
┌─────────────────────────────────────┐
│ Основной бот (bot.py) │
│ ┌───────────────────────────────┐ │
│ │ Message Handler │ │
│ │ - URL extraction │ │
│ │ - Source detection │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ HTTP API Clients │──┼──┐
│ │ - YouTube API Client │ │ │
│ │ - Instagram API Client │ │ │
│ │ - VK API Client │ │ │
│ └───────────────────────────────┘ │ │
│ ┌───────────────────────────────┐ │ │
│ │ SQLite Database │ │ │
│ │ - Users │ │ │
│ │ - Stats │ │ │
│ └───────────────────────────────┘ │ │
│ ┌───────────────────────────────┐ │ │
│ │ Video Storage │ │ │
│ │ - video/ directory │ │ │
│ └───────────────────────────────┘ │ │
└─────────────────────────────────────┘ │
│ HTTP API
│ POST /download/stream
│
┌──────────────────────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ YouTube Downloader│ │Instagram Download│ │ VK Downloader │
│ Service │ │ Service │ │ Service │
│ ┌──────────────┐ │ │ ┌──────────────┐ │ │ ┌──────────────┐│
│ │ Flask API │ │ │ │ Flask API │ │ │ │ Flask API ││
│ └──────────────┘ │ │ └──────────────┘ │ │ └──────────────┘│
│ ┌──────────────┐ │ │ ┌──────────────┐ │ │ ┌──────────────┐│
│ │ yt-dlp │ │ │ │ yt-dlp │ │ │ │ yt-dlp ││
│ │ (YouTube) │ │ │ │ (Instagram) │ │ │ │ (VK only) ││
│ └──────────────┘ │ │ └──────────────┘ │ │ └──────────────┘│
│ Port: 5557 │ │ Port: 5556 │ │ Port: 5555 │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Компоненты системы
1. Основной бот (bot.py)
Расположение: Корень проекта
Технологии:
python-telegram-bot(v20.7) — асинхронный фреймворк для Telegram Bot APIhttpx— асинхронный HTTP клиент для запросов к сервисам загрузчиковsqlite3— база данных для хранения статистики
Архитектурные решения:
Обработка сообщений
- Асинхронная обработка через
asyncio - Каждый пользовательский запрос обрабатывается независимой корутиной
- Параллельная обработка нескольких запросов
- Автоматическое извлечение URL из текста сообщений (работа в группах)
Скачивание видео
- Все источники: HTTP запросы к соответствующим микросервисам через
httpx - YouTube:
POST http://youtube-downloader:5000/download/stream - Instagram:
POST http://instagram-downloader:5000/download/stream - VK:
POST http://vk-downloader:5000/download/stream - Получение бинарных данных и сохранение во временный файл
- Отправка через Telegram API
Хранение видео
- Все скачанные видео сохраняются в папке
video/на хосте - Файлы не удаляются автоматически (сохраняются для пользователей)
- Автоматическая очистка только
.partфайлов (недокачанные)
База данных
- SQLite с двумя таблицами:
users— информация о пользователях (chat_id, username, first_name, first_seen, last_seen)stats— статистика (total_downloads)
- Инициализация при запуске через
init_database() - Файл базы:
data/bot.db
Обработка ошибок
- Retry механизм для всех источников (3 попытки по умолчанию)
- Логирование всех ошибок
- Информативные сообщения пользователю
- Автоматическая очистка
.partфайлов при ошибках
2. YouTube Downloader Service
Расположение: youtube-downloader/
Технологии:
- Flask — веб-фреймворк для REST API
yt-dlp— библиотека для скачивания видео с YouTube- Flask-CORS — для поддержки CORS
API Endpoints:
-
GET /health— проверка работоспособности сервиса- Возвращает:
{"status": "ok", "service": "youtube-downloader"}
- Возвращает:
-
POST /download/stream— скачивание видео- Request:
{"url": "https://youtube.com/watch?v=..."} - Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)
- Request:
Особенности:
- Использует специальные настройки yt-dlp для YouTube (player_client, headers)
- Поддержка различных форматов видео (mp4, webm, mkv)
- Временные файлы сохраняются в
downloads/и удаляются после отправки
Порт: 5557 (внешний) → 5000 (внутренний)
3. Instagram Downloader Service
Расположение: instagram-downloader/
Технологии:
- Flask — веб-фреймворк для REST API
yt-dlp— библиотека для скачивания видео с Instagram- Flask-CORS — для поддержки CORS
API Endpoints:
-
GET /health— проверка работоспособности сервиса- Возвращает:
{"status": "ok", "service": "instagram-downloader"}
- Возвращает:
-
POST /download/stream— скачивание видео- Request:
{"url": "https://instagram.com/p/..."} - Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)
- Request:
Особенности:
- Требует файл с cookies Instagram (
instagram_cookies.txtв папке сервиса) - Автоматическая проверка срока действия cookies
- Поддержка CSRF токенов и session cookies
- Скрипты для получения/обновления cookies в папке сервиса
Порт: 5556 (внешний) → 5000 (внутренний)
4. VK Downloader Service
Расположение: vk-downloader/
Технологии:
- Flask — веб-фреймворк для REST API
yt-dlp— библиотека для скачивания видео с VK- Flask-CORS — для поддержки CORS
API Endpoints:
-
GET /health— проверка работоспособности сервиса- Возвращает:
{"status": "ok", "service": "vk-downloader"}
- Возвращает:
-
POST /download/stream— скачивание видео- Request:
{"url": "https://vk.com/clip-..."} - Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)
- Request:
Особенности:
- Специальные заголовки для VK (User-Agent, Referer)
- Обработка кириллицы в именах файлов
- Временные файлы сохраняются в
downloads/и удаляются после отправки
Порт: 5555 (внешний) → 5000 (внутренний)
5. Определение источника видео
Функция detect_video_source(url) анализирует домен URL:
- youtube.com / youtu.be → 'youtube'
- instagram.com → 'instagram'
- vk.com / vkontakte.ru → 'vk'
- иначе → 'unknown'
6. Потоки данных
Общий поток скачивания
User → Bot → extract_urls_from_text() → detect_video_source()
↓
HTTP POST /download/stream → [YouTube/Instagram/VK] Service
↓
yt-dlp → video file → HTTP Response (binary)
↓
Bot receives binary → saves to video/ → Telegram API → User
Детальный поток для каждого источника
YouTube:
User → Bot → download_youtube_video()
↓
httpx.AsyncClient → POST http://youtube-downloader:5000/download/stream
↓
YouTube Service → yt-dlp → binary data
↓
Bot saves to video/ → sends to User
Instagram:
User → Bot → download_instagram_video()
↓
httpx.AsyncClient → POST http://instagram-downloader:5000/download/stream
↓
Instagram Service → yt-dlp (with cookies) → binary data
↓
Bot saves to video/ → sends to User
VK:
User → Bot → download_vk_video()
↓
httpx.AsyncClient → POST http://vk-downloader:5000/download/stream
↓
VK Service → yt-dlp → binary data
↓
Bot saves to video/ → sends to User
7. База данных
Схема:
CREATE TABLE users (
chat_id INTEGER PRIMARY KEY,
username TEXT,
first_name TEXT,
first_seen TEXT NOT NULL,
last_seen TEXT NOT NULL
);
CREATE TABLE stats (
id INTEGER PRIMARY KEY CHECK (id = 1),
total_downloads INTEGER DEFAULT 0
);
Операции:
add_user()— добавление/обновление пользователя (при каждом взаимодействии)get_total_users()— получение количества уникальных пользователейincrement_downloads()— увеличение счетчика скачанных видеоget_total_downloads()— получение количества скачанных видео
Персистентность:
- База хранится в
data/bot.dbна хосте - Монтируется как volume в Docker
- Сохраняется между перезапусками контейнера
Docker архитектура
Основной бот
Расположение: Корень проекта
Образ:
- Базовый:
python:3.11-slim - Python пакеты из
requirements.txt(python-telegram-bot, httpx)
Volumes:
./video:/app/video— сохраненные видео (не удаляются)./data:/app/data:Z— база данных (SELinux relabel)
Network:
network_mode: host— для доступа к сервисам по localhost или IP
Запуск:
docker compose up -d
YouTube Downloader Service
Расположение: youtube-downloader/
Образ:
- Базовый:
python:3.11-slim - Зависимости:
ffmpeg,wget - Python пакеты: Flask, flask-cors, yt-dlp
Volumes:
./downloads:/app/downloads— временные файлы
Ports:
5557:5000— внешний порт 5557, внутренний 5000
Запуск:
cd youtube-downloader && docker compose up -d
Instagram Downloader Service
Расположение: instagram-downloader/
Образ:
- Базовый:
python:3.11-slim - Зависимости:
ffmpeg,wget - Python пакеты: Flask, flask-cors, yt-dlp
Volumes:
./downloads:/app/downloads— временные файлы./instagram_cookies.txt:/app/instagram_cookies.txt:ro— cookies (read-only)
Environment:
INSTAGRAM_COOKIES_FILE=/app/instagram_cookies.txt
Ports:
5556:5000— внешний порт 5556, внутренний 5000
Запуск:
cd instagram-downloader && docker compose up -d
VK Downloader Service
Расположение: vk-downloader/
Образ:
- Базовый:
python:3.11-slim - Зависимости:
ffmpeg,wget - Python пакеты: Flask, flask-cors, yt-dlp, requests
Volumes:
./downloads:/app/downloads— временные файлы
Ports:
5555:5000— внешний порт 5555, внутренний 5000
Запуск:
cd vk-downloader && docker compose up -d
Безопасность
Переменные окружения
- Токен бота хранится в
.env(не коммитится в Git) - Cookies для Instagram хранятся в файле
instagram-downloader/instagram_cookies.txt(не коммитится) - URL сервисов настраиваются через
.env
Ограничения доступа
- Сервисы загрузчиков доступны только по указанным IP/URL
- Нет аутентификации между ботом и сервисами (можно добавить API key)
- Cookies файл монтируется read-only
Файловая система
- Видео сохраняются в
video/и не удаляются автоматически - Временные файлы в сервисах удаляются после отправки
- Автоматическая очистка только
.partфайлов
Масштабирование
Текущие ограничения
-
Основной бот:
- Один экземпляр (можно запустить несколько с разными токенами)
- Параллельная обработка запросов через asyncio
- Ограничения: ресурсы CPU/сети
-
Сервисы загрузчиков:
- Flask dev server — последовательная обработка
- Один экземпляр контейнера каждого сервиса
- Можно масштабировать горизонтально
Рекомендации для масштабирования
-
Сервисы загрузчиков:
- Использовать Gunicorn с несколькими worker'ами:
gunicorn -w 4 -b 0.0.0.0:5000 app:app - Горизонтальное масштабирование: несколько контейнеров за nginx/HAProxy
- Load balancing для распределения нагрузки
- Использовать Gunicorn с несколькими worker'ами:
-
Основной бот:
- Webhook режим вместо polling (для больших нагрузок)
- Кеширование информации о видео
- Очередь задач (Celery) для скачивания
-
База данных:
- Миграция на PostgreSQL для многопользовательской нагрузки
- Connection pooling
Мониторинг
Логирование
- Все компоненты логируют в stdout/stderr
- Docker автоматически собирает логи
- Уровни: INFO, WARNING, ERROR
Метрики (можно добавить)
- Количество запросов в секунду
- Время обработки запроса
- Количество ошибок
- Размер скачанных файлов
Health checks
- Все сервисы:
GET /health - Основной бот: проверка через статус контейнера
Производительность
Оптимизации
-
Асинхронная обработка:
- Основной бот использует asyncio для неблокирующих операций
- HTTP запросы к сервисам через httpx (асинхронный)
-
Хранение видео:
- Видео сохраняются на хосте (volume), не в образе контейнера
- Файлы доступны для пользователей после скачивания
-
Кеширование:
- Можно добавить кеш информации о видео (title, duration)
- Кеш для часто запрашиваемых видео
Узкие места
-
Сервисы загрузчиков:
- Последовательная обработка запросов (Flask dev server)
- Скачивание файла перед отправкой (занимает память)
-
Сеть:
- Зависимость от скорости интернета
- Задержки при обращении к внешним сервисам
- Задержки между ботом и сервисами загрузчиков
Развертывание
Локальная разработка
# Запуск сервисов загрузчиков (каждый в своей папке)
cd youtube-downloader && docker compose up -d
cd ../instagram-downloader && docker compose up -d
cd ../vk-downloader && docker compose up -d
# Запуск основного бота (из корня проекта)
cd ..
docker compose up -d
Продакшен (раздельное развертывание)
Хост 1 (с VPN для YouTube/Instagram):
- Основной бот
- YouTube сервис (порт 5557)
- Instagram сервис (порт 5556)
- VPN для доступа к YouTube/Instagram
.env:YOUTUBE_DOWNLOADER_URL=http://localhost:5557INSTAGRAM_DOWNLOADER_URL=http://localhost:5556VK_DOWNLOADER_URL=http://<host2_ip>:5555
Хост 2 (без VPN для VK):
- VK Downloader Service (порт 5555)
- Доступен по IP для хоста 1
- Можно масштабировать горизонтально
CI/CD (опционально)
- Автоматический build Docker образов
- Тестирование перед деплоем
- Автоматический деплой при коммите в main
Будущие улучшения
-
Аутентификация между сервисами:
- API key для сервисов загрузчиков
- JWT токены
-
Очередь задач:
- Celery/RQ для фоновой обработки
- Retry механизм через очередь
-
Мониторинг:
- Prometheus метрики
- Grafana дашборды
-
Улучшение сервисов:
- Переход на FastAPI (более производительный)
- Поддержка WebSockets для прогресса
- Stream ответа вместо полной загрузки в память
-
Хранение видео:
- Организация по датам/пользователям
- Автоматическая очистка старых файлов (опционально)
- Интеграция с облачным хранилищем