mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-02-28 19:29:46 +00:00
[ie/aenetworks] Fix extractor (#14959)
Closes #14578 Authored by: Sipherdrakon
This commit is contained in:
@@ -5,10 +5,12 @@ from ..utils import (
|
|||||||
ExtractorError,
|
ExtractorError,
|
||||||
GeoRestrictedError,
|
GeoRestrictedError,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
|
make_archive_id,
|
||||||
remove_start,
|
remove_start,
|
||||||
traverse_obj,
|
|
||||||
update_url_query,
|
update_url_query,
|
||||||
|
url_or_none,
|
||||||
)
|
)
|
||||||
|
from ..utils.traversal import traverse_obj
|
||||||
|
|
||||||
|
|
||||||
class AENetworksBaseIE(ThePlatformIE): # XXX: Do not subclass from concrete IE
|
class AENetworksBaseIE(ThePlatformIE): # XXX: Do not subclass from concrete IE
|
||||||
@@ -29,6 +31,19 @@ class AENetworksBaseIE(ThePlatformIE): # XXX: Do not subclass from concrete IE
|
|||||||
'historyvault.com': (None, 'historyvault', None),
|
'historyvault.com': (None, 'historyvault', None),
|
||||||
'biography.com': (None, 'biography', None),
|
'biography.com': (None, 'biography', None),
|
||||||
}
|
}
|
||||||
|
_GRAPHQL_QUERY = '''
|
||||||
|
query getUserVideo($videoId: ID!) {
|
||||||
|
video(id: $videoId) {
|
||||||
|
title
|
||||||
|
publicUrl
|
||||||
|
programId
|
||||||
|
tvSeasonNumber
|
||||||
|
tvSeasonEpisodeNumber
|
||||||
|
series {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}'''
|
||||||
|
|
||||||
def _extract_aen_smil(self, smil_url, video_id, auth=None):
|
def _extract_aen_smil(self, smil_url, video_id, auth=None):
|
||||||
query = {
|
query = {
|
||||||
@@ -73,19 +88,39 @@ class AENetworksBaseIE(ThePlatformIE): # XXX: Do not subclass from concrete IE
|
|||||||
|
|
||||||
def _extract_aetn_info(self, domain, filter_key, filter_value, url):
|
def _extract_aetn_info(self, domain, filter_key, filter_value, url):
|
||||||
requestor_id, brand, software_statement = self._DOMAIN_MAP[domain]
|
requestor_id, brand, software_statement = self._DOMAIN_MAP[domain]
|
||||||
|
if filter_key == 'canonical':
|
||||||
|
webpage = self._download_webpage(url, filter_value)
|
||||||
|
graphql_video_id = self._search_regex(
|
||||||
|
r'<meta\b[^>]+\bcontent="[^"]*\btpid/(\d+)"', webpage,
|
||||||
|
'id') or self._html_search_meta('videoId', webpage, 'GraphQL video ID', fatal=True)
|
||||||
|
else:
|
||||||
|
graphql_video_id = filter_value
|
||||||
|
|
||||||
result = self._download_json(
|
result = self._download_json(
|
||||||
f'https://feeds.video.aetnd.com/api/v2/{brand}/videos',
|
'https://yoga.appsvcs.aetnd.com/', graphql_video_id,
|
||||||
filter_value, query={f'filter[{filter_key}]': filter_value})
|
query={
|
||||||
result = traverse_obj(
|
'brand': brand,
|
||||||
result, ('results',
|
'mode': 'live',
|
||||||
lambda k, v: k == 0 and v[filter_key] == filter_value),
|
'platform': 'web',
|
||||||
get_all=False)
|
},
|
||||||
if not result:
|
data=json.dumps({
|
||||||
|
'operationName': 'getUserVideo',
|
||||||
|
'variables': {
|
||||||
|
'videoId': graphql_video_id,
|
||||||
|
},
|
||||||
|
'query': self._GRAPHQL_QUERY,
|
||||||
|
}).encode(),
|
||||||
|
headers={
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
})
|
||||||
|
|
||||||
|
result = traverse_obj(result, ('data', 'video', {dict}))
|
||||||
|
media_url = traverse_obj(result, ('publicUrl', {url_or_none}))
|
||||||
|
if not media_url:
|
||||||
raise ExtractorError('Show not found in A&E feed (too new?)', expected=True,
|
raise ExtractorError('Show not found in A&E feed (too new?)', expected=True,
|
||||||
video_id=remove_start(filter_value, '/'))
|
video_id=remove_start(filter_value, '/'))
|
||||||
title = result['title']
|
title = result['title']
|
||||||
video_id = result['id']
|
video_id = result['programId']
|
||||||
media_url = result['publicUrl']
|
|
||||||
theplatform_metadata = self._download_theplatform_metadata(self._search_regex(
|
theplatform_metadata = self._download_theplatform_metadata(self._search_regex(
|
||||||
r'https?://link\.theplatform\.com/s/([^?]+)', media_url, 'theplatform_path'), video_id)
|
r'https?://link\.theplatform\.com/s/([^?]+)', media_url, 'theplatform_path'), video_id)
|
||||||
info = self._parse_theplatform_metadata(theplatform_metadata)
|
info = self._parse_theplatform_metadata(theplatform_metadata)
|
||||||
@@ -100,9 +135,13 @@ class AENetworksBaseIE(ThePlatformIE): # XXX: Do not subclass from concrete IE
|
|||||||
info.update(self._extract_aen_smil(media_url, video_id, auth))
|
info.update(self._extract_aen_smil(media_url, video_id, auth))
|
||||||
info.update({
|
info.update({
|
||||||
'title': title,
|
'title': title,
|
||||||
'series': result.get('seriesName'),
|
'display_id': graphql_video_id,
|
||||||
'season_number': int_or_none(result.get('tvSeasonNumber')),
|
'_old_archive_ids': [make_archive_id(self, graphql_video_id)],
|
||||||
'episode_number': int_or_none(result.get('tvSeasonEpisodeNumber')),
|
**traverse_obj(result, {
|
||||||
|
'series': ('series', 'title', {str}),
|
||||||
|
'season_number': ('tvSeasonNumber', {int_or_none}),
|
||||||
|
'episode_number': ('tvSeasonEpisodeNumber', {int_or_none}),
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
return info
|
return info
|
||||||
|
|
||||||
@@ -116,7 +155,7 @@ class AENetworksIE(AENetworksBaseIE):
|
|||||||
(?:shows/[^/?#]+/)?videos/[^/?#]+
|
(?:shows/[^/?#]+/)?videos/[^/?#]+
|
||||||
)'''
|
)'''
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://www.history.com/shows/mountain-men/season-1/episode-1',
|
'url': 'https://www.history.com/shows/mountain-men/season-1/episode-1',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '22253814',
|
'id': '22253814',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
@@ -139,11 +178,11 @@ class AENetworksIE(AENetworksBaseIE):
|
|||||||
},
|
},
|
||||||
'params': {'skip_download': 'm3u8'},
|
'params': {'skip_download': 'm3u8'},
|
||||||
'add_ie': ['ThePlatform'],
|
'add_ie': ['ThePlatform'],
|
||||||
'skip': 'Geo-restricted - This content is not available in your location.',
|
'skip': 'This content requires a valid, unexpired auth token',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://www.aetv.com/shows/duck-dynasty/season-9/episode-1',
|
'url': 'https://www.aetv.com/shows/duck-dynasty/season-9/episode-1',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '600587331957',
|
'id': '147486',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Inlawful Entry',
|
'title': 'Inlawful Entry',
|
||||||
'description': 'md5:57c12115a2b384d883fe64ca50529e08',
|
'description': 'md5:57c12115a2b384d883fe64ca50529e08',
|
||||||
@@ -160,6 +199,8 @@ class AENetworksIE(AENetworksBaseIE):
|
|||||||
'season_number': 9,
|
'season_number': 9,
|
||||||
'series': 'Duck Dynasty',
|
'series': 'Duck Dynasty',
|
||||||
'age_limit': 0,
|
'age_limit': 0,
|
||||||
|
'display_id': '600587331957',
|
||||||
|
'_old_archive_ids': ['aenetworks 600587331957'],
|
||||||
},
|
},
|
||||||
'params': {'skip_download': 'm3u8'},
|
'params': {'skip_download': 'm3u8'},
|
||||||
'add_ie': ['ThePlatform'],
|
'add_ie': ['ThePlatform'],
|
||||||
@@ -186,6 +227,7 @@ class AENetworksIE(AENetworksBaseIE):
|
|||||||
},
|
},
|
||||||
'params': {'skip_download': 'm3u8'},
|
'params': {'skip_download': 'm3u8'},
|
||||||
'add_ie': ['ThePlatform'],
|
'add_ie': ['ThePlatform'],
|
||||||
|
'skip': '404 Not Found',
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.aetv.com/specials/hunting-jonbenets-killer-the-untold-story',
|
'url': 'https://www.aetv.com/specials/hunting-jonbenets-killer-the-untold-story',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
@@ -209,6 +251,7 @@ class AENetworksIE(AENetworksBaseIE):
|
|||||||
},
|
},
|
||||||
'params': {'skip_download': 'm3u8'},
|
'params': {'skip_download': 'm3u8'},
|
||||||
'add_ie': ['ThePlatform'],
|
'add_ie': ['ThePlatform'],
|
||||||
|
'skip': 'This content requires a valid, unexpired auth token',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://www.fyi.tv/shows/tiny-house-nation/season-1/episode-8',
|
'url': 'http://www.fyi.tv/shows/tiny-house-nation/season-1/episode-8',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
@@ -259,7 +302,7 @@ class AENetworksListBaseIE(AENetworksBaseIE):
|
|||||||
domain, slug = self._match_valid_url(url).groups()
|
domain, slug = self._match_valid_url(url).groups()
|
||||||
_, brand, _ = self._DOMAIN_MAP[domain]
|
_, brand, _ = self._DOMAIN_MAP[domain]
|
||||||
playlist = self._call_api(self._RESOURCE, slug, brand, self._FIELDS)
|
playlist = self._call_api(self._RESOURCE, slug, brand, self._FIELDS)
|
||||||
base_url = f'http://watch.{domain}'
|
base_url = f'https://watch.{domain}'
|
||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
for item in (playlist.get(self._ITEMS_KEY) or []):
|
for item in (playlist.get(self._ITEMS_KEY) or []):
|
||||||
|
|||||||
Reference in New Issue
Block a user