2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
   7 from ..compat 
import compat_HTTPError
 
  16 class EaglePlatformIE(InfoExtractor
): 
  19                         eagleplatform:(?P<custom_host>[^/]+):| 
  20                         https?://(?P<host>.+?\.media\.eagleplatform\.com)/index/player\?.*\brecord_id= 
  25         # http://lenta.ru/news/2015/03/06/navalny/ 
  26         'url': 'http://lentaru.media.eagleplatform.com/index/player?player=new&record_id=227304&player_template_id=5201', 
  27         # Not checking MD5 as sometimes the direct HTTP link results in 404 and HLS is used 
  31             'title': 'Навальный вышел на свободу', 
  32             'description': 'md5:d97861ac9ae77377f3f20eaf9d04b4f5', 
  33             'thumbnail': r
're:^https?://.*\.jpg$', 
  39         # http://muz-tv.ru/play/7129/ 
  40         # http://media.clipyou.ru/index/player?record_id=12820&width=730&height=415&autoplay=true 
  41         'url': 'eagleplatform:media.clipyou.ru:12820', 
  42         'md5': '358597369cf8ba56675c1df15e7af624', 
  46             'title': "'O Sole Mio", 
  47             'thumbnail': r
're:^https?://.*\.jpg$', 
  51         'skip': 'Georestricted', 
  53         # referrer protected video (https://tvrain.ru/lite/teleshow/kak_vse_nachinalos/namin-418921/) 
  54         'url': 'eagleplatform:tvrainru.media.eagleplatform.com:582306', 
  55         'only_matching': True, 
  59     def _extract_url(webpage
): 
  60         # Regular iframe embedding 
  62             r
'<iframe[^>]+src=(["\'])(?P
<url
>(?
:https?
:)?
//.+?\
.media\
.eagleplatform\
.com
/index
/player
\?.+?
)\
1', 
  65             return mobj.group('url
') 
  68                             src=(?P<qjs>["\'])(?:https?:)?//(?P<host>(?:(?!(?P=qjs)).)+\.media\.eagleplatform\.com)/player/player\.js(?P=qjs) 
  71         # "Basic usage" embedding (see http://dultonmedia.github.io/eplayer/) 
  76                         class=(?P<qclass>["\'])eagleplayer(?P=qclass)[^>]+ 
  77                         data-id=["\'](?P<id>\d+) 
  78             ''' % PLAYER_JS_RE, webpage) 
  80             return 'eagleplatform
:%(host)s:%(id)s' % mobj.groupdict() 
  81         # Generalization of "Javascript code usage", "Combined usage" and 
  82         # "Usage without attaching to DOM" embeddings (see 
  83         # http://dultonmedia.github.io/eplayer/) 
  93                             \bid\s*:\s*["\']?(?P<id>\d+) 
  99             ''' % PLAYER_JS_RE, webpage) 
 101             return 'eagleplatform
:%(host)s:%(id)s' % mobj.groupdict() 
 104     def _handle_error(response): 
 105         status = int_or_none(response.get('status
', 200)) 
 107             raise ExtractorError(' '.join(response['errors
']), expected=True) 
 109     def _download_json(self, url_or_request, video_id, *args, **kwargs): 
 111             response = super(EaglePlatformIE, self)._download_json( 
 112                 url_or_request, video_id, *args, **kwargs) 
 113         except ExtractorError as ee: 
 114             if isinstance(ee.cause, compat_HTTPError): 
 115                 response = self._parse_json(ee.cause.read().decode('utf
-8'), video_id) 
 116                 self._handle_error(response) 
 120     def _get_video_url(self, url_or_request, video_id, note='Downloading JSON metadata
'): 
 121         return self._download_json(url_or_request, video_id, note)['data
'][0] 
 123     def _real_extract(self, url): 
 124         url, smuggled_data = unsmuggle_url(url, {}) 
 126         mobj = re.match(self._VALID_URL, url) 
 127         host, video_id = mobj.group('custom_host
') or mobj.group('host
'), mobj.group('id') 
 134         referrer = smuggled_data.get('referrer
') 
 136             headers['Referer
'] = referrer 
 137             query['referrer
'] = referrer 
 139         player_data = self._download_json( 
 140             'http
://%s/api
/player_data
' % host, video_id, 
 141             headers=headers, query=query) 
 143         media = player_data['data
']['playlist
']['viewports
'][0]['medialist
'][0] 
 145         title = media['title
'] 
 146         description = media.get('description
') 
 147         thumbnail = self._proto_relative_url(media.get('snapshot
'), 'http
:') 
 148         duration = int_or_none(media.get('duration
')) 
 149         view_count = int_or_none(media.get('views
')) 
 151         age_restriction = media.get('age_restriction
') 
 154             age_limit = 0 if age_restriction == 'allow_all
' else 18 
 156         secure_m3u8 = self._proto_relative_url(media['sources
']['secure_m3u8
']['auto
'], 'http
:') 
 160         m3u8_url = self._get_video_url(secure_m3u8, video_id, 'Downloading m3u8 JSON
') 
 161         m3u8_formats = self._extract_m3u8_formats( 
 162             m3u8_url, video_id, 'mp4
', entry_protocol='m3u8_native
', 
 163             m3u8_id='hls
', fatal=False) 
 164         formats.extend(m3u8_formats) 
 166         m3u8_formats_dict = {} 
 167         for f in m3u8_formats: 
 168             if f.get('height
') is not None: 
 169                 m3u8_formats_dict[f['height
']] = f 
 171         mp4_data = self._download_json( 
 172             # Secure mp4 URL is constructed according to Player.prototype.mp4 from 
 173             # http://lentaru.media.eagleplatform.com/player/player.js 
 174             re.sub(r'm3u8|hlsvod|hls|f4m
', 'mp4s
', secure_m3u8), 
 175             video_id, 'Downloading mp4 JSON
', fatal=False) 
 177             for format_id, format_url in mp4_data.get('data
', {}).items(): 
 178                 if not url_or_none(format_url): 
 180                 height = int_or_none(format_id) 
 181                 if height is not None and m3u8_formats_dict.get(height): 
 182                     f = m3u8_formats_dict[height].copy() 
 184                         'format_id
': f['format_id
'].replace('hls
', 'http
'), 
 189                         'format_id
': 'http
-%s' % format_id, 
 190                         'height
': int_or_none(format_id), 
 192                 f['url
'] = format_url 
 195         self._sort_formats(formats) 
 200             'description
': description, 
 201             'thumbnail
': thumbnail, 
 202             'duration
': duration, 
 203             'view_count
': view_count, 
 204             'age_limit
': age_limit,