videoDownloadTGbot/ARCHITECTURE.md
vrubelroman 772e9fd5b4
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 1m47s
chore: remove obsolete per-folder scripts, add cookies-cron reference, update docs
- Remove get_cookies.sh (targets a container without yt-dlp, already
  broken), get_cookies_local.sh, start_all.sh/stop_all.sh — these
  implement the old per-service-compose startup that now conflicts
  with the unified root docker-compose.yml.
- Add cookies-cron/ — a reference copy of the scripts actually running
  via cron on the separate browser-equipped machine, with setup
  requirements and instructions for standing up a new cron host.
- Update README.md/ARCHITECTURE.md to describe the current unified
  docker-compose + CI/CD deploy flow and host-mounted cookies instead
  of the old per-folder workflow.
2026-06-30 22:16:40 +00:00

254 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Архитектура системы
Документ описывает внутреннюю архитектуру и принципы работы Telegram Video Download Bot.
## Общая архитектура
Система состоит из микросервисной архитектуры с раздельными сервисами для каждого источника видео:
1. **Основной бот** (`bot.py`) — Telegram бот, обрабатывающий запросы пользователей
2. **YouTube Downloader Service** (`youtube-downloader/`) — порт 5557
3. **Instagram Downloader Service** (`instagram-downloader/`) — порт 5556
4. **VK Downloader Service** (`vk-downloader/`) — порт 5555
5. **Yapfiles Downloader Service** (`yapfiles-downloader/`) — порт 5558
6. **TikTok Downloader Service** (`tiktok-downloader/`) — порт 5559
```
┌─────────────────┐
│ Telegram User │
└────────┬────────┘
┌─────────────────────────────────────────────────────────┐
│ Основной бот (bot.py) │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Message Handler │ │
│ │ - URL extraction │ │
│ │ - Source detection (YouTube/Instagram/TikTok/VK/ │ │
│ │ Yapfiles) │ │
│ │ - Localization (ru/en) │ │
│ └────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ HTTP API Clients (httpx) │ │
│ │ - YouTube, Instagram, TikTok, VK, Yapfiles │ │
│ └────────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ SQLite Database (data/bot.db) │ │
│ │ - users (chat_id, username, locale, ...) │ │
│ │ - stats (total_downloads) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│ HTTP POST /download/stream
┌────────┬────────┬────────┬────────┬────────┐
│YouTube │Instagram│ TikTok │ VK │Yapfiles│
│ :5557 │ :5556 │ :5559 │ :5555 │ :5558 │
│ │ │ │ │ │
│yt-dlp │yt-dlp │yt-dlp │yt-dlp │requests│
│ │+cookies│ │ │+parsing│
└────────┴────────┴────────┴────────┴────────┘
```
## Компоненты системы
### 1. Основной бот (bot.py)
**Технологии:**
- `python-telegram-bot` — асинхронный фреймворк для Telegram Bot API
- `httpx` — асинхронный HTTP клиент
- `sqlite3` — база данных
**Ключевые функции:**
#### Локализация
```python
TEXTS = {
'ru': { 'start': '...', 'support': '...', ... },
'en': { 'start': '...', 'support': '...', ... }
}
def get_locale_from_language_code(language_code: str) -> str:
# 'ru*' → 'ru', иначе → 'en'
```
#### Определение источника
```python
def detect_video_source(url: str) -> str:
# youtube.com, youtu.be → 'youtube'
# instagram.com → 'instagram'
# tiktok.com → 'tiktok'
# vk.com, vkontakte.ru → 'vk'
# yapfiles.ru → 'yapfiles'
# иначе → 'unknown'
```
#### Команды
- `/start` — приветствие с локализацией
- `/stat` — статистика бота
- `/support` — информация о боте и контакт автора
### 2. Сервисы загрузчиков
Все сервисы имеют единый API:
| Endpoint | Метод | Описание |
|----------|-------|----------|
| `/health` | GET | Проверка работоспособности |
| `/download/stream` | POST | Скачивание видео |
**Request:**
```json
{"url": "https://..."}
```
**Response:** Бинарные данные видео или JSON с ошибкой.
#### YouTube Downloader (порт 5557)
- Использует `yt-dlp` с настройками для YouTube
- Поддержка shorts, плейлистов
#### Instagram Downloader (порт 5556)
- Использует `yt-dlp` с cookies
- Требует `instagram_cookies.txt`
#### TikTok Downloader (порт 5559)
- Использует `yt-dlp`
- Поддержка коротких и полных ссылок
#### VK Downloader (порт 5555)
- Использует `yt-dlp` с русскими заголовками
- Не требует VPN в РФ
#### Yapfiles Downloader (порт 5558)
- Парсит HTML страницу
- Извлекает прямую ссылку на видео
- Использует `requests` + `BeautifulSoup`
### 3. База данных
**Схема:**
```sql
CREATE TABLE users (
chat_id INTEGER PRIMARY KEY,
username TEXT,
first_name TEXT,
first_seen TEXT NOT NULL,
last_seen TEXT NOT NULL,
locale TEXT DEFAULT 'en' -- ru/en
);
CREATE TABLE stats (
id INTEGER PRIMARY KEY CHECK (id = 1),
total_downloads INTEGER DEFAULT 0
);
```
**Миграция:** При запуске бот автоматически добавляет колонку `locale` если её нет (для совместимости со старой базой).
### 4. Скрипт рассылки (broadcast.py)
Консольная утилита для отправки сообщений всем пользователям:
```bash
./broadcast.py -y "Текст сообщения"
./broadcast.py -y --html "<b>Жирный</b> текст"
./broadcast.py -y --file message.txt
./broadcast.py --list # показать пользователей
```
Автоматически читает `.env` для получения токена бота.
## Docker архитектура
### Порты
| Сервис | Внешний порт | Внутренний порт |
|--------|--------------|-----------------|
| VK | 5555 | 5000 |
| Instagram | 5556 | 5000 |
| YouTube | 5557 | 5000 |
| Yapfiles | 5558 | 5000 |
| TikTok | 5559 | 5000 |
### Volumes
**Основной бот:**
- `./video:/app/video` — скачанные видео
- `./data:/app/data` — база данных
**Сервисы загрузчиков:**
- `./downloads:/app/downloads` — временные файлы
- (YouTube) `./youtube_cookies.txt:/app/youtube_cookies.txt`
- (Instagram) `./instagram_cookies.txt:/app/instagram_cookies.txt`
Cookies монтируются с хоста (не read-only — внешний крон на отдельной машине обновляет файл по `scp`), а не запекаются в образ — это позволяет обновлять их без пересборки/передеплоя сервиса.
## Потоки данных
```
User → Telegram → Bot
detect_video_source(url)
download_{source}_video()
HTTP POST → Service → yt-dlp/parser
binary video data
save to video/ → send to User
increment_downloads()
```
## Развертывание
### Текущая схема: единый docker-compose + CI/CD
Все 7 сервисов собираются и запускаются одним `docker-compose.yml` из корня репозитория (build-контексты на подпапки, единый `docker compose up -d --build`). Прод деплоится автоматически Forgejo Actions (`.forgejo/workflows/deploy.yml`) при пуше в `main`:
```
push в main → сборка всех 7 образов → push в Gitea registry
→ docker save | ssh | docker load на прод-хост
(registry недоступен напрямую с внешнего VPS)
→ docker compose up -d --remove-orphans на проде
```
На проде используется `docker-compose.prod.yml` (только `image:`, без `build:`).
### Гипотетический вариант: раздельное развёртывание
**Хост 1 (с VPN для YouTube/Instagram/TikTok):**
- Основной бот
- YouTube, Instagram, TikTok сервисы
**Хост 2 (без VPN):**
- VK, Yapfiles сервисы
В `.env` на хосте 1:
```env
VK_DOWNLOADER_URL=http://<host2_ip>:5555
YAPFILES_DOWNLOADER_URL=http://<host2_ip>:5558
```
## Безопасность
- Токен бота в `.env` (не коммитится)
- Cookies YouTube/Instagram закоммичены в репозиторий как fallback внутри образа; актуальные версии приходят на хост кроном и монтируются поверх (см. `README.md#cookies-на-проде`)
- Сервисы доступны только по указанным URL
- Можно добавить API key между сервисами
## Мониторинг
- Все сервисы логируют в stdout
- Health check: `GET /health` на каждом сервисе
- Логи Docker: `docker compose logs -f`
## Будущие улучшения
1. **Аутентификация между сервисами** — API key/JWT
2. **Очередь задач** — Celery для фоновой обработки
3. **Prometheus метрики** — мониторинг производительности
4. **Кеширование** — Redis для частых запросов
5. **Поддержка новых источников** — Twitter, Facebook, etc.