You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
3.4 KiB

  1. from __future__ import unicode_literals
  2. import random
  3. import re
  4. import string
  5. from .discoverygo import DiscoveryGoBaseIE
  6. from ..utils import (
  7. ExtractorError,
  8. update_url_query,
  9. )
  10. from ..compat import compat_HTTPError
  11. class DiscoveryIE(DiscoveryGoBaseIE):
  12. _VALID_URL = r'''(?x)https?://(?:www\.)?(?:
  13. discovery|
  14. investigationdiscovery|
  15. discoverylife|
  16. animalplanet|
  17. ahctv|
  18. destinationamerica|
  19. sciencechannel|
  20. tlc|
  21. velocity
  22. )\.com(?P<path>/tv-shows/[^/]+/(?:video|full-episode)s/(?P<id>[^./?#]+))'''
  23. _TESTS = [{
  24. 'url': 'https://www.discovery.com/tv-shows/cash-cab/videos/dave-foley',
  25. 'info_dict': {
  26. 'id': '5a2d9b4d6b66d17a5026e1fd',
  27. 'ext': 'mp4',
  28. 'title': 'Dave Foley',
  29. 'description': 'md5:4b39bcafccf9167ca42810eb5f28b01f',
  30. 'duration': 608,
  31. },
  32. 'params': {
  33. 'skip_download': True, # requires ffmpeg
  34. }
  35. }, {
  36. 'url': 'https://www.investigationdiscovery.com/tv-shows/final-vision/full-episodes/final-vision',
  37. 'only_matching': True,
  38. }]
  39. _GEO_COUNTRIES = ['US']
  40. _GEO_BYPASS = False
  41. def _real_extract(self, url):
  42. path, display_id = re.match(self._VALID_URL, url).groups()
  43. webpage = self._download_webpage(url, display_id)
  44. react_data = self._parse_json(self._search_regex(
  45. r'window\.__reactTransmitPacket\s*=\s*({.+?});',
  46. webpage, 'react data'), display_id)
  47. content_blocks = react_data['layout'][path]['contentBlocks']
  48. video = next(cb for cb in content_blocks if cb.get('type') == 'video')['content']['items'][0]
  49. video_id = video['id']
  50. access_token = self._download_json(
  51. 'https://www.discovery.com/anonymous', display_id, query={
  52. 'authLink': update_url_query(
  53. 'https://login.discovery.com/v1/oauth2/authorize', {
  54. 'client_id': react_data['application']['apiClientId'],
  55. 'redirect_uri': 'https://fusion.ddmcdn.com/app/mercury-sdk/180/redirectHandler.html',
  56. 'response_type': 'anonymous',
  57. 'state': 'nonce,' + ''.join([random.choice(string.ascii_letters) for _ in range(32)]),
  58. })
  59. })['access_token']
  60. try:
  61. stream = self._download_json(
  62. 'https://api.discovery.com/v1/streaming/video/' + video_id,
  63. display_id, headers={
  64. 'Authorization': 'Bearer ' + access_token,
  65. })
  66. except ExtractorError as e:
  67. if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
  68. e_description = self._parse_json(
  69. e.cause.read().decode(), display_id)['description']
  70. if 'resource not available for country' in e_description:
  71. self.raise_geo_restricted(countries=self._GEO_COUNTRIES)
  72. if 'Authorized Networks' in e_description:
  73. raise ExtractorError(
  74. 'This video is only available via cable service provider subscription that'
  75. ' is not currently supported. You may want to use --cookies.', expected=True)
  76. raise ExtractorError(e_description)
  77. raise
  78. return self._extract_video_info(video, stream, display_id)