diff --git a/youtube_dl/extractor/rutube.py b/youtube_dl/extractor/rutube.py index 8f54d5675..7a8767473 100644 --- a/youtube_dl/extractor/rutube.py +++ b/youtube_dl/extractor/rutube.py @@ -1,6 +1,7 @@ # coding: utf-8 from __future__ import unicode_literals +import json import re import itertools @@ -17,10 +18,12 @@ from ..utils import ( try_get, unified_timestamp, url_or_none, -) + ExtractorError) class RutubeBaseIE(InfoExtractor): + _NETRC_MACHINE = 'rutube' + def _download_api_info(self, video_id, query=None): if not query: query = {} @@ -55,8 +58,39 @@ class RutubeBaseIE(InfoExtractor): 'view_count': int_or_none(video.get('hits')), 'comment_count': int_or_none(video.get('comments_count')), 'is_live': bool_or_none(video.get('is_livestream')), + 'is_club': bool_or_none(video.get('is_club')), } + def _real_initialize(self): + self._login() + + def _login(self): + username, password = self._get_login_info() + if username is None: + return + + login = self._download_json( + 'https://pass.rutube.ru/api/accounts/phone/login/', None, + 'Logging in', 'Unable to log in', + data=json.dumps({ + 'phone': username, + 'password': password, + }).encode(), + headers={ + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + expected_status=400) + if not login.get('success'): + msg = login.get('message') + raise ExtractorError( + 'Unable to log in. %s said: %s' % (self.IE_NAME, msg), + expected=True) + + self._download_webpage( + 'https://rutube.ru/social/auth/rupass/?callback_path=/social/login/rupass/', + None, False) + def _download_and_extract_info(self, video_id, query=None): return self._extract_info( self._download_api_info(video_id, query=query), video_id) @@ -66,7 +100,7 @@ class RutubeBaseIE(InfoExtractor): query = {} query['format'] = 'json' return self._download_json( - 'http://rutube.ru/api/play/options/%s/' % video_id, + 'https://rutube.ru/api/play/options/%s/' % video_id, video_id, 'Downloading options JSON', 'Unable to download options JSON', headers=self.geo_verification_headers(), query=query) @@ -141,7 +175,29 @@ class RutubeIE(RutubeBaseIE): def _real_extract(self, url): video_id = self._match_id(url) info = self._download_and_extract_info(video_id) - info['formats'] = self._download_and_extract_formats(video_id) + query = {} + + if info['is_club']: + visitor_json, urlh = self._download_webpage_handle( + 'https://rutube.ru/api/accounts/visitor/', video_id, + 'Downloading visitor JSON', 'Unable to download visitor JSON') + if not visitor_json: + self.raise_login_required() + + visitor = self._parse_json(visitor_json, video_id) + club_params = visitor['club_params_encrypted'] + ad = self._download_json( + 'https://mtr.rutube.ru/api/v3/interactive?%s&video_id=%s' % + (club_params, video_id), + video_id, 'Downloading AD JSON', 'Unable to download AD JSON') + club_token = ad['award'] + + query.update({ + 'club_token': club_token, + 'no_404': 'true', + }) + + info['formats'] = self._download_and_extract_formats(video_id, query) return info