| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | # encoding: utf-8 | 
					
						
							|  |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import base64 | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  | import re | 
					
						
							|  |  |  | import time | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | from .common import InfoExtractor | 
					
						
							|  |  |  | from ..utils import ( | 
					
						
							| 
									
										
										
										
											2015-04-09 14:01:33 +02:00
										 |  |  |     ExtractorError, | 
					
						
							| 
									
										
										
										
											2015-02-27 12:24:51 +01:00
										 |  |  |     float_or_none, | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |     remove_end, | 
					
						
							| 
									
										
										
										
											2015-11-21 22:18:17 +06:00
										 |  |  |     sanitized_Request, | 
					
						
							| 
									
										
										
										
											2015-04-04 13:11:55 +02:00
										 |  |  |     std_headers, | 
					
						
							| 
									
										
										
										
											2015-02-27 12:24:51 +01:00
										 |  |  |     struct_unpack, | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  | def _decrypt_url(png): | 
					
						
							| 
									
										
										
										
											2015-05-22 00:09:15 +06:00
										 |  |  |     encrypted_data = base64.b64decode(png.encode('utf-8')) | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |     text_index = encrypted_data.find(b'tEXt') | 
					
						
							|  |  |  |     text_chunk = encrypted_data[text_index - 4:] | 
					
						
							|  |  |  |     length = struct_unpack('!I', text_chunk[:4])[0] | 
					
						
							|  |  |  |     # Use bytearray to get integers when iterating in both python 2.x and 3.x | 
					
						
							|  |  |  |     data = bytearray(text_chunk[8:8 + length]) | 
					
						
							|  |  |  |     data = [chr(b) for b in data if b != 0] | 
					
						
							|  |  |  |     hash_index = data.index('#') | 
					
						
							|  |  |  |     alphabet_data = data[:hash_index] | 
					
						
							|  |  |  |     url_data = data[hash_index + 1:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     alphabet = [] | 
					
						
							|  |  |  |     e = 0 | 
					
						
							|  |  |  |     d = 0 | 
					
						
							|  |  |  |     for l in alphabet_data: | 
					
						
							|  |  |  |         if d == 0: | 
					
						
							|  |  |  |             alphabet.append(l) | 
					
						
							|  |  |  |             d = e = (e + 1) % 4 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             d -= 1 | 
					
						
							|  |  |  |     url = '' | 
					
						
							|  |  |  |     f = 0 | 
					
						
							|  |  |  |     e = 3 | 
					
						
							|  |  |  |     b = 1 | 
					
						
							|  |  |  |     for letter in url_data: | 
					
						
							|  |  |  |         if f == 0: | 
					
						
							|  |  |  |             l = int(letter) * 10 | 
					
						
							|  |  |  |             f = 1 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if e == 0: | 
					
						
							|  |  |  |                 l += int(letter) | 
					
						
							|  |  |  |                 url += alphabet[l] | 
					
						
							|  |  |  |                 e = (b + 3) % 4 | 
					
						
							|  |  |  |                 f = 0 | 
					
						
							|  |  |  |                 b += 1 | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 e -= 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return url | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | class RTVEALaCartaIE(InfoExtractor): | 
					
						
							|  |  |  |     IE_NAME = 'rtve.es:alacarta' | 
					
						
							|  |  |  |     IE_DESC = 'RTVE a la carta' | 
					
						
							| 
									
										
										
										
											2015-01-30 23:12:53 +01:00
										 |  |  |     _VALID_URL = r'http://www\.rtve\.es/(m/)?alacarta/videos/[^/]+/[^/]+/(?P<id>\d+)' | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |     _TESTS = [{ | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  |         'url': 'http://www.rtve.es/alacarta/videos/balonmano/o-swiss-cup-masculina-final-espana-suecia/2491869/', | 
					
						
							| 
									
										
										
										
											2014-07-21 12:14:06 +02:00
										 |  |  |         'md5': '1d49b7e1ca7a7502c56a4bf1b60f1b43', | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '2491869', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'Balonmano - Swiss Cup masculina. Final: España-Suecia', | 
					
						
							| 
									
										
										
										
											2015-02-27 12:24:51 +01:00
										 |  |  |             'duration': 5024.566, | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  |         }, | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |     }, { | 
					
						
							|  |  |  |         'note': 'Live stream', | 
					
						
							|  |  |  |         'url': 'http://www.rtve.es/alacarta/videos/television/24h-live/1694255/', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '1694255', | 
					
						
							|  |  |  |             'ext': 'flv', | 
					
						
							|  |  |  |             'title': 'TODO', | 
					
						
							| 
									
										
										
										
											2015-01-30 23:05:06 +01:00
										 |  |  |         }, | 
					
						
							|  |  |  |         'skip': 'The f4m manifest can\'t be used yet', | 
					
						
							| 
									
										
										
										
											2015-01-30 23:12:53 +01:00
										 |  |  |     }, { | 
					
						
							|  |  |  |         'url': 'http://www.rtve.es/m/alacarta/videos/cuentame-como-paso/cuentame-como-paso-t16-ultimo-minuto-nuestra-vida-capitulo-276/2969138/?media=tve', | 
					
						
							|  |  |  |         'only_matching': True, | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |     }] | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-04 13:11:55 +02:00
										 |  |  |     def _real_initialize(self): | 
					
						
							|  |  |  |         user_agent_b64 = base64.b64encode(std_headers['User-Agent'].encode('utf-8')).decode('utf-8') | 
					
						
							|  |  |  |         manager_info = self._download_json( | 
					
						
							|  |  |  |             'http://www.rtve.es/odin/loki/' + user_agent_b64, | 
					
						
							|  |  |  |             None, 'Fetching manager info') | 
					
						
							|  |  |  |         self._manager = manager_info['manager'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         mobj = re.match(self._VALID_URL, url) | 
					
						
							|  |  |  |         video_id = mobj.group('id') | 
					
						
							|  |  |  |         info = self._download_json( | 
					
						
							|  |  |  |             'http://www.rtve.es/api/videos/%s/config/alacarta_videos.json' % video_id, | 
					
						
							|  |  |  |             video_id)['page']['items'][0] | 
					
						
							| 
									
										
										
										
											2015-04-09 14:01:33 +02:00
										 |  |  |         if info['state'] == 'DESPU': | 
					
						
							|  |  |  |             raise ExtractorError('The video is no longer available', expected=True) | 
					
						
							| 
									
										
										
										
											2015-04-04 13:11:55 +02:00
										 |  |  |         png_url = 'http://www.rtve.es/ztnr/movil/thumbnail/%s/videos/%s.png' % (self._manager, video_id) | 
					
						
							| 
									
										
										
										
											2015-11-21 22:18:17 +06:00
										 |  |  |         png_request = sanitized_Request(png_url) | 
					
						
							| 
									
										
										
										
											2015-09-01 20:30:58 +02:00
										 |  |  |         png_request.add_header('Referer', url) | 
					
						
							|  |  |  |         png = self._download_webpage(png_request, video_id, 'Downloading url information') | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |         video_url = _decrypt_url(png) | 
					
						
							| 
									
										
										
										
											2015-01-30 23:05:06 +01:00
										 |  |  |         if not video_url.endswith('.f4m'): | 
					
						
							| 
									
										
										
										
											2015-11-17 21:11:42 +06:00
										 |  |  |             video_url = video_url.replace( | 
					
						
							| 
									
										
										
										
											2015-01-30 23:05:06 +01:00
										 |  |  |                 'resources/', 'auth/resources/' | 
					
						
							|  |  |  |             ).replace('.net.rtve', '.multimedia.cdn.rtve') | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 21:52:07 +01:00
										 |  |  |         subtitles = None | 
					
						
							|  |  |  |         if info.get('sbtFile') is not None: | 
					
						
							|  |  |  |             subtitles = self.extract_subtitles(video_id, info['sbtFile']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  |         return { | 
					
						
							|  |  |  |             'id': video_id, | 
					
						
							|  |  |  |             'title': info['title'], | 
					
						
							|  |  |  |             'url': video_url, | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |             'thumbnail': info.get('image'), | 
					
						
							|  |  |  |             'page_url': url, | 
					
						
							| 
									
										
										
										
											2015-02-23 21:52:07 +01:00
										 |  |  |             'subtitles': subtitles, | 
					
						
							| 
									
										
										
										
											2015-02-27 12:24:51 +01:00
										 |  |  |             'duration': float_or_none(info.get('duration'), scale=1000), | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 21:52:07 +01:00
										 |  |  |     def _get_subtitles(self, video_id, sub_file): | 
					
						
							|  |  |  |         subs = self._download_json( | 
					
						
							|  |  |  |             sub_file + '.json', video_id, | 
					
						
							|  |  |  |             'Downloading subtitles info')['page']['items'] | 
					
						
							| 
									
										
										
										
											2015-02-24 11:37:27 +01:00
										 |  |  |         return dict( | 
					
						
							|  |  |  |             (s['lang'], [{'ext': 'vtt', 'url': s['src']}]) | 
					
						
							| 
									
										
										
										
											2015-02-23 21:52:07 +01:00
										 |  |  |             for s in subs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-15 22:17:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-15 21:45:14 +01:00
										 |  |  | class RTVEInfantilIE(InfoExtractor): | 
					
						
							| 
									
										
										
										
											2015-03-15 22:17:40 +01:00
										 |  |  |     IE_NAME = 'rtve.es:infantil' | 
					
						
							|  |  |  |     IE_DESC = 'RTVE infantil' | 
					
						
							|  |  |  |     _VALID_URL = r'https?://(?:www\.)?rtve\.es/infantil/serie/(?P<show>[^/]*)/video/(?P<short_title>[^/]*)/(?P<id>[0-9]+)/' | 
					
						
							| 
									
										
										
										
											2015-03-15 21:45:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     _TESTS = [{ | 
					
						
							|  |  |  |         'url': 'http://www.rtve.es/infantil/serie/cleo/video/maneras-vivir/3040283/', | 
					
						
							|  |  |  |         'md5': '915319587b33720b8e0357caaa6617e6', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '3040283', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'Maneras de vivir', | 
					
						
							|  |  |  |             'thumbnail': 'http://www.rtve.es/resources/jpg/6/5/1426182947956.JPG', | 
					
						
							|  |  |  |             'duration': 357.958, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2015-03-15 22:17:40 +01:00
										 |  |  |     }] | 
					
						
							| 
									
										
										
										
											2015-03-15 21:45:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							| 
									
										
										
										
											2015-03-15 22:17:40 +01:00
										 |  |  |         video_id = self._match_id(url) | 
					
						
							| 
									
										
										
										
											2015-03-15 21:45:14 +01:00
										 |  |  |         info = self._download_json( | 
					
						
							|  |  |  |             'http://www.rtve.es/api/videos/%s/config/alacarta_videos.json' % video_id, | 
					
						
							|  |  |  |             video_id)['page']['items'][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         webpage = self._download_webpage(url, video_id) | 
					
						
							|  |  |  |         vidplayer_id = self._search_regex( | 
					
						
							|  |  |  |             r' id="vidplayer([0-9]+)"', webpage, 'internal video ID') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         png_url = 'http://www.rtve.es/ztnr/movil/thumbnail/default/videos/%s.png' % vidplayer_id | 
					
						
							|  |  |  |         png = self._download_webpage(png_url, video_id, 'Downloading url information') | 
					
						
							|  |  |  |         video_url = _decrypt_url(png) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             'id': video_id, | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': info['title'], | 
					
						
							|  |  |  |             'url': video_url, | 
					
						
							|  |  |  |             'thumbnail': info.get('image'), | 
					
						
							|  |  |  |             'duration': float_or_none(info.get('duration'), scale=1000), | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  | class RTVELiveIE(InfoExtractor): | 
					
						
							|  |  |  |     IE_NAME = 'rtve.es:live' | 
					
						
							|  |  |  |     IE_DESC = 'RTVE.es live streams' | 
					
						
							| 
									
										
										
										
											2014-08-22 18:47:49 +02:00
										 |  |  |     _VALID_URL = r'http://www\.rtve\.es/(?:deportes/directo|noticias|television)/(?P<id>[a-zA-Z0-9-]+)' | 
					
						
							| 
									
										
										
										
											2014-08-22 18:40:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     _TESTS = [{ | 
					
						
							|  |  |  |         'url': 'http://www.rtve.es/noticias/directo-la-1/', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': 'directo-la-1', | 
					
						
							|  |  |  |             'ext': 'flv', | 
					
						
							|  |  |  |             'title': 're:^La 1 de TVE [0-9]{4}-[0-9]{2}-[0-9]{2}Z[0-9]{6}$', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'params': { | 
					
						
							|  |  |  |             'skip_download': 'live stream', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         mobj = re.match(self._VALID_URL, url) | 
					
						
							|  |  |  |         start_time = time.gmtime() | 
					
						
							|  |  |  |         video_id = mobj.group('id') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         webpage = self._download_webpage(url, video_id) | 
					
						
							|  |  |  |         player_url = self._search_regex( | 
					
						
							|  |  |  |             r'<param name="movie" value="([^"]+)"/>', webpage, 'player URL') | 
					
						
							|  |  |  |         title = remove_end(self._og_search_title(webpage), ' en directo') | 
					
						
							|  |  |  |         title += ' ' + time.strftime('%Y-%m-%dZ%H%M%S', start_time) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vidplayer_id = self._search_regex( | 
					
						
							|  |  |  |             r' id="vidplayer([0-9]+)"', webpage, 'internal video ID') | 
					
						
							|  |  |  |         png_url = 'http://www.rtve.es/ztnr/movil/thumbnail/default/videos/%s.png' % vidplayer_id | 
					
						
							|  |  |  |         png = self._download_webpage(png_url, video_id, 'Downloading url information') | 
					
						
							|  |  |  |         video_url = _decrypt_url(png) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             'id': video_id, | 
					
						
							|  |  |  |             'ext': 'flv', | 
					
						
							|  |  |  |             'title': title, | 
					
						
							|  |  |  |             'url': video_url, | 
					
						
							|  |  |  |             'app': 'rtve-live-live?ovpfv=2.1.2', | 
					
						
							|  |  |  |             'player_url': player_url, | 
					
						
							|  |  |  |             'rtmp_live': True, | 
					
						
							| 
									
										
										
										
											2014-04-07 16:56:15 +02:00
										 |  |  |         } |