| 
									
										
										
										
											2014-01-26 14:05:34 +05:30
										 |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  | import random | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | import string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .discoverygo import DiscoveryGoBaseIE | 
					
						
							| 
									
										
										
										
											2018-05-02 09:32:53 +01:00
										 |  |  | from ..compat import ( | 
					
						
							|  |  |  |     compat_str, | 
					
						
							|  |  |  |     compat_urllib_parse_unquote, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-01-08 17:36:56 +01:00
										 |  |  | from ..utils import ( | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |     ExtractorError, | 
					
						
							| 
									
										
										
										
											2018-02-10 00:55:11 +07:00
										 |  |  |     try_get, | 
					
						
							| 
									
										
										
										
											2015-01-08 17:36:56 +01:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  | from ..compat import compat_HTTPError | 
					
						
							| 
									
										
										
										
											2014-01-26 14:05:34 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  | class DiscoveryIE(DiscoveryGoBaseIE): | 
					
						
							| 
									
										
										
										
											2018-12-17 16:34:51 +01:00
										 |  |  |     _VALID_URL = r'''(?x)https?://
 | 
					
						
							|  |  |  |         (?P<site> | 
					
						
							|  |  |  |             (?:www\.)? | 
					
						
							|  |  |  |                 (?: | 
					
						
							|  |  |  |                     discovery| | 
					
						
							|  |  |  |                     investigationdiscovery| | 
					
						
							|  |  |  |                     discoverylife| | 
					
						
							|  |  |  |                     animalplanet| | 
					
						
							|  |  |  |                     ahctv| | 
					
						
							|  |  |  |                     destinationamerica| | 
					
						
							|  |  |  |                     sciencechannel| | 
					
						
							|  |  |  |                     tlc| | 
					
						
							|  |  |  |                     velocity | 
					
						
							|  |  |  |                 )| | 
					
						
							|  |  |  |             watch\. | 
					
						
							|  |  |  |                 (?: | 
					
						
							|  |  |  |                     hgtv| | 
					
						
							|  |  |  |                     foodnetwork| | 
					
						
							|  |  |  |                     travelchannel| | 
					
						
							|  |  |  |                     diynetwork| | 
					
						
							|  |  |  |                     cookingchanneltv| | 
					
						
							|  |  |  |                     motortrend | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         )\.com(?P<path>/tv-shows/[^/]+/(?:video|full-episode)s/(?P<id>[^./?#]+))''' | 
					
						
							| 
									
										
										
										
											2015-06-07 16:34:19 +08:00
										 |  |  |     _TESTS = [{ | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         'url': 'https://www.discovery.com/tv-shows/cash-cab/videos/dave-foley', | 
					
						
							| 
									
										
										
										
											2014-01-26 14:05:34 +05:30
										 |  |  |         'info_dict': { | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |             'id': '5a2d9b4d6b66d17a5026e1fd', | 
					
						
							| 
									
										
										
										
											2015-06-07 16:34:19 +08:00
										 |  |  |             'ext': 'mp4', | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |             'title': 'Dave Foley', | 
					
						
							|  |  |  |             'description': 'md5:4b39bcafccf9167ca42810eb5f28b01f', | 
					
						
							|  |  |  |             'duration': 608, | 
					
						
							| 
									
										
										
										
											2014-01-27 12:41:30 +01:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2015-06-07 16:34:19 +08:00
										 |  |  |         'params': { | 
					
						
							|  |  |  |             'skip_download': True,  # requires ffmpeg | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }, { | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         'url': 'https://www.investigationdiscovery.com/tv-shows/final-vision/full-episodes/final-vision', | 
					
						
							|  |  |  |         'only_matching': True, | 
					
						
							| 
									
										
										
										
											2015-06-07 16:34:19 +08:00
										 |  |  |     }] | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |     _GEO_COUNTRIES = ['US'] | 
					
						
							|  |  |  |     _GEO_BYPASS = False | 
					
						
							| 
									
										
										
										
											2014-01-26 14:05:34 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							| 
									
										
										
										
											2018-02-10 00:55:11 +07:00
										 |  |  |         site, path, display_id = re.match(self._VALID_URL, url).groups() | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         webpage = self._download_webpage(url, display_id) | 
					
						
							| 
									
										
										
										
											2014-01-26 14:05:34 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         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'] | 
					
						
							| 
									
										
										
										
											2016-03-27 07:03:08 +06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-02 09:32:53 +01:00
										 |  |  |         access_token = None | 
					
						
							|  |  |  |         cookies = self._get_cookies(url) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # prefer Affiliate Auth Token over Anonymous Auth Token | 
					
						
							|  |  |  |         auth_storage_cookie = cookies.get('eosAf') or cookies.get('eosAn') | 
					
						
							|  |  |  |         if auth_storage_cookie and auth_storage_cookie.value: | 
					
						
							|  |  |  |             auth_storage = self._parse_json(compat_urllib_parse_unquote( | 
					
						
							|  |  |  |                 compat_urllib_parse_unquote(auth_storage_cookie.value)), | 
					
						
							|  |  |  |                 video_id, fatal=False) or {} | 
					
						
							|  |  |  |             access_token = auth_storage.get('a') or auth_storage.get('access_token') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not access_token: | 
					
						
							|  |  |  |             access_token = self._download_json( | 
					
						
							| 
									
										
										
										
											2018-12-17 16:34:51 +01:00
										 |  |  |                 'https://%s.com/anonymous' % site, display_id, query={ | 
					
						
							| 
									
										
										
										
											2018-05-02 09:32:53 +01:00
										 |  |  |                     'authRel': 'authorization', | 
					
						
							|  |  |  |                     'client_id': try_get( | 
					
						
							|  |  |  |                         react_data, lambda x: x['application']['apiClientId'], | 
					
						
							|  |  |  |                         compat_str) or '3020a40c2356a645b4b4', | 
					
						
							|  |  |  |                     'nonce': ''.join([random.choice(string.ascii_letters) for _ in range(32)]), | 
					
						
							|  |  |  |                     'redirectUri': 'https://fusion.ddmcdn.com/app/mercury-sdk/180/redirectHandler.html?https://www.%s.com' % site, | 
					
						
							|  |  |  |                 })['access_token'] | 
					
						
							| 
									
										
										
										
											2016-04-30 20:49:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2019-01-02 17:46:07 +01:00
										 |  |  |             headers = self.geo_verification_headers() | 
					
						
							|  |  |  |             headers['Authorization'] = 'Bearer ' + access_token | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |             stream = self._download_json( | 
					
						
							|  |  |  |                 'https://api.discovery.com/v1/streaming/video/' + video_id, | 
					
						
							| 
									
										
										
										
											2019-01-02 17:46:07 +01:00
										 |  |  |                 display_id, headers=headers) | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         except ExtractorError as e: | 
					
						
							| 
									
										
										
										
											2018-05-02 09:32:53 +01:00
										 |  |  |             if isinstance(e.cause, compat_HTTPError) and e.cause.code in (401, 403): | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |                 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 | 
					
						
							| 
									
										
										
										
											2015-06-07 16:34:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 10:33:03 +01:00
										 |  |  |         return self._extract_video_info(video, stream, display_id) |