diff --git a/.env.example b/.env.example index 1c33000..18b1f52 100644 --- a/.env.example +++ b/.env.example @@ -19,5 +19,5 @@ TIKTOK_DOWNLOADER_URL=http://localhost:5559 # Admin Bot Configuration -ADMIN_BOT_TOKEN=8575250350:AAHte7xaQFS3FvoKyul9tl5DTFzEkT7ZQTs +ADMIN_BOT_TOKEN=8128669173:AAGEEBuBwDm36jChqcFB31P3_VP4-EzK5aM # Chat ID будет автоматически сохранен при первом использовании админ бота (команда /stat) diff --git a/instagram-downloader/docker-compose.yml b/instagram-downloader/docker-compose.yml index 91c0092..50e9d9b 100644 --- a/instagram-downloader/docker-compose.yml +++ b/instagram-downloader/docker-compose.yml @@ -3,17 +3,11 @@ services: build: . container_name: instagram_downloader_service restart: unless-stopped - ports: - - "5556:5556" volumes: - ./downloads:/app/downloads - ./instagram_cookies.txt:/app/instagram_cookies.txt environment: - INSTAGRAM_COOKIES_FILE=/app/instagram_cookies.txt - PORT=5556 - dns: - - 8.8.8.8 - - 8.8.4.4 - extra_hosts: - - "host.docker.internal:host-gateway" + network_mode: host diff --git a/youtube-downloader/TROUBLESHOOTING.md b/youtube-downloader/TROUBLESHOOTING.md new file mode 100644 index 0000000..fcf60c3 --- /dev/null +++ b/youtube-downloader/TROUBLESHOOTING.md @@ -0,0 +1,78 @@ +# Устранение проблем с YouTube Downloader + +## Ошибка 500 при скачивании + +### Диагностика + +1. **Проверьте статус сервиса:** + ```bash + curl http://localhost:5557/health | python3 -m json.tool + ``` + + Должен вернуть: + ```json + { + "status": "ok", + "service": "youtube-downloader", + "cookies": { + "file": "/app/youtube_cookies.txt", + "status": "valid", + "valid": true + } + } + ``` + +2. **Проверьте логи:** + ```bash + docker logs youtube_downloader_service --tail=50 + ``` + +### Обновление куков + +Если куки устарели (статус `invalid` или `not_found`): + +1. **На сервере, где получаются куки:** + ```bash + cd youtube-downloader + ./get_youtube_cookies.sh + ``` + +2. **Скопируйте файл на продакшн хост:** + ```bash + # Если используется rsync/scp + scp youtube_cookies.txt user@production-host:/path/to/youtube-downloader/ + ``` + +3. **Перезапустите контейнер:** + ```bash + cd youtube-downloader + docker-compose restart + ``` + +### Частые проблемы + +1. **Куки устарели:** + - Обновите куки на сервере с Firefox + - Скопируйте файл на продакшн хост + - Перезапустите контейнер + +2. **Видео недоступно:** + - Проверьте, что видео не удалено + - Проверьте, что видео не приватное + - Для 18+ видео нужны валидные куки + +3. **Проблемы с сетью:** + - Проверьте доступность YouTube + - Проверьте firewall/прокси настройки + +## Проверка работы + +После обновления куков проверьте: +```bash +curl -X POST http://localhost:5557/download/stream \ + -H "Content-Type: application/json" \ + -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}' \ + --output test_video.mp4 +``` + +Если скачивание успешно - проблема решена. diff --git a/youtube-downloader/app.py b/youtube-downloader/app.py index 964026d..adfa2ba 100644 --- a/youtube-downloader/app.py +++ b/youtube-downloader/app.py @@ -182,8 +182,16 @@ def download_youtube_video(url: str, max_retries: int = 3) -> Path: 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) + try: + with yt_dlp.YoutubeDL(strategy['opts'].copy()) as ydl: + info = ydl.extract_info(url, download=False) + except Exception as info_error: + error_str = str(info_error).lower() + logger.warning(f"YouTube: ошибка при получении информации о видео: {str(info_error)[:200]}") + # Если ошибка связана с куками - пробуем следующую стратегию + if any(keyword in error_str for keyword in ['bot', 'sign in', 'cookies', 'private', 'unavailable']): + continue + raise video_title = info.get('title', 'video') if info else 'video' logger.info(f"YouTube: получена информация о видео: {video_title}") @@ -260,7 +268,28 @@ def download_youtube_video(url: str, max_retries: int = 3) -> Path: @app.route('/health', methods=['GET']) def health(): """Health check endpoint""" - return jsonify({'status': 'ok', 'service': 'youtube-downloader'}), 200 + cookies_file = os.getenv('YOUTUBE_COOKIES_FILE', 'youtube_cookies.txt') + cookies_file_path = Path(cookies_file) + cookies_status = 'not_found' + cookies_valid = False + + if cookies_file_path.exists(): + cookies_status = 'found' + cookies_valid = _is_valid_cookies_file(cookies_file_path) + if cookies_valid: + cookies_status = 'valid' + else: + cookies_status = 'invalid' + + return jsonify({ + 'status': 'ok', + 'service': 'youtube-downloader', + 'cookies': { + 'file': str(cookies_file_path), + 'status': cookies_status, + 'valid': cookies_valid + } + }), 200 @app.route('/download/stream', methods=['POST']) @@ -308,7 +337,10 @@ def download_stream(): except Exception as e: error_str = str(e) + import traceback + error_traceback = traceback.format_exc() logger.error(f"Ошибка при скачивании: {error_str}") + logger.error(f"Traceback: {error_traceback}") # Улучшаем сообщение об ошибке error_msg = error_str @@ -318,6 +350,14 @@ def download_stream(): "💡 Совет: YouTube требует авторизацию для этого видео (18+, приватное и т.д.). " "Попробуйте открыть видео в браузере, авторизоваться, затем повторить запрос." ) + elif 'unable to download' in error_str.lower() or 'http error' in error_str.lower(): + error_msg = ( + f"{error_str}\n\n" + "💡 Возможные причины:\n" + "1. Видео недоступно или удалено\n" + "2. Проблемы с сетью или доступом к YouTube\n" + "3. Куки устарели - обновите файл youtube_cookies.txt" + ) return jsonify({'error': error_msg}), 500 @@ -325,6 +365,21 @@ def download_stream(): if __name__ == '__main__': port = int(os.getenv('PORT', 5000)) # Внутренний порт контейнера host = os.getenv('HOST', '0.0.0.0') + + # Проверяем куки при старте + cookies_file = os.getenv('YOUTUBE_COOKIES_FILE', 'youtube_cookies.txt') + cookies_file_path = Path(cookies_file) + if cookies_file_path.exists(): + cookies_valid = _is_valid_cookies_file(cookies_file_path) + if cookies_valid: + logger.info(f"YouTube: файл куков найден и валиден: {cookies_file_path}") + else: + logger.warning(f"YouTube: файл куков найден, но не валиден: {cookies_file_path}") + logger.warning("YouTube: сервис будет работать, но может потребоваться обновление куков") + else: + logger.warning(f"YouTube: файл куков не найден: {cookies_file_path}") + logger.warning("YouTube: сервис будет работать без куков (может не работать для 18+ и приватных видео)") + logger.info(f"Запуск YouTube Downloader сервиса на {host}:{port}") app.run(host=host, port=port, debug=False)