mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-06-18 15:55:30 +02:00
[ie/turner] Adapt extractors to new AdobePass flow (#13131)
Authored by: bashonly
This commit is contained in:
parent
2d7949d564
commit
0daddc780d
@ -84,6 +84,8 @@ class AdultSwimIE(TurnerBaseIE):
|
|||||||
'skip': '404 Not Found',
|
'skip': '404 Not Found',
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
_SOFTWARE_STATEMENT = 'eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIwNjg5ZmU2My00OTc5LTQxZmQtYWYxNC1hYjVlNmJjNWVkZWIiLCJuYmYiOjE1MzcxOTA2NzQsImlzcyI6ImF1dGguYWRvYmUuY29tIiwiaWF0IjoxNTM3MTkwNjc0fQ.Xl3AEduM0s1TxDQ6-XssdKIiLm261hhsEv1C1yo_nitIajZThSI9rXILqtIzO0aujoHhdzUnu_dUCq9ffiSBzEG632tTa1la-5tegHtce80cMhewBN4n2t8n9O5tiaPx8MPY8ALdm5wS7QzWE6DO_LTJKgE8Bl7Yv-CWJT4q4SywtNiQWLVOuhBRnDyfsRezxRwptw8qTn9dv5ZzUrVJaby5fDZ_nOncMKvegOgaKd5KEuCAGQ-mg-PSuValMjGuf6FwDguGaK7IyI5Y2oOrzXmD4Dj7q4WBg8w9QoZhtLeAU56mcsGILolku2R5FHlVLO9xhjResyt-pfmegOkpSw'
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
show_path, episode_path = self._match_valid_url(url).groups()
|
show_path, episode_path = self._match_valid_url(url).groups()
|
||||||
display_id = episode_path or show_path
|
display_id = episode_path or show_path
|
||||||
@ -152,7 +154,7 @@ class AdultSwimIE(TurnerBaseIE):
|
|||||||
# CDN_TOKEN_APP_ID from:
|
# CDN_TOKEN_APP_ID from:
|
||||||
# https://d2gg02c3xr550i.cloudfront.net/assets/asvp.e9c8bef24322d060ef87.bundle.js
|
# https://d2gg02c3xr550i.cloudfront.net/assets/asvp.e9c8bef24322d060ef87.bundle.js
|
||||||
'appId': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6ImFzLXR2ZS1kZXNrdG9wLXB0enQ2bSIsInByb2R1Y3QiOiJ0dmUiLCJuZXR3b3JrIjoiYXMiLCJwbGF0Zm9ybSI6ImRlc2t0b3AiLCJpYXQiOjE1MzI3MDIyNzl9.BzSCk-WYOZ2GMCIaeVb8zWnzhlgnXuJTCu0jGp_VaZE',
|
'appId': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6ImFzLXR2ZS1kZXNrdG9wLXB0enQ2bSIsInByb2R1Y3QiOiJ0dmUiLCJuZXR3b3JrIjoiYXMiLCJwbGF0Zm9ybSI6ImRlc2t0b3AiLCJpYXQiOjE1MzI3MDIyNzl9.BzSCk-WYOZ2GMCIaeVb8zWnzhlgnXuJTCu0jGp_VaZE',
|
||||||
}, {
|
}, self._SOFTWARE_STATEMENT, {
|
||||||
'url': url,
|
'url': url,
|
||||||
'site_name': 'AdultSwim',
|
'site_name': 'AdultSwim',
|
||||||
'auth_required': auth,
|
'auth_required': auth,
|
||||||
|
@ -19,7 +19,8 @@ from ..utils import (
|
|||||||
class NBACVPBaseIE(TurnerBaseIE):
|
class NBACVPBaseIE(TurnerBaseIE):
|
||||||
def _extract_nba_cvp_info(self, path, video_id, fatal=False):
|
def _extract_nba_cvp_info(self, path, video_id, fatal=False):
|
||||||
return self._extract_cvp_info(
|
return self._extract_cvp_info(
|
||||||
f'http://secure.nba.com/{path}', video_id, {
|
# XXX: The 3rd argument (None) needs to be the AdobePass software_statement
|
||||||
|
f'http://secure.nba.com/{path}', video_id, None, {
|
||||||
'default': {
|
'default': {
|
||||||
'media_src': 'http://nba.cdn.turner.com/nba/big',
|
'media_src': 'http://nba.cdn.turner.com/nba/big',
|
||||||
},
|
},
|
||||||
@ -94,6 +95,7 @@ class NBAWatchBaseIE(NBACVPBaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class NBAWatchEmbedIE(NBAWatchBaseIE):
|
class NBAWatchEmbedIE(NBAWatchBaseIE):
|
||||||
|
_WORKING = False
|
||||||
IE_NAME = 'nba:watch:embed'
|
IE_NAME = 'nba:watch:embed'
|
||||||
_VALID_URL = NBAWatchBaseIE._VALID_URL_BASE + r'embed\?.*?\bid=(?P<id>\d+)'
|
_VALID_URL = NBAWatchBaseIE._VALID_URL_BASE + r'embed\?.*?\bid=(?P<id>\d+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
@ -115,6 +117,7 @@ class NBAWatchEmbedIE(NBAWatchBaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class NBAWatchIE(NBAWatchBaseIE):
|
class NBAWatchIE(NBAWatchBaseIE):
|
||||||
|
_WORKING = False
|
||||||
IE_NAME = 'nba:watch'
|
IE_NAME = 'nba:watch'
|
||||||
_VALID_URL = NBAWatchBaseIE._VALID_URL_BASE + r'(?:nba/)?video/(?P<id>.+?(?=/index\.html)|(?:[^/]+/)*[^/?#&]+)'
|
_VALID_URL = NBAWatchBaseIE._VALID_URL_BASE + r'(?:nba/)?video/(?P<id>.+?(?=/index\.html)|(?:[^/]+/)*[^/?#&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
@ -167,6 +170,7 @@ class NBAWatchIE(NBAWatchBaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class NBAWatchCollectionIE(NBAWatchBaseIE):
|
class NBAWatchCollectionIE(NBAWatchBaseIE):
|
||||||
|
_WORKING = False
|
||||||
IE_NAME = 'nba:watch:collection'
|
IE_NAME = 'nba:watch:collection'
|
||||||
_VALID_URL = NBAWatchBaseIE._VALID_URL_BASE + r'list/collection/(?P<id>[^/?#&]+)'
|
_VALID_URL = NBAWatchBaseIE._VALID_URL_BASE + r'list/collection/(?P<id>[^/?#&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
@ -336,6 +340,7 @@ class NBABaseIE(NBACVPBaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class NBAEmbedIE(NBABaseIE):
|
class NBAEmbedIE(NBABaseIE):
|
||||||
|
_WORKING = False
|
||||||
IE_NAME = 'nba:embed'
|
IE_NAME = 'nba:embed'
|
||||||
_VALID_URL = r'https?://secure\.nba\.com/assets/amp/include/video/(?:topI|i)frame\.html\?.*?\bcontentId=(?P<id>[^?#&]+)'
|
_VALID_URL = r'https?://secure\.nba\.com/assets/amp/include/video/(?:topI|i)frame\.html\?.*?\bcontentId=(?P<id>[^?#&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
@ -358,6 +363,7 @@ class NBAEmbedIE(NBABaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class NBAIE(NBABaseIE):
|
class NBAIE(NBABaseIE):
|
||||||
|
_WORKING = False
|
||||||
IE_NAME = 'nba'
|
IE_NAME = 'nba'
|
||||||
_VALID_URL = NBABaseIE._VALID_URL_BASE + f'(?!{NBABaseIE._CHANNEL_PATH_REGEX})video/(?P<id>(?:[^/]+/)*[^/?#&]+)'
|
_VALID_URL = NBABaseIE._VALID_URL_BASE + f'(?!{NBABaseIE._CHANNEL_PATH_REGEX})video/(?P<id>(?:[^/]+/)*[^/?#&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
@ -385,6 +391,7 @@ class NBAIE(NBABaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class NBAChannelIE(NBABaseIE):
|
class NBAChannelIE(NBABaseIE):
|
||||||
|
_WORKING = False
|
||||||
IE_NAME = 'nba:channel'
|
IE_NAME = 'nba:channel'
|
||||||
_VALID_URL = NBABaseIE._VALID_URL_BASE + f'(?:{NBABaseIE._CHANNEL_PATH_REGEX})/(?P<id>[^/?#&]+)'
|
_VALID_URL = NBABaseIE._VALID_URL_BASE + f'(?:{NBABaseIE._CHANNEL_PATH_REGEX})/(?P<id>[^/?#&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
|
@ -32,6 +32,10 @@ class TBSIE(TurnerBaseIE):
|
|||||||
'url': 'http://www.tntdrama.com/movies/star-wars-a-new-hope',
|
'url': 'http://www.tntdrama.com/movies/star-wars-a-new-hope',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
_SOFTWARE_STATEMENT_MAP = {
|
||||||
|
'tbs': 'eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJkZTA0NTYxZS1iMTFhLTRlYTgtYTg5NC01NjI3MGM1NmM2MWIiLCJuYmYiOjE1MzcxODkzOTAsImlzcyI6ImF1dGguYWRvYmUuY29tIiwiaWF0IjoxNTM3MTg5MzkwfQ.Z7ny66kaqNDdCHf9Y9KsV12LrBxrLkGGxlYe2XGm6qsw2T-k1OCKC1TMzeqiZP735292MMRAQkcJDKrMIzNbAuf9nCdIcv4kE1E2nqUnjPMBduC1bHffZp8zlllyrN2ElDwM8Vhwv_5nElLRwWGEt0Kaq6KJAMZA__WDxKWC18T-wVtsOZWXQpDqO7nByhfj2t-Z8c3TUNVsA_wHgNXlkzJCZ16F2b7yGLT5ZhLPupOScd3MXC5iPh19HSVIok22h8_F_noTmGzmMnIRQi6bWYWK2zC7TQ_MsYHfv7V6EaG5m1RKZTV6JAwwoJQF_9ByzarLV1DGwZxD9-eQdqswvg',
|
||||||
|
'tntdrama': 'eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIwOTMxYTU4OS1jZjEzLTRmNjMtYTJmYy03MzhjMjE1NWU5NjEiLCJuYmYiOjE1MzcxOTA4MjcsImlzcyI6ImF1dGguYWRvYmUuY29tIiwiaWF0IjoxNTM3MTkwODI3fQ.AucKvtws7oekTXi80_zX4-BlgJD9GLvlOI9FlBCjdlx7Pa3eJ0AqbogynKMiatMbnLOTMHGjd7tTiq422unmZjBz70dhePAe9BbW0dIo7oQ57vZ-VBYw_tWYRPmON61MwAbLVlqROD3n_zURs85S8TlkQx9aNx9x_riGGELjd8l05CVa_pOluNhYvuIFn6wmrASOKI1hNEblBDWh468UWP571-fe4zzi0rlYeeHd-cjvtWvOB3bQsWrUVbK4pRmqvzEH59j0vNF-ihJF9HncmUicYONe47Mib3elfMok23v4dB1_UAlQY_oawfNcynmEnJQCcqFmbHdEwTW6gMiYsA',
|
||||||
|
}
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
site, path, display_id = self._match_valid_url(url).groups()
|
site, path, display_id = self._match_valid_url(url).groups()
|
||||||
@ -48,7 +52,7 @@ class TBSIE(TurnerBaseIE):
|
|||||||
drupal_settings['ngtv_token_url']).query)
|
drupal_settings['ngtv_token_url']).query)
|
||||||
|
|
||||||
info = self._extract_ngtv_info(
|
info = self._extract_ngtv_info(
|
||||||
media_id, tokenizer_query, {
|
media_id, tokenizer_query, self._SOFTWARE_STATEMENT_MAP[site], {
|
||||||
'url': url,
|
'url': url,
|
||||||
'site_name': site[:3].upper(),
|
'site_name': site[:3].upper(),
|
||||||
'auth_required': video_data.get('authRequired') == '1' or is_live,
|
'auth_required': video_data.get('authRequired') == '1' or is_live,
|
||||||
|
@ -156,6 +156,7 @@ class TeamcocoIE(TeamcocoBaseIE):
|
|||||||
|
|
||||||
|
|
||||||
class ConanClassicIE(TeamcocoBaseIE):
|
class ConanClassicIE(TeamcocoBaseIE):
|
||||||
|
_WORKING = False
|
||||||
_VALID_URL = r'https?://(?:(?:www\.)?conanclassic|conan25\.teamcoco)\.com/(?P<id>([^/]+/)*[^/?#]+)'
|
_VALID_URL = r'https?://(?:(?:www\.)?conanclassic|conan25\.teamcoco)\.com/(?P<id>([^/]+/)*[^/?#]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'https://conanclassic.com/video/ice-cube-kevin-hart-conan-share-lyft',
|
'url': 'https://conanclassic.com/video/ice-cube-kevin-hart-conan-share-lyft',
|
||||||
@ -263,7 +264,7 @@ class ConanClassicIE(TeamcocoBaseIE):
|
|||||||
info.update(self._extract_ngtv_info(media_id, {
|
info.update(self._extract_ngtv_info(media_id, {
|
||||||
'accessToken': token,
|
'accessToken': token,
|
||||||
'accessTokenType': 'jws',
|
'accessTokenType': 'jws',
|
||||||
}))
|
}, None)) # TODO: the None arg needs to be the AdobePass software_statement
|
||||||
else:
|
else:
|
||||||
formats, subtitles = self._get_formats_and_subtitles(
|
formats, subtitles = self._get_formats_and_subtitles(
|
||||||
traverse_obj(response, ('data', 'findRecordVideoMetadata')), video_id)
|
traverse_obj(response, ('data', 'findRecordVideoMetadata')), video_id)
|
||||||
|
@ -20,6 +20,7 @@ class TruTVIE(TurnerBaseIE):
|
|||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
_SOFTWARE_STATEMENT = 'eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhYzQyOTkwMi0xMDYzLTQyNTQtYWJlYS1iZTY2ODM4MTVmZGIiLCJuYmYiOjE1MzcxOTA4NjgsImlzcyI6ImF1dGguYWRvYmUuY29tIiwiaWF0IjoxNTM3MTkwODY4fQ.ewXl5LDMDvvx3nDXV4jCdSwUq_sOluKoOVsIjznAo6Zo4zrGe9rjlZ9DOmQKW66g6VRMexJsJ5vM1EkY8TC5-YcQw_BclK1FPGO1rH3Wf7tX_l0b1BVbSJQKIj9UgqDp_QbGcBXz24kN4So3U22mhs6di9PYyyfG68ccKL2iRprcVKWCslIHwUF-T7FaEqb0K57auilxeW1PONG2m-lIAcZ62DUwqXDWvw0CRoWI08aVVqkkhnXaSsQfLs5Ph1Pfh9Oq3g_epUm9Ss45mq6XM7gbOb5omTcKLADRKK-PJVB_JXnZnlsXbG0ttKE1cTKJ738qu7j4aipYTf-W0nKF5Q'
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
series_slug, clip_slug, video_id = self._match_valid_url(url).groups()
|
series_slug, clip_slug, video_id = self._match_valid_url(url).groups()
|
||||||
@ -39,7 +40,7 @@ class TruTVIE(TurnerBaseIE):
|
|||||||
title = video_data['title'].strip()
|
title = video_data['title'].strip()
|
||||||
|
|
||||||
info = self._extract_ngtv_info(
|
info = self._extract_ngtv_info(
|
||||||
media_id, {}, {
|
media_id, {}, self._SOFTWARE_STATEMENT, {
|
||||||
'url': url,
|
'url': url,
|
||||||
'site_name': 'truTV',
|
'site_name': 'truTV',
|
||||||
'auth_required': video_data.get('isAuthRequired'),
|
'auth_required': video_data.get('isAuthRequired'),
|
||||||
|
@ -22,7 +22,7 @@ class TurnerBaseIE(AdobePassIE):
|
|||||||
def _extract_timestamp(self, video_data):
|
def _extract_timestamp(self, video_data):
|
||||||
return int_or_none(xpath_attr(video_data, 'dateCreated', 'uts'))
|
return int_or_none(xpath_attr(video_data, 'dateCreated', 'uts'))
|
||||||
|
|
||||||
def _add_akamai_spe_token(self, tokenizer_src, video_url, content_id, ap_data, custom_tokenizer_query=None):
|
def _add_akamai_spe_token(self, tokenizer_src, video_url, content_id, ap_data, software_statement, custom_tokenizer_query=None):
|
||||||
secure_path = self._search_regex(r'https?://[^/]+(.+/)', video_url, 'secure path') + '*'
|
secure_path = self._search_regex(r'https?://[^/]+(.+/)', video_url, 'secure path') + '*'
|
||||||
token = self._AKAMAI_SPE_TOKEN_CACHE.get(secure_path)
|
token = self._AKAMAI_SPE_TOKEN_CACHE.get(secure_path)
|
||||||
if not token:
|
if not token:
|
||||||
@ -34,7 +34,8 @@ class TurnerBaseIE(AdobePassIE):
|
|||||||
else:
|
else:
|
||||||
query['videoId'] = content_id
|
query['videoId'] = content_id
|
||||||
if ap_data.get('auth_required'):
|
if ap_data.get('auth_required'):
|
||||||
query['accessToken'] = self._extract_mvpd_auth(ap_data['url'], content_id, ap_data['site_name'], ap_data['site_name'])
|
query['accessToken'] = self._extract_mvpd_auth(
|
||||||
|
ap_data['url'], content_id, ap_data['site_name'], ap_data['site_name'], software_statement)
|
||||||
auth = self._download_xml(
|
auth = self._download_xml(
|
||||||
tokenizer_src, content_id, query=query)
|
tokenizer_src, content_id, query=query)
|
||||||
error_msg = xpath_text(auth, 'error/msg')
|
error_msg = xpath_text(auth, 'error/msg')
|
||||||
@ -46,7 +47,7 @@ class TurnerBaseIE(AdobePassIE):
|
|||||||
self._AKAMAI_SPE_TOKEN_CACHE[secure_path] = token
|
self._AKAMAI_SPE_TOKEN_CACHE[secure_path] = token
|
||||||
return video_url + '?hdnea=' + token
|
return video_url + '?hdnea=' + token
|
||||||
|
|
||||||
def _extract_cvp_info(self, data_src, video_id, path_data={}, ap_data={}, fatal=False):
|
def _extract_cvp_info(self, data_src, video_id, software_statement, path_data={}, ap_data={}, fatal=False):
|
||||||
video_data = self._download_xml(
|
video_data = self._download_xml(
|
||||||
data_src, video_id,
|
data_src, video_id,
|
||||||
transform_source=lambda s: fix_xml_ampersands(s).strip(),
|
transform_source=lambda s: fix_xml_ampersands(s).strip(),
|
||||||
@ -101,7 +102,7 @@ class TurnerBaseIE(AdobePassIE):
|
|||||||
video_url = self._add_akamai_spe_token(
|
video_url = self._add_akamai_spe_token(
|
||||||
secure_path_data['tokenizer_src'],
|
secure_path_data['tokenizer_src'],
|
||||||
secure_path_data['media_src'] + video_url,
|
secure_path_data['media_src'] + video_url,
|
||||||
content_id, ap_data)
|
content_id, ap_data, software_statement)
|
||||||
elif not re.match('https?://', video_url):
|
elif not re.match('https?://', video_url):
|
||||||
base_path_data = path_data.get(ext, path_data.get('default', {}))
|
base_path_data = path_data.get(ext, path_data.get('default', {}))
|
||||||
media_src = base_path_data.get('media_src')
|
media_src = base_path_data.get('media_src')
|
||||||
@ -215,10 +216,12 @@ class TurnerBaseIE(AdobePassIE):
|
|||||||
'is_live': is_live,
|
'is_live': is_live,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _extract_ngtv_info(self, media_id, tokenizer_query, ap_data=None):
|
def _extract_ngtv_info(self, media_id, tokenizer_query, software_statement, ap_data=None):
|
||||||
|
if not isinstance(ap_data, dict):
|
||||||
|
ap_data = {}
|
||||||
is_live = ap_data.get('is_live')
|
is_live = ap_data.get('is_live')
|
||||||
streams_data = self._download_json(
|
streams_data = self._download_json(
|
||||||
f'http://medium.ngtv.io/media/{media_id}/tv',
|
f'https://medium.ngtv.io/media/{media_id}/tv',
|
||||||
media_id)['media']['tv']
|
media_id)['media']['tv']
|
||||||
duration = None
|
duration = None
|
||||||
chapters = []
|
chapters = []
|
||||||
@ -230,8 +233,8 @@ class TurnerBaseIE(AdobePassIE):
|
|||||||
continue
|
continue
|
||||||
if stream_data.get('playlistProtection') == 'spe':
|
if stream_data.get('playlistProtection') == 'spe':
|
||||||
m3u8_url = self._add_akamai_spe_token(
|
m3u8_url = self._add_akamai_spe_token(
|
||||||
'http://token.ngtv.io/token/token_spe',
|
'https://token.ngtv.io/token/token_spe',
|
||||||
m3u8_url, media_id, ap_data or {}, tokenizer_query)
|
m3u8_url, media_id, ap_data, software_statement, tokenizer_query)
|
||||||
formats.extend(self._extract_m3u8_formats(
|
formats.extend(self._extract_m3u8_formats(
|
||||||
m3u8_url, media_id, 'mp4', m3u8_id='hls', live=is_live, fatal=False))
|
m3u8_url, media_id, 'mp4', m3u8_id='hls', live=is_live, fatal=False))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user