]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/mildom.py
2 from __future__
import unicode_literals
5 from datetime
import datetime
9 from .common
import InfoExtractor
18 from ..compat
import (
23 class MildomBaseIE(InfoExtractor
):
25 _DISPATCHER_CONFIG
= None
27 def _call_api(self
, url
, video_id
, query
=None, note
='Downloading JSON metadata', init
=False):
30 query
['__platform'] = 'web'
31 url
= update_url_query(url
, self
._common
_queries
(query
, init
=init
))
32 content
= self
._download
_json
(url
, video_id
, note
=note
)
33 if content
['code'] == 0:
34 return content
['body']
36 self
.raise_no_formats(
37 f
'Video not found or premium content. {content["code"]} - {content["message"]}',
40 def _common_queries(self
, query
={}, init
=False):
41 dc
= self
._fetch
_dispatcher
_config
()
43 'timestamp': self
.iso_timestamp(),
44 '__guest_id': '' if init
else self
.guest_id(),
45 '__location': dc
['location'],
46 '__country': dc
['country'],
47 '__cluster': dc
['cluster'],
49 '__la': self
.lang_code(),
57 def _fetch_dispatcher_config(self
):
58 if not self
._DISPATCHER
_CONFIG
:
59 tmp
= self
._download
_json
(
60 'https://disp.mildom.com/serverListV2', 'initialization',
61 note
='Downloading dispatcher_config', data
=json
.dumps({
63 'data': base64
.b64encode(json
.dumps({
72 'rtm': self
.iso_timestamp(),
73 'ua': std_headers
['User-Agent'],
74 }).encode('utf8')).decode('utf8').replace('\n', ''),
76 self
._DISPATCHER
_CONFIG
= self
._parse
_json
(base64
.b64decode(tmp
['data']), 'initialization')
77 return self
._DISPATCHER
_CONFIG
81 'new Date().toISOString()'
82 return datetime
.utcnow().isoformat()[0:-3] + 'Z'
88 self
._GUEST
_ID
= try_get(
90 lambda x
: x
._call
_api
(
91 'https://cloudac.mildom.com/nonolive/gappserv/guest/h5init', 'initialization',
92 note
='Downloading guest token', init
=True)['guest_id'] or None,
93 lambda x
: x
._get
_cookies
('https://www.mildom.com').get('gid').value
,
94 lambda x
: x
._get
_cookies
('https://m.mildom.com').get('gid').value
,
103 class MildomIE(MildomBaseIE
):
105 IE_DESC
= 'Record ongoing live by specific user in Mildom'
106 _VALID_URL
= r
'https?://(?:(?:www|m)\.)mildom\.com/(?P<id>\d+)'
108 def _real_extract(self
, url
):
109 video_id
= self
._match
_id
(url
)
110 url
= 'https://www.mildom.com/%s' % video_id
112 webpage
= self
._download
_webpage
(url
, video_id
)
114 enterstudio
= self
._call
_api
(
115 'https://cloudac.mildom.com/nonolive/gappserv/live/enterstudio', video_id
,
116 note
='Downloading live metadata', query
={'user_id': video_id}
)
117 result_video_id
= enterstudio
.get('log_id', video_id
)
121 lambda x
: self
._html
_search
_meta
('twitter:description', webpage
),
122 lambda x
: x
['anchor_intro'],
124 description
= try_get(
126 lambda x
: x
['intro'],
127 lambda x
: x
['live_intro'],
131 lambda x
: self
._html
_search
_meta
('twitter:title', webpage
),
132 lambda x
: x
['loginname'],
135 servers
= self
._call
_api
(
136 'https://cloudac.mildom.com/nonolive/gappserv/live/liveserver', result_video_id
,
137 note
='Downloading live server list', query
={
139 'live_server_type': 'hls',
142 stream_query
= self
._common
_queries
({
143 'streamReqId': random_uuidv4(),
146 m3u8_url
= update_url_query(servers
['stream_server'] + '/%s_master.m3u8' % video_id
, stream_query
)
147 formats
= self
._extract
_m
3u8_formats
(m3u8_url
, result_video_id
, 'mp4', headers
={
148 'Referer': 'https://www.mildom.com/',
149 'Origin': 'https://www.mildom.com',
150 }, note
='Downloading m3u8 information')
152 del stream_query
['streamReqId'], stream_query
['timestamp']
154 fmt
.setdefault('http_headers', {})['Referer'] = 'https://www.mildom.com/'
156 self
._sort
_formats
(formats
)
159 'id': result_video_id
,
161 'description': description
,
162 'timestamp': float_or_none(enterstudio
.get('live_start_ms'), scale
=1000),
163 'uploader': uploader
,
164 'uploader_id': video_id
,
170 class MildomVodIE(MildomBaseIE
):
171 IE_NAME
= 'mildom:vod'
172 IE_DESC
= 'Download a VOD in Mildom'
173 _VALID_URL
= r
'https?://(?:(?:www|m)\.)mildom\.com/playback/(?P<user_id>\d+)/(?P<id>(?P=user_id)-[a-zA-Z0-9]+-?[0-9]*)'
175 'url': 'https://www.mildom.com/playback/10882672/10882672-1597662269',
177 'id': '10882672-1597662269',
179 'title': '始めてのミルダム配信じゃぃ!',
180 'thumbnail': r
're:^https?://.*\.(png|jpg)$',
181 'upload_date': '20200817',
183 'description': 'ゲームをしたくて!',
184 'timestamp': 1597662269.0,
185 'uploader_id': '10882672',
186 'uploader': 'kson組長(けいそん)',
189 'url': 'https://www.mildom.com/playback/10882672/10882672-1597758589870-477',
191 'id': '10882672-1597758589870-477',
193 'title': '【kson】感染メイズ!麻酔銃で無双する',
194 'thumbnail': r
're:^https?://.*\.(png|jpg)$',
195 'timestamp': 1597759093.0,
196 'uploader': 'kson組長(けいそん)',
198 'uploader_id': '10882672',
199 'description': 'このステージ絶対乗り越えたい',
200 'upload_date': '20200818',
203 'url': 'https://www.mildom.com/playback/10882672/10882672-buha9td2lrn97fk2jme0',
205 'id': '10882672-buha9td2lrn97fk2jme0',
207 'title': '【kson組長】CART RACER!!!',
208 'thumbnail': r
're:^https?://.*\.(png|jpg)$',
209 'uploader_id': '10882672',
210 'uploader': 'kson組長(けいそん)',
211 'upload_date': '20201104',
212 'timestamp': 1604494797.0,
214 'description': 'WTF',
218 def _real_extract(self
, url
):
219 m
= self
._match
_valid
_url
(url
)
220 user_id
, video_id
= m
.group('user_id'), m
.group('id')
221 url
= 'https://www.mildom.com/playback/%s/%s' % (user_id
, video_id
)
223 webpage
= self
._download
_webpage
(url
, video_id
)
225 autoplay
= self
._call
_api
(
226 'https://cloudac.mildom.com/nonolive/videocontent/playback/getPlaybackDetail', video_id
,
227 note
='Downloading playback metadata', query
={
233 lambda x
: self
._html
_search
_meta
('og:description', webpage
),
234 lambda x
: x
['title'],
236 description
= try_get(
238 lambda x
: x
['video_intro'],
242 lambda x
: x
['author_info']['login_name'],
246 'url': autoplay
['audio_url'],
247 'format_id': 'audio',
248 'protocol': 'm3u8_native',
253 for fmt
in autoplay
['video_link']:
255 'format_id': 'video-%s' % fmt
['name'],
257 'protocol': 'm3u8_native',
258 'width': fmt
['level'] * autoplay
['video_width'] // autoplay
['video_height'],
259 'height': fmt
['level'],
265 self
._sort
_formats
(formats
)
270 'description': description
,
271 'timestamp': float_or_none(autoplay
['publish_time'], scale
=1000),
272 'duration': float_or_none(autoplay
['video_length'], scale
=1000),
273 'thumbnail': dict_get(autoplay
, ('upload_pic', 'video_pic')),
274 'uploader': uploader
,
275 'uploader_id': user_id
,
280 class MildomUserVodIE(MildomBaseIE
):
281 IE_NAME
= 'mildom:user:vod'
282 IE_DESC
= 'Download all VODs from specific user in Mildom'
283 _VALID_URL
= r
'https?://(?:(?:www|m)\.)mildom\.com/profile/(?P<id>\d+)'
285 'url': 'https://www.mildom.com/profile/10093333',
288 'title': 'Uploads from ねこばたけ',
290 'playlist_mincount': 351,
292 'url': 'https://www.mildom.com/profile/10882672',
295 'title': 'Uploads from kson組長(けいそん)',
297 'playlist_mincount': 191,
300 def _entries(self
, user_id
):
301 for page
in itertools
.count(1):
302 reply
= self
._call
_api
(
303 'https://cloudac.mildom.com/nonolive/videocontent/profile/playbackList',
304 user_id
, note
='Downloading page %d' % page
, query
={
312 yield self
.url_result('https://www.mildom.com/playback/%s/%s' % (user_id
, x
['v_id']))
314 def _real_extract(self
, url
):
315 user_id
= self
._match
_id
(url
)
316 self
.to_screen('This will download all VODs belonging to user. To download ongoing live video, use "https://www.mildom.com/%s" instead' % user_id
)
318 profile
= self
._call
_api
(
319 'https://cloudac.mildom.com/nonolive/gappserv/user/profileV2', user_id
,
320 query
={'user_id': user_id}
, note
='Downloading user profile')['user_info']
322 return self
.playlist_result(
323 self
._entries
(user_id
), user_id
, 'Uploads from %s' % profile
['loginname'])