gaia.py 4.3 KB

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