diff --git a/backend/app/services/downloader.py b/backend/app/services/downloader.py index 90c14f1..5431868 100644 --- a/backend/app/services/downloader.py +++ b/backend/app/services/downloader.py @@ -143,7 +143,13 @@ def _twitter_syndication_info(tweet_id: str) -> dict: 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }) resp = urllib.request.urlopen(req, timeout=15) - return json.loads(resp.read().decode()) + data = json.loads(resp.read().decode()) + + # Check for restricted content (TweetTombstone) + if data.get('__typename') == 'TweetTombstone': + raise ValueError('内容受限不支持下载(敏感内容/年龄限制),需要登录账号访问') + + return data def _parse_twitter_video(url: str) -> dict: @@ -499,6 +505,14 @@ def parse_video_url(url: str) -> dict: result = _parse_twitter_video(url) result.pop('_formats_full', None) return result + except ValueError as e: + error_msg = str(e) + # If it's restricted content error, don't fallback to yt-dlp + if '内容受限不支持下载' in error_msg: + logger.error(f"Twitter content restricted: {error_msg}") + raise + # For other errors, fallback to yt-dlp + logger.warning(f"Twitter syndication failed, falling back to yt-dlp: {e}") except Exception as e: logger.warning(f"Twitter syndication failed, falling back to yt-dlp: {e}") @@ -569,6 +583,14 @@ def download_video(url: str, format_id: str = "best", progress_callback=None, ta logger.info(f"Using Twitter syndication API for download: {url}") try: return _download_twitter_video(url, format_id, progress_callback, task_id=task_id) + except ValueError as e: + error_msg = str(e) + # If it's restricted content error, don't fallback to yt-dlp + if '内容受限不支持下载' in error_msg: + logger.error(f"Twitter content restricted: {error_msg}") + raise + # For other errors, fallback to yt-dlp + logger.warning(f"Twitter syndication download failed, falling back to yt-dlp: {e}") except Exception as e: logger.warning(f"Twitter syndication download failed, falling back to yt-dlp: {e}")