96fddeac0321f117caafd7785f4c1f53be75c361
[youtube-dl] / youtube_dl / extractor / imggaming.py
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     try_get,
13 )
14
15
16 class ImgGamingBaseIE(InfoExtractor):
17     _API_BASE = 'https://dce-frontoffice.imggaming.com/api/v2/'
18     _API_KEY = '857a1e5d-e35e-4fdf-805b-a87b6f8364bf'
19     _HEADERS = None
20     _LOGIN_REQUIRED = True
21     _LOGIN_SUFFIX = ''
22     _MANIFEST_HEADERS = {'Accept-Encoding': 'identity'}
23     _REALM = None
24     _TOKEN = None
25     _VALID_URL_TEMPL = r'https?://%s/(?P<type>live|video)/(?P<id>\d+)'
26
27     def _real_initialize(self):
28         if not self._LOGIN_REQUIRED:
29             return
30
31         self._HEADERS = {
32             'Realm': 'dce.' + self._REALM,
33             'x-api-key': self._API_KEY,
34         }
35
36         email, password = self._get_login_info()
37         if email is None:
38             self.raise_login_required()
39
40         p_headers = self._HEADERS.copy()
41         p_headers['Content-Type'] = 'application/json'
42         self._HEADERS['Authorization'] = 'Bearer ' + self._download_json(
43             self._API_BASE + 'login' + self._LOGIN_SUFFIX,
44             None, 'Logging in', data=json.dumps({
45                 'id': email,
46                 'secret': password,
47             }).encode(), headers=p_headers)['authorisationToken']
48
49     def _extract_media_id(self, url, display_id):
50         return display_id
51
52     def _extract_dve_api_url(self, media_id, media_type):
53         url = self._API_BASE + 'stream'
54         if media_type == 'video':
55             url += '/vod/' + media_id
56         else:
57             url += '?eventId=' + media_id
58         try:
59             return self._download_json(
60                 url, media_id, headers=self._HEADERS)['playerUrlCallback']
61         except ExtractorError as e:
62             if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
63                 raise ExtractorError(
64                     self._parse_json(e.cause.read().decode(), media_id)['messages'][0],
65                     expected=True)
66             raise
67
68     def _real_extract(self, url):
69         media_type, display_id = re.match(self._VALID_URL, url).groups()
70         media_id = self._extract_media_id(url, display_id)
71         dve_api_url = self._extract_dve_api_url(media_id, media_type)
72         video_data = self._download_json(dve_api_url, media_id)
73         is_live = media_type == 'live'
74         if is_live:
75             title = self._live_title(self._download_json(
76                 self._API_BASE + 'event/' + media_id,
77                 media_id, headers=self._HEADERS)['title'])
78         else:
79             title = video_data['name']
80
81         formats = []
82         for proto in ('hls', 'dash'):
83             media_url = video_data.get(proto + 'Url') or try_get(video_data, lambda x: x[proto]['url'])
84             if not media_url:
85                 continue
86             if proto == 'hls':
87                 m3u8_formats = self._extract_m3u8_formats(
88                     media_url, media_id, 'mp4', 'm3u8' if is_live else 'm3u8_native',
89                     m3u8_id='hls', fatal=False, headers=self._MANIFEST_HEADERS)
90                 for f in m3u8_formats:
91                     f.setdefault('http_headers', {}).update(self._MANIFEST_HEADERS)
92                     formats.append(f)
93             else:
94                 formats.extend(self._extract_mpd_formats(
95                     media_url, media_id, mpd_id='dash', fatal=False,
96                     headers=self._MANIFEST_HEADERS))
97         self._sort_formats(formats)
98
99         return {
100             'id': media_id,
101             'display_id': display_id,
102             'title': title,
103             'formats': formats,
104             'thumbnail': video_data.get('thumbnailUrl'),
105             'description': video_data.get('description'),
106             'duration': int_or_none(video_data.get('duration')),
107             'tags': video_data.get('tags'),
108             'is_live': is_live,
109         }