- 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.
11 KiB
Архитектура системы
Документ описывает внутреннюю архитектуру и принципы работы Telegram Video Download Bot.
Общая архитектура
Система состоит из микросервисной архитектуры с раздельными сервисами для каждого источника видео:
- Основной бот (
bot.py) — Telegram бот, обрабатывающий запросы пользователей - YouTube Downloader Service (
youtube-downloader/) — порт 5557 - Instagram Downloader Service (
instagram-downloader/) — порт 5556 - VK Downloader Service (
vk-downloader/) — порт 5555 - Yapfiles Downloader Service (
yapfiles-downloader/) — порт 5558 - 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 APIhttpx— асинхронный HTTP клиентsqlite3— база данных
Ключевые функции:
Локализация
TEXTS = {
'ru': { 'start': '...', 'support': '...', ... },
'en': { 'start': '...', 'support': '...', ... }
}
def get_locale_from_language_code(language_code: str) -> str:
# 'ru*' → 'ru', иначе → 'en'
Определение источника
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:
{"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. База данных
Схема:
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)
Консольная утилита для отправки сообщений всем пользователям:
./broadcast.py -y "Текст сообщения"
./broadcast.py -y --html "<b>Жирный</b> текст"
./broadcast.py -y --file message.txt
./broadcast.py --list # показать пользователей
Автоматически читает .env для получения токена бота.
Docker архитектура
Порты
| Сервис | Внешний порт | Внутренний порт |
|---|---|---|
| VK | 5555 | 5000 |
| 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:
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
Будущие улучшения
- Аутентификация между сервисами — API key/JWT
- Очередь задач — Celery для фоновой обработки
- Prometheus метрики — мониторинг производительности
- Кеширование — Redis для частых запросов
- Поддержка новых источников — Twitter, Facebook, etc.