feat(bot): proactive cookie health-check + simpler user-facing errors
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 51s

Add /cookies/check to youtube-downloader and instagram-downloader,
polled every 30 min from bot.py; alerts the admin bot on
healthy->broken transitions (with a 24h re-reminder cap while still
broken) and on recovery. Also stop leaking raw exception text to end
users - they now see a plain, friendly English message while the
admin bot still gets full technical detail via notify_admin_error.
This commit is contained in:
vrubelroman 2026-07-25 22:30:49 +00:00
parent be1acaaf2b
commit 5092d882e5
3 changed files with 166 additions and 4 deletions

View file

@ -486,6 +486,37 @@ def formats():
return jsonify({'error': str(e)}), 500
YOUTUBE_COOKIE_TEST_URL = os.getenv(
'YOUTUBE_COOKIE_TEST_URL',
'https://www.youtube.com/watch?v=jNQXAC9IVRw' # "Me at the zoo" — первое видео на YouTube, публичное, без возрастных ограничений
)
YOUTUBE_COOKIE_INVALID_MARKERS = ('no longer valid', 'have likely been rotated')
@app.route('/cookies/check', methods=['POST'])
def cookies_check():
"""Проверяет, рабочие ли сейчас YouTube cookies (для проактивного мониторинга)."""
cookies_file = Path(os.getenv('YOUTUBE_COOKIES_FILE', '/app/youtube_cookies.txt'))
if not (cookies_file.exists() and cookies_file.stat().st_size > 0):
return jsonify({'cookies_present': False, 'cookies_valid': None,
'detail': 'cookies file missing or empty'}), 200
# Без --quiet/--no-warnings: сигнал ротации кук — это подавляемый WARNING, а не ошибка с ненулевым returncode
cmd = _build_ytdlp_base_cmd() + ['--dump-json', YOUTUBE_COOKIE_TEST_URL]
try:
result = _run_ytdlp(cmd, timeout=INFO_TIMEOUT)
except Exception as e:
return jsonify({'cookies_present': True, 'cookies_valid': False,
'detail': f'yt-dlp invocation failed: {e}'}), 200
stderr = result.stderr
if any(marker in stderr for marker in YOUTUBE_COOKIE_INVALID_MARKERS) or result.returncode != 0:
return jsonify({'cookies_present': True, 'cookies_valid': False,
'detail': stderr.strip()[-500:]}), 200
return jsonify({'cookies_present': True, 'cookies_valid': True, 'detail': ''}), 200
@app.route('/download/stream', methods=['POST'])
def download_stream():
request_id = str(uuid.uuid4())[:8]