chore: remove obsolete per-folder scripts, add cookies-cron reference, update docs
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 1m47s
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 1m47s
- 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.
This commit is contained in:
parent
b3550f4aaf
commit
772e9fd5b4
12 changed files with 479 additions and 171 deletions
|
|
@ -179,7 +179,10 @@ CREATE TABLE stats (
|
||||||
|
|
||||||
**Сервисы загрузчиков:**
|
**Сервисы загрузчиков:**
|
||||||
- `./downloads:/app/downloads` — временные файлы
|
- `./downloads:/app/downloads` — временные файлы
|
||||||
- (Instagram) `./instagram_cookies.txt:/app/instagram_cookies.txt:ro`
|
- (YouTube) `./youtube_cookies.txt:/app/youtube_cookies.txt`
|
||||||
|
- (Instagram) `./instagram_cookies.txt:/app/instagram_cookies.txt`
|
||||||
|
|
||||||
|
Cookies монтируются с хоста (не read-only — внешний крон на отдельной машине обновляет файл по `scp`), а не запекаются в образ — это позволяет обновлять их без пересборки/передеплоя сервиса.
|
||||||
|
|
||||||
## Потоки данных
|
## Потоки данных
|
||||||
|
|
||||||
|
|
@ -201,17 +204,20 @@ User → Telegram → Bot
|
||||||
|
|
||||||
## Развертывание
|
## Развертывание
|
||||||
|
|
||||||
### Вариант 1: Все на одном хосте
|
### Текущая схема: единый docker-compose + CI/CD
|
||||||
|
|
||||||
```bash
|
Все 7 сервисов собираются и запускаются одним `docker-compose.yml` из корня репозитория (build-контексты на подпапки, единый `docker compose up -d --build`). Прод деплоится автоматически Forgejo Actions (`.forgejo/workflows/deploy.yml`) при пуше в `main`:
|
||||||
# Запуск всех сервисов
|
|
||||||
for dir in youtube instagram vk yapfiles tiktok; do
|
```
|
||||||
cd ${dir}-downloader && docker compose up -d && cd ..
|
push в main → сборка всех 7 образов → push в Gitea registry
|
||||||
done
|
→ docker save | ssh | docker load на прод-хост
|
||||||
docker compose up -d
|
(registry недоступен напрямую с внешнего VPS)
|
||||||
|
→ docker compose up -d --remove-orphans на проде
|
||||||
```
|
```
|
||||||
|
|
||||||
### Вариант 2: Раздельное развертывание
|
На проде используется `docker-compose.prod.yml` (только `image:`, без `build:`).
|
||||||
|
|
||||||
|
### Гипотетический вариант: раздельное развёртывание
|
||||||
|
|
||||||
**Хост 1 (с VPN для YouTube/Instagram/TikTok):**
|
**Хост 1 (с VPN для YouTube/Instagram/TikTok):**
|
||||||
- Основной бот
|
- Основной бот
|
||||||
|
|
@ -229,7 +235,7 @@ YAPFILES_DOWNLOADER_URL=http://<host2_ip>:5558
|
||||||
## Безопасность
|
## Безопасность
|
||||||
|
|
||||||
- Токен бота в `.env` (не коммитится)
|
- Токен бота в `.env` (не коммитится)
|
||||||
- Cookies Instagram в отдельном файле (не коммитится)
|
- Cookies YouTube/Instagram закоммичены в репозиторий как fallback внутри образа; актуальные версии приходят на хост кроном и монтируются поверх (см. `README.md#cookies-на-проде`)
|
||||||
- Сервисы доступны только по указанным URL
|
- Сервисы доступны только по указанным URL
|
||||||
- Можно добавить API key между сервисами
|
- Можно добавить API key между сервисами
|
||||||
|
|
||||||
|
|
|
||||||
39
README.md
39
README.md
|
|
@ -86,18 +86,16 @@ cd instagram-downloader
|
||||||
|
|
||||||
### 4. Запуск сервисов
|
### 4. Запуск сервисов
|
||||||
|
|
||||||
**Каждый сервис запускается отдельно:**
|
Все 7 сервисов (бот, admin-бот, 5 загрузчиков) собираются и запускаются одной командой из корня проекта — единый `docker-compose.yml` уже содержит build-контексты для всех подпапок:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Запуск сервисов загрузчиков
|
docker compose up -d --build
|
||||||
cd youtube-downloader && docker compose up -d && cd ..
|
```
|
||||||
cd instagram-downloader && docker compose up -d && cd ..
|
|
||||||
cd vk-downloader && docker compose up -d && cd ..
|
|
||||||
cd yapfiles-downloader && docker compose up -d && cd ..
|
|
||||||
cd tiktok-downloader && docker compose up -d && cd ..
|
|
||||||
|
|
||||||
# Запуск основного бота (из корня проекта)
|
Перезапустить/пересобрать только один сервис (например, при правке `youtube-downloader/app.py`):
|
||||||
docker compose up -d
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build youtube-downloader
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Проверка статуса
|
### 5. Проверка статуса
|
||||||
|
|
@ -172,20 +170,21 @@ Content-Type: application/json
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Cookies на проде (YouTube/Instagram)
|
||||||
|
|
||||||
|
В проде `youtube_cookies.txt`/`instagram_cookies.txt` монтируются в контейнеры с хоста (`docker-compose.prod.yml`), а не запекаются в образ — это позволяет обновлять их без пересборки/передеплоя. `yt-dlp`/`app.py` читают файл с диска при каждом запросе — рестарт контейнера не требуется.
|
||||||
|
|
||||||
|
Куки получает по крону (раз в 20 минут) отдельная машина с графическим окружением и реальным залогиненным браузером (на самом проде это сделать нельзя — там нет GUI/браузера), и разливает результат по `scp` сразу на прод и на тестовый стенд. Скрипты для этого, требования к cron-машине и инструкция по развёртыванию на новой машине — в [`cookies-cron/`](cookies-cron/README.md). Это копия того, что реально крутится на cron-машине; `youtube-downloader/get_youtube_cookies.sh` и `instagram-downloader/get_instagram_cookies.sh` в подпапках сервисов — более старые версии тех же скриптов, с тех пор разошедшиеся.
|
||||||
|
|
||||||
## Обновление
|
## Обновление
|
||||||
|
|
||||||
|
Деплой на прод выполняется автоматически через Forgejo CI/CD (`.forgejo/workflows/deploy.yml`) при пуше в `main`: сборка всех 7 образов → push в registry → `docker save`/`ssh`/`docker load` на прод-хост (registry не доступен с внешнего VPS напрямую) → `docker compose up -d --remove-orphans`.
|
||||||
|
|
||||||
|
Для ручного локального обновления:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git pull
|
git pull
|
||||||
|
docker compose up -d --build
|
||||||
# Пересобрать и перезапустить основной бот
|
|
||||||
docker compose down && docker compose up -d --build
|
|
||||||
|
|
||||||
# Пересобрать сервисы загрузчиков
|
|
||||||
cd youtube-downloader && docker compose up -d --build && cd ..
|
|
||||||
cd instagram-downloader && docker compose up -d --build && cd ..
|
|
||||||
cd vk-downloader && docker compose up -d --build && cd ..
|
|
||||||
cd yapfiles-downloader && docker compose up -d --build && cd ..
|
|
||||||
cd tiktok-downloader && docker compose up -d --build && cd ..
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Локализация
|
## Локализация
|
||||||
|
|
@ -204,7 +203,7 @@ cd tiktok-downloader && docker compose up -d --build && cd ..
|
||||||
- Проверьте, что все сервисы запущены и доступны
|
- Проверьте, что все сервисы запущены и доступны
|
||||||
|
|
||||||
### Сервис не работает
|
### Сервис не работает
|
||||||
- Проверьте логи сервиса: `cd <service>-downloader && docker compose logs -f`
|
- Проверьте логи сервиса: `docker compose logs -f <service>-downloader`
|
||||||
- Проверьте URL в `.env`
|
- Проверьте URL в `.env`
|
||||||
- Для Instagram: проверьте валидность cookies
|
- Для Instagram: проверьте валидность cookies
|
||||||
|
|
||||||
|
|
|
||||||
36
cookies-cron/README.md
Normal file
36
cookies-cron/README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# cookies-cron
|
||||||
|
|
||||||
|
Скрипты для регулярного обновления `youtube_cookies.txt`/`instagram_cookies.txt` из реального авторизованного браузера и доставки их по `scp` на прод и тестовые стенды.
|
||||||
|
|
||||||
|
Это **точная копия** скриптов, которые сейчас реально работают по крону на отдельной машине (не на проде — на проде GUI/браузера нет в принципе). Здесь они лежат для справки и на случай, если cron-машину придётся поднимать заново. Ничего в этом репозитории/CI их не запускает и не использует автоматически.
|
||||||
|
|
||||||
|
## Где это должно стоять и работать
|
||||||
|
|
||||||
|
- Машина с **графическим окружением и реальным браузером** (используется Firefox, см. `BROWSER="firefox"` в обоих скриптах) — обычный десктоп/ноутбук, не сервер.
|
||||||
|
- В этом браузере должны быть **активные авторизованные сессии** на youtube.com и на instagram.com — скрипты не логинятся сами, они просто экспортируют куки из уже залогиненного браузера через `yt-dlp --cookies-from-browser`. Если сессии нет (вышел из аккаунта/куки протухли) — экспортируется пустой/неполный набор куков, и видео с этими доменами перестают скачиваться (в Instagram это проявляется как `login required` без всякой ошибки в самом cron-скрипте).
|
||||||
|
- На машине должен быть установлен **`yt-dlp`** и доступен в `PATH` для cron-окружения (не только для интерактивного шелла — у cron urezанный `PATH`). Скрипты исторически не проверяют, что `yt-dlp` реально нашёлся и отработал — при отсутствии `yt-dlp` они тихо «успешно завершаются», просто переиспользуя старый файл cookies. Если куки на проде не обновляются неделями без видимых ошибок — первым делом проверьте `which yt-dlp` на cron-машине.
|
||||||
|
|
||||||
|
## Файлы
|
||||||
|
|
||||||
|
- **`get_instagram_cookies.sh`** / **`get_youtube_cookies.sh`** — извлекают куки из Firefox в локальные `instagram_cookies.txt`/`youtube_cookies.txt` рядом со скриптом.
|
||||||
|
- **`update_cookies.sh`** — оркестратор: гоняет оба скрипта выше, затем разливает результат по `scp` на:
|
||||||
|
- прод (`REMOTE_HOST`/`REMOTE_INSTAGRAM_PATH`/`REMOTE_YOUTUBE_PATH`) — обязательный шаг, при ошибке скрипт падает с `error_exit`;
|
||||||
|
- тестовый стенд (`DEV_HOST`/`DEV_INSTAGRAM_PATH`/`DEV_YOUTUBE_PATH`) — необязательный, при недоступности стенда просто пишет warning и продолжает.
|
||||||
|
|
||||||
|
Значения этих переменных сейчас захардкожены под текущую инфраструктуру (SSH-алиасы `germany`/`hermesDev` из `~/.ssh/config` той машины, где крон запущен) — при разворачивании на новой cron-машине их нужно поправить под актуальные хосты/пути.
|
||||||
|
|
||||||
|
## Установка на новую cron-машину
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. yt-dlp должен быть в PATH (включая cron-окружение)
|
||||||
|
sudo dnf install -y yt-dlp # или: pip install --user yt-dlp / pipx install yt-dlp
|
||||||
|
|
||||||
|
# 2. Залогиниться в Firefox на youtube.com и instagram.com
|
||||||
|
|
||||||
|
# 3. Прописать актуальные REMOTE_HOST/DEV_HOST и пути в update_cookies.sh
|
||||||
|
|
||||||
|
# 4. Добавить в crontab
|
||||||
|
*/20 * * * * /bin/bash -c '/path/to/cookies-cron/update_cookies.sh' >> /path/to/cookies-cron/cron_error.log 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
На принимающей стороне (прод и тестовый стенд) cookies монтируются в контейнеры с хоста — см. `docker-compose.prod.yml`/`docker-compose.yml` и раздел «Cookies на проде» в корневом `README.md`. Перезапуск контейнеров после доставки не требуется — `yt-dlp` читает файл с диска при каждом запросе.
|
||||||
76
cookies-cron/get_instagram_cookies.sh
Executable file
76
cookies-cron/get_instagram_cookies.sh
Executable file
|
|
@ -0,0 +1,76 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Скрипт для получения cookies Instagram через yt-dlp из Firefox
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
COOKIES_FILE="$SCRIPT_DIR/instagram_cookies.txt"
|
||||||
|
BROWSER="firefox"
|
||||||
|
|
||||||
|
# Если запущено с sudo, используем HOME реального пользователя
|
||||||
|
if [ -n "$SUDO_USER" ]; then
|
||||||
|
REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
|
||||||
|
export HOME="$REAL_HOME"
|
||||||
|
echo "⚠️ Обнаружен sudo, использую домашнюю директорию пользователя: $HOME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Получение cookies Instagram из Firefox..."
|
||||||
|
echo "Файл cookies будет сохранен в: $COOKIES_FILE"
|
||||||
|
echo "Получаю cookies..."
|
||||||
|
|
||||||
|
# Извлекаем cookies из браузера напрямую из базы данных (быстро)
|
||||||
|
# --cookies-from-browser извлекает все cookies для домена
|
||||||
|
# Используем один запрос - все cookies для instagram.com будут извлечены
|
||||||
|
echo "Получаю cookies из браузера..."
|
||||||
|
timeout 10 yt-dlp \
|
||||||
|
--cookies-from-browser "$BROWSER" \
|
||||||
|
--cookies "$COOKIES_FILE" \
|
||||||
|
--no-download \
|
||||||
|
--quiet \
|
||||||
|
--socket-timeout 5 \
|
||||||
|
"https://www.instagram.com" 2>&1 | head -20 || true
|
||||||
|
|
||||||
|
# Проверяем, был ли создан файл cookies (не проверяем EXIT_CODE, т.к. команды могут завершиться с ошибками, но cookies могут быть получены)
|
||||||
|
|
||||||
|
if [ -f "$COOKIES_FILE" ]; then
|
||||||
|
# Проверяем, что файл содержит данные (не только заголовки)
|
||||||
|
COOKIE_LINES=$(grep -v '^#' "$COOKIES_FILE" | grep -v '^$' | wc -l)
|
||||||
|
|
||||||
|
if [ "$COOKIE_LINES" -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
|
||||||
|
echo " Найдено строк с cookies: $COOKIE_LINES"
|
||||||
|
echo ""
|
||||||
|
echo "Теперь перезапустите instagram-downloader:"
|
||||||
|
echo " docker compose -f instagram-downloader/docker-compose.yml restart"
|
||||||
|
echo ""
|
||||||
|
echo "Или перезапустите все сервисы:"
|
||||||
|
echo " ./stop_all.sh && ./start_all.sh"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "❌ Ошибка: файл cookies создан, но не содержит данных"
|
||||||
|
rm -f "$COOKIES_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "❌ Ошибка: файл cookies не был создан"
|
||||||
|
echo ""
|
||||||
|
echo "Возможные причины:"
|
||||||
|
echo "1. Firefox не найден или недоступен"
|
||||||
|
echo "2. Проблемы с правами доступа к файлу cookies браузера"
|
||||||
|
echo "3. Cookies не найдены в браузере"
|
||||||
|
echo ""
|
||||||
|
echo "Проверка:"
|
||||||
|
if [ -n "$SUDO_USER" ]; then
|
||||||
|
REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
|
||||||
|
FIREFOX_DIR="$REAL_HOME/.mozilla/firefox"
|
||||||
|
else
|
||||||
|
FIREFOX_DIR="$HOME/.mozilla/firefox"
|
||||||
|
fi
|
||||||
|
if [ -d "$FIREFOX_DIR" ]; then
|
||||||
|
echo " ✓ Директория Firefox найдена: $FIREFOX_DIR"
|
||||||
|
else
|
||||||
|
echo " ✗ Директория Firefox не найдена: $FIREFOX_DIR"
|
||||||
|
echo " Попробуйте запустить скрипт БЕЗ sudo: ./get_instagram_cookies.sh"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
217
cookies-cron/get_youtube_cookies.sh
Executable file
217
cookies-cron/get_youtube_cookies.sh
Executable file
|
|
@ -0,0 +1,217 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Скрипт для получения cookies YouTube через yt-dlp из Firefox
|
||||||
|
# Предназначен для запуска на Ubuntu 24.04 с авторизованным Firefox
|
||||||
|
# Результат копируется через cron на серверы со службами скачивания
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
COOKIES_FILE="$SCRIPT_DIR/youtube_cookies.txt"
|
||||||
|
BROWSER="firefox"
|
||||||
|
TEMP_FILE="${COOKIES_FILE}.tmp"
|
||||||
|
|
||||||
|
# Определяем HOME пользователя (работает для sudo и обычного запуска)
|
||||||
|
if [ -n "$SUDO_USER" ]; then
|
||||||
|
REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
|
||||||
|
export HOME="$REAL_HOME"
|
||||||
|
elif [ -z "$HOME" ] || [ "$HOME" = "/root" ]; then
|
||||||
|
# Если HOME не установлен или это root, пытаемся найти реального пользователя
|
||||||
|
REAL_USER=$(whoami)
|
||||||
|
if [ "$REAL_USER" != "root" ]; then
|
||||||
|
export HOME=$(getent passwd "$REAL_USER" | cut -d: -f6)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверка для cron: если запущен без терминала, меньше вывода
|
||||||
|
if [ -t 0 ]; then
|
||||||
|
VERBOSE=1
|
||||||
|
else
|
||||||
|
VERBOSE=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo "Получение cookies YouTube из Firefox..."
|
||||||
|
echo "Файл cookies будет сохранен в: $COOKIES_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем наличие yt-dlp
|
||||||
|
if ! command -v yt-dlp &> /dev/null; then
|
||||||
|
echo "ERROR: yt-dlp не найден в системе" >&2
|
||||||
|
echo "Установите: sudo apt install yt-dlp (Ubuntu) или pip install yt-dlp" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo "Получаю cookies..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Удаляем старый временный файл
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
|
||||||
|
# Извлекаем cookies из браузера напрямую из базы данных
|
||||||
|
# --cookies-from-browser извлекает cookies для всех доменов, связанных с URL
|
||||||
|
# Используем один запрос с основным URL - cookies для всех поддоменов будут извлечены
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo "Получаю cookies из браузера..."
|
||||||
|
timeout 10 yt-dlp \
|
||||||
|
--cookies-from-browser "$BROWSER" \
|
||||||
|
--cookies "$TEMP_FILE" \
|
||||||
|
--no-download \
|
||||||
|
--quiet \
|
||||||
|
--socket-timeout 5 \
|
||||||
|
"https://www.youtube.com" > /dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
timeout 10 yt-dlp \
|
||||||
|
--cookies-from-browser "$BROWSER" \
|
||||||
|
--cookies "$TEMP_FILE" \
|
||||||
|
--no-download \
|
||||||
|
--quiet \
|
||||||
|
--socket-timeout 5 \
|
||||||
|
"https://www.youtube.com" > /dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Функция проверки валидности куков
|
||||||
|
check_cookies() {
|
||||||
|
local file="$1"
|
||||||
|
local current_time=$(date +%s)
|
||||||
|
|
||||||
|
# Проверяем существование файла
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем, что файл содержит данные (не только заголовки)
|
||||||
|
local cookie_lines=$(grep -v '^#' "$file" | grep -v '^$' | wc -l)
|
||||||
|
if [ "$cookie_lines" -eq 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем наличие YouTube-куков
|
||||||
|
local youtube_cookies=$(grep -E '\.youtube\.com|youtube\.com' "$file" | grep -v '^#' | wc -l)
|
||||||
|
if [ "$youtube_cookies" -eq 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем срок действия куков (должен быть хотя бы один не просроченный)
|
||||||
|
local valid_cookies=0
|
||||||
|
local expired_cookies=0
|
||||||
|
|
||||||
|
# Используем awk для более надежного парсинга
|
||||||
|
while IFS=$'\t' read -r domain flag path secure expiration name value; do
|
||||||
|
# Пропускаем комментарии и пустые строки
|
||||||
|
[[ "$domain" =~ ^#.*$ ]] && continue
|
||||||
|
[[ -z "$domain" ]] && continue
|
||||||
|
|
||||||
|
# Проверяем только YouTube-куки
|
||||||
|
if [[ "$domain" =~ youtube\.com ]]; then
|
||||||
|
if [ "$expiration" = "0" ] || [ -z "$expiration" ]; then
|
||||||
|
# Сессионные куки (expiration=0) считаем валидными
|
||||||
|
valid_cookies=$((valid_cookies + 1))
|
||||||
|
else
|
||||||
|
# Проверяем срок действия
|
||||||
|
if [ "$expiration" -gt "$current_time" ] 2>/dev/null; then
|
||||||
|
valid_cookies=$((valid_cookies + 1))
|
||||||
|
else
|
||||||
|
expired_cookies=$((expired_cookies + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$file"
|
||||||
|
|
||||||
|
# Должен быть хотя бы один валидный YouTube-куки
|
||||||
|
if [ "$valid_cookies" -eq 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Если есть просроченные куки, выводим предупреждение, но не считаем критичным
|
||||||
|
if [ "$expired_cookies" -gt 0 ] && [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo "⚠️ Предупреждение: найдено $expired_cookies просроченных YouTube-куков" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Проверяем результат
|
||||||
|
if [ -f "$TEMP_FILE" ] && check_cookies "$TEMP_FILE"; then
|
||||||
|
# Куки валидны, переносим во временный файл в финальный
|
||||||
|
mv "$TEMP_FILE" "$COOKIES_FILE"
|
||||||
|
|
||||||
|
# Собираем статистику для вывода
|
||||||
|
COOKIE_LINES=$(grep -v '^#' "$COOKIES_FILE" | grep -v '^$' | wc -l)
|
||||||
|
YOUTUBE_COOKIES=$(grep -E '\.youtube\.com|youtube\.com' "$COOKIES_FILE" | grep -v '^#' | wc -l)
|
||||||
|
IMPORTANT_COOKIES=$(grep -E 'VISITOR_INFO1_LIVE|__Secure-3PSID|PREF|__Secure-YNID' "$COOKIES_FILE" | grep -v '^#' | wc -l)
|
||||||
|
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
|
||||||
|
echo " Всего строк с cookies: $COOKIE_LINES"
|
||||||
|
echo " YouTube-куков: $YOUTUBE_COOKIES"
|
||||||
|
echo " Важных куков: $IMPORTANT_COOKIES"
|
||||||
|
echo ""
|
||||||
|
echo "Файл готов к копированию на серверы через cron"
|
||||||
|
else
|
||||||
|
# Минимальный вывод для cron (можно логировать в файл)
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - YouTube cookies updated: $YOUTUBE_COOKIES cookies, $IMPORTANT_COOKIES important"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
# Очищаем временный файл при ошибке
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "❌ Ошибка: не удалось получить валидные YouTube-куки"
|
||||||
|
echo ""
|
||||||
|
echo "Возможные причины:"
|
||||||
|
echo "1. В Firefox нет куков для YouTube"
|
||||||
|
echo "2. Откройте YouTube в Firefox и войдите в аккаунт"
|
||||||
|
echo "3. Все куки просрочены - обновите их в браузере"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Failed to get valid YouTube cookies" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$COOKIES_FILE" ]; then
|
||||||
|
# Если файла не было, это критичная ошибка
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
# Если файл был, просто оставляем старый (лучше работать со старыми куками чем без них)
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo "⚠️ Оставляю существующий файл cookies без изменений"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$TEMP_FILE" ] && [ ! -f "$COOKIES_FILE" ]; then
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "❌ Ошибка: файл cookies не был создан"
|
||||||
|
echo ""
|
||||||
|
echo "Возможные причины:"
|
||||||
|
echo "1. Firefox не найден или недоступен"
|
||||||
|
echo "2. Проблемы с правами доступа к файлу cookies браузера"
|
||||||
|
echo "3. Cookies не найдены в браузере"
|
||||||
|
echo ""
|
||||||
|
echo "Проверка:"
|
||||||
|
FIREFOX_DIR="$HOME/.mozilla/firefox"
|
||||||
|
if [ -d "$FIREFOX_DIR" ]; then
|
||||||
|
echo " ✓ Директория Firefox найдена: $FIREFOX_DIR"
|
||||||
|
else
|
||||||
|
echo " ✗ Директория Firefox не найдена: $FIREFOX_DIR"
|
||||||
|
echo " Убедитесь что Firefox установлен и вы авторизованы на YouTube"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Cookies file was not created" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Если был старый файл, оставляем его
|
||||||
|
if [ -f "$COOKIES_FILE" ]; then
|
||||||
|
if [ "$VERBOSE" = "1" ]; then
|
||||||
|
echo "⚠️ Оставляю существующий файл cookies без изменений"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
111
cookies-cron/update_cookies.sh
Executable file
111
cookies-cron/update_cookies.sh
Executable file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Скрипт для обновления cookies Instagram и YouTube через cron
|
||||||
|
# Запускает скрипты получения cookies и копирует их на удаленный хост
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Определяем директорию скрипта
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
# Настройки
|
||||||
|
INSTAGRAM_SCRIPT="$SCRIPT_DIR/get_instagram_cookies.sh"
|
||||||
|
YOUTUBE_SCRIPT="$SCRIPT_DIR/get_youtube_cookies.sh"
|
||||||
|
INSTAGRAM_COOKIES="$SCRIPT_DIR/instagram_cookies.txt"
|
||||||
|
YOUTUBE_COOKIES="$SCRIPT_DIR/youtube_cookies.txt"
|
||||||
|
REMOTE_HOST="germany"
|
||||||
|
REMOTE_INSTAGRAM_PATH="/root/services/videoDownloadTGbot/instagram_cookies.txt"
|
||||||
|
REMOTE_YOUTUBE_PATH="/root/services/videoDownloadTGbot/youtube_cookies.txt"
|
||||||
|
DEV_HOST="hermesDev"
|
||||||
|
DEV_INSTAGRAM_PATH="services/videoDownloadTGbot/instagram-downloader/instagram_cookies.txt"
|
||||||
|
DEV_YOUTUBE_PATH="services/videoDownloadTGbot/youtube-downloader/youtube_cookies.txt"
|
||||||
|
LOG_FILE="$SCRIPT_DIR/cron.log"
|
||||||
|
|
||||||
|
# Функция логирования
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Функция обработки ошибок
|
||||||
|
error_exit() {
|
||||||
|
log "ОШИБКА: $*"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
log "=== Начало обновления cookies ==="
|
||||||
|
|
||||||
|
# Проверяем наличие скриптов
|
||||||
|
if [ ! -f "$INSTAGRAM_SCRIPT" ]; then
|
||||||
|
error_exit "Скрипт не найден: $INSTAGRAM_SCRIPT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$YOUTUBE_SCRIPT" ]; then
|
||||||
|
error_exit "Скрипт не найден: $YOUTUBE_SCRIPT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем, что скрипты исполняемые
|
||||||
|
chmod +x "$INSTAGRAM_SCRIPT" "$YOUTUBE_SCRIPT"
|
||||||
|
|
||||||
|
# Получаем cookies Instagram
|
||||||
|
log "Получение cookies Instagram..."
|
||||||
|
if bash "$INSTAGRAM_SCRIPT" >> "$LOG_FILE" 2>&1; then
|
||||||
|
if [ -f "$INSTAGRAM_COOKIES" ]; then
|
||||||
|
log "✅ Cookies Instagram успешно получены"
|
||||||
|
else
|
||||||
|
error_exit "Файл cookies Instagram не был создан"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
error_exit "Ошибка при получении cookies Instagram (код возврата: $?)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Получаем cookies YouTube
|
||||||
|
log "Получение cookies YouTube..."
|
||||||
|
if bash "$YOUTUBE_SCRIPT" >> "$LOG_FILE" 2>&1; then
|
||||||
|
if [ -f "$YOUTUBE_COOKIES" ]; then
|
||||||
|
log "✅ Cookies YouTube успешно получены"
|
||||||
|
else
|
||||||
|
error_exit "Файл cookies YouTube не был создан"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# YouTube скрипт может завершиться с кодом 0, даже если новый файл не создан (использует старый)
|
||||||
|
if [ -f "$YOUTUBE_COOKIES" ]; then
|
||||||
|
log "✅ Cookies YouTube (возможно использован старый файл)"
|
||||||
|
else
|
||||||
|
error_exit "Файл cookies YouTube не найден"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Копируем cookies на удаленный хост (прод)
|
||||||
|
log "Копирование cookies на удаленный хост $REMOTE_HOST..."
|
||||||
|
|
||||||
|
# Копируем Instagram cookies
|
||||||
|
if scp -q "$INSTAGRAM_COOKIES" "${REMOTE_HOST}:${REMOTE_INSTAGRAM_PATH}" 2>>"$LOG_FILE"; then
|
||||||
|
log "✅ Instagram cookies скопированы на $REMOTE_HOST"
|
||||||
|
else
|
||||||
|
error_exit "Ошибка при копировании Instagram cookies (код возврата: $?)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Копируем YouTube cookies
|
||||||
|
if scp -q "$YOUTUBE_COOKIES" "${REMOTE_HOST}:${REMOTE_YOUTUBE_PATH}" 2>>"$LOG_FILE"; then
|
||||||
|
log "✅ YouTube cookies скопированы на $REMOTE_HOST"
|
||||||
|
else
|
||||||
|
error_exit "Ошибка при копировании YouTube cookies (код возврата: $?)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Копируем cookies на тестовый стенд (не блокируем прод-доставку, если стенд недоступен)
|
||||||
|
log "Копирование cookies на тестовый стенд $DEV_HOST..."
|
||||||
|
|
||||||
|
if scp -q "$INSTAGRAM_COOKIES" "${DEV_HOST}:${DEV_INSTAGRAM_PATH}" 2>>"$LOG_FILE"; then
|
||||||
|
log "✅ Instagram cookies скопированы на $DEV_HOST"
|
||||||
|
else
|
||||||
|
log "⚠️ Не удалось скопировать Instagram cookies на $DEV_HOST (продолжаем)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if scp -q "$YOUTUBE_COOKIES" "${DEV_HOST}:${DEV_YOUTUBE_PATH}" 2>>"$LOG_FILE"; then
|
||||||
|
log "✅ YouTube cookies скопированы на $DEV_HOST"
|
||||||
|
else
|
||||||
|
log "⚠️ Не удалось скопировать YouTube cookies на $DEV_HOST (продолжаем)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "=== Обновление cookies завершено успешно ==="
|
||||||
|
exit 0
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Простой способ получить cookies Instagram
|
|
||||||
|
|
||||||
echo "Выберите способ получения cookies:"
|
|
||||||
echo "1) Автоматически из браузера Chrome (нужно чтобы Chrome был запущен)"
|
|
||||||
echo "2) Автоматически из браузера Firefox (нужно чтобы Firefox был запущен)"
|
|
||||||
echo ""
|
|
||||||
read -p "Ваш выбор (1 или 2): " choice
|
|
||||||
|
|
||||||
if [ "$choice" = "1" ]; then
|
|
||||||
docker compose exec bot yt-dlp --cookies-from-browser chrome --cookies /app/instagram_cookies.txt --no-download https://www.instagram.com 2>&1 | head -10
|
|
||||||
echo ""
|
|
||||||
echo "✅ Cookies сохранены в instagram_cookies.txt"
|
|
||||||
elif [ "$choice" = "2" ]; then
|
|
||||||
docker compose exec bot yt-dlp --cookies-from-browser firefox --cookies /app/instagram_cookies.txt --no-download https://www.instagram.com 2>&1 | head -10
|
|
||||||
echo ""
|
|
||||||
echo "✅ Cookies сохранены в instagram_cookies.txt"
|
|
||||||
else
|
|
||||||
echo "Неверный выбор"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Теперь перезапустите бота: docker compose restart bot"
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Получение cookies Instagram локально (на вашем компьютере, не в Docker)
|
|
||||||
|
|
||||||
echo "========================================="
|
|
||||||
echo "Получение cookies Instagram"
|
|
||||||
echo "========================================="
|
|
||||||
echo ""
|
|
||||||
echo "ВАЖНО: Запустите эту команду на вашем компьютере (не в Docker),"
|
|
||||||
echo " после того как вы залогинились в Instagram в браузере"
|
|
||||||
echo ""
|
|
||||||
echo "Выберите браузер:"
|
|
||||||
echo "1) Chrome/Chromium"
|
|
||||||
echo "2) Firefox"
|
|
||||||
read -p "Ваш выбор (1 или 2): " choice
|
|
||||||
|
|
||||||
if [ "$choice" = "1" ]; then
|
|
||||||
# Для Chrome
|
|
||||||
if command -v yt-dlp &> /dev/null; then
|
|
||||||
yt-dlp --cookies-from-browser chrome --cookies ./instagram_cookies.txt --no-download https://www.instagram.com
|
|
||||||
else
|
|
||||||
echo "❌ yt-dlp не установлен. Установите: pip install yt-dlp"
|
|
||||||
echo ""
|
|
||||||
echo "Или используйте расширение браузера:"
|
|
||||||
echo "Chrome: https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
elif [ "$choice" = "2" ]; then
|
|
||||||
# Для Firefox
|
|
||||||
if command -v yt-dlp &> /dev/null; then
|
|
||||||
yt-dlp --cookies-from-browser firefox --cookies ./instagram_cookies.txt --no-download https://www.instagram.com
|
|
||||||
else
|
|
||||||
echo "❌ yt-dlp не установлен. Установите: pip install yt-dlp"
|
|
||||||
echo ""
|
|
||||||
echo "Или используйте расширение браузера:"
|
|
||||||
echo "Firefox: https://addons.mozilla.org/en-US/firefox/addon/cookies-txt/"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Неверный выбор"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "./instagram_cookies.txt" ]; then
|
|
||||||
echo ""
|
|
||||||
echo "✅ Cookies сохранены в instagram_cookies.txt"
|
|
||||||
echo ""
|
|
||||||
echo "Теперь перезапустите бота:"
|
|
||||||
echo " docker compose restart bot"
|
|
||||||
else
|
|
||||||
echo "❌ Ошибка: файл cookies не создан"
|
|
||||||
fi
|
|
||||||
|
|
@ -45,11 +45,8 @@ if [ -f "$COOKIES_FILE" ]; then
|
||||||
echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
|
echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
|
||||||
echo " Найдено строк с cookies: $COOKIE_LINES"
|
echo " Найдено строк с cookies: $COOKIE_LINES"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Теперь перезапустите instagram-downloader:"
|
echo "Если cookies смонтированы с хоста (см. docker-compose.yml/docker-compose.prod.yml),"
|
||||||
echo " docker compose -f instagram-downloader/docker-compose.yml restart"
|
echo "перезапуск не нужен — yt-dlp читает файл заново при каждом запросе."
|
||||||
echo ""
|
|
||||||
echo "Или перезапустите все сервисы:"
|
|
||||||
echo " ./stop_all.sh && ./start_all.sh"
|
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "❌ Ошибка: файл cookies создан, но не содержит данных"
|
echo "❌ Ошибка: файл cookies создан, но не содержит данных"
|
||||||
|
|
|
||||||
32
start_all.sh
32
start_all.sh
|
|
@ -1,32 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Скрипт для запуска всех сервисов
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
cd "$SCRIPT_DIR"
|
|
||||||
|
|
||||||
echo "🚀 Запуск всех сервисов..."
|
|
||||||
|
|
||||||
# Сервисы загрузчиков
|
|
||||||
services=("youtube-downloader" "instagram-downloader" "vk-downloader" "yapfiles-downloader" "tiktok-downloader")
|
|
||||||
|
|
||||||
for service in "${services[@]}"; do
|
|
||||||
echo ""
|
|
||||||
echo "📦 Запуск $service..."
|
|
||||||
cd "$SCRIPT_DIR/$service"
|
|
||||||
docker compose up -d --build
|
|
||||||
done
|
|
||||||
|
|
||||||
# Основной бот
|
|
||||||
echo ""
|
|
||||||
echo "🤖 Запуск основного бота..."
|
|
||||||
cd "$SCRIPT_DIR"
|
|
||||||
docker compose up -d --build
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "✅ Все сервисы запущены!"
|
|
||||||
echo ""
|
|
||||||
echo "📊 Статус контейнеров:"
|
|
||||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "(video_download|youtube|instagram|vk|yapfiles|tiktok|NAMES)"
|
|
||||||
|
|
||||||
24
stop_all.sh
24
stop_all.sh
|
|
@ -1,24 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Скрипт для остановки всех сервисов
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
cd "$SCRIPT_DIR"
|
|
||||||
|
|
||||||
echo "🛑 Остановка всех сервисов..."
|
|
||||||
|
|
||||||
# Основной бот
|
|
||||||
echo "🤖 Остановка основного бота..."
|
|
||||||
docker compose down 2>/dev/null || true
|
|
||||||
|
|
||||||
# Сервисы загрузчиков
|
|
||||||
services=("youtube-downloader" "instagram-downloader" "vk-downloader" "yapfiles-downloader" "tiktok-downloader")
|
|
||||||
|
|
||||||
for service in "${services[@]}"; do
|
|
||||||
echo "📦 Остановка $service..."
|
|
||||||
cd "$SCRIPT_DIR/$service"
|
|
||||||
docker compose down 2>/dev/null || true
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "✅ Все сервисы остановлены!"
|
|
||||||
|
|
||||||
|
|
@ -68,11 +68,8 @@ if [ -f "$COOKIES_FILE" ]; then
|
||||||
echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
|
echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
|
||||||
echo " Найдено строк с cookies: $COOKIE_LINES"
|
echo " Найдено строк с cookies: $COOKIE_LINES"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Теперь перезапустите youtube-downloader:"
|
echo "Если cookies смонтированы с хоста (см. docker-compose.yml/docker-compose.prod.yml),"
|
||||||
echo " docker compose -f youtube-downloader/docker-compose.yml restart"
|
echo "перезапуск не нужен — yt-dlp читает файл заново при каждом запросе."
|
||||||
echo ""
|
|
||||||
echo "Или перезапустите все сервисы:"
|
|
||||||
echo " ./stop_all.sh && ./start_all.sh"
|
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "❌ Ошибка: файл cookies создан, но не содержит данных"
|
echo "❌ Ошибка: файл cookies создан, но не содержит данных"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue