]> jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/wimtv.py
[cleanup] Revert unnecessary changes in 51d9739f8031fb37d8e25b0e9f1abea561e3d2e3
[yt-dlp.git] / yt_dlp / extractor / wimtv.py
1 # coding: utf-8
2 from __future__ import unicode_literals
3
4 import re
5
6 from .common import InfoExtractor
7 from ..utils import (
8 determine_ext,
9 parse_duration,
10 urlencode_postdata,
11 ExtractorError,
12 )
13
14
15 class WimTVIE(InfoExtractor):
16 _player = None
17 _UUID_RE = r'[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}'
18 _VALID_URL = r'''(?x)
19 https?://platform.wim.tv/
20 (?:
21 (?:embed/)?\?
22 |\#/webtv/.+?/
23 )
24 (?P<type>vod|live|cast)[=/]
25 (?P<id>%s).*?''' % _UUID_RE
26 _TESTS = [{
27 # vod stream
28 'url': 'https://platform.wim.tv/embed/?vod=db29fb32-bade-47b6-a3a6-cb69fe80267a',
29 'md5': 'db29fb32-bade-47b6-a3a6-cb69fe80267a',
30 'info_dict': {
31 'id': 'db29fb32-bade-47b6-a3a6-cb69fe80267a',
32 'ext': 'mp4',
33 'title': 'AMA SUPERCROSS 2020 - R2 ST. LOUIS',
34 'duration': 6481,
35 'thumbnail': r're:https?://.+?/thumbnail/.+?/720$'
36 },
37 'params': {
38 'skip_download': True,
39 },
40 }, {
41 # live stream
42 'url': 'https://platform.wim.tv/embed/?live=28e22c22-49db-40f3-8c37-8cbb0ff44556&autostart=true',
43 'info_dict': {
44 'id': '28e22c22-49db-40f3-8c37-8cbb0ff44556',
45 'ext': 'mp4',
46 'title': 'Streaming MSmotorTV',
47 'is_live': True,
48 },
49 'params': {
50 'skip_download': True,
51 },
52 }, {
53 'url': 'https://platform.wim.tv/#/webtv/automotornews/vod/422492b6-539e-474d-9c6b-68c9d5893365',
54 'only_matching': True,
55 }, {
56 'url': 'https://platform.wim.tv/#/webtv/renzoarborechannel/cast/f47e0d15-5b45-455e-bf0d-dba8ffa96365',
57 'only_matching': True,
58 }]
59
60 @staticmethod
61 def _extract_urls(webpage):
62 return [
63 mobj.group('url')
64 for mobj in re.finditer(
65 r'<iframe[^>]+src=["\'](?P<url>%s)' % WimTVIE._VALID_URL,
66 webpage)]
67
68 def _real_initialize(self):
69 if not self._player:
70 self._get_player_data()
71
72 def _get_player_data(self):
73 msg_id = 'Player data'
74 self._player = {}
75
76 datas = [{
77 'url': 'https://platform.wim.tv/common/libs/player/wimtv/wim-rest.js',
78 'vars': [{
79 'regex': r'appAuth = "(.+?)"',
80 'variable': 'app_auth',
81 }]
82 }, {
83 'url': 'https://platform.wim.tv/common/config/endpointconfig.js',
84 'vars': [{
85 'regex': r'PRODUCTION_HOSTNAME_THUMB = "(.+?)"',
86 'variable': 'thumb_server',
87 }, {
88 'regex': r'PRODUCTION_HOSTNAME_THUMB\s*\+\s*"(.+?)"',
89 'variable': 'thumb_server_path',
90 }]
91 }]
92
93 for data in datas:
94 temp = self._download_webpage(data['url'], msg_id)
95 for var in data['vars']:
96 val = self._search_regex(var['regex'], temp, msg_id)
97 if not val:
98 raise ExtractorError('%s not found' % var['variable'])
99 self._player[var['variable']] = val
100
101 def _generate_token(self):
102 json = self._download_json(
103 'https://platform.wim.tv/wimtv-server/oauth/token', 'Token generation',
104 headers={'Authorization': 'Basic %s' % self._player['app_auth']},
105 data=urlencode_postdata({'grant_type': 'client_credentials'}))
106 token = json.get('access_token')
107 if not token:
108 raise ExtractorError('access token not generated')
109 return token
110
111 def _generate_thumbnail(self, thumb_id, width='720'):
112 if not thumb_id or not self._player.get('thumb_server'):
113 return None
114 if not self._player.get('thumb_server_path'):
115 self._player['thumb_server_path'] = ''
116 return '%s%s/asset/thumbnail/%s/%s' % (
117 self._player['thumb_server'],
118 self._player['thumb_server_path'],
119 thumb_id, width)
120
121 def _real_extract(self, url):
122 urlc = re.match(self._VALID_URL, url).groupdict()
123 video_id = urlc['id']
124 stream_type = is_live = None
125 if urlc['type'] in {'live', 'cast'}:
126 stream_type = urlc['type'] + '/channel'
127 is_live = True
128 else:
129 stream_type = 'vod'
130 is_live = False
131 token = self._generate_token()
132 json = self._download_json(
133 'https://platform.wim.tv/wimtv-server/api/public/%s/%s/play' % (
134 stream_type, video_id), video_id,
135 headers={'Authorization': 'Bearer %s' % token,
136 'Content-Type': 'application/json'},
137 data=bytes('{}', 'utf-8'))
138
139 formats = []
140 for src in json.get('srcs') or []:
141 if src.get('mimeType') == 'application/x-mpegurl':
142 formats.extend(
143 self._extract_m3u8_formats(
144 src.get('uniqueStreamer'), video_id, 'mp4'))
145 if src.get('mimeType') == 'video/flash':
146 formats.append({
147 'format_id': 'rtmp',
148 'url': src.get('uniqueStreamer'),
149 'ext': determine_ext(src.get('uniqueStreamer'), 'flv'),
150 'rtmp_live': is_live,
151 })
152 json = json.get('resource')
153 thumb = self._generate_thumbnail(json.get('thumbnailId'))
154 self._sort_formats(formats)
155
156 return {
157 'id': video_id,
158 'title': json.get('title') or json.get('name'),
159 'duration': parse_duration(json.get('duration')),
160 'formats': formats,
161 'thumbnail': thumb,
162 'is_live': is_live,
163 }