| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  | # coding: utf-8 | 
					
						
							|  |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .common import InfoExtractor | 
					
						
							| 
									
										
										
										
											2016-04-16 16:47:16 +08:00
										 |  |  | from ..compat import compat_HTTPError | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  | from ..utils import ( | 
					
						
							|  |  |  |     ExtractorError, | 
					
						
							|  |  |  |     int_or_none, | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |     url_basename, | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EaglePlatformIE(InfoExtractor): | 
					
						
							|  |  |  |     _VALID_URL = r'''(?x)
 | 
					
						
							|  |  |  |                     (?: | 
					
						
							|  |  |  |                         eagleplatform:(?P<custom_host>[^/]+):| | 
					
						
							|  |  |  |                         https?://(?P<host>.+?\.media\.eagleplatform\.com)/index/player\?.*\brecord_id= | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                     (?P<id>\d+) | 
					
						
							|  |  |  |                 '''
 | 
					
						
							|  |  |  |     _TESTS = [{ | 
					
						
							|  |  |  |         # http://lenta.ru/news/2015/03/06/navalny/ | 
					
						
							|  |  |  |         'url': 'http://lentaru.media.eagleplatform.com/index/player?player=new&record_id=227304&player_template_id=5201', | 
					
						
							| 
									
										
										
										
											2016-04-25 22:48:17 +08:00
										 |  |  |         # Not checking MD5 as sometimes the direct HTTP link results in 404 and HLS is used | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '227304', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'Навальный вышел на свободу', | 
					
						
							|  |  |  |             'description': 'md5:d97861ac9ae77377f3f20eaf9d04b4f5', | 
					
						
							|  |  |  |             'thumbnail': 're:^https?://.*\.jpg$', | 
					
						
							|  |  |  |             'duration': 87, | 
					
						
							|  |  |  |             'view_count': int, | 
					
						
							|  |  |  |             'age_limit': 0, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     }, { | 
					
						
							|  |  |  |         # http://muz-tv.ru/play/7129/ | 
					
						
							|  |  |  |         # http://media.clipyou.ru/index/player?record_id=12820&width=730&height=415&autoplay=true | 
					
						
							|  |  |  |         'url': 'eagleplatform:media.clipyou.ru:12820', | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |         'md5': '358597369cf8ba56675c1df15e7af624', | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '12820', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': "'O Sole Mio", | 
					
						
							|  |  |  |             'thumbnail': 're:^https?://.*\.jpg$', | 
					
						
							|  |  |  |             'duration': 216, | 
					
						
							|  |  |  |             'view_count': int, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2015-04-04 23:36:45 +06:00
										 |  |  |         'skip': 'Georestricted', | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  |     }] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-27 01:12:46 +06:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def _handle_error(response): | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  |         status = int_or_none(response.get('status', 200)) | 
					
						
							|  |  |  |         if status != 200: | 
					
						
							|  |  |  |             raise ExtractorError(' '.join(response['errors']), expected=True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 17:37:30 +01:00
										 |  |  |     def _download_json(self, url_or_request, video_id, note='Downloading JSON metadata'): | 
					
						
							| 
									
										
										
										
											2016-04-16 16:47:16 +08:00
										 |  |  |         try: | 
					
						
							|  |  |  |             response = super(EaglePlatformIE, self)._download_json(url_or_request, video_id, note) | 
					
						
							|  |  |  |         except ExtractorError as ee: | 
					
						
							|  |  |  |             if isinstance(ee.cause, compat_HTTPError): | 
					
						
							|  |  |  |                 response = self._parse_json(ee.cause.read().decode('utf-8'), video_id) | 
					
						
							|  |  |  |                 self._handle_error(response) | 
					
						
							|  |  |  |             raise | 
					
						
							| 
									
										
										
										
											2015-09-26 17:37:30 +01:00
										 |  |  |         return response | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _get_video_url(self, url_or_request, video_id, note='Downloading JSON metadata'): | 
					
						
							|  |  |  |         return self._download_json(url_or_request, video_id, note)['data'][0] | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         mobj = re.match(self._VALID_URL, url) | 
					
						
							|  |  |  |         host, video_id = mobj.group('custom_host') or mobj.group('host'), mobj.group('id') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         player_data = self._download_json( | 
					
						
							|  |  |  |             'http://%s/api/player_data?id=%s' % (host, video_id), video_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         media = player_data['data']['playlist']['viewports'][0]['medialist'][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         title = media['title'] | 
					
						
							|  |  |  |         description = media.get('description') | 
					
						
							| 
									
										
										
										
											2015-09-27 01:17:44 +06:00
										 |  |  |         thumbnail = self._proto_relative_url(media.get('snapshot'), 'http:') | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  |         duration = int_or_none(media.get('duration')) | 
					
						
							|  |  |  |         view_count = int_or_none(media.get('views')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         age_restriction = media.get('age_restriction') | 
					
						
							|  |  |  |         age_limit = None | 
					
						
							|  |  |  |         if age_restriction: | 
					
						
							|  |  |  |             age_limit = 0 if age_restriction == 'allow_all' else 18 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 18:53:57 +01:00
										 |  |  |         secure_m3u8 = self._proto_relative_url(media['sources']['secure_m3u8']['auto'], 'http:') | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |         formats = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-26 15:30:02 +01:00
										 |  |  |         m3u8_url = self._get_video_url(secure_m3u8, video_id, 'Downloading m3u8 JSON') | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |         m3u8_formats = self._extract_m3u8_formats( | 
					
						
							| 
									
										
										
										
											2015-09-26 15:30:02 +01:00
										 |  |  |             m3u8_url, video_id, | 
					
						
							| 
									
										
										
										
											2015-10-18 20:24:33 +06:00
										 |  |  |             'mp4', entry_protocol='m3u8_native', m3u8_id='hls') | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |         formats.extend(m3u8_formats) | 
					
						
							| 
									
										
										
										
											2015-09-26 15:30:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         mp4_url = self._get_video_url( | 
					
						
							| 
									
										
										
										
											2015-09-27 01:10:39 +06:00
										 |  |  |             # Secure mp4 URL is constructed according to Player.prototype.mp4 from | 
					
						
							|  |  |  |             # http://lentaru.media.eagleplatform.com/player/player.js | 
					
						
							|  |  |  |             re.sub(r'm3u8|hlsvod|hls|f4m', 'mp4', secure_m3u8), | 
					
						
							| 
									
										
										
										
											2015-09-26 15:30:02 +01:00
										 |  |  |             video_id, 'Downloading mp4 JSON') | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |         mp4_url_basename = url_basename(mp4_url) | 
					
						
							|  |  |  |         for m3u8_format in m3u8_formats: | 
					
						
							|  |  |  |             mobj = re.search('/([^/]+)/index\.m3u8', m3u8_format['url']) | 
					
						
							|  |  |  |             if mobj: | 
					
						
							|  |  |  |                 http_format = m3u8_format.copy() | 
					
						
							| 
									
										
										
										
											2016-04-25 22:48:17 +08:00
										 |  |  |                 video_url = mp4_url.replace(mp4_url_basename, mobj.group(1)) | 
					
						
							|  |  |  |                 if not self._is_valid_url(video_url, video_id): | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |                 http_format.update({ | 
					
						
							| 
									
										
										
										
											2016-04-25 22:48:17 +08:00
										 |  |  |                     'url': video_url, | 
					
						
							| 
									
										
										
										
											2016-04-22 14:32:38 +01:00
										 |  |  |                     'format_id': m3u8_format['format_id'].replace('hls', 'http'), | 
					
						
							|  |  |  |                     'protocol': 'http', | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |                 formats.append(http_format) | 
					
						
							| 
									
										
										
										
											2015-09-26 15:30:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-07 22:16:23 +06:00
										 |  |  |         self._sort_formats(formats) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             'id': video_id, | 
					
						
							|  |  |  |             'title': title, | 
					
						
							|  |  |  |             'description': description, | 
					
						
							|  |  |  |             'thumbnail': thumbnail, | 
					
						
							|  |  |  |             'duration': duration, | 
					
						
							|  |  |  |             'view_count': view_count, | 
					
						
							|  |  |  |             'age_limit': age_limit, | 
					
						
							|  |  |  |             'formats': formats, | 
					
						
							|  |  |  |         } |