| 
									
										
										
										
											2017-07-30 19:09:44 +07:00
										 |  |  | # coding: utf-8 | 
					
						
							|  |  |  | from __future__ import unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .common import InfoExtractor | 
					
						
							|  |  |  | from ..compat import compat_str | 
					
						
							|  |  |  | from ..utils import ( | 
					
						
							|  |  |  |     int_or_none, | 
					
						
							|  |  |  |     js_to_json, | 
					
						
							|  |  |  |     strip_or_none, | 
					
						
							|  |  |  |     try_get, | 
					
						
							| 
									
										
										
										
											2018-07-30 23:28:44 +07:00
										 |  |  |     unescapeHTML, | 
					
						
							| 
									
										
										
										
											2017-07-30 19:09:44 +07:00
										 |  |  |     unified_timestamp, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WatchBoxIE(InfoExtractor): | 
					
						
							|  |  |  |     _VALID_URL = r'https?://(?:www\.)?watchbox\.de/(?P<kind>serien|filme)/(?:[^/]+/)*[^/]+-(?P<id>\d+)' | 
					
						
							|  |  |  |     _TESTS = [{ | 
					
						
							|  |  |  |         # film | 
					
						
							|  |  |  |         'url': 'https://www.watchbox.de/filme/free-jimmy-12325.html', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '341368', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'Free Jimmy', | 
					
						
							|  |  |  |             'description': 'md5:bcd8bafbbf9dc0ef98063d344d7cc5f6', | 
					
						
							|  |  |  |             'thumbnail': r're:^https?://.*\.jpg$', | 
					
						
							|  |  |  |             'duration': 4890, | 
					
						
							|  |  |  |             'age_limit': 16, | 
					
						
							|  |  |  |             'release_year': 2009, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'params': { | 
					
						
							|  |  |  |             'format': 'bestvideo', | 
					
						
							|  |  |  |             'skip_download': True, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'expected_warnings': ['Failed to download m3u8 information'], | 
					
						
							|  |  |  |     }, { | 
					
						
							|  |  |  |         # episode | 
					
						
							|  |  |  |         'url': 'https://www.watchbox.de/serien/ugly-americans-12231/staffel-1/date-in-der-hoelle-328286.html', | 
					
						
							|  |  |  |         'info_dict': { | 
					
						
							|  |  |  |             'id': '328286', | 
					
						
							|  |  |  |             'ext': 'mp4', | 
					
						
							|  |  |  |             'title': 'S01 E01 - Date in der Hölle', | 
					
						
							|  |  |  |             'description': 'md5:2f31c74a8186899f33cb5114491dae2b', | 
					
						
							|  |  |  |             'thumbnail': r're:^https?://.*\.jpg$', | 
					
						
							|  |  |  |             'duration': 1291, | 
					
						
							|  |  |  |             'age_limit': 12, | 
					
						
							|  |  |  |             'release_year': 2010, | 
					
						
							|  |  |  |             'series': 'Ugly Americans', | 
					
						
							|  |  |  |             'season_number': 1, | 
					
						
							|  |  |  |             'episode': 'Date in der Hölle', | 
					
						
							|  |  |  |             'episode_number': 1, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'params': { | 
					
						
							|  |  |  |             'format': 'bestvideo', | 
					
						
							|  |  |  |             'skip_download': True, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         'expected_warnings': ['Failed to download m3u8 information'], | 
					
						
							|  |  |  |     }, { | 
					
						
							|  |  |  |         'url': 'https://www.watchbox.de/serien/ugly-americans-12231/staffel-2/der-ring-des-powers-328270', | 
					
						
							|  |  |  |         'only_matching': True, | 
					
						
							|  |  |  |     }] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _real_extract(self, url): | 
					
						
							|  |  |  |         mobj = re.match(self._VALID_URL, url) | 
					
						
							|  |  |  |         kind, video_id = mobj.group('kind', 'id') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         webpage = self._download_webpage(url, video_id) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 23:28:44 +07:00
										 |  |  |         player_config = self._parse_json( | 
					
						
							| 
									
										
										
										
											2017-07-30 19:09:44 +07:00
										 |  |  |             self._search_regex( | 
					
						
							| 
									
										
										
										
											2018-07-30 23:28:44 +07:00
										 |  |  |                 r'data-player-conf=(["\'])(?P<data>{.+?})\1', webpage, | 
					
						
							|  |  |  |                 'player config', default='{}', group='data'), | 
					
						
							|  |  |  |             video_id, transform_source=unescapeHTML, fatal=False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not player_config: | 
					
						
							|  |  |  |             player_config = self._parse_json( | 
					
						
							|  |  |  |                 self._search_regex( | 
					
						
							|  |  |  |                     r'playerConf\s*=\s*({.+?})\s*;', webpage, 'player config', | 
					
						
							|  |  |  |                     default='{}'), | 
					
						
							|  |  |  |                 video_id, transform_source=js_to_json, fatal=False) or {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         source = player_config.get('source') or {} | 
					
						
							| 
									
										
										
										
											2017-07-30 19:09:44 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         video_id = compat_str(source.get('videoId') or video_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         devapi = self._download_json( | 
					
						
							|  |  |  |             'http://api.watchbox.de/devapi/id/%s' % video_id, video_id, query={ | 
					
						
							|  |  |  |                 'format': 'json', | 
					
						
							|  |  |  |                 'apikey': 'hbbtv', | 
					
						
							|  |  |  |             }, fatal=False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         item = try_get(devapi, lambda x: x['items'][0], dict) or {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         title = item.get('title') or try_get( | 
					
						
							|  |  |  |             item, lambda x: x['movie']['headline_movie'], | 
					
						
							|  |  |  |             compat_str) or source['title'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         formats = [] | 
					
						
							|  |  |  |         hls_url = item.get('media_videourl_hls') or source.get('hls') | 
					
						
							|  |  |  |         if hls_url: | 
					
						
							|  |  |  |             formats.extend(self._extract_m3u8_formats( | 
					
						
							|  |  |  |                 hls_url, video_id, 'mp4', entry_protocol='m3u8_native', | 
					
						
							|  |  |  |                 m3u8_id='hls', fatal=False)) | 
					
						
							|  |  |  |         dash_url = item.get('media_videourl_wv') or source.get('dash') | 
					
						
							|  |  |  |         if dash_url: | 
					
						
							|  |  |  |             formats.extend(self._extract_mpd_formats( | 
					
						
							|  |  |  |                 dash_url, video_id, mpd_id='dash', fatal=False)) | 
					
						
							|  |  |  |         mp4_url = item.get('media_videourl') | 
					
						
							|  |  |  |         if mp4_url: | 
					
						
							|  |  |  |             formats.append({ | 
					
						
							|  |  |  |                 'url': mp4_url, | 
					
						
							|  |  |  |                 'format_id': 'mp4', | 
					
						
							|  |  |  |                 'width': int_or_none(item.get('width')), | 
					
						
							|  |  |  |                 'height': int_or_none(item.get('height')), | 
					
						
							|  |  |  |                 'tbr': int_or_none(item.get('bitrate')), | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         self._sort_formats(formats) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         description = strip_or_none(item.get('descr')) | 
					
						
							|  |  |  |         thumbnail = item.get('media_content_thumbnail_large') or source.get('poster') or item.get('media_thumbnail') | 
					
						
							|  |  |  |         duration = int_or_none(item.get('media_length') or source.get('length')) | 
					
						
							|  |  |  |         timestamp = unified_timestamp(item.get('pubDate')) | 
					
						
							|  |  |  |         view_count = int_or_none(item.get('media_views')) | 
					
						
							|  |  |  |         age_limit = int_or_none(try_get(item, lambda x: x['movie']['fsk'])) | 
					
						
							|  |  |  |         release_year = int_or_none(try_get(item, lambda x: x['movie']['rel_year'])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         info = { | 
					
						
							|  |  |  |             'id': video_id, | 
					
						
							|  |  |  |             'title': title, | 
					
						
							|  |  |  |             'description': description, | 
					
						
							|  |  |  |             'thumbnail': thumbnail, | 
					
						
							|  |  |  |             'duration': duration, | 
					
						
							|  |  |  |             'timestamp': timestamp, | 
					
						
							|  |  |  |             'view_count': view_count, | 
					
						
							|  |  |  |             'age_limit': age_limit, | 
					
						
							|  |  |  |             'release_year': release_year, | 
					
						
							|  |  |  |             'formats': formats, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if kind.lower() == 'serien': | 
					
						
							|  |  |  |             series = try_get( | 
					
						
							|  |  |  |                 item, lambda x: x['special']['title'], | 
					
						
							|  |  |  |                 compat_str) or source.get('format') | 
					
						
							|  |  |  |             season_number = int_or_none(self._search_regex( | 
					
						
							|  |  |  |                 r'^S(\d{1,2})\s*E\d{1,2}', title, 'season number', | 
					
						
							|  |  |  |                 default=None) or self._search_regex( | 
					
						
							|  |  |  |                     r'/staffel-(\d+)/', url, 'season number', default=None)) | 
					
						
							|  |  |  |             episode = source.get('title') | 
					
						
							|  |  |  |             episode_number = int_or_none(self._search_regex( | 
					
						
							|  |  |  |                 r'^S\d{1,2}\s*E(\d{1,2})', title, 'episode number', | 
					
						
							|  |  |  |                 default=None)) | 
					
						
							|  |  |  |             info.update({ | 
					
						
							|  |  |  |                 'series': series, | 
					
						
							|  |  |  |                 'season_number': season_number, | 
					
						
							|  |  |  |                 'episode': episode, | 
					
						
							|  |  |  |                 'episode_number': episode_number, | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return info |