diff --git a/yt_dlp/extractor/streaks.py b/yt_dlp/extractor/streaks.py index 1b3718473d..60123d67b7 100644 --- a/yt_dlp/extractor/streaks.py +++ b/yt_dlp/extractor/streaks.py @@ -33,16 +33,20 @@ class StreaksBaseIE(InfoExtractor): **(headers or {}), }) except ExtractorError as e: - if isinstance(e.cause, HTTPError) and e.cause.status in {403, 404}: + if isinstance(e.cause, HTTPError) and e.cause.status in (403, 404): error = self._parse_json(e.cause.response.read().decode(), media_id, fatal=False) message = traverse_obj(error, ('message', {str})) code = traverse_obj(error, ('code', {str})) + error_id = traverse_obj(error, ('id', {int})) if code == 'REQUEST_FAILED': - self.raise_geo_restricted(message, countries=self._GEO_COUNTRIES) - elif code == 'MEDIA_NOT_FOUND': - raise ExtractorError(message, expected=True) - elif code or message: - raise ExtractorError(join_nonempty(code, message, delim=': ')) + if error_id == 124: + self.raise_geo_restricted(countries=self._GEO_COUNTRIES) + elif error_id == 126: + raise ExtractorError('Access is denied (possibly due to invalid/missing API key)') + if code == 'MEDIA_NOT_FOUND': + raise ExtractorError(join_nonempty(code, message, delim=': '), expected=True) + if code or message: + raise ExtractorError(join_nonempty(code, error_id, message, delim=': ')) raise streaks_id = response['id'] diff --git a/yt_dlp/extractor/tver.py b/yt_dlp/extractor/tver.py index 805150db45..3b6a0390af 100644 --- a/yt_dlp/extractor/tver.py +++ b/yt_dlp/extractor/tver.py @@ -1,3 +1,5 @@ +import datetime as dt + from .streaks import StreaksBaseIE from ..utils import ( ExtractorError, @@ -7,6 +9,7 @@ from ..utils import ( smuggle_url, str_or_none, strip_or_none, + time_seconds, update_url_query, ) from ..utils.traversal import require, traverse_obj @@ -96,6 +99,7 @@ class TVerIE(StreaksBaseIE): 'Referer': 'https://tver.jp/', } _PLATFORM_QUERY = {} + _STREAKS_API_INFO = {} def _real_initialize(self): session_info = self._download_json( @@ -105,6 +109,9 @@ class TVerIE(StreaksBaseIE): 'platform_uid': 'platform_uid', 'platform_token': 'platform_token', })) + self._STREAKS_API_INFO = self._download_json( + 'https://player.tver.jp/player/streaks_info_v2.json', None, + 'Downloading STREAKS API info', 'Unable to download STREAKS API info') def _call_platform_api(self, path, video_id, note=None, fatal=True, query=None): return self._download_json( @@ -223,10 +230,14 @@ class TVerIE(StreaksBaseIE): 'ie_key': 'BrightcoveNew', } + project_id = video_info['streaks']['projectID'] + key_idx = dt.datetime.fromtimestamp(time_seconds(hours=9), dt.timezone.utc).month % 6 or 6 + return { - **self._extract_from_streaks_api(video_info['streaks']['projectID'], streaks_id, { + **self._extract_from_streaks_api(project_id, streaks_id, { 'Origin': 'https://tver.jp', 'Referer': 'https://tver.jp/', + 'X-Streaks-Api-Key': self._STREAKS_API_INFO[project_id]['api_key'][f'key0{key_idx}'], }), **metadata, 'id': video_id,