2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
   9     compat_urllib_parse_unquote
, 
  21 class GaiaIE(InfoExtractor
): 
  22     _VALID_URL 
= r
'https?://(?:www\.)?gaia\.com/video/(?P<id>[^/?]+).*?\bfullplayer=(?P<type>feature|preview)' 
  24         'url': 'https://www.gaia.com/video/connecting-universal-consciousness?fullplayer=feature', 
  28             'title': 'Connecting with Universal Consciousness', 
  29             'description': 'md5:844e209ad31b7d31345f5ed689e3df6f', 
  30             'upload_date': '20151116', 
  31             'timestamp': 1447707266, 
  36             'skip_download': True, 
  39         'url': 'https://www.gaia.com/video/connecting-universal-consciousness?fullplayer=preview', 
  43             'title': 'Connecting with Universal Consciousness', 
  44             'description': 'md5:844e209ad31b7d31345f5ed689e3df6f', 
  45             'upload_date': '20151116', 
  46             'timestamp': 1447707266, 
  51             'skip_download': True, 
  54     _NETRC_MACHINE 
= 'gaia' 
  57     def _real_initialize(self
): 
  58         auth 
= self
._get
_cookies
('https://www.gaia.com/').get('auth') 
  60             auth 
= self
._parse
_json
( 
  61                 compat_urllib_parse_unquote(auth
.value
), 
  64             username
, password 
= self
._get
_login
_info
() 
  67             auth 
= self
._download
_json
( 
  68                 'https://auth.gaia.com/v1/login', 
  69                 None, data
=urlencode_postdata({ 
  73             if auth
.get('success') is False: 
  74                 raise ExtractorError(', '.join(auth
['messages']), expected
=True) 
  76             self
._jwt 
= auth
.get('jwt') 
  78     def _real_extract(self
, url
): 
  79         display_id
, vtype 
= re
.search(self
._VALID
_URL
, url
).groups() 
  80         node_id 
= self
._download
_json
( 
  81             'https://brooklyn.gaia.com/pathinfo', display_id
, query
={ 
  82                 'path': 'video/' + display_id
, 
  84         node 
= self
._download
_json
( 
  85             'https://brooklyn.gaia.com/node/%d' % node_id
, node_id
) 
  87         media_id 
= compat_str(vdata
['nid']) 
  92             headers 
= {'Authorization': 'Bearer ' + self
._jwt
} 
  93         media 
= self
._download
_json
( 
  94             'https://brooklyn.gaia.com/media/' + media_id
, 
  95             media_id
, headers
=headers
) 
  96         formats 
= self
._extract
_m
3u8_formats
( 
  97             media
['mediaUrls']['bcHLS'], media_id
, 'mp4') 
  98         self
._sort
_formats
(formats
) 
 101         text_tracks 
= media
.get('textTracks', {}) 
 102         for key 
in ('captions', 'subtitles'): 
 103             for lang
, sub_url 
in text_tracks
.get(key
, {}).items(): 
 104                 subtitles
.setdefault(lang
, []).append({ 
 108         fivestar 
= node
.get('fivestar', {}) 
 109         fields 
= node
.get('fields', {}) 
 111         def get_field_value(key
, value_key
='value'): 
 112             return try_get(fields
, lambda x
: x
[key
][0][value_key
]) 
 116             'display_id': display_id
, 
 119             'description': strip_or_none(get_field_value('body') or get_field_value('teaser')), 
 120             'timestamp': int_or_none(node
.get('created')), 
 121             'subtitles': subtitles
, 
 122             'duration': int_or_none(vdata
.get('duration')), 
 123             'like_count': int_or_none(try_get(fivestar
, lambda x
: x
['up_count']['value'])), 
 124             'dislike_count': int_or_none(try_get(fivestar
, lambda x
: x
['down_count']['value'])), 
 125             'comment_count': int_or_none(node
.get('comment_count')), 
 126             'series': try_get(node
, lambda x
: x
['series']['title'], compat_str
), 
 127             'season_number': int_or_none(get_field_value('season')), 
 128             'season_id': str_or_none(get_field_value('series_nid', 'nid')), 
 129             'episode_number': int_or_none(get_field_value('episode')),