From ab82f94032c9e67f2148ac09ddb99756662f87b8 Mon Sep 17 00:00:00 2001 From: vrubelroman Date: Wed, 10 Dec 2025 16:22:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=B0=D1=80=D1=85=D0=B8=D1=82=D0=B5=D0=BA=D1=82=D1=83=D1=80?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 8 ++ ARCHITECTURE.md | 346 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 195 +++++++++++++++++++++++++-- 3 files changed, 535 insertions(+), 14 deletions(-) create mode 100644 ARCHITECTURE.md diff --git a/.env.example b/.env.example index faa5798..4dd775f 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,10 @@ +# Токен Telegram бота (получить у @BotFather) TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here + +# Имя бота (username без @, используется в подписи видео) TELEGRAM_BOT_USERNAME=vrubelVideoDownload_bot + +# URL VK сервиса для скачивания видео (должен быть на хосте без VPN) +# Для локальной разработки: http://localhost:5555 +# Для продакшена: http://:5555 +VK_DOWNLOADER_URL=http://localhost:5555 diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..3c1185a --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,346 @@ +# Архитектура системы + +Документ описывает внутреннюю архитектуру и принципы работы 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://: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 ответа вместо полной загрузки в память + diff --git a/README.md b/README.md index 8e2fd4b..91e351b 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,197 @@ # Telegram Video Download Bot -Бот для скачивания видео из различных источников (YouTube, Instagram, VK). +Telegram бот для скачивания видео с YouTube, Instagram и VK. Поддерживает раздельное развертывание сервисов для работы с VPN и без VPN. -## Запуск +## Возможности + +- 📹 Скачивание видео с YouTube +- 📸 Скачивание видео с Instagram (требуются cookies) +- 🎬 Скачивание видео с VK (через отдельный микросервис) +- 📊 Статистика скачанных видео и пользователей +- 🔄 Автоматическое сохранение статистики в базу данных + +## Требования + +- Docker и Docker Compose +- Telegram Bot Token (получить у [@BotFather](https://t.me/BotFather)) +- Для Instagram: файл с cookies (см. раздел Instagram ниже) + +## Быстрый старт + +### 1. Клонирование репозитория ```bash -docker-compose up -d +git clone +cd videoDownloadBot ``` -## Поддерживаемые источники +### 2. Настройка переменных окружения -- YouTube (youtube.com, youtu.be) -- Instagram (instagram.com) -- VK (vk.com, vkontakte.ru) +Скопируйте `.env.example` в `.env` и заполните: + +```bash +cp .env.example .env +nano .env # или используйте любой редактор +``` + +**Необходимые переменные:** + +```env +TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here +TELEGRAM_BOT_USERNAME=your_bot_username +VK_DOWNLOADER_URL=http://localhost:5555 +``` + +- **TELEGRAM_BOT_TOKEN** — токен бота от @BotFather +- **TELEGRAM_BOT_USERNAME** — username бота (без @), используется в подписи видео +- **VK_DOWNLOADER_URL** — URL VK сервиса (для локальной разработки: `http://localhost:5555`, для продакшена: `http://:5555`) + +### 3. Настройка Instagram (опционально) + +Если планируете скачивать видео с Instagram: + +1. Экспортируйте cookies из браузера (см. `INSTAGRAM_COOKIES_INSTRUCTIONS.md`) +2. Сохраните файл как `instagram_cookies.txt` в корне проекта +3. Формат: Netscape cookies file + +**Примечание:** Без cookies Instagram может блокировать запросы. + +### 4. Запуск основного бота + +```bash +docker compose up -d +``` + +Бот запустится и будет готов к работе! + +Проверить статус: +```bash +docker compose ps +docker compose logs -f bot +``` + +### 5. Запуск VK сервиса (опционально) + +VK сервис можно запустить на том же хосте или на отдельном хосте без VPN: + +```bash +cd vk-downloader +docker compose up -d +``` + +Для работы на отдельном хосте: +1. Скопируйте папку `vk-downloader` на целевой хост +2. Запустите: `docker compose up -d` +3. Обновите `VK_DOWNLOADER_URL` в `.env` основного бота: `http://:5555` ## Использование -1. Найдите бота в Telegram +1. Найдите вашего бота в Telegram по username 2. Отправьте команду `/start` -3. Отправьте ссылку на видео -4. Получите скачанное видео +3. Отправьте ссылку на видео (YouTube, Instagram или VK) +4. Дождитесь скачивания и получите файл + +### Команды + +- `/start` — начало работы с ботом +- `/stat` — статистика: количество пользователей и скачанных видео ## Структура проекта -- `bot.py` - основной код бота -- `docker-compose.yml` - конфигурация Docker Compose -- `Dockerfile` - образ Docker для бота -- `requirements.txt` - зависимости Python +``` +videoDownloadBot/ +├── bot.py # Основной код бота +├── requirements.txt # Python зависимости +├── Dockerfile # Образ для основного бота +├── docker-compose.yml # Конфигурация основного бота +├── .env.example # Пример конфигурации +├── instagram_cookies.txt # Cookies для Instagram (создать вручную) +├── data/ # База данных SQLite (создается автоматически) +├── video/ # Временные файлы видео (создается автоматически) +└── vk-downloader/ # Микросервис для VK + ├── app.py # Flask API сервис + ├── Dockerfile # Образ для VK сервиса + └── docker-compose.yml # Конфигурация VK сервиса +``` +## Обновление + +```bash +git pull +docker compose build +docker compose up -d +``` + +## Логи + +Просмотр логов основного бота: +```bash +docker compose logs -f bot +``` + +Просмотр логов VK сервиса: +```bash +cd vk-downloader +docker compose logs -f +``` + +## Остановка + +```bash +# Основной бот +docker compose down + +# VK сервис +cd vk-downloader +docker compose down +``` + +## Развертывание на продакшене + +### Вариант 1: Все на одном хосте (с VPN) + +1. Настройте VPN для доступа к YouTube и Instagram +2. Запустите основной бот и VK сервис на одном хосте +3. В `.env` укажите: `VK_DOWNLOADER_URL=http://localhost:5555` + +### Вариант 2: Раздельное развертывание (рекомендуется) + +**Хост 1 (с VPN):** +- Основной бот (YouTube, Instagram) +- В `.env`: `VK_DOWNLOADER_URL=http://:5555` + +**Хост 2 (без VPN):** +- VK сервис (`vk-downloader/`) +- В `.env` основного бота: IP этого хоста + +**Преимущества:** +- VK работает быстрее без VPN +- Меньше нагрузка на VPN канал +- Возможность масштабирования VK сервиса отдельно + +## Troubleshooting + +### Бот не отвечает +- Проверьте логи: `docker compose logs bot` +- Убедитесь, что токен правильный в `.env` + +### Instagram не работает +- Проверьте наличие `instagram_cookies.txt` +- Обновите cookies (они могут истечь) + +### VK не работает +- Проверьте, что VK сервис запущен: `cd vk-downloader && docker compose ps` +- Проверьте URL в `.env`: `VK_DOWNLOADER_URL` +- Проверьте доступность порта 5555 + +### База данных не сохраняется +- Проверьте права на папку `data/` +- Убедитесь, что volume смонтирован в `docker-compose.yml` + +## Лицензия + +MIT + +## Поддержка + +При возникновении проблем создайте issue в репозитории.