]> jfr.im git - yt-dlp.git/blame - yt_dlp/extractor/sovietscloset.py
[docs,cleanup] Add deprecation warning in docs
[yt-dlp.git] / yt_dlp / extractor / sovietscloset.py
CommitLineData
421ddcb8
C
1# coding: utf-8
2from __future__ import unicode_literals
3
4from .common import InfoExtractor
5from ..utils import (
6 js_to_json,
7 try_get,
8 unified_timestamp
9)
10
11
12class SovietsClosetBaseIE(InfoExtractor):
13 MEDIADELIVERY_REFERER = {'Referer': 'https://iframe.mediadelivery.net/'}
14
15 def parse_nuxt_jsonp(self, nuxt_jsonp_url, video_id, name):
16 nuxt_jsonp = self._download_webpage(nuxt_jsonp_url, video_id, note=f'Downloading {name} __NUXT_JSONP__')
17 js, arg_keys, arg_vals = self._search_regex(
18 r'__NUXT_JSONP__\(.*?\(function\((?P<arg_keys>.*?)\)\{return\s(?P<js>\{.*?\})\}\((?P<arg_vals>.*?)\)',
19 nuxt_jsonp, '__NUXT_JSONP__', group=['js', 'arg_keys', 'arg_vals'])
20
21 args = dict(zip(arg_keys.split(','), arg_vals.split(',')))
22
23 for key, val in args.items():
24 if val in ('undefined', 'void 0'):
25 args[key] = 'null'
26
27 return self._parse_json(js_to_json(js, args), video_id)['data'][0]
28
29 def video_meta(self, video_id, game_name, category_name, episode_number, stream_date):
30 title = game_name
31 if category_name and category_name != 'Misc':
32 title += f' - {category_name}'
33 if episode_number:
34 title += f' #{episode_number}'
35
36 timestamp = unified_timestamp(stream_date)
37
38 return {
39 'id': video_id,
40 'title': title,
41 'http_headers': self.MEDIADELIVERY_REFERER,
42 'uploader': 'SovietWomble',
43 'creator': 'SovietWomble',
44 'release_timestamp': timestamp,
45 'timestamp': timestamp,
46 'uploader_id': 'SovietWomble',
47 'uploader_url': 'https://www.twitch.tv/SovietWomble',
48 'was_live': True,
49 'availability': 'public',
50 'series': game_name,
51 'season': category_name,
52 'episode_number': episode_number,
53 }
54
55
56class SovietsClosetIE(SovietsClosetBaseIE):
57 _VALID_URL = r'https?://(?:www\.)?sovietscloset\.com/video/(?P<id>[0-9]+)/?'
58 _TESTS = [
59 {
60 'url': 'https://sovietscloset.com/video/1337',
61 'md5': '11e58781c4ca5b283307aa54db5b3f93',
62 'info_dict': {
63 'id': '1337',
64 'ext': 'mp4',
65 'title': 'The Witcher #13',
66 'thumbnail': r're:^https?://.*\.b-cdn\.net/2f0cfbf4-3588-43a9-a7d6-7c9ea3755e67/thumbnail\.jpg$',
67 'uploader': 'SovietWomble',
68 'creator': 'SovietWomble',
69 'release_timestamp': 1492091580,
70 'release_date': '20170413',
71 'timestamp': 1492091580,
72 'upload_date': '20170413',
73 'uploader_id': 'SovietWomble',
74 'uploader_url': 'https://www.twitch.tv/SovietWomble',
75 'was_live': True,
76 'availability': 'public',
77 'series': 'The Witcher',
78 'season': 'Misc',
79 'episode_number': 13,
80 },
81 },
82 {
83 'url': 'https://sovietscloset.com/video/1105',
84 'md5': '578b1958a379e7110ba38697042e9efb',
85 'info_dict': {
86 'id': '1105',
87 'ext': 'mp4',
88 'title': 'Arma 3 - Zeus Games #3',
89 'uploader': 'SovietWomble',
90 'thumbnail': r're:^https?://.*\.b-cdn\.net/c0e5e76f-3a93-40b4-bf01-12343c2eec5d/thumbnail\.jpg$',
91 'uploader': 'SovietWomble',
92 'creator': 'SovietWomble',
93 'release_timestamp': 1461157200,
94 'release_date': '20160420',
95 'timestamp': 1461157200,
96 'upload_date': '20160420',
97 'uploader_id': 'SovietWomble',
98 'uploader_url': 'https://www.twitch.tv/SovietWomble',
99 'was_live': True,
100 'availability': 'public',
101 'series': 'Arma 3',
102 'season': 'Zeus Games',
103 'episode_number': 3,
104 },
105 },
106 ]
107
108 def _extract_bunnycdn_iframe(self, video_id, bunnycdn_id):
109 iframe = self._download_webpage(
110 f'https://iframe.mediadelivery.net/embed/5105/{bunnycdn_id}',
111 video_id, note='Downloading BunnyCDN iframe', headers=self.MEDIADELIVERY_REFERER)
112
113 m3u8_url = self._search_regex(r'(https?://.*?\.m3u8)', iframe, 'm3u8 url')
114 thumbnail_url = self._search_regex(r'(https?://.*?thumbnail\.jpg)', iframe, 'thumbnail url')
115
116 m3u8_formats = self._extract_m3u8_formats(m3u8_url, video_id, headers=self.MEDIADELIVERY_REFERER)
117 self._sort_formats(m3u8_formats)
118
119 return {
120 'formats': m3u8_formats,
121 'thumbnail': thumbnail_url,
122 }
123
124 def _real_extract(self, url):
125 video_id = self._match_id(url)
126 webpage = self._download_webpage(url, video_id)
127
128 static_assets_base = self._search_regex(r'staticAssetsBase:\"(.*?)\"', webpage, 'staticAssetsBase')
129 static_assets_base = f'https://sovietscloset.com{static_assets_base}'
130
131 stream = self.parse_nuxt_jsonp(f'{static_assets_base}/video/{video_id}/payload.js', video_id, 'video')['stream']
132
133 return {
134 **self.video_meta(
135 video_id=video_id, game_name=stream['game']['name'],
136 category_name=try_get(stream, lambda x: x['subcategory']['name'], str),
137 episode_number=stream.get('number'), stream_date=stream.get('date')),
138 **self._extract_bunnycdn_iframe(video_id, stream['bunnyId']),
139 }
140
141
142class SovietsClosetPlaylistIE(SovietsClosetBaseIE):
143 _VALID_URL = r'https?://(?:www\.)?sovietscloset\.com/(?!video)(?P<id>[^#?]+)'
144 _TESTS = [
145
146 {
147 'url': 'https://sovietscloset.com/The-Witcher',
148 'info_dict': {
149 'id': 'The-Witcher',
150 'title': 'The Witcher',
151 },
152 'playlist_mincount': 31,
153 },
154 {
155 'url': 'https://sovietscloset.com/Arma-3/Zeus-Games',
156 'info_dict': {
157 'id': 'Arma-3/Zeus-Games',
158 'title': 'Arma 3 - Zeus Games',
159 },
160 'playlist_mincount': 3,
161 },
162 {
163 'url': 'https://sovietscloset.com/arma-3/zeus-games/',
164 'info_dict': {
165 'id': 'arma-3/zeus-games',
166 'title': 'Arma 3 - Zeus Games',
167 },
168 'playlist_mincount': 3,
169 },
170 ]
171
172 def _real_extract(self, url):
173 playlist_id = self._match_id(url)
174 if playlist_id.endswith('/'):
175 playlist_id = playlist_id[:-1]
176
177 webpage = self._download_webpage(url, playlist_id)
178
179 static_assets_base = self._search_regex(r'staticAssetsBase:\"(.*?)\"', webpage, 'staticAssetsBase')
180 static_assets_base = f'https://sovietscloset.com{static_assets_base}'
181
182 sovietscloset = self.parse_nuxt_jsonp(f'{static_assets_base}/payload.js', playlist_id, 'global')['games']
183
184 if '/' in playlist_id:
185 game_slug, category_slug = playlist_id.lower().split('/')
186 else:
187 game_slug = playlist_id.lower()
188 category_slug = 'misc'
189
190 game = next(game for game in sovietscloset if game['slug'].lower() == game_slug)
191 category = next(cat for cat in game['subcategories'] if cat['slug'].lower() == category_slug)
192 playlist_title = game.get('name') or game_slug
193 if category_slug != 'misc':
194 playlist_title += f' - {category.get("name") or category_slug}'
195 entries = [{
196 **self.url_result(f'https://sovietscloset.com/video/{stream["id"]}', ie=SovietsClosetIE.ie_key()),
197 **self.video_meta(
198 video_id=stream['id'], game_name=game['name'], category_name=category.get('name'),
199 episode_number=i + 1, stream_date=stream.get('date')),
200 } for i, stream in enumerate(category['streams'])]
201
202 return self.playlist_result(entries, playlist_id, playlist_title)