youtube-dl

Another place where youtube-dl lives on
git clone git://git.oshgnacknak.de/youtube-dl.git
Log | Files | Refs | README | LICENSE

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         }