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.

162 lines
5.5 KiB

  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. import re
  4. from .common import InfoExtractor
  5. from ..compat import compat_str
  6. from ..utils import (
  7. determine_ext,
  8. ExtractorError,
  9. int_or_none,
  10. )
  11. class HotStarBaseIE(InfoExtractor):
  12. _GEO_COUNTRIES = ['IN']
  13. def _download_json(self, *args, **kwargs):
  14. response = super(HotStarBaseIE, self)._download_json(*args, **kwargs)
  15. if response['resultCode'] != 'OK':
  16. if kwargs.get('fatal'):
  17. raise ExtractorError(
  18. response['errorDescription'], expected=True)
  19. return None
  20. return response['resultObj']
  21. def _download_content_info(self, content_id):
  22. return self._download_json(
  23. 'https://account.hotstar.com/AVS/besc', content_id, query={
  24. 'action': 'GetAggregatedContentDetails',
  25. 'appVersion': '5.0.40',
  26. 'channel': 'PCTV',
  27. 'contentId': content_id,
  28. })['contentInfo'][0]
  29. class HotStarIE(HotStarBaseIE):
  30. _VALID_URL = r'https?://(?:www\.)?hotstar\.com/(?:.+?[/-])?(?P<id>\d{10})'
  31. _TESTS = [{
  32. 'url': 'http://www.hotstar.com/on-air-with-aib--english-1000076273',
  33. 'info_dict': {
  34. 'id': '1000076273',
  35. 'ext': 'mp4',
  36. 'title': 'On Air With AIB',
  37. 'description': 'md5:c957d8868e9bc793ccb813691cc4c434',
  38. 'timestamp': 1447227000,
  39. 'upload_date': '20151111',
  40. 'duration': 381,
  41. },
  42. 'params': {
  43. # m3u8 download
  44. 'skip_download': True,
  45. }
  46. }, {
  47. 'url': 'http://www.hotstar.com/sports/cricket/rajitha-sizzles-on-debut-with-329/2001477583',
  48. 'only_matching': True,
  49. }, {
  50. 'url': 'http://www.hotstar.com/1000000515',
  51. 'only_matching': True,
  52. }]
  53. def _real_extract(self, url):
  54. video_id = self._match_id(url)
  55. video_data = self._download_content_info(video_id)
  56. title = video_data['episodeTitle']
  57. if video_data.get('encrypted') == 'Y':
  58. raise ExtractorError('This video is DRM protected.', expected=True)
  59. formats = []
  60. for f in ('JIO',):
  61. format_data = self._download_json(
  62. 'http://getcdn.hotstar.com/AVS/besc',
  63. video_id, 'Downloading %s JSON metadata' % f,
  64. fatal=False, query={
  65. 'action': 'GetCDN',
  66. 'asJson': 'Y',
  67. 'channel': f,
  68. 'id': video_id,
  69. 'type': 'VOD',
  70. })
  71. if format_data:
  72. format_url = format_data.get('src')
  73. if not format_url:
  74. continue
  75. ext = determine_ext(format_url)
  76. if ext == 'm3u8':
  77. formats.extend(self._extract_m3u8_formats(
  78. format_url, video_id, 'mp4',
  79. m3u8_id='hls', fatal=False))
  80. elif ext == 'f4m':
  81. # produce broken files
  82. continue
  83. else:
  84. formats.append({
  85. 'url': format_url,
  86. 'width': int_or_none(format_data.get('width')),
  87. 'height': int_or_none(format_data.get('height')),
  88. })
  89. self._sort_formats(formats)
  90. return {
  91. 'id': video_id,
  92. 'title': title,
  93. 'description': video_data.get('description'),
  94. 'duration': int_or_none(video_data.get('duration')),
  95. 'timestamp': int_or_none(video_data.get('broadcastDate')),
  96. 'formats': formats,
  97. 'episode': title,
  98. 'episode_number': int_or_none(video_data.get('episodeNumber')),
  99. 'series': video_data.get('contentTitle'),
  100. }
  101. class HotStarPlaylistIE(HotStarBaseIE):
  102. IE_NAME = 'hotstar:playlist'
  103. _VALID_URL = r'(?P<url>https?://(?:www\.)?hotstar\.com/tv/[^/]+/(?P<content_id>\d+))/(?P<type>[^/]+)/(?P<id>\d+)'
  104. _TESTS = [{
  105. 'url': 'http://www.hotstar.com/tv/pratidaan/14982/episodes/14812/9993',
  106. 'info_dict': {
  107. 'id': '14812',
  108. },
  109. 'playlist_mincount': 75,
  110. }, {
  111. 'url': 'http://www.hotstar.com/tv/pratidaan/14982/popular-clips/9998/9998',
  112. 'only_matching': True,
  113. }]
  114. _ITEM_TYPES = {
  115. 'episodes': 'EPISODE',
  116. 'popular-clips': 'CLIPS',
  117. }
  118. def _real_extract(self, url):
  119. mobj = re.match(self._VALID_URL, url)
  120. base_url = mobj.group('url')
  121. content_id = mobj.group('content_id')
  122. playlist_type = mobj.group('type')
  123. content_info = self._download_content_info(content_id)
  124. playlist_id = compat_str(content_info['categoryId'])
  125. collection = self._download_json(
  126. 'https://search.hotstar.com/AVS/besc', playlist_id, query={
  127. 'action': 'SearchContents',
  128. 'appVersion': '5.0.40',
  129. 'channel': 'PCTV',
  130. 'moreFilters': 'series:%s;' % playlist_id,
  131. 'query': '*',
  132. 'searchOrder': 'last_broadcast_date desc,year desc,title asc',
  133. 'type': self._ITEM_TYPES.get(playlist_type, 'EPISODE'),
  134. })
  135. entries = [
  136. self.url_result(
  137. '%s/_/%s' % (base_url, video['contentId']),
  138. ie=HotStarIE.ie_key(), video_id=video['contentId'])
  139. for video in collection['response']['docs']
  140. if video.get('contentId')]
  141. return self.playlist_result(entries, playlist_id)