imggaming.py (5111B)
1 # coding: utf-8 2 from __future__ import unicode_literals 3 4 import json 5 import re 6 7 from .common import InfoExtractor 8 from ..compat import compat_HTTPError 9 from ..utils import ( 10 ExtractorError, 11 int_or_none, 12 str_or_none, 13 try_get, 14 ) 15 16 17 class ImgGamingBaseIE(InfoExtractor): 18 _API_BASE = 'https://dce-frontoffice.imggaming.com/api/v2/' 19 _API_KEY = '857a1e5d-e35e-4fdf-805b-a87b6f8364bf' 20 _HEADERS = None 21 _MANIFEST_HEADERS = {'Accept-Encoding': 'identity'} 22 _REALM = None 23 _VALID_URL_TEMPL = r'https?://(?P<domain>%s)/(?P<type>live|playlist|video)/(?P<id>\d+)(?:\?.*?\bplaylistId=(?P<playlist_id>\d+))?' 24 25 def _real_initialize(self): 26 self._HEADERS = { 27 'Realm': 'dce.' + self._REALM, 28 'x-api-key': self._API_KEY, 29 } 30 31 email, password = self._get_login_info() 32 if email is None: 33 self.raise_login_required() 34 35 p_headers = self._HEADERS.copy() 36 p_headers['Content-Type'] = 'application/json' 37 self._HEADERS['Authorization'] = 'Bearer ' + self._download_json( 38 self._API_BASE + 'login', 39 None, 'Logging in', data=json.dumps({ 40 'id': email, 41 'secret': password, 42 }).encode(), headers=p_headers)['authorisationToken'] 43 44 def _call_api(self, path, media_id): 45 return self._download_json( 46 self._API_BASE + path + media_id, media_id, headers=self._HEADERS) 47 48 def _extract_dve_api_url(self, media_id, media_type): 49 stream_path = 'stream' 50 if media_type == 'video': 51 stream_path += '/vod/' 52 else: 53 stream_path += '?eventId=' 54 try: 55 return self._call_api( 56 stream_path, media_id)['playerUrlCallback'] 57 except ExtractorError as e: 58 if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403: 59 raise ExtractorError( 60 self._parse_json(e.cause.read().decode(), media_id)['messages'][0], 61 expected=True) 62 raise 63 64 def _real_extract(self, url): 65 domain, media_type, media_id, playlist_id = re.match(self._VALID_URL, url).groups() 66 67 if playlist_id: 68 if self._downloader.params.get('noplaylist'): 69 self.to_screen('Downloading just video %s because of --no-playlist' % media_id) 70 else: 71 self.to_screen('Downloading playlist %s - add --no-playlist to just download video' % playlist_id) 72 media_type, media_id = 'playlist', playlist_id 73 74 if media_type == 'playlist': 75 playlist = self._call_api('vod/playlist/', media_id) 76 entries = [] 77 for video in try_get(playlist, lambda x: x['videos']['vods']) or []: 78 video_id = str_or_none(video.get('id')) 79 if not video_id: 80 continue 81 entries.append(self.url_result( 82 'https://%s/video/%s' % (domain, video_id), 83 self.ie_key(), video_id)) 84 return self.playlist_result( 85 entries, media_id, playlist.get('title'), 86 playlist.get('description')) 87 88 dve_api_url = self._extract_dve_api_url(media_id, media_type) 89 video_data = self._download_json(dve_api_url, media_id) 90 is_live = media_type == 'live' 91 if is_live: 92 title = self._live_title(self._call_api('event/', media_id)['title']) 93 else: 94 title = video_data['name'] 95 96 formats = [] 97 for proto in ('hls', 'dash'): 98 media_url = video_data.get(proto + 'Url') or try_get(video_data, lambda x: x[proto]['url']) 99 if not media_url: 100 continue 101 if proto == 'hls': 102 m3u8_formats = self._extract_m3u8_formats( 103 media_url, media_id, 'mp4', 'm3u8' if is_live else 'm3u8_native', 104 m3u8_id='hls', fatal=False, headers=self._MANIFEST_HEADERS) 105 for f in m3u8_formats: 106 f.setdefault('http_headers', {}).update(self._MANIFEST_HEADERS) 107 formats.append(f) 108 else: 109 formats.extend(self._extract_mpd_formats( 110 media_url, media_id, mpd_id='dash', fatal=False, 111 headers=self._MANIFEST_HEADERS)) 112 self._sort_formats(formats) 113 114 subtitles = {} 115 for subtitle in video_data.get('subtitles', []): 116 subtitle_url = subtitle.get('url') 117 if not subtitle_url: 118 continue 119 subtitles.setdefault(subtitle.get('lang', 'en_US'), []).append({ 120 'url': subtitle_url, 121 }) 122 123 return { 124 'id': media_id, 125 'title': title, 126 'formats': formats, 127 'thumbnail': video_data.get('thumbnailUrl'), 128 'description': video_data.get('description'), 129 'duration': int_or_none(video_data.get('duration')), 130 'tags': video_data.get('tags'), 131 'is_live': is_live, 132 'subtitles': subtitles, 133 }