Enhance YouTube downloader with improved cookie validation and download strategies. Update cookie extraction script for better error handling and user feedback.

This commit is contained in:
vrubel 2025-12-25 21:38:13 +03:00
parent a918f93dfa
commit e6c6734768
2 changed files with 378 additions and 236 deletions

View file

@ -4,6 +4,7 @@ YouTube Video Downloader Service
""" """
import os import os
import logging import logging
import time
from pathlib import Path from pathlib import Path
from flask import Flask, request, jsonify from flask import Flask, request, jsonify
from flask_cors import CORS from flask_cors import CORS
@ -33,195 +34,227 @@ def _safe_filename(title: str) -> str:
def _is_valid_cookies_file(cookies_path: Path) -> bool: def _is_valid_cookies_file(cookies_path: Path) -> bool:
"""Проверяет, что файл cookies существует и содержит данные (не только заголовки)""" """Проверяет, что файл cookies существует и содержит валидные YouTube-куки"""
if not cookies_path.exists(): if not cookies_path.exists():
return False return False
try: try:
with open(cookies_path, 'r', encoding='utf-8', errors='ignore') as f: with open(cookies_path, 'r', encoding='utf-8', errors='ignore') as f:
lines = [line.strip() for line in f.readlines() if line.strip() and not line.strip().startswith('#')] content = f.read()
# Проверяем, что есть хотя бы одна строка с данными cookie
return len(lines) > 0 # Простая проверка: есть ли YouTube-куки в файле
has_youtube_domain = '.youtube.com' in content or 'youtube.com' in content
if not has_youtube_domain:
logger.warning("YouTube: в файле cookies нет YouTube-куков")
return False
# Проверяем строки с данными (не комментарии)
lines = [line.strip() for line in content.split('\n') if line.strip() and not line.strip().startswith('#')]
if len(lines) == 0:
return False
# Проверяем наличие YouTube-куков и важных параметров
youtube_cookies_count = 0
important_cookies_count = 0
current_time = int(time.time())
for line in lines:
# Формат Netscape cookie: domain, flag, path, secure, expiration, name, value
# Разделяем по табуляции, но учитываем что значения могут содержать табы
parts = line.split('\t')
if len(parts) >= 7: # Должно быть минимум 7 полей
domain = parts[0].strip()
expiration = parts[4].strip()
cookie_name = parts[5].strip() if len(parts) > 5 else ''
# Проверяем домен
if '.youtube.com' in domain or domain == 'youtube.com':
youtube_cookies_count += 1
# Проверяем срок действия (0 означает сессионный куки, это нормально)
is_valid = True
if expiration != '0':
try:
exp_time = int(expiration)
if exp_time < current_time:
is_valid = False
logger.debug(f"YouTube: просроченный куки {cookie_name} (истек: {exp_time})")
except (ValueError, OverflowError):
pass
# Проверяем наличие важных куков
if is_valid and any(important in cookie_name for important in ['VISITOR_INFO1_LIVE', '__Secure-3PSID', 'PREF', '__Secure-YNID', 'YSC']):
important_cookies_count += 1
if youtube_cookies_count > 0:
if important_cookies_count > 0:
logger.debug(f"YouTube: найдены валидные куки ({youtube_cookies_count} YouTube-куков, {important_cookies_count} важных)")
else:
logger.warning(f"YouTube: найдены YouTube-куки ({youtube_cookies_count}), но нет важных параметров")
return True
else:
logger.warning("YouTube: в файле cookies нет валидных YouTube-куков")
return False
except Exception as e: except Exception as e:
logger.warning(f"Ошибка при проверке файла cookies: {e}") logger.warning(f"Ошибка при проверке файла cookies: {e}")
return False return False
def download_youtube_video(url: str, max_retries: int = 3) -> Path: def download_youtube_video(url: str, max_retries: int = 3) -> Path:
"""Скачивает видео с YouTube - используем cookies для обхода блокировок""" """
Скачивает видео с YouTube с умной стратегией использования куков:
1. Сначала пробуем БЕЗ куков (работает в большинстве случаев)
2. Если нужны куки (18+, приватные, проверка на бота) - пробуем файл куков
3. Если файл не работает - пробуем автоматически из браузера (если доступен)
"""
cookies_file = os.getenv('YOUTUBE_COOKIES_FILE', 'youtube_cookies.txt') cookies_file = os.getenv('YOUTUBE_COOKIES_FILE', 'youtube_cookies.txt')
cookies_file_path = Path(cookies_file) cookies_file_path = Path(cookies_file)
cookies_valid = _is_valid_cookies_file(cookies_file_path) # Проверяем наличие валидного файла куков (но не используем сразу)
if not cookies_valid: cookies_file_valid = _is_valid_cookies_file(cookies_file_path)
logger.warning(f"YouTube: файл cookies не найден или невалиден ({cookies_file_path}). "
f"Работаем без cookies. Для лучшей работы рекомендуется обновить cookies через скрипт get_youtube_cookies.sh")
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
# Определяем, это Shorts или обычное видео
is_shorts = '/shorts/' in url
player_clients = ['android', 'ios', 'web'] if is_shorts else ['android', 'web']
def create_ydl_opts(use_cookies_from_file: bool = False, use_browser_cookies: str = None):
"""Создает опции для yt-dlp"""
opts = {
'quiet': False,
'no_warnings': False,
'user_agent': user_agent,
'socket_timeout': 60,
'extractor_args': {
'youtube': {
'player_client': player_clients,
'player_skip': ['webpage'],
},
},
'http_headers': {
'User-Agent': user_agent,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-us,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
},
}
if use_browser_cookies:
# Автоматически получаем куки из браузера (не нужен файл)
opts['cookiesfrombrowser'] = (use_browser_cookies,)
logger.info(f"YouTube: используем автоматические куки из браузера {use_browser_cookies}")
elif use_cookies_from_file and cookies_file_valid:
opts['cookiefile'] = str(cookies_file_path.absolute())
logger.info(f"YouTube: используем куки из файла {cookies_file_path.absolute()}")
else:
logger.info(f"YouTube: работаем БЕЗ куков (в большинстве случаев это работает)")
return opts
# Стратегии попыток: без куков -> файл куков -> браузер куки
strategies = [
{'name': 'без куков', 'opts': create_ydl_opts(use_cookies_from_file=False)},
]
if cookies_file_valid:
strategies.append({
'name': 'куки из файла',
'opts': create_ydl_opts(use_cookies_from_file=True)
})
# Добавляем стратегии с браузерами (в Docker обычно нет браузеров, но пробуем)
# yt-dlp автоматически обработает ошибку, если браузер недоступен
for browser in ['firefox', 'chrome', 'chromium']:
strategies.append({
'name': f'куки из браузера {browser}',
'opts': create_ydl_opts(use_browser_cookies=browser)
})
last_error = None last_error = None
for attempt in range(max_retries): for attempt in range(max_retries):
try: for strategy in strategies:
# Определяем, это Shorts или обычное видео
is_shorts = '/shorts/' in url
# Базовые настройки для получения информации
# Для Shorts используем более надежные клиенты
player_clients = ['android', 'ios', 'web'] if is_shorts else ['android', 'web']
ydl_opts_info = {
'quiet': False,
'no_warnings': False,
'user_agent': user_agent,
'socket_timeout': 60,
'extractor_args': {
'youtube': {
'player_client': player_clients,
'player_skip': ['webpage'],
},
},
'http_headers': {
'User-Agent': user_agent,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-us,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
},
}
# Если есть валидный файл с cookies, используем его
if cookies_valid:
ydl_opts_info['cookiefile'] = str(cookies_file_path.absolute())
logger.info(f"YouTube: используем cookies из {cookies_file_path.absolute()} (попытка {attempt + 1})")
else:
logger.info(f"YouTube: работаем без cookies (попытка {attempt + 1})")
# Пробуем получить информацию о видео
info = None
try: try:
with yt_dlp.YoutubeDL(ydl_opts_info) as ydl: logger.info(f"YouTube: попытка {attempt + 1}/{max_retries}, стратегия: {strategy['name']}")
# Получаем информацию о видео
with yt_dlp.YoutubeDL(strategy['opts'].copy()) as ydl:
info = ydl.extract_info(url, download=False) info = ydl.extract_info(url, download=False)
except Exception as info_error:
# Если не получилось с cookies, пробуем без них
if cookies_valid and ('cookies' in str(info_error).lower() or 'bot' in str(info_error).lower()):
logger.warning("YouTube: не удалось получить информацию с cookies, пробуем без них")
ydl_opts_info.pop('cookiefile', None)
with yt_dlp.YoutubeDL(ydl_opts_info) as ydl:
info = ydl.extract_info(url, download=False)
cookies_valid = False # Отключаем cookies для скачивания тоже
else:
raise
video_title = info.get('title', 'video') if info else 'video' video_title = info.get('title', 'video') if info else 'video'
logger.info(f"YouTube: получена информация о видео: {video_title}") logger.info(f"YouTube: получена информация о видео: {video_title}")
# Настройки для скачивания с более гибким форматом
# Пробуем разные варианты форматов, если один не работает
format_options = [
'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', # Предпочтительный
'best[ext=mp4]/best', # Простой fallback
'bestvideo+bestaudio/best', # Без ограничения по расширению
'best', # Самый простой вариант
]
download_success = False
for format_option in format_options:
ydl_opts_download = {
'format': format_option,
'outtmpl': _safe_filename(video_title),
'quiet': False,
'no_warnings': False,
'user_agent': user_agent,
'socket_timeout': 60,
'extractor_args': {
'youtube': {
'player_client': ['android', 'ios', 'web'] if is_shorts else ['android', 'web'],
'player_skip': ['webpage'],
},
},
'http_headers': {
'User-Agent': user_agent,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-us,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
},
}
# Если есть валидный файл с cookies, используем его для скачивания # Настройки для скачивания с более гибким форматом
use_cookies_this_attempt = cookies_valid format_options = [
if use_cookies_this_attempt: 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
ydl_opts_download['cookiefile'] = str(cookies_file_path.absolute()) 'best[ext=mp4]/best',
'bestvideo+bestaudio/best',
'best',
]
logger.info(f"YouTube: начинаем скачивание (попытка {attempt + 1}/{max_retries}, Shorts: {is_shorts}, формат: {format_option}, cookies: {use_cookies_this_attempt})") # Используем ту же стратегию куков для скачивания
for format_option in format_options:
try: download_opts = strategy['opts'].copy()
with yt_dlp.YoutubeDL(ydl_opts_download) as ydl: download_opts.update({
ydl.download([url]) 'format': format_option,
download_success = True 'outtmpl': _safe_filename(video_title),
break })
except Exception as download_error:
error_str = str(download_error) logger.info(f"YouTube: скачивание (формат: {format_option}, стратегия: {strategy['name']})")
# Если ошибка с cookies, пробуем без них
if use_cookies_this_attempt and ('cookies' in error_str.lower() or 'bot' in error_str.lower() or 'sign in' in error_str.lower()): try:
logger.warning(f"YouTube: ошибка с cookies для формата {format_option}, пробуем без cookies...") with yt_dlp.YoutubeDL(download_opts) as ydl:
ydl_opts_download.pop('cookiefile', None) ydl.download([url])
try:
with yt_dlp.YoutubeDL(ydl_opts_download) as ydl: # Находим скачанный файл
ydl.download([url]) downloaded_files = list(DOWNLOADS_DIR.glob('*'))
download_success = True if downloaded_files:
cookies_valid = False # Отключаем cookies для следующих попыток downloaded_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
break logger.info(f"YouTube: успешно скачано стратегией '{strategy['name']}'")
except Exception: return downloaded_files[0]
# Если и без cookies не получилось, пробуем следующий формат else:
logger.warning(f"YouTube: не удалось скачать без cookies, пробуем следующий формат...") raise Exception("Файл не был найден после скачивания")
except Exception as download_error:
error_str = str(download_error).lower()
# Если ошибка "bot" или "sign in" - пробуем следующую стратегию
if any(keyword in error_str for keyword in ['bot', 'sign in', 'cookies']):
logger.warning(f"YouTube: ошибка с куками для формата {format_option}, пробуем следующую стратегию...")
break # Переходим к следующей стратегии
# Если ошибка формата - пробуем следующий формат
if 'format is not available' in error_str or 'requested format' in error_str:
logger.warning(f"YouTube: формат {format_option} недоступен, пробуем следующий...")
continue continue
# Если ошибка формата, пробуем следующий формат
elif 'format is not available' in error_str.lower() or 'requested format' in error_str.lower(): # Другая ошибка - логируем и пробуем следующий формат
logger.warning(f"YouTube: формат {format_option} недоступен, пробуем следующий...") logger.warning(f"YouTube: ошибка формата {format_option}: {str(download_error)[:100]}")
continue continue
else:
# Другая ошибка - пробуем следующий формат
logger.warning(f"YouTube: ошибка при скачивании формата {format_option}: {error_str[:100]}, пробуем следующий...")
continue
if not download_success:
raise Exception("Не удалось скачать видео ни с одним из доступных форматов")
# Находим скачанный файл
downloaded_files = list(DOWNLOADS_DIR.glob('*'))
if downloaded_files:
downloaded_files.sort(key=lambda x: x.stat().st_mtime, reverse=True)
return downloaded_files[0]
else:
raise Exception("Файл не был найден после скачивания")
except Exception as e: # Если все форматы не подошли для этой стратегии, пробуем следующую
last_error = e continue
error_str = str(e)
logger.warning(f"YouTube: попытка {attempt + 1}/{max_retries} не удалась: {error_str}") except Exception as e:
error_str = str(e).lower()
# Если ошибка связана с форматом, пробуем другие настройки logger.warning(f"YouTube: стратегия '{strategy['name']}' не сработала: {str(e)[:100]}")
if 'format is not available' in error_str.lower() or 'requested format' in error_str.lower():
logger.warning("YouTube: проблема с форматом, пробуем другие настройки на следующей попытке") # Если ошибка "bot" или "sign in" - пробуем следующую стратегию
# На следующей попытке попробуем другие player_client if any(keyword in error_str for keyword in ['bot', 'sign in', 'cookies']):
if attempt < max_retries - 1:
import time
time.sleep((attempt + 1) * 2)
continue continue
# Если ошибка связана с cookies и они были использованы, попробуем без cookies на следующей попытке # Для других ошибок - пробуем следующую стратегию или следующую попытку
if 'cookies' in error_str.lower() or 'bot' in error_str.lower() or 'sign in' in error_str.lower(): last_error = e
if cookies_valid and attempt == 0:
logger.warning("YouTube: ошибка с cookies, попробуем обновить cookies или работать без них") # Если все стратегии не сработали, делаем паузу перед следующей попыткой
# На следующей попытке попробуем без cookies if attempt < max_retries - 1:
cookies_valid = False time.sleep((attempt + 1) * 2)
if attempt < max_retries - 1:
import time
time.sleep((attempt + 1) * 2)
raise last_error or Exception("Неизвестная ошибка при скачивании с YouTube") raise last_error or Exception("Не удалось скачать видео ни с одной стратегией")
@app.route('/health', methods=['GET']) @app.route('/health', methods=['GET'])
@ -277,17 +310,14 @@ def download_stream():
error_str = str(e) error_str = str(e)
logger.error(f"Ошибка при скачивании: {error_str}") logger.error(f"Ошибка при скачивании: {error_str}")
# Улучшаем сообщение об ошибке, если проблема с cookies # Улучшаем сообщение об ошибке
error_msg = error_str
if 'cookies' in error_str.lower() or 'bot' in error_str.lower() or 'sign in' in error_str.lower(): if 'cookies' in error_str.lower() or 'bot' in error_str.lower() or 'sign in' in error_str.lower():
error_msg = ( error_msg = (
f"{error_str}\n\n" f"{error_str}\n\n"
"💡 Совет: Cookies устарели или недействительны. " "💡 Совет: YouTube требует авторизацию для этого видео (18+, приватное и т.д.). "
"Обновите cookies, запустив скрипт:\n" "Попробуйте открыть видео в браузере, авторизоваться, затем повторить запрос."
" ./youtube-downloader/get_youtube_cookies.sh\n"
"Затем перезапустите сервис."
) )
else:
error_msg = error_str
return jsonify({'error': error_msg}), 500 return jsonify({'error': error_msg}), 500

