1 from .common
import InfoExtractor
8 class VideomoreBaseIE(InfoExtractor
):
9 _API_BASE_URL
= 'https://more.tv/api/v3/web/'
10 _VALID_URL_BASE
= r
'https?://(?:videomore\.ru|more\.tv)/'
12 def _download_page_data(self
, display_id
):
13 return self
._download
_json
(
14 self
._API
_BASE
_URL
+ 'PageData', display_id
, query
={
15 'url': '/' + display_id
,
16 })['attributes']['response']['data']
18 def _track_url_result(self
, track
):
19 track_vod
= track
['trackVod']
20 video_url
= track_vod
.get('playerLink') or track_vod
['link']
21 return self
.url_result(
22 video_url
, VideomoreIE
.ie_key(), track_vod
.get('hubId'))
25 class VideomoreIE(InfoExtractor
):
28 videomore:(?P<sid>\d+)$|
37 (?:player\.)?videomore\.ru|
38 siren\.more\.tv/player
39 )/[^/]*\?.*?\btrack_id=|
40 odysseus\.more.tv/player/(?P<partner_id>\d+)/
43 (?:[/?#&]|\.(?:xml|json)|$)
45 _EMBED_REGEX
= [r
'''(?x)
47 <iframe[^>]+src=([\'"])|
48 <object[^>]+data=(["\'])https?
://videomore\
.ru
/player\
.swf
\?.*config
=
49 )(?P
<url
>https?
://videomore\
.ru
/[^?
#"']+/\d+(?:\.xml)?)
52 'url': 'http://videomore.ru/kino_v_detalayah/5_sezon/367617',
53 'md5': '44455a346edc0d509ac5b5a5b531dc35',
57 'title': 'Кино в деталях 5 сезон В гостях Алексей Чумаков и Юлия Ковальчук',
58 'series': 'Кино в деталях',
59 'episode': 'В гостях Алексей Чумаков и Юлия Ковальчук',
60 'thumbnail': r're:^https?://.*\.jpg',
66 'skip': 'The video is not available for viewing.',
68 'url': 'http://videomore.ru/embed/259974',
72 'title': 'Молодежка 2 сезон 40 серия',
73 'series': 'Молодежка',
75 'episode': '40 серия',
76 'thumbnail': r're:^https?://.*\.jpg',
82 'skip_download': True,
85 'url': 'http://videomore.ru/molodezhka/sezon_promo/341073',
89 'title': 'Промо Команда проиграла из-за Бакина?',
90 'episode': 'Команда проиграла из-за Бакина?',
91 'thumbnail': r're:^https?://.*\.jpg',
97 'skip_download': True,
99 'skip': 'The video is not available for viewing.',
101 'url': 'http://videomore.ru/elki_3?track_id=364623',
102 'only_matching': True,
104 'url': 'http://videomore.ru/embed/364623',
105 'only_matching': True,
107 'url': 'http://videomore.ru/video/tracks/364623.xml',
108 'only_matching': True,
110 'url': 'http://videomore.ru/video/tracks/364623.json',
111 'only_matching': True,
113 'url': 'http://videomore.ru/video/tracks/158031/quotes/33248',
114 'only_matching': True,
116 'url': 'videomore:367617',
117 'only_matching': True,
119 'url': 'https://player.videomore.ru/?partner_id=97&track_id=736234&autoplay=0&userToken=',
120 'only_matching': True,
122 'url': 'https://odysseus.more.tv/player/1788/352317',
123 'only_matching': True,
125 'url': 'https://siren.more.tv/player/config?track_id=352317&partner_id=1788&user_token=',
126 'only_matching': True,
130 def _real_extract(self, url):
131 mobj = self._match_valid_url(url)
132 video_id = mobj.group('sid') or mobj.group('id')
133 partner_id = mobj.group('partner_id') or parse_qs(url).get('partner_id', [None])[0] or '97'
135 item = self._download_json(
136 'https://siren.more.tv/player/config', video_id, query={
137 'partner_id': partner_id,
138 'track_id': video_id,
139 })['data']['playlist']['items'][0]
141 title = item.get('title')
142 series = item.get('project_name')
143 season = item.get('season_name')
144 episode = item.get('episode_name')
147 for v in (series, season, episode):
150 title = ' '.join(title)
152 streams = item.get('streams') or []
153 for protocol in ('DASH', 'HLS'):
154 stream_url = item.get(protocol.lower() + '_url')
156 streams.append({'protocol': protocol, 'url': stream_url})
159 for stream in streams:
160 stream_url = stream.get('url')
163 protocol = stream.get('protocol')
164 if protocol == 'DASH':
165 formats.extend(self._extract_mpd_formats(
166 stream_url, video_id, mpd_id='dash', fatal=False))
167 elif protocol == 'HLS':
168 formats.extend(self._extract_m3u8_formats(
169 stream_url, video_id, 'mp4', 'm3u8_native',
170 m3u8_id='hls', fatal=False))
171 elif protocol == 'MSS':
172 formats.extend(self._extract_ism_formats(
173 stream_url, video_id, ism_id='mss', fatal=False))
176 error = item.get('error')
178 if error in ('Данное видео недоступно для просмотра на территории этой страны', 'Данное видео доступно для просмотра только на территории России'):
179 self.raise_geo_restricted(countries=['RU'], metadata_available=True)
180 self.raise_no_formats(error, expected=True)
188 'thumbnail': item.get('thumbnail_url'),
189 'duration': int_or_none(item.get('duration')),
190 'view_count': int_or_none(item.get('views')),
191 'age_limit': int_or_none(item.get('min_age')),
196 class VideomoreVideoIE(VideomoreBaseIE):
197 IE_NAME = 'videomore:video'
198 _VALID_URL = VideomoreBaseIE._VALID_URL_BASE + r'(?P<id>(?:(?:[^/]+/){2})?[^/?#&]+)(?:/*|[?#&].*?)$'
200 # single video with og:video:iframe
201 'url': 'http://videomore.ru/elki_3',
207 'thumbnail': r're:^https?://.*\.jpg',
213 'skip_download': True,
215 'skip': 'Requires logging in',
217 # season single series with og:video:iframe
218 'url': 'http://videomore.ru/poslednii_ment/1_sezon/14_seriya',
222 'title': 'Последний мент 1 сезон 14 серия',
223 'series': 'Последний мент',
225 'episode': '14 серия',
226 'thumbnail': r're:^https?://.*\.jpg',
232 'skip_download': True,
235 'url': 'http://videomore.ru/sejchas_v_seti/serii_221-240/226_vypusk',
236 'only_matching': True,
238 # single video without og:video:iframe
239 'url': 'http://videomore.ru/marin_i_ego_druzya',
243 'title': '1 серия. Здравствуй, Аквавилль!',
244 'description': 'md5:c6003179538b5d353e7bcd5b1372b2d7',
245 'thumbnail': r're:^https?://.*\.jpg',
251 'skip_download': True,
253 'skip': 'redirects to https://more.tv/',
255 'url': 'https://videomore.ru/molodezhka/6_sezon/29_seriya?utm_so',
256 'only_matching': True,
258 'url': 'https://more.tv/poslednii_ment/1_sezon/14_seriya',
259 'only_matching': True,
263 def suitable(cls, url):
264 return False if VideomoreIE.suitable(url) else super().suitable(url)
266 def _real_extract(self, url):
267 display_id = self._match_id(url)
268 return self._track_url_result(self._download_page_data(display_id))
271 class VideomoreSeasonIE(VideomoreBaseIE):
272 IE_NAME = 'videomore:season'
273 _VALID_URL = VideomoreBaseIE._VALID_URL_BASE + r'(?!embed)(?P<id>[^/]+/[^/?#&]+)(?:/*|[?#&].*?)$'
275 'url': 'http://videomore.ru/molodezhka/film_o_filme',
277 'id': 'molodezhka/film_o_filme',
278 'title': 'Фильм о фильме',
280 'playlist_mincount': 3,
282 'url': 'http://videomore.ru/molodezhka/sezon_promo?utm_so',
283 'only_matching': True,
285 'url': 'https://more.tv/molodezhka/film_o_filme',
286 'only_matching': True,
290 def suitable(cls, url):
291 return (False if (VideomoreIE.suitable(url) or VideomoreVideoIE.suitable(url))
292 else super().suitable(url))
294 def _real_extract(self, url):
295 display_id = self._match_id(url)
296 season = self._download_page_data(display_id)
297 season_id = str(season['id'])
298 tracks = self._download_json(
299 self._API_BASE_URL + f'seasons/{season_id}/tracks',
303 entries.append(self._track_url_result(track))
304 return self.playlist_result(entries, display_id, season.get('title'))