| @@ -1,14 +1,18 @@ | |||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| from .common import InfoExtractor | import random | ||||||
|  | import re | ||||||
|  | import string | ||||||
|  |  | ||||||
|  | from .discoverygo import DiscoveryGoBaseIE | ||||||
| from ..utils import ( | from ..utils import ( | ||||||
|     parse_duration, |     ExtractorError, | ||||||
|     parse_iso8601, |     update_url_query, | ||||||
| ) | ) | ||||||
| from ..compat import compat_str | from ..compat import compat_HTTPError | ||||||
|  |  | ||||||
|  |  | ||||||
| class DiscoveryIE(InfoExtractor): | class DiscoveryIE(DiscoveryGoBaseIE): | ||||||
|     _VALID_URL = r'''(?x)https?://(?:www\.)?(?: |     _VALID_URL = r'''(?x)https?://(?:www\.)?(?: | ||||||
|             discovery| |             discovery| | ||||||
|             investigationdiscovery| |             investigationdiscovery| | ||||||
| @@ -19,79 +23,65 @@ class DiscoveryIE(InfoExtractor): | |||||||
|             sciencechannel| |             sciencechannel| | ||||||
|             tlc| |             tlc| | ||||||
|             velocity |             velocity | ||||||
|         )\.com/(?:[^/]+/)*(?P<id>[^./?#]+)''' |         )\.com(?P<path>/tv-shows/[^/]+/(?:video|full-episode)s/(?P<id>[^./?#]+))''' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|         'url': 'http://www.discovery.com/tv-shows/mythbusters/videos/mission-impossible-outtakes.htm', |         'url': 'https://www.discovery.com/tv-shows/cash-cab/videos/dave-foley', | ||||||
|         'info_dict': { |         'info_dict': { | ||||||
|             'id': '20769', |             'id': '5a2d9b4d6b66d17a5026e1fd', | ||||||
|             'ext': 'mp4', |             'ext': 'mp4', | ||||||
|             'title': 'Mission Impossible Outtakes', |             'title': 'Dave Foley', | ||||||
|             'description': ('Watch Jamie Hyneman and Adam Savage practice being' |             'description': 'md5:4b39bcafccf9167ca42810eb5f28b01f', | ||||||
|                             ' each other -- to the point of confusing Jamie\'s dog -- and ' |             'duration': 608, | ||||||
|                             'don\'t miss Adam moon-walking as Jamie ... behind Jamie\'s' |  | ||||||
|                             ' back.'), |  | ||||||
|             'duration': 156, |  | ||||||
|             'timestamp': 1302032462, |  | ||||||
|             'upload_date': '20110405', |  | ||||||
|             'uploader_id': '103207', |  | ||||||
|         }, |         }, | ||||||
|         'params': { |         'params': { | ||||||
|             'skip_download': True,  # requires ffmpeg |             'skip_download': True,  # requires ffmpeg | ||||||
|         } |         } | ||||||
|     }, { |     }, { | ||||||
|         'url': 'http://www.discovery.com/tv-shows/mythbusters/videos/mythbusters-the-simpsons', |         'url': 'https://www.investigationdiscovery.com/tv-shows/final-vision/full-episodes/final-vision', | ||||||
|         'info_dict': { |         'only_matching': True, | ||||||
|             'id': 'mythbusters-the-simpsons', |  | ||||||
|             'title': 'MythBusters: The Simpsons', |  | ||||||
|         }, |  | ||||||
|         'playlist_mincount': 10, |  | ||||||
|     }, { |  | ||||||
|         'url': 'http://www.animalplanet.com/longfin-eels-maneaters/', |  | ||||||
|         'info_dict': { |  | ||||||
|             'id': '78326', |  | ||||||
|             'ext': 'mp4', |  | ||||||
|             'title': 'Longfin Eels: Maneaters?', |  | ||||||
|             'description': 'Jeremy Wade tests whether or not New Zealand\'s longfin eels are man-eaters by covering himself in fish guts and getting in the water with them.', |  | ||||||
|             'upload_date': '20140725', |  | ||||||
|             'timestamp': 1406246400, |  | ||||||
|             'duration': 116, |  | ||||||
|             'uploader_id': '103207', |  | ||||||
|         }, |  | ||||||
|         'params': { |  | ||||||
|             'skip_download': True,  # requires ffmpeg |  | ||||||
|         } |  | ||||||
|     }] |     }] | ||||||
|  |     _GEO_COUNTRIES = ['US'] | ||||||
|  |     _GEO_BYPASS = False | ||||||
|  |  | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         display_id = self._match_id(url) |         path, display_id = re.match(self._VALID_URL, url).groups() | ||||||
|         info = self._download_json(url + '?flat=1', display_id) |         webpage = self._download_webpage(url, display_id) | ||||||
|  |  | ||||||
|         video_title = info.get('playlist_title') or info.get('video_title') |         react_data = self._parse_json(self._search_regex( | ||||||
|  |             r'window\.__reactTransmitPacket\s*=\s*({.+?});', | ||||||
|  |             webpage, 'react data'), display_id) | ||||||
|  |         content_blocks = react_data['layout'][path]['contentBlocks'] | ||||||
|  |         video = next(cb for cb in content_blocks if cb.get('type') == 'video')['content']['items'][0] | ||||||
|  |         video_id = video['id'] | ||||||
|  |  | ||||||
|         entries = [] |         access_token = self._download_json( | ||||||
|  |             'https://www.discovery.com/anonymous', display_id, query={ | ||||||
|         for idx, video_info in enumerate(info['playlist']): |                 'authLink': update_url_query( | ||||||
|             subtitles = {} |                     'https://login.discovery.com/v1/oauth2/authorize', { | ||||||
|             caption_url = video_info.get('captionsUrl') |                         'client_id': react_data['application']['apiClientId'], | ||||||
|             if caption_url: |                         'redirect_uri': 'https://fusion.ddmcdn.com/app/mercury-sdk/180/redirectHandler.html', | ||||||
|                 subtitles = { |                         'response_type': 'anonymous', | ||||||
|                     'en': [{ |                         'state': 'nonce,' + ''.join([random.choice(string.ascii_letters) for _ in range(32)]), | ||||||
|                         'url': caption_url, |  | ||||||
|                     }] |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             entries.append({ |  | ||||||
|                 '_type': 'url_transparent', |  | ||||||
|                 'url': 'http://players.brightcove.net/103207/default_default/index.html?videoId=ref:%s' % video_info['referenceId'], |  | ||||||
|                 'id': compat_str(video_info['id']), |  | ||||||
|                 'title': video_info['title'], |  | ||||||
|                 'description': video_info.get('description'), |  | ||||||
|                 'duration': parse_duration(video_info.get('video_length')), |  | ||||||
|                 'webpage_url': video_info.get('href') or video_info.get('url'), |  | ||||||
|                 'thumbnail': video_info.get('thumbnailURL'), |  | ||||||
|                 'alt_title': video_info.get('secondary_title'), |  | ||||||
|                 'timestamp': parse_iso8601(video_info.get('publishedDate')), |  | ||||||
|                 'subtitles': subtitles, |  | ||||||
|                     }) |                     }) | ||||||
|  |             })['access_token'] | ||||||
|  |  | ||||||
|         return self.playlist_result(entries, display_id, video_title) |         try: | ||||||
|  |             stream = self._download_json( | ||||||
|  |                 'https://api.discovery.com/v1/streaming/video/' + video_id, | ||||||
|  |                 display_id, headers={ | ||||||
|  |                     'Authorization': 'Bearer ' + access_token, | ||||||
|  |                 }) | ||||||
|  |         except ExtractorError as e: | ||||||
|  |             if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403: | ||||||
|  |                 e_description = self._parse_json( | ||||||
|  |                     e.cause.read().decode(), display_id)['description'] | ||||||
|  |                 if 'resource not available for country' in e_description: | ||||||
|  |                     self.raise_geo_restricted(countries=self._GEO_COUNTRIES) | ||||||
|  |                 if 'Authorized Networks' in e_description: | ||||||
|  |                     raise ExtractorError( | ||||||
|  |                         'This video is only available via cable service provider subscription that' | ||||||
|  |                         ' is not currently supported. You may want to use --cookies.', expected=True) | ||||||
|  |                 raise ExtractorError(e_description) | ||||||
|  |             raise | ||||||
|  |  | ||||||
|  |         return self._extract_video_info(video, stream, display_id) | ||||||
|   | |||||||
| @@ -27,42 +27,9 @@ class DiscoveryGoBaseIE(InfoExtractor): | |||||||
|             velocitychannel |             velocitychannel | ||||||
|         )go\.com/%s(?P<id>[^/?#&]+)''' |         )go\.com/%s(?P<id>[^/?#&]+)''' | ||||||
|  |  | ||||||
|  |     def _extract_video_info(self, video, stream, display_id): | ||||||
| class DiscoveryGoIE(DiscoveryGoBaseIE): |  | ||||||
|     _VALID_URL = DiscoveryGoBaseIE._VALID_URL_TEMPLATE % r'(?:[^/]+/)+' |  | ||||||
|     _GEO_COUNTRIES = ['US'] |  | ||||||
|     _TEST = { |  | ||||||
|         'url': 'https://www.discoverygo.com/bering-sea-gold/reaper-madness/', |  | ||||||
|         'info_dict': { |  | ||||||
|             'id': '58c167d86b66d12f2addeb01', |  | ||||||
|             'ext': 'mp4', |  | ||||||
|             'title': 'Reaper Madness', |  | ||||||
|             'description': 'md5:09f2c625c99afb8946ed4fb7865f6e78', |  | ||||||
|             'duration': 2519, |  | ||||||
|             'series': 'Bering Sea Gold', |  | ||||||
|             'season_number': 8, |  | ||||||
|             'episode_number': 6, |  | ||||||
|             'age_limit': 14, |  | ||||||
|         }, |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     def _real_extract(self, url): |  | ||||||
|         display_id = self._match_id(url) |  | ||||||
|  |  | ||||||
|         webpage = self._download_webpage(url, display_id) |  | ||||||
|  |  | ||||||
|         container = extract_attributes( |  | ||||||
|             self._search_regex( |  | ||||||
|                 r'(<div[^>]+class=["\']video-player-container[^>]+>)', |  | ||||||
|                 webpage, 'video container')) |  | ||||||
|  |  | ||||||
|         video = self._parse_json( |  | ||||||
|             container.get('data-video') or container.get('data-json'), |  | ||||||
|             display_id) |  | ||||||
|  |  | ||||||
|         title = video['name'] |         title = video['name'] | ||||||
|  |  | ||||||
|         stream = video.get('stream') |  | ||||||
|         if not stream: |         if not stream: | ||||||
|             if video.get('authenticated') is True: |             if video.get('authenticated') is True: | ||||||
|                 raise ExtractorError( |                 raise ExtractorError( | ||||||
| @@ -124,6 +91,43 @@ class DiscoveryGoIE(DiscoveryGoBaseIE): | |||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DiscoveryGoIE(DiscoveryGoBaseIE): | ||||||
|  |     _VALID_URL = DiscoveryGoBaseIE._VALID_URL_TEMPLATE % r'(?:[^/]+/)+' | ||||||
|  |     _GEO_COUNTRIES = ['US'] | ||||||
|  |     _TEST = { | ||||||
|  |         'url': 'https://www.discoverygo.com/bering-sea-gold/reaper-madness/', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '58c167d86b66d12f2addeb01', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Reaper Madness', | ||||||
|  |             'description': 'md5:09f2c625c99afb8946ed4fb7865f6e78', | ||||||
|  |             'duration': 2519, | ||||||
|  |             'series': 'Bering Sea Gold', | ||||||
|  |             'season_number': 8, | ||||||
|  |             'episode_number': 6, | ||||||
|  |             'age_limit': 14, | ||||||
|  |         }, | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     def _real_extract(self, url): | ||||||
|  |         display_id = self._match_id(url) | ||||||
|  |  | ||||||
|  |         webpage = self._download_webpage(url, display_id) | ||||||
|  |  | ||||||
|  |         container = extract_attributes( | ||||||
|  |             self._search_regex( | ||||||
|  |                 r'(<div[^>]+class=["\']video-player-container[^>]+>)', | ||||||
|  |                 webpage, 'video container')) | ||||||
|  |  | ||||||
|  |         video = self._parse_json( | ||||||
|  |             container.get('data-video') or container.get('data-json'), | ||||||
|  |             display_id) | ||||||
|  |  | ||||||
|  |         stream = video.get('stream') | ||||||
|  |  | ||||||
|  |         return self._extract_video_info(video, stream, display_id) | ||||||
|  |  | ||||||
|  |  | ||||||
| class DiscoveryGoPlaylistIE(DiscoveryGoBaseIE): | class DiscoveryGoPlaylistIE(DiscoveryGoBaseIE): | ||||||
|     _VALID_URL = DiscoveryGoBaseIE._VALID_URL_TEMPLATE % '' |     _VALID_URL = DiscoveryGoBaseIE._VALID_URL_TEMPLATE % '' | ||||||
|     _TEST = { |     _TEST = { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Remita Amine
					Remita Amine