1 from .common
import InfoExtractor
2 from ..utils
import try_get
, unified_timestamp
5 class SovietsClosetBaseIE(InfoExtractor
):
6 MEDIADELIVERY_REFERER
= {'Referer': 'https://iframe.mediadelivery.net/'}
8 def parse_nuxt_jsonp(self
, nuxt_jsonp_url
, video_id
, name
):
9 nuxt_jsonp
= self
._download
_webpage
(nuxt_jsonp_url
, video_id
, note
=f
'Downloading {name} __NUXT_JSONP__')
10 return self
._search
_nuxt
_data
(nuxt_jsonp
, video_id
, '__NUXT_JSONP__')
12 def video_meta(self
, video_id
, game_name
, category_name
, episode_number
, stream_date
):
14 if category_name
and category_name
!= 'Misc':
15 title
+= f
' - {category_name}'
17 title
+= f
' #{episode_number}'
19 timestamp
= unified_timestamp(stream_date
)
24 'http_headers': self
.MEDIADELIVERY_REFERER
,
25 'uploader': 'SovietWomble',
26 'creator': 'SovietWomble',
27 'release_timestamp': timestamp
,
28 'timestamp': timestamp
,
29 'uploader_id': 'SovietWomble',
30 'uploader_url': 'https://www.twitch.tv/SovietWomble',
32 'availability': 'public',
34 'season': category_name
,
35 'episode_number': episode_number
,
39 class SovietsClosetIE(SovietsClosetBaseIE
):
40 _VALID_URL
= r
'https?://(?:www\.)?sovietscloset\.com/video/(?P<id>[0-9]+)/?'
43 'url': 'https://sovietscloset.com/video/1337',
44 'md5': 'bd012b04b261725510ca5383074cdd55',
48 'title': 'The Witcher #13',
49 'thumbnail': r
're:^https?://.*\.b-cdn\.net/2f0cfbf4-3588-43a9-a7d6-7c9ea3755e67/thumbnail\.jpg$',
50 'uploader': 'SovietWomble',
51 'creator': 'SovietWomble',
52 'release_timestamp': 1492091580,
53 'release_date': '20170413',
54 'timestamp': 1492091580,
55 'upload_date': '20170413',
56 'uploader_id': 'SovietWomble',
57 'uploader_url': 'https://www.twitch.tv/SovietWomble',
60 'availability': 'public',
61 'series': 'The Witcher',
64 'episode': 'Episode 13',
68 'url': 'https://sovietscloset.com/video/1105',
69 'md5': '89fa928f183893cb65a0b7be846d8a90',
73 'title': 'Arma 3 - Zeus Games #5',
74 'uploader': 'SovietWomble',
75 'thumbnail': r
're:^https?://.*\.b-cdn\.net/c0e5e76f-3a93-40b4-bf01-12343c2eec5d/thumbnail\.jpg$',
76 'creator': 'SovietWomble',
77 'release_timestamp': 1461157200,
78 'release_date': '20160420',
79 'timestamp': 1461157200,
80 'upload_date': '20160420',
81 'uploader_id': 'SovietWomble',
82 'uploader_url': 'https://www.twitch.tv/SovietWomble',
85 'availability': 'public',
87 'season': 'Zeus Games',
89 'episode': 'Episode 5',
94 def _extract_bunnycdn_iframe(self
, video_id
, bunnycdn_id
):
95 iframe
= self
._download
_webpage
(
96 f
'https://iframe.mediadelivery.net/embed/5105/{bunnycdn_id}',
97 video_id
, note
='Downloading BunnyCDN iframe', headers
=self
.MEDIADELIVERY_REFERER
)
99 m3u8_url
= self
._search
_regex
(r
'(https?://.*?\.m3u8)', iframe
, 'm3u8 url')
100 thumbnail_url
= self
._search
_regex
(r
'(https?://.*?thumbnail\.jpg)', iframe
, 'thumbnail url')
102 m3u8_formats
= self
._extract
_m
3u8_formats
(m3u8_url
, video_id
, headers
=self
.MEDIADELIVERY_REFERER
)
107 duration
= self
._extract
_m
3u8_vod
_duration
(
108 m3u8_formats
[0]['url'], video_id
, headers
=self
.MEDIADELIVERY_REFERER
)
111 'formats': m3u8_formats
,
112 'thumbnail': thumbnail_url
,
113 'duration': duration
,
116 def _real_extract(self
, url
):
117 video_id
= self
._match
_id
(url
)
118 webpage
= self
._download
_webpage
(url
, video_id
)
120 static_assets_base
= self
._search
_regex
(r
'(/_nuxt/static/\d+)', webpage
, 'staticAssetsBase')
121 static_assets_base
= f
'https://sovietscloset.com{static_assets_base}'
123 stream
= self
.parse_nuxt_jsonp(f
'{static_assets_base}/video/{video_id}/payload.js', video_id
, 'video')['stream']
127 video_id
=video_id
, game_name
=stream
['game']['name'],
128 category_name
=try_get(stream
, lambda x
: x
['subcategory']['name'], str),
129 episode_number
=stream
.get('number'), stream_date
=stream
.get('date')),
130 **self
._extract
_bunnycdn
_iframe
(video_id
, stream
['bunnyId']),
134 class SovietsClosetPlaylistIE(SovietsClosetBaseIE
):
135 _VALID_URL
= r
'https?://(?:www\.)?sovietscloset\.com/(?!video)(?P<id>[^#?]+)'
139 'url': 'https://sovietscloset.com/The-Witcher',
142 'title': 'The Witcher',
144 'playlist_mincount': 31,
147 'url': 'https://sovietscloset.com/Arma-3/Zeus-Games',
149 'id': 'Arma-3/Zeus-Games',
150 'title': 'Arma 3 - Zeus Games',
152 'playlist_mincount': 3,
155 'url': 'https://sovietscloset.com/arma-3/zeus-games/',
157 'id': 'arma-3/zeus-games',
158 'title': 'Arma 3 - Zeus Games',
160 'playlist_mincount': 3,
163 'url': 'https://sovietscloset.com/Total-War-Warhammer',
165 'id': 'Total-War-Warhammer',
166 'title': 'Total War: Warhammer - Greenskins',
168 'playlist_mincount': 33,
172 def _real_extract(self
, url
):
173 playlist_id
= self
._match
_id
(url
)
174 if playlist_id
.endswith('/'):
175 playlist_id
= playlist_id
[:-1]
177 webpage
= self
._download
_webpage
(url
, playlist_id
)
179 static_assets_base
= self
._search
_regex
(r
'(/_nuxt/static/\d+)', webpage
, 'staticAssetsBase')
180 static_assets_base
= f
'https://sovietscloset.com{static_assets_base}'
182 sovietscloset
= self
.parse_nuxt_jsonp(f
'{static_assets_base}/payload.js', playlist_id
, 'global')['games']
184 if '/' in playlist_id
:
185 game_slug
, category_slug
= playlist_id
.lower().split('/')
187 game_slug
= playlist_id
.lower()
188 category_slug
= 'misc'
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
.get('slug', '').lower() == category_slug
),
192 game
['subcategories'][0])
193 category_slug
= category
.get('slug', '').lower() or category_slug
194 playlist_title
= game
.get('name') or game_slug
195 if category_slug
!= 'misc':
196 playlist_title
+= f
' - {category.get("name") or category_slug}'
198 **self
.url_result(f
'https://sovietscloset.com/video/{stream["id"]}', ie
=SovietsClosetIE
.ie_key()),
200 video_id
=stream
['id'], game_name
=game
['name'], category_name
=category
.get('name'),
201 episode_number
=i
+ 1, stream_date
=stream
.get('date')),
202 } for i
, stream
in enumerate(category
['streams'])]
204 return self
.playlist_result(entries
, playlist_id
, playlist_title
)