gaia.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. from .common import InfoExtractor
  2. from ..compat import (
  3. compat_str,
  4. compat_urllib_parse_unquote,
  5. )
  6. from ..utils import (
  7. ExtractorError,
  8. int_or_none,
  9. str_or_none,
  10. strip_or_none,
  11. try_get,
  12. urlencode_postdata,
  13. )
  14. class GaiaIE(InfoExtractor):
  15. _VALID_URL = r'https?://(?:www\.)?gaia\.com/video/(?P<id>[^/?]+).*?\bfullplayer=(?P<type>feature|preview)'
  16. _TESTS = [{
  17. 'url': 'https://www.gaia.com/video/connecting-universal-consciousness?fullplayer=feature',
  18. 'info_dict': {
  19. 'id': '89356',
  20. 'ext': 'mp4',
  21. 'title': 'Connecting with Universal Consciousness',
  22. 'description': 'md5:844e209ad31b7d31345f5ed689e3df6f',
  23. 'upload_date': '20151116',
  24. 'timestamp': 1447707266,
  25. 'duration': 936,
  26. },
  27. 'params': {
  28. # m3u8 download
  29. 'skip_download': True,
  30. },
  31. }, {
  32. 'url': 'https://www.gaia.com/video/connecting-universal-consciousness?fullplayer=preview',
  33. 'info_dict': {
  34. 'id': '89351',
  35. 'ext': 'mp4',
  36. 'title': 'Connecting with Universal Consciousness',
  37. 'description': 'md5:844e209ad31b7d31345f5ed689e3df6f',
  38. 'upload_date': '20151116',
  39. 'timestamp': 1447707266,
  40. 'duration': 53,
  41. },
  42. 'params': {
  43. # m3u8 download
  44. 'skip_download': True,
  45. },
  46. }]
  47. _NETRC_MACHINE = 'gaia'
  48. _jwt = None
  49. def _real_initialize(self):
  50. auth = self._get_cookies('https://www.gaia.com/').get('auth')
  51. if auth:
  52. auth = self._parse_json(compat_urllib_parse_unquote(auth.value), None, fatal=False)
  53. self._jwt = auth.get('jwt')
  54. def _perform_login(self, username, password):
  55. if self._jwt:
  56. return
  57. auth = self._download_json(
  58. 'https://auth.gaia.com/v1/login',
  59. None, data=urlencode_postdata({
  60. 'username': username,
  61. 'password': password
  62. }))
  63. if auth.get('success') is False:
  64. raise ExtractorError(', '.join(auth['messages']), expected=True)
  65. self._jwt = auth.get('jwt')
  66. def _real_extract(self, url):
  67. display_id, vtype = self._match_valid_url(url).groups()
  68. node_id = self._download_json(
  69. 'https://brooklyn.gaia.com/pathinfo', display_id, query={
  70. 'path': 'video/' + display_id,
  71. })['id']
  72. node = self._download_json(
  73. 'https://brooklyn.gaia.com/node/%d' % node_id, node_id)
  74. vdata = node[vtype]
  75. media_id = compat_str(vdata['nid'])
  76. title = node['title']
  77. headers = None
  78. if self._jwt:
  79. headers = {'Authorization': 'Bearer ' + self._jwt}
  80. media = self._download_json(
  81. 'https://brooklyn.gaia.com/media/' + media_id,
  82. media_id, headers=headers)
  83. formats = self._extract_m3u8_formats(
  84. media['mediaUrls']['bcHLS'], media_id, 'mp4')
  85. subtitles = {}
  86. text_tracks = media.get('textTracks', {})
  87. for key in ('captions', 'subtitles'):
  88. for lang, sub_url in text_tracks.get(key, {}).items():
  89. subtitles.setdefault(lang, []).append({
  90. 'url': sub_url,
  91. })
  92. fivestar = node.get('fivestar', {})
  93. fields = node.get('fields', {})
  94. def get_field_value(key, value_key='value'):
  95. return try_get(fields, lambda x: x[key][0][value_key])
  96. return {
  97. 'id': media_id,
  98. 'display_id': display_id,
  99. 'title': title,
  100. 'formats': formats,
  101. 'description': strip_or_none(get_field_value('body') or get_field_value('teaser')),
  102. 'timestamp': int_or_none(node.get('created')),
  103. 'subtitles': subtitles,
  104. 'duration': int_or_none(vdata.get('duration')),
  105. 'like_count': int_or_none(try_get(fivestar, lambda x: x['up_count']['value'])),
  106. 'dislike_count': int_or_none(try_get(fivestar, lambda x: x['down_count']['value'])),
  107. 'comment_count': int_or_none(node.get('comment_count')),
  108. 'series': try_get(node, lambda x: x['series']['title'], compat_str),
  109. 'season_number': int_or_none(get_field_value('season')),
  110. 'season_id': str_or_none(get_field_value('series_nid', 'nid')),
  111. 'episode_number': int_or_none(get_field_value('episode')),
  112. }