346 lines
14 KiB
Markdown
346 lines
14 KiB
Markdown
# Архитектура системы
|
||
|
||
Документ описывает внутреннюю архитектуру и принципы работы Telegram Video Download Bot.
|
||
|
||
## Общая архитектура
|
||
|
||
Система состоит из двух основных компонентов:
|
||
|
||
1. **Основной бот** (`bot.py`) — Telegram бот, обрабатывающий запросы пользователей
|
||
2. **VK Downloader Service** (`vk-downloader/`) — отдельный микросервис для скачивания видео с VK
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ Telegram User │
|
||
└────────┬────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────┐
|
||
│ Основной бот (bot.py) │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ YouTube Download Handler │ │
|
||
│ └───────────────────────────────┘ │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ Instagram Download Handler │ │
|
||
│ └───────────────────────────────┘ │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ VK API Client │──┼──┐
|
||
│ └───────────────────────────────┘ │ │
|
||
│ ┌───────────────────────────────┐ │ │
|
||
│ │ SQLite Database │ │ │
|
||
│ │ - Users │ │ │
|
||
│ │ - Stats │ │ │
|
||
│ └───────────────────────────────┘ │ │
|
||
└─────────────────────────────────────┘ │
|
||
│ HTTP API
|
||
│ POST /download/stream
|
||
▼
|
||
┌──────────────────────┐
|
||
│ VK Downloader │
|
||
│ Service │
|
||
│ ┌────────────────┐ │
|
||
│ │ Flask API │ │
|
||
│ └────────────────┘ │
|
||
│ ┌────────────────┐ │
|
||
│ │ yt-dlp │ │
|
||
│ │ (VK only) │ │
|
||
│ └────────────────┘ │
|
||
└──────────────────────┘
|
||
```
|
||
|
||
## Компоненты системы
|
||
|
||
### 1. Основной бот (bot.py)
|
||
|
||
**Технологии:**
|
||
- `python-telegram-bot` (v20.7) — асинхронный фреймворк для Telegram Bot API
|
||
- `yt-dlp` — библиотека для скачивания видео
|
||
- `httpx` — асинхронный HTTP клиент для запросов к VK сервису
|
||
- `sqlite3` — база данных для хранения статистики
|
||
|
||
**Архитектурные решения:**
|
||
|
||
#### Обработка сообщений
|
||
- Асинхронная обработка через `asyncio`
|
||
- Каждый пользовательский запрос обрабатывается независимой корутиной
|
||
- Параллельная обработка нескольких запросов
|
||
|
||
#### Скачивание видео
|
||
- **YouTube/Instagram**: Прямое скачивание через `yt-dlp` в executor (не блокирует event loop)
|
||
- **VK**: HTTP запрос к внешнему микросервису через `httpx`
|
||
|
||
#### База данных
|
||
- SQLite с двумя таблицами:
|
||
- `users` — информация о пользователях (chat_id, username, first_name, first_seen, last_seen)
|
||
- `stats` — статистика (total_downloads)
|
||
- Инициализация при запуске через `init_database()`
|
||
- Файл базы: `data/bot.db`
|
||
|
||
#### Обработка ошибок
|
||
- Retry механизм для всех источников (3 попытки по умолчанию)
|
||
- Логирование всех ошибок
|
||
- Информативные сообщения пользователю
|
||
|
||
### 2. VK Downloader Service
|
||
|
||
**Технологии:**
|
||
- Flask — веб-фреймворк для REST API
|
||
- `yt-dlp` — библиотека для скачивания видео с VK
|
||
- Flask-CORS — для поддержки CORS (если нужно)
|
||
|
||
**API Endpoints:**
|
||
|
||
1. `GET /health` — проверка работоспособности сервиса
|
||
- Возвращает: `{"status": "ok", "service": "vk-downloader"}`
|
||
|
||
2. `POST /download/stream` — скачивание видео
|
||
- Request: `{"url": "https://vk.com/clip-..."}`
|
||
- Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)
|
||
|
||
**Особенности реализации:**
|
||
|
||
#### Обработка кириллицы
|
||
- Имена файлов с кириллицей конвертируются в ASCII для HTTP заголовков
|
||
- Оригинальное имя сохраняется в файловой системе
|
||
|
||
#### Управление файлами
|
||
- Временные файлы сохраняются в `downloads/`
|
||
- Файлы удаляются после отправки клиенту
|
||
- Использование UUID для уникальности имен
|
||
|
||
#### Ограничения
|
||
- Flask dev server (однопоточный) — обрабатывает запросы последовательно
|
||
- Для продакшена рекомендуется использовать Gunicorn с несколькими worker'ами
|
||
|
||
### 3. Определение источника видео
|
||
|
||
Функция `detect_video_source(url)` анализирует домен URL:
|
||
|
||
```python
|
||
- youtube.com / youtu.be → 'youtube'
|
||
- instagram.com → 'instagram'
|
||
- vk.com / vkontakte.ru → 'vk'
|
||
- иначе → 'unknown'
|
||
```
|
||
|
||
### 4. Потоки данных
|
||
|
||
#### Скачивание с YouTube/Instagram
|
||
|
||
```
|
||
User → Bot → detect_video_source() → download_youtube_video() / download_instagram_video()
|
||
↓
|
||
yt-dlp (executor) → video file → Telegram API → User
|
||
```
|
||
|
||
#### Скачивание с VK
|
||
|
||
```
|
||
User → Bot → detect_video_source() → download_vk_video()
|
||
↓
|
||
HTTP POST /download/stream → VK Service
|
||
↓
|
||
yt-dlp → video file → HTTP Response (binary)
|
||
↓
|
||
Bot receives binary → saves to disk → Telegram API → User
|
||
```
|
||
|
||
### 5. База данных
|
||
|
||
**Схема:**
|
||
|
||
```sql
|
||
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`
|
||
- Зависимости: `ffmpeg`, `wget`
|
||
- Python пакеты из `requirements.txt`
|
||
|
||
**Volumes:**
|
||
- `./video:/app/video` — временные файлы видео
|
||
- `./instagram_cookies.txt:/app/instagram_cookies.txt` — cookies для Instagram
|
||
- `./data:/app/data:Z` — база данных (SELinux relabel)
|
||
|
||
**Network:**
|
||
- `network_mode: host` — для доступа к VK сервису через localhost
|
||
|
||
### VK Downloader Service
|
||
|
||
**Образ:**
|
||
- Базовый: `python:3.11-slim`
|
||
- Зависимости: `ffmpeg`, `wget`
|
||
- Python пакеты: Flask, flask-cors, yt-dlp, requests
|
||
|
||
**Volumes:**
|
||
- `./downloads:/app/downloads` — временные файлы
|
||
|
||
**Ports:**
|
||
- `5555:5000` — внешний порт 5555, внутренний 5000
|
||
|
||
**Network:**
|
||
- Отдельная сеть `vk_network` (можно использовать host network для доступа)
|
||
|
||
## Безопасность
|
||
|
||
### Переменные окружения
|
||
- Токен бота хранится в `.env` (не коммитится в Git)
|
||
- Cookies для Instagram хранятся в файле (не коммитится)
|
||
|
||
### Ограничения доступа
|
||
- VK сервис доступен только по указанному IP/URL
|
||
- Нет аутентификации между ботом и VK сервисом (можно добавить API key)
|
||
|
||
### Файловая система
|
||
- Временные файлы удаляются после отправки
|
||
- Cookies файл монтируется read-only (опционально)
|
||
|
||
## Масштабирование
|
||
|
||
### Текущие ограничения
|
||
|
||
1. **Основной бот:**
|
||
- Один экземпляр (можно запустить несколько с разными токенами)
|
||
- Параллельная обработка запросов ограничена ресурсами CPU/сети
|
||
|
||
2. **VK сервис:**
|
||
- Flask dev server — последовательная обработка
|
||
- Один экземпляр контейнера
|
||
|
||
### Рекомендации для масштабирования
|
||
|
||
1. **VK сервис:**
|
||
- Использовать Gunicorn с несколькими worker'ами:
|
||
```bash
|
||
gunicorn -w 4 -b 0.0.0.0:5000 app:app
|
||
```
|
||
- Горизонтальное масштабирование: несколько контейнеров за nginx/HAProxy
|
||
- Load balancing для распределения нагрузки
|
||
|
||
2. **Основной бот:**
|
||
- Webhook режим вместо polling (для больших нагрузок)
|
||
- Кеширование информации о видео
|
||
- Очередь задач (Celery) для скачивания
|
||
|
||
3. **База данных:**
|
||
- Миграция на PostgreSQL для многопользовательской нагрузки
|
||
- Connection pooling
|
||
|
||
## Мониторинг
|
||
|
||
### Логирование
|
||
- Все компоненты логируют в stdout/stderr
|
||
- Docker автоматически собирает логи
|
||
- Уровни: INFO, WARNING, ERROR
|
||
|
||
### Метрики (можно добавить)
|
||
- Количество запросов в секунду
|
||
- Время обработки запроса
|
||
- Количество ошибок
|
||
- Размер скачанных файлов
|
||
|
||
### Health checks
|
||
- VK сервис: `GET /health`
|
||
- Основной бот: проверка через статус контейнера
|
||
|
||
## Производительность
|
||
|
||
### Оптимизации
|
||
|
||
1. **Асинхронная обработка:**
|
||
- Основной бот использует asyncio для неблокирующих операций
|
||
- yt-dlp запускается в executor для YouTube/Instagram
|
||
|
||
2. **Временные файлы:**
|
||
- Хранение в памяти (tmpfs) для быстрого доступа (опционально)
|
||
- Автоматическая очистка после отправки
|
||
|
||
3. **Кеширование:**
|
||
- Можно добавить кеш информации о видео (title, duration)
|
||
- Кеш для часто запрашиваемых видео
|
||
|
||
### Узкие места
|
||
|
||
1. **VK сервис:**
|
||
- Последовательная обработка запросов
|
||
- Скачивание файла перед отправкой (занимает память)
|
||
|
||
2. **Сеть:**
|
||
- Зависимость от скорости интернета
|
||
- Задержки при обращении к внешнему VK сервису
|
||
|
||
## Развертывание
|
||
|
||
### Локальная разработка
|
||
```bash
|
||
# Основной бот
|
||
docker compose up -d
|
||
|
||
# VK сервис
|
||
cd vk-downloader && docker compose up -d
|
||
```
|
||
|
||
### Продакшен (раздельное развертывание)
|
||
|
||
**Хост 1 (с VPN):**
|
||
- Основной бот
|
||
- VPN для доступа к YouTube/Instagram
|
||
- `.env`: `VK_DOWNLOADER_URL=http://<host2_ip>:5555`
|
||
|
||
**Хост 2 (без VPN):**
|
||
- VK Downloader Service
|
||
- Доступен по IP для хоста 1
|
||
- Можно масштабировать горизонтально
|
||
|
||
### CI/CD (опционально)
|
||
|
||
1. Автоматический build Docker образов
|
||
2. Тестирование перед деплоем
|
||
3. Автоматический деплой при коммите в main
|
||
|
||
## Будущие улучшения
|
||
|
||
1. **Аутентификация между сервисами:**
|
||
- API key для VK сервиса
|
||
- JWT токены
|
||
|
||
2. **Очередь задач:**
|
||
- Celery/RQ для фоновой обработки
|
||
- Retry механизм через очередь
|
||
|
||
3. **Мониторинг:**
|
||
- Prometheus метрики
|
||
- Grafana дашборды
|
||
|
||
4. **Улучшение VK сервиса:**
|
||
- Переход на FastAPI (более производительный)
|
||
- Поддержка WebSockets для прогресса
|
||
- Stream ответа вместо полной загрузки в память
|
||
|