diff --git a/yt_dlp/extractor/cbc.py b/yt_dlp/extractor/cbc.py index 319771655e..527bfe03dd 100644 --- a/yt_dlp/extractor/cbc.py +++ b/yt_dlp/extractor/cbc.py @@ -11,7 +11,6 @@ from ..utils import ( float_or_none, int_or_none, js_to_json, - jwt_decode_hs256, mimetype2ext, orderedSet, parse_age_limit, @@ -620,9 +619,6 @@ class CBCGemIE(CBCGemBaseIE): 'https://services.radio-canada.ca/ott/catalog/v1/gem/settings', None, 'Downloading site settings', query={'device': 'web'})['identityManagement']['ropc'] - def _is_jwt_expired(self, token): - return jwt_decode_hs256(token)['exp'] - time.time() < 300 - def _call_oauth_api(self, oauth_data, note='Refreshing access token'): response = self._download_json( self._ropc_settings['url'], None, note, data=urlencode_postdata({ @@ -657,7 +653,7 @@ class CBCGemIE(CBCGemBaseIE): raise def _fetch_access_token(self): - if self._is_jwt_expired(self._access_token): + if self._is_jwt_token_expired(self._access_token): try: self._call_oauth_api({ 'grant_type': 'refresh_token', @@ -675,7 +671,7 @@ class CBCGemIE(CBCGemBaseIE): if not self._get_login_info()[0]: return None - if not self._claims_token or self._is_jwt_expired(self._claims_token): + if not self._claims_token or self._is_jwt_token_expired(self._claims_token): self._claims_token = self._download_json( 'https://services.radio-canada.ca/ott/subscription/v2/gem/Subscriber/profile', None, 'Downloading claims token', query={'device': 'web'}, diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py index b816d788fa..3ae318c18a 100644 --- a/yt_dlp/extractor/common.py +++ b/yt_dlp/extractor/common.py @@ -69,6 +69,7 @@ from ..utils import ( int_or_none, join_nonempty, js_to_json, + jwt_decode_hs256, mimetype2ext, netrc_from_content, orderedSet, @@ -994,6 +995,10 @@ class InfoExtractor: return encoding + @staticmethod + def _is_jwt_token_expired(token): + return jwt_decode_hs256(token)['exp'] - time.time() < 300 + def __check_blocked(self, content): first_block = content[:512] if ('Access to this site is blocked' in content diff --git a/yt_dlp/extractor/digitalconcerthall.py b/yt_dlp/extractor/digitalconcerthall.py index 4c4fe470da..bc876ad5d1 100644 --- a/yt_dlp/extractor/digitalconcerthall.py +++ b/yt_dlp/extractor/digitalconcerthall.py @@ -1,5 +1,3 @@ -import time - from .common import InfoExtractor from ..networking.exceptions import HTTPError from ..utils import ( @@ -84,16 +82,14 @@ class DigitalConcertHallIE(InfoExtractor): 'User-Agent': _USER_AGENT, } _access_token = None - _access_token_expiry = 0 _refresh_token = None @property def _access_token_is_expired(self): - return self._access_token_expiry - 30 <= int(time.time()) + return self._is_jwt_token_expired(self._access_token) def _set_access_token(self, value): self._access_token = value - self._access_token_expiry = traverse_obj(value, ({jwt_decode_hs256}, 'exp', {int})) or 0 def _cache_tokens(self, /): self.cache.store(self._NETRC_MACHINE, 'tokens', { diff --git a/yt_dlp/extractor/iwara.py b/yt_dlp/extractor/iwara.py index 5b5c367ad8..882789cf4e 100644 --- a/yt_dlp/extractor/iwara.py +++ b/yt_dlp/extractor/iwara.py @@ -1,7 +1,6 @@ import functools import hashlib import json -import time import urllib.parse from .common import InfoExtractor @@ -9,11 +8,9 @@ from ..utils import ( ExtractorError, OnDemandPagedList, int_or_none, - jwt_decode_hs256, mimetype2ext, qualities, traverse_obj, - try_call, unified_timestamp, ) @@ -25,7 +22,7 @@ class IwaraBaseIE(InfoExtractor): def _is_token_expired(self, token, token_type): # User token TTL == ~3 weeks, Media token TTL == ~1 hour - if (try_call(lambda: jwt_decode_hs256(token)['exp']) or 0) <= int(time.time() - 120): + if self._is_jwt_token_expired(token): self.to_screen(f'{token_type} token has expired') return True diff --git a/yt_dlp/extractor/jiocinema.py b/yt_dlp/extractor/jiocinema.py index 94c85064ef..a4db9d47c9 100644 --- a/yt_dlp/extractor/jiocinema.py +++ b/yt_dlp/extractor/jiocinema.py @@ -4,7 +4,6 @@ import json import random import re import string -import time from .common import InfoExtractor from ..utils import ( @@ -106,11 +105,8 @@ class JioCinemaBaseIE(InfoExtractor): 'os': ('os', {str}), })}, data=data) - def _is_token_expired(self, token): - return (try_call(lambda: jwt_decode_hs256(token)['exp']) or 0) <= int(time.time() - 180) - def _perform_login(self, username, password): - if self._ACCESS_TOKEN and not self._is_token_expired(self._ACCESS_TOKEN): + if self._ACCESS_TOKEN and not self._is_jwt_token_expired(self._ACCESS_TOKEN): return UUID_RE = r'[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}' @@ -185,7 +181,7 @@ class JioCinemaBaseIE(InfoExtractor): if JioCinemaBaseIE._REFRESH_TOKEN: self._cache_token('access') self.to_screen(f'Logging in as device ID "{JioCinemaBaseIE._DEVICE_ID}"') - if self._is_token_expired(JioCinemaBaseIE._ACCESS_TOKEN): + if self._is_jwt_token_expired(JioCinemaBaseIE._ACCESS_TOKEN): self._refresh_token() @@ -250,9 +246,9 @@ class JioCinemaIE(JioCinemaBaseIE): def _real_extract(self, url): video_id = self._match_id(url) - if not self._ACCESS_TOKEN and self._is_token_expired(self._GUEST_TOKEN): + if not self._ACCESS_TOKEN and self._is_jwt_token_expired(self._GUEST_TOKEN): self._fetch_guest_token() - elif self._ACCESS_TOKEN and self._is_token_expired(self._ACCESS_TOKEN): + elif self._ACCESS_TOKEN and self._is_jwt_token_expired(self._ACCESS_TOKEN): self._refresh_token() playback = self._call_api( diff --git a/yt_dlp/extractor/mlb.py b/yt_dlp/extractor/mlb.py index 935bf85615..61b56817ea 100644 --- a/yt_dlp/extractor/mlb.py +++ b/yt_dlp/extractor/mlb.py @@ -1,6 +1,5 @@ import json import re -import time import uuid from .common import InfoExtractor @@ -10,7 +9,6 @@ from ..utils import ( determine_ext, int_or_none, join_nonempty, - jwt_decode_hs256, parse_duration, parse_iso8601, try_get, @@ -350,11 +348,10 @@ mutation initPlaybackSession( _device_id = None _session_id = None _access_token = None - _token_expiry = 0 @property def _api_headers(self): - if (self._token_expiry - 120) <= time.time(): + if self._is_jwt_token_expired(self._access_token): self.write_debug('Access token has expired; re-logging in') self._perform_login(*self._get_login_info()) return {'Authorization': f'Bearer {self._access_token}'} @@ -392,7 +389,6 @@ mutation initPlaybackSession( raise ExtractorError('Invalid username or password', expected=True) raise - self._token_expiry = traverse_obj(self._access_token, ({jwt_decode_hs256}, 'exp', {int})) or 0 self._set_device_id(username) self._session_id = self._call_api({ diff --git a/yt_dlp/extractor/qdance.py b/yt_dlp/extractor/qdance.py index 4f71657c3f..680da2cf52 100644 --- a/yt_dlp/extractor/qdance.py +++ b/yt_dlp/extractor/qdance.py @@ -1,11 +1,9 @@ import json -import time from .common import InfoExtractor from ..utils import ( ExtractorError, int_or_none, - jwt_decode_hs256, str_or_none, traverse_obj, try_call, @@ -116,7 +114,7 @@ class QDanceIE(InfoExtractor): self.raise_login_required() def _get_auth(self): - if (try_call(lambda: jwt_decode_hs256(self._access_token)['exp']) or 0) <= int(time.time() - 120): + if self._is_jwt_token_expired(self._access_token): if not self._refresh_token: raise ExtractorError( 'Cannot refresh access token, login with yt-dlp or refresh cookies in browser') diff --git a/yt_dlp/extractor/stacommu.py b/yt_dlp/extractor/stacommu.py index 8300185183..26710a140b 100644 --- a/yt_dlp/extractor/stacommu.py +++ b/yt_dlp/extractor/stacommu.py @@ -1,5 +1,3 @@ -import time - from .wrestleuniverse import WrestleUniverseBaseIE from ..utils import ( int_or_none, @@ -22,7 +20,7 @@ class StacommuBaseIE(WrestleUniverseBaseIE): @WrestleUniverseBaseIE._TOKEN.getter def _TOKEN(self): - if self._REAL_TOKEN and self._TOKEN_EXPIRY <= int(time.time()): + if self._REAL_TOKEN and self._is_jwt_token_expired(self._REAL_TOKEN): self._refresh_token() return self._REAL_TOKEN diff --git a/yt_dlp/extractor/vrt.py b/yt_dlp/extractor/vrt.py index 5def2bacf4..5c945d2065 100644 --- a/yt_dlp/extractor/vrt.py +++ b/yt_dlp/extractor/vrt.py @@ -13,7 +13,6 @@ from ..utils import ( get_element_by_class, get_element_html_by_class, int_or_none, - jwt_decode_hs256, jwt_encode_hs256, make_archive_id, merge_dicts, @@ -316,10 +315,6 @@ class VrtNUIE(VRTBaseIE): # Refresh token cookie is scoped to /vrtmax/sso, others are scoped to / return try_call(lambda: self._get_cookies('https://www.vrt.be/vrtmax/sso')[cookie_name].value) - @staticmethod - def _is_jwt_token_expired(token): - return jwt_decode_hs256(token)['exp'] - time.time() < 300 - def _perform_login(self, username, password): refresh_token = self._get_vrt_cookie(self._REFRESH_TOKEN_COOKIE_NAME) if refresh_token and not self._is_jwt_token_expired(refresh_token): diff --git a/yt_dlp/extractor/wrestleuniverse.py b/yt_dlp/extractor/wrestleuniverse.py index d401d6d39d..3a9293f44f 100644 --- a/yt_dlp/extractor/wrestleuniverse.py +++ b/yt_dlp/extractor/wrestleuniverse.py @@ -1,7 +1,6 @@ import base64 import binascii import json -import time import uuid from .common import InfoExtractor @@ -9,7 +8,6 @@ from ..dependencies import Cryptodome from ..utils import ( ExtractorError, int_or_none, - jwt_decode_hs256, traverse_obj, try_call, url_basename, @@ -25,7 +23,6 @@ class WrestleUniverseBaseIE(InfoExtractor): _API_HOST = 'api.wrestle-universe.com' _API_PATH = None _REAL_TOKEN = None - _TOKEN_EXPIRY = None _REFRESH_TOKEN = None _DEVICE_ID = None _LOGIN_QUERY = {'key': 'AIzaSyCaRPBsDQYVDUWWBXjsTrHESi2r_F3RAdA'} @@ -40,13 +37,13 @@ class WrestleUniverseBaseIE(InfoExtractor): @property def _TOKEN(self): - if not self._REAL_TOKEN or not self._TOKEN_EXPIRY: + if not self._REAL_TOKEN: token = try_call(lambda: self._get_cookies('https://www.wrestle-universe.com/')['token'].value) if not token and not self._REFRESH_TOKEN: self.raise_login_required() self._TOKEN = token - if not self._REAL_TOKEN or self._TOKEN_EXPIRY <= int(time.time()): + if not self._REAL_TOKEN or self._is_jwt_token_expired(self._REAL_TOKEN): if not self._REFRESH_TOKEN: raise ExtractorError( 'Expired token. Refresh your cookies in browser and try again', expected=True) @@ -58,11 +55,6 @@ class WrestleUniverseBaseIE(InfoExtractor): def _TOKEN(self, value): self._REAL_TOKEN = value - expiry = traverse_obj(value, ({jwt_decode_hs256}, 'exp', {int_or_none})) - if not expiry: - raise ExtractorError('There was a problem with the auth token') - self._TOKEN_EXPIRY = expiry - def _perform_login(self, username, password): login = self._download_json( 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword', None, diff --git a/yt_dlp/extractor/zee5.py b/yt_dlp/extractor/zee5.py index fb523de03b..dc975d05a4 100644 --- a/yt_dlp/extractor/zee5.py +++ b/yt_dlp/extractor/zee5.py @@ -1,5 +1,4 @@ import json -import time import uuid from .common import InfoExtractor @@ -124,10 +123,9 @@ class Zee5IE(InfoExtractor): else: raise ExtractorError(self._LOGIN_HINT, expected=True) - token = jwt_decode_hs256(self._USER_TOKEN) - if token.get('exp', 0) <= int(time.time()): + if self._is_jwt_token_expired(self._USER_TOKEN): raise ExtractorError('User token has expired', expected=True) - self._USER_COUNTRY = token.get('current_country') + self._USER_COUNTRY = jwt_decode_hs256(self._USER_TOKEN).get('current_country') def _real_extract(self, url): video_id, display_id = self._match_valid_url(url).group('id', 'display_id')