]>
Commit | Line | Data |
---|---|---|
53bfd6b2 | 1 | from __future__ import unicode_literals |
2 | ||
cb0c2310 RA |
3 | import random |
4 | import re | |
5 | import string | |
6 | ||
7 | from .discoverygo import DiscoveryGoBaseIE | |
3cc0d0b8 RA |
8 | from ..compat import ( |
9 | compat_str, | |
10 | compat_urllib_parse_unquote, | |
11 | ) | |
9298d4e3 | 12 | from ..utils import ( |
cb0c2310 | 13 | ExtractorError, |
9d5871fd | 14 | try_get, |
9298d4e3 | 15 | ) |
cb0c2310 | 16 | from ..compat import compat_HTTPError |
53bfd6b2 | 17 | |
18 | ||
cb0c2310 | 19 | class DiscoveryIE(DiscoveryGoBaseIE): |
9d5871fd | 20 | _VALID_URL = r'''(?x)https?://(?:www\.)?(?P<site> |
fec040e7 | 21 | discovery| |
22 | investigationdiscovery| | |
23 | discoverylife| | |
24 | animalplanet| | |
25 | ahctv| | |
26 | destinationamerica| | |
27 | sciencechannel| | |
28 | tlc| | |
29 | velocity | |
cb0c2310 | 30 | )\.com(?P<path>/tv-shows/[^/]+/(?:video|full-episode)s/(?P<id>[^./?#]+))''' |
65ba8b23 | 31 | _TESTS = [{ |
cb0c2310 | 32 | 'url': 'https://www.discovery.com/tv-shows/cash-cab/videos/dave-foley', |
53bfd6b2 | 33 | 'info_dict': { |
cb0c2310 | 34 | 'id': '5a2d9b4d6b66d17a5026e1fd', |
65ba8b23 | 35 | 'ext': 'mp4', |
cb0c2310 RA |
36 | 'title': 'Dave Foley', |
37 | 'description': 'md5:4b39bcafccf9167ca42810eb5f28b01f', | |
38 | 'duration': 608, | |
9b05bd42 | 39 | }, |
65ba8b23 YCH |
40 | 'params': { |
41 | 'skip_download': True, # requires ffmpeg | |
42 | } | |
43 | }, { | |
cb0c2310 RA |
44 | 'url': 'https://www.investigationdiscovery.com/tv-shows/final-vision/full-episodes/final-vision', |
45 | 'only_matching': True, | |
65ba8b23 | 46 | }] |
cb0c2310 RA |
47 | _GEO_COUNTRIES = ['US'] |
48 | _GEO_BYPASS = False | |
53bfd6b2 | 49 | |
50 | def _real_extract(self, url): | |
9d5871fd | 51 | site, path, display_id = re.match(self._VALID_URL, url).groups() |
cb0c2310 | 52 | webpage = self._download_webpage(url, display_id) |
53bfd6b2 | 53 | |
cb0c2310 RA |
54 | react_data = self._parse_json(self._search_regex( |
55 | r'window\.__reactTransmitPacket\s*=\s*({.+?});', | |
56 | webpage, 'react data'), display_id) | |
57 | content_blocks = react_data['layout'][path]['contentBlocks'] | |
58 | video = next(cb for cb in content_blocks if cb.get('type') == 'video')['content']['items'][0] | |
59 | video_id = video['id'] | |
19dbaeec | 60 | |
3cc0d0b8 RA |
61 | access_token = None |
62 | cookies = self._get_cookies(url) | |
63 | ||
64 | # prefer Affiliate Auth Token over Anonymous Auth Token | |
65 | auth_storage_cookie = cookies.get('eosAf') or cookies.get('eosAn') | |
66 | if auth_storage_cookie and auth_storage_cookie.value: | |
67 | auth_storage = self._parse_json(compat_urllib_parse_unquote( | |
68 | compat_urllib_parse_unquote(auth_storage_cookie.value)), | |
69 | video_id, fatal=False) or {} | |
70 | access_token = auth_storage.get('a') or auth_storage.get('access_token') | |
71 | ||
72 | if not access_token: | |
73 | access_token = self._download_json( | |
74 | 'https://www.%s.com/anonymous' % site, display_id, query={ | |
75 | 'authRel': 'authorization', | |
76 | 'client_id': try_get( | |
77 | react_data, lambda x: x['application']['apiClientId'], | |
78 | compat_str) or '3020a40c2356a645b4b4', | |
79 | 'nonce': ''.join([random.choice(string.ascii_letters) for _ in range(32)]), | |
80 | 'redirectUri': 'https://fusion.ddmcdn.com/app/mercury-sdk/180/redirectHandler.html?https://www.%s.com' % site, | |
81 | })['access_token'] | |
93f7a31b | 82 | |
cb0c2310 RA |
83 | try: |
84 | stream = self._download_json( | |
85 | 'https://api.discovery.com/v1/streaming/video/' + video_id, | |
86 | display_id, headers={ | |
87 | 'Authorization': 'Bearer ' + access_token, | |
88 | }) | |
89 | except ExtractorError as e: | |
3cc0d0b8 | 90 | if isinstance(e.cause, compat_HTTPError) and e.cause.code in (401, 403): |
cb0c2310 RA |
91 | e_description = self._parse_json( |
92 | e.cause.read().decode(), display_id)['description'] | |
93 | if 'resource not available for country' in e_description: | |
94 | self.raise_geo_restricted(countries=self._GEO_COUNTRIES) | |
95 | if 'Authorized Networks' in e_description: | |
96 | raise ExtractorError( | |
97 | 'This video is only available via cable service provider subscription that' | |
98 | ' is not currently supported. You may want to use --cookies.', expected=True) | |
99 | raise ExtractorError(e_description) | |
100 | raise | |
65ba8b23 | 101 | |
cb0c2310 | 102 | return self._extract_video_info(video, stream, display_id) |