# Архитектура системы

Документ описывает внутреннюю архитектуру и принципы работы Telegram Video Download Bot.

## Общая архитектура

Система состоит из микросервисной архитектуры с раздельными сервисами для каждого источника видео:

1. **Основной бот** (`bot.py` в корне проекта) — Telegram бот, обрабатывающий запросы пользователей и оркестрирующий запросы к сервисам
2. **YouTube Downloader Service** (`youtube-downloader/`) — микросервис для скачивания видео с YouTube
3. **Instagram Downloader Service** (`instagram-downloader/`) — микросервис для скачивания видео с Instagram
4. **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 API
- `httpx` — асинхронный 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:**

1. `GET /health` — проверка работоспособности сервиса
   - Возвращает: `{"status": "ok", "service": "youtube-downloader"}`

2. `POST /download/stream` — скачивание видео
   - Request: `{"url": "https://youtube.com/watch?v=..."}`
   - Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)

**Особенности:**
- Использует специальные настройки 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:**

1. `GET /health` — проверка работоспособности сервиса
   - Возвращает: `{"status": "ok", "service": "instagram-downloader"}`

2. `POST /download/stream` — скачивание видео
   - Request: `{"url": "https://instagram.com/p/..."}`
   - Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)

**Особенности:**
- Требует файл с 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:**

1. `GET /health` — проверка работоспособности сервиса
   - Возвращает: `{"status": "ok", "service": "vk-downloader"}`

2. `POST /download/stream` — скачивание видео
   - Request: `{"url": "https://vk.com/clip-..."}`
   - Response: Бинарные данные видео (200 OK) или JSON с ошибкой (400/500)

**Особенности:**
- Специальные заголовки для VK (User-Agent, Referer)
- Обработка кириллицы в именах файлов
- Временные файлы сохраняются в `downloads/` и удаляются после отправки

**Порт:** 5555 (внешний) → 5000 (внутренний)

### 5. Определение источника видео

Функция `detect_video_source(url)` анализирует домен URL:

```python
- 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. База данных

**Схема:**

```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`
- Python пакеты из `requirements.txt` (python-telegram-bot, httpx)

**Volumes:**
- `./video:/app/video` — сохраненные видео (не удаляются)
- `./data:/app/data:Z` — база данных (SELinux relabel)

**Network:**
- `network_mode: host` — для доступа к сервисам по localhost или IP

**Запуск:**
```bash
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

**Запуск:**
```bash
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

**Запуск:**
```bash
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

**Запуск:**
```bash
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` файлов

## Масштабирование

### Текущие ограничения

1. **Основной бот:**
   - Один экземпляр (можно запустить несколько с разными токенами)
   - Параллельная обработка запросов через asyncio
   - Ограничения: ресурсы CPU/сети

2. **Сервисы загрузчиков:**
   - Flask dev server — последовательная обработка
   - Один экземпляр контейнера каждого сервиса
   - Можно масштабировать горизонтально

### Рекомендации для масштабирования

1. **Сервисы загрузчиков:**
   - Использовать 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
- Все сервисы: `GET /health`
- Основной бот: проверка через статус контейнера

## Производительность

### Оптимизации

1. **Асинхронная обработка:**
   - Основной бот использует asyncio для неблокирующих операций
   - HTTP запросы к сервисам через httpx (асинхронный)

2. **Хранение видео:**
   - Видео сохраняются на хосте (volume), не в образе контейнера
   - Файлы доступны для пользователей после скачивания

3. **Кеширование:**
   - Можно добавить кеш информации о видео (title, duration)
   - Кеш для часто запрашиваемых видео

### Узкие места

1. **Сервисы загрузчиков:**
   - Последовательная обработка запросов (Flask dev server)
   - Скачивание файла перед отправкой (занимает память)

2. **Сеть:**
   - Зависимость от скорости интернета
   - Задержки при обращении к внешним сервисам
   - Задержки между ботом и сервисами загрузчиков

## Развертывание

### Локальная разработка

```bash
# Запуск сервисов загрузчиков (каждый в своей папке)
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:5557`
  - `INSTAGRAM_DOWNLOADER_URL=http://localhost:5556`
  - `VK_DOWNLOADER_URL=http://<host2_ip>:5555`

**Хост 2 (без VPN для VK):**
- VK Downloader Service (порт 5555)
- Доступен по IP для хоста 1
- Можно масштабировать горизонтально

### CI/CD (опционально)

1. Автоматический build Docker образов
2. Тестирование перед деплоем
3. Автоматический деплой при коммите в main

## Будущие улучшения

1. **Аутентификация между сервисами:**
   - API key для сервисов загрузчиков
   - JWT токены

2. **Очередь задач:**
   - Celery/RQ для фоновой обработки
   - Retry механизм через очередь

3. **Мониторинг:**
   - Prometheus метрики
   - Grafana дашборды

4. **Улучшение сервисов:**
   - Переход на FastAPI (более производительный)
   - Поддержка WebSockets для прогресса
   - Stream ответа вместо полной загрузки в память

5. **Хранение видео:**
   - Организация по датам/пользователям
   - Автоматическая очистка старых файлов (опционально)
   - Интеграция с облачным хранилищем