View file

@ -1,106 +1,218 @@
#!/bin/bash #!/bin/bash
# Скрипт для получения cookies YouTube через yt-dlp из Firefox # Скрипт для получения cookies YouTube через yt-dlp из Firefox
# Предназначен для запуска на Ubuntu 24.04 с авторизованным Firefox
# Результат копируется через cron на серверы со службами скачивания
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COOKIES_FILE="$SCRIPT_DIR/youtube_cookies.txt" COOKIES_FILE="$SCRIPT_DIR/youtube_cookies.txt"
BROWSER="firefox" BROWSER="firefox"
TEMP_FILE="${COOKIES_FILE}.tmp"
# Если запущено с sudo, используем HOME реального пользователя # Определяем HOME пользователя (работает для sudo и обычного запуска)
if [ -n "$SUDO_USER" ]; then if [ -n "$SUDO_USER" ]; then
REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
export HOME="$REAL_HOME" export HOME="$REAL_HOME"
echo "⚠️ Обнаружен sudo, использую домашнюю директорию пользователя: $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 fi
echo "Получение cookies YouTube из Firefox..." # Проверка для cron: если запущен без терминала, меньше вывода
echo "Файл cookies будет сохранен в: $COOKIES_FILE" 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 # Проверяем наличие yt-dlp
if ! command -v yt-dlp &> /dev/null; then if ! command -v yt-dlp &> /dev/null; then
echo "" echo "ERROR: yt-dlp не найден в системе" >&2
echo "❌ yt-dlp не найден в системе" echo "Установите: sudo apt install yt-dlp (Ubuntu) или pip install yt-dlp" >&2
echo ""
echo "Установите yt-dlp одним из способов:"
echo ""
echo "1. Через pacman (Arch Linux):"
echo " sudo pacman -S yt-dlp"
echo ""
echo "2. Через pip:"
echo " pip install yt-dlp"
echo " или"
echo " pip3 install yt-dlp"
echo ""
echo "3. Через pipx (рекомендуется):"
echo " pipx install yt-dlp"
echo ""
exit 1 exit 1
fi fi
echo "Получаю cookies..." if [ "$VERBOSE" = "1" ]; then
echo "Получаю cookies..."
fi
# Используем простой способ: извлекаем cookies из браузера и сохраняем в файл # Удаляем старый временный файл
# Используем конкретное короткое видео (не плейлист, не главную страницу) rm -f "$TEMP_FILE"
# Таймаут 10 секунд
# Извлекаем cookies из браузера и сохраняем во временный файл
# Используем главную страницу YouTube для получения всех необходимых куков
# --no-download - не скачивать видео # --no-download - не скачивать видео
# --skip-download - пропустить скачивание # --skip-download - пропустить скачивание
# --flat-playlist - не извлекать информацию о видео в плейлистах if [ "$VERBOSE" = "1" ]; then
# Перенаправляем весь вывод, чтобы не видеть процесс скачивания yt-dlp \
timeout 10 yt-dlp \ --cookies-from-browser "$BROWSER" \
--cookies-from-browser "$BROWSER" \ --cookies "$TEMP_FILE" \
--cookies "$COOKIES_FILE" \ --no-download \
--no-download \ --skip-download \
--skip-download \ "https://www.youtube.com" > /dev/null 2>&1
--flat-playlist \ else
--quiet \ yt-dlp \
"https://www.youtube.com/watch?v=jNQXAC9IVRw" > /dev/null 2>&1 || true --cookies-from-browser "$BROWSER" \
--cookies "$TEMP_FILE" \
--no-download \
--skip-download \
--quiet \
"https://www.youtube.com" > /dev/null 2>&1
fi
EXIT_CODE=$? EXIT_CODE=$?
# Не важно, какой код возврата - главное проверить, создался ли файл cookies # Функция проверки валидности куков
# yt-dlp может вернуть ошибку, но cookies все равно сохранить check_cookies() {
local file="$1"
if [ -f "$COOKIES_FILE" ]; then local current_time=$(date +%s)
# Проверяем, что файл содержит данные (не только заголовки)
COOKIE_LINES=$(grep -v '^#' "$COOKIES_FILE" | grep -v '^$' | wc -l)
if [ "$COOKIE_LINES" -gt 0 ]; then # Проверяем существование файла
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 ""
echo "✅ Cookies успешно сохранены в $COOKIES_FILE" echo "✅ Cookies успешно сохранены в $COOKIES_FILE"
echo " Найдено строк с cookies: $COOKIE_LINES" echo " Всего строк с cookies: $COOKIE_LINES"
echo " YouTube-куков: $YOUTUBE_COOKIES"
echo " Важных куков: $IMPORTANT_COOKIES"
echo "" echo ""
echo "Теперь перезапустите youtube-downloader:" echo "Файл готов к копированию на серверы через cron"
echo " docker compose -f youtube-downloader/docker-compose.yml restart"
echo ""
echo "Или перезапустите все сервисы:"
echo " ./stop_all.sh && ./start_all.sh"
else else
echo "" # Минимальный вывод для cron (можно логировать в файл)
echo "❌ Ошибка: файл cookies создан, но не содержит данных" echo "$(date '+%Y-%m-%d %H:%M:%S') - YouTube cookies updated: $YOUTUBE_COOKIES cookies, $IMPORTANT_COOKIES important"
rm -f "$COOKIES_FILE"
exit 1
fi fi
exit 0
else else
echo "" # Очищаем временный файл при ошибке
echo "❌ Ошибка: файл cookies не был создан" rm -f "$TEMP_FILE"
echo ""
echo "Возможные причины:" if [ "$VERBOSE" = "1" ]; then
echo "1. Firefox не найден или недоступен" echo ""
echo "2. Проблемы с правами доступа к файлу cookies браузера" echo "❌ Ошибка: не удалось получить валидные YouTube-куки"
echo "3. Cookies не найдены в браузере" echo ""
echo "" echo "Возможные причины:"
echo "Проверка:" echo "1. В Firefox нет куков для YouTube"
if [ -n "$SUDO_USER" ]; then echo "2. Откройте YouTube в Firefox и войдите в аккаунт"
REAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) echo "3. Все куки просрочены - обновите их в браузере"
FIREFOX_DIR="$REAL_HOME/.mozilla/firefox" echo ""
else else
FIREFOX_DIR="$HOME/.mozilla/firefox" echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Failed to get valid YouTube cookies" >&2
fi fi
if [ -d "$FIREFOX_DIR" ]; then
echo " ✓ Директория Firefox найдена: $FIREFOX_DIR" if [ ! -f "$COOKIES_FILE" ]; then
# Если файла не было, это критичная ошибка
exit 1
else else
echo " ✗ Директория Firefox не найдена: $FIREFOX_DIR" # Если файл был, просто оставляем старый (лучше работать со старыми куками чем без них)
echo " Попробуйте запустить скрипт БЕЗ sudo: ./get_youtube_cookies.sh" 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
exit 1
fi fi