You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
5.0 KiB

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