[extractor] Add `_perform_login` function (#2943)

* Adds new functions `_initialize_pre_login` and `_perform_login` as part of the extractor API
* Adds `ie.supports_login` to the public API
pull/3048/head^2
pukkandan 3 years ago committed by GitHub
parent 028f6437f1
commit 52efa4b312
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,11 +12,6 @@ from test.helper import FakeYDL, is_download_test
from yt_dlp.extractor import IqiyiIE
class IqiyiIEWithCredentials(IqiyiIE):
def _get_login_info(self):
return 'foo', 'bar'
class WarningLogger(object):
def __init__(self):
self.messages = []
@ -40,8 +35,8 @@ class TestIqiyiSDKInterpreter(unittest.TestCase):
If `sign` is incorrect, /validate call throws an HTTP 556 error
'''
logger = WarningLogger()
ie = IqiyiIEWithCredentials(FakeYDL({'logger': logger}))
ie._login()
ie = IqiyiIE(FakeYDL({'logger': logger}))
ie._perform_login('foo', 'bar')
self.assertTrue('unable to log in:' in logger.messages[0])

@ -7,18 +7,19 @@ import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from yt_dlp.extractor import (
gen_extractors,
)
from yt_dlp.extractor import gen_extractor_classes
from yt_dlp.extractor.common import InfoExtractor
NO_LOGIN = InfoExtractor._perform_login
class TestNetRc(unittest.TestCase):
def test_netrc_present(self):
for ie in gen_extractors():
if not hasattr(ie, '_login'):
for ie in gen_extractor_classes():
if ie._perform_login is NO_LOGIN:
continue
self.assertTrue(
hasattr(ie, '_NETRC_MACHINE'),
ie._NETRC_MACHINE,
'Extractor %s supports login, but is missing a _NETRC_MACHINE property' % ie.IE_NAME)

@ -291,15 +291,7 @@ class AbemaTVIE(AbemaTVBaseIE):
return self._MEDIATOKEN
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
def _perform_login(self, username, password):
if '@' in username: # don't strictly check if it's email address or not
ep, method = 'user/email', 'email'
else:

@ -126,10 +126,7 @@ Format: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text'''
}])
return subtitles
def _real_initialize(self):
username, password = self._get_login_info()
if not username:
return
def _perform_login(self, username, password):
try:
access_token = (self._download_json(
self._API_BASE_URL + 'authentication/login', None,

@ -184,14 +184,7 @@ class AfreecaTVIE(InfoExtractor):
video_key['part'] = int(m.group('part'))
return video_key
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_form = {
'szWork': 'login',
'szType': 'json',

@ -74,14 +74,7 @@ class AluraIE(InfoExtractor):
"formats": formats
}
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
pass
def _perform_login(self, username, password):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login popup')

@ -15,25 +15,21 @@ from ..compat import compat_HTTPError
class AnimeLabBaseIE(InfoExtractor):
_LOGIN_REQUIRED = True
_LOGIN_URL = 'https://www.animelab.com/login'
_NETRC_MACHINE = 'animelab'
_LOGGED_IN = False
def _login(self):
def is_logged_in(login_webpage):
return 'Sign In' not in login_webpage
def _is_logged_in(self, login_page=None):
if not self._LOGGED_IN:
if not login_page:
login_page = self._download_webpage(self._LOGIN_URL, None, 'Downloading login page')
AnimeLabBaseIE._LOGGED_IN = 'Sign In' not in login_page
return self._LOGGED_IN
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')
# Check if already logged in
if is_logged_in(login_page):
def _perform_login(self, username, password):
if self._is_logged_in():
return
(username, password) = self._get_login_info()
if username is None and self._LOGIN_REQUIRED:
self.raise_login_required('Login is required to access any AnimeLab content')
login_form = {
'email': username,
'password': password,
@ -47,17 +43,14 @@ class AnimeLabBaseIE(InfoExtractor):
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 400:
raise ExtractorError('Unable to log in (wrong credentials?)', expected=True)
else:
raise
raise
# if login was successful
if is_logged_in(response):
return
raise ExtractorError('Unable to login (cannot verify if logged in)')
if not self._is_logged_in(response):
raise ExtractorError('Unable to login (cannot verify if logged in)')
def _real_initialize(self):
self._login()
if not self._is_logged_in():
self.raise_login_required('Login is required to access any AnimeLab content')
class AnimeLabIE(AnimeLabBaseIE):

@ -53,11 +53,7 @@ class AnimeOnDemandIE(InfoExtractor):
'only_matching': True,
}]
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')
@ -93,9 +89,6 @@ class AnimeOnDemandIE(InfoExtractor):
raise ExtractorError('Unable to login: %s' % error, expected=True)
raise ExtractorError('Unable to log in')
def _real_initialize(self):
self._login()
def _real_extract(self, url):
anime_id = self._match_id(url)

@ -37,9 +37,6 @@ class AtresPlayerIE(InfoExtractor):
]
_API_BASE = 'https://api.atresplayer.com/'
def _real_initialize(self):
self._login()
def _handle_error(self, e, code):
if isinstance(e.cause, compat_HTTPError) and e.cause.code == code:
error = self._parse_json(e.cause.read(), None)
@ -48,11 +45,7 @@ class AtresPlayerIE(InfoExtractor):
raise ExtractorError(error['error_description'], expected=True)
raise
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
self._request_webpage(
self._API_BASE + 'login', None, 'Downloading login page')

@ -264,11 +264,7 @@ class BBCCoUkIE(InfoExtractor):
'only_matching': True,
}]
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading signin page')
@ -294,9 +290,6 @@ class BBCCoUkIE(InfoExtractor):
'Unable to login: %s' % error, expected=True)
raise ExtractorError('Unable to log in')
def _real_initialize(self):
self._login()
class MediaSelectionError(Exception):
def __init__(self, id):
self.id = id

@ -821,11 +821,7 @@ class BiliIntlBaseIE(InfoExtractor):
'extractor_key': BiliIntlIE.ie_key(),
}
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
try:
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_v1_5
@ -856,9 +852,6 @@ class BiliIntlBaseIE(InfoExtractor):
else:
raise ExtractorError('Unable to log in')
def _real_initialize(self):
self._login()
class BiliIntlIE(BiliIntlBaseIE):
_VALID_URL = r'https?://(?:www\.)?bili(?:bili\.tv|intl\.com)/(?:[a-z]{2}/)?play/(?P<season_id>\d+)/(?P<id>\d+)'

@ -274,14 +274,7 @@ class VrtNUIE(GigyaBaseIE):
_APIKEY = '3_0Z2HujMtiWq_pkAjgnS2Md2E11a1AwZjYiBETtwNE-EoEHDINgtnvcAOpNgmrVGy'
_CONTEXT_ID = 'R3595707040'
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
auth_info = self._gigya_login({
'APIKey': self._APIKEY,
'targetEnv': 'jssdk',

@ -432,7 +432,15 @@ class InfoExtractor(object):
Subclasses may also override suitable() if necessary, but ensure the function
signature is preserved and that this function imports everything it needs
(except other extractors), so that lazy_extractors works correctly
(except other extractors), so that lazy_extractors works correctly.
To support username + password (or netrc) login, the extractor must define a
_NETRC_MACHINE and re-define _perform_login(username, password) and
(optionally) _initialize_pre_login() methods. The _perform_login method will
be called between _initialize_pre_login and _real_initialize if credentials
are passed by the user. In cases where it is necessary to have the login
process as part of the extraction rather than initialization, _perform_login
can be left undefined.
_GEO_BYPASS attribute may be set to False in order to disable
geo restriction bypass mechanisms for a particular extractor.
@ -460,9 +468,10 @@ class InfoExtractor(object):
_GEO_COUNTRIES = None
_GEO_IP_BLOCKS = None
_WORKING = True
_NETRC_MACHINE = None
_LOGIN_HINTS = {
'any': 'Use --cookies, --username and --password, or --netrc to provide account credentials',
'any': 'Use --cookies, --cookies-from-browser, --username and --password, or --netrc to provide account credentials',
'cookies': (
'Use --cookies-from-browser or --cookies for the authentication. '
'See https://github.com/ytdl-org/youtube-dl#how-do-i-pass-cookies-to-youtube-dl for how to manually pass cookies'),
@ -512,6 +521,10 @@ class InfoExtractor(object):
"""Getter method for _WORKING."""
return cls._WORKING
@classmethod
def supports_login(cls):
return bool(cls._NETRC_MACHINE)
def initialize(self):
"""Initializes an instance (authentication, etc)."""
self._printed_messages = set()
@ -520,6 +533,13 @@ class InfoExtractor(object):
'ip_blocks': self._GEO_IP_BLOCKS,
})
if not self._ready:
self._initialize_pre_login()
if self.supports_login():
username, password = self._get_login_info()
if username:
self._perform_login(username, password)
elif self.get_param('username') and False not in (self.IE_DESC, self._NETRC_MACHINE):
self.report_warning(f'Login with password is not supported for this website. {self._LOGIN_HINTS["cookies"]}')
self._real_initialize()
self._ready = True
@ -665,6 +685,14 @@ class InfoExtractor(object):
"""Sets a YoutubeDL instance as the downloader for this IE."""
self._downloader = downloader
def _initialize_pre_login(self):
""" Intialization before login. Redefine in subclasses."""
pass
def _perform_login(self, username, password):
""" Login with username and password. Redefine in subclasses."""
pass
def _real_initialize(self):
"""Real initialization process. Redefine in subclasses."""
pass
@ -1098,12 +1126,15 @@ class InfoExtractor(object):
def raise_login_required(
self, msg='This video is only available for registered users',
metadata_available=False, method='any'):
metadata_available=False, method=NO_DEFAULT):
if metadata_available and (
self.get_param('ignore_no_formats_error') or self.get_param('wait_for_video')):
self.report_warning(msg)
return
if method is NO_DEFAULT:
method = 'any' if self.supports_login() else 'cookies'
if method is not None:
assert method in self._LOGIN_HINTS, 'Invalid login method'
msg = '%s. %s' % (msg, self._LOGIN_HINTS[method])
raise ExtractorError(msg, expected=True)
@ -3680,9 +3711,8 @@ class InfoExtractor(object):
def mark_watched(self, *args, **kwargs):
if not self.get_param('mark_watched', False):
return
if (hasattr(self, '_NETRC_MACHINE') and self._get_login_info()[0] is not None
or self.get_param('cookiefile')
or self.get_param('cookiesfrombrowser')):
if (self.supports_login() and self._get_login_info()[0] is not None
or self.get_param('cookiefile') or self.get_param('cookiesfrombrowser')):
self._mark_watched(*args, **kwargs)
def _mark_watched(self, *args, **kwargs):

@ -57,10 +57,7 @@ class CrunchyrollBaseIE(InfoExtractor):
'Content-Type': 'application/x-www-form-urlencoded',
})
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
if self._get_cookies(self._LOGIN_URL).get('etp_rt'):
return
@ -89,9 +86,6 @@ class CrunchyrollBaseIE(InfoExtractor):
if not self._get_cookies(self._LOGIN_URL).get('etp_rt'):
raise ExtractorError('Login succeeded but did not set etp_rt cookie')
def _real_initialize(self):
self._login()
@staticmethod
def _add_skip_wall(url):
parsed_url = compat_urlparse.urlparse(url)

@ -33,14 +33,11 @@ class CuriosityStreamBaseIE(InfoExtractor):
self._handle_errors(result)
return result['data']
def _real_initialize(self):
email, password = self._get_login_info()
if email is None:
return
def _perform_login(self, username, password):
result = self._download_json(
'https://api.curiositystream.com/v1/login', None,
note='Logging in', data=urlencode_postdata({
'email': email,
'email': username,
'password': password,
}))
self._handle_errors(result)

@ -45,10 +45,7 @@ class DigitalConcertHallIE(InfoExtractor):
'playlist_count': 3,
}]
def _login(self):
username, password = self._get_login_info()
if not username:
self.raise_login_required()
def _perform_login(self, username, password):
token_response = self._download_json(
self._OAUTH_URL,
None, 'Obtaining token', errnote='Unable to obtain token', data=urlencode_postdata({
@ -78,7 +75,8 @@ class DigitalConcertHallIE(InfoExtractor):
self.raise_login_required(msg='Login info incorrect')
def _real_initialize(self):
self._login()
if not self._ACCESS_TOKEN:
self.raise_login_required(method='password')
def _entries(self, items, language, **kwargs):
for item in items:

@ -39,11 +39,7 @@ class EroProfileIE(InfoExtractor):
'skip': 'Requires login',
}]
def _login(self):
(username, password) = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
query = compat_urllib_parse_urlencode({
'username': username,
'password': password,
@ -62,9 +58,6 @@ class EroProfileIE(InfoExtractor):
r'<script[^>]+?src="([^"]+)"', login_page, 'login redirect url')
self._download_webpage(redirect_url, None, False)
def _real_initialize(self):
self._login()
def _real_extract(self, url):
display_id = self._match_id(url)

@ -329,11 +329,7 @@ class FacebookIE(InfoExtractor):
urls.append(mobj.group('url'))
return urls
def _login(self):
useremail, password = self._get_login_info()
if useremail is None:
return
def _perform_login(self, username, password):
login_page_req = sanitized_Request(self._LOGIN_URL)
self._set_cookie('facebook.com', 'locale', 'en_US')
login_page = self._download_webpage(login_page_req, None,
@ -345,7 +341,7 @@ class FacebookIE(InfoExtractor):
lgnrnd = self._search_regex(r'name="lgnrnd" value="([^"]*?)"', login_page, 'lgnrnd')
login_form = {
'email': useremail,
'email': username,
'pass': password,
'lsd': lsd,
'lgnrnd': lgnrnd,
@ -392,9 +388,6 @@ class FacebookIE(InfoExtractor):
self.report_warning('unable to log in: %s' % error_to_compat_str(err))
return
def _real_initialize(self):
self._login()
def _extract_from_url(self, url, video_id):
webpage = self._download_webpage(
url.replace('://m.facebook.com/', '://www.facebook.com/'), video_id)

@ -49,30 +49,26 @@ class FancodeVodIE(InfoExtractor):
'referer': 'https://fancode.com',
}
def _login(self):
def _perform_login(self, username, password):
# Access tokens are shortlived, so get them using the refresh token.
username, password = self._get_login_info()
if username == 'refresh' and password is not None:
self.report_login()
data = '''{
"query":"mutation RefreshToken($refreshToken: String\\u0021) { refreshToken(refreshToken: $refreshToken) { accessToken }}",
"variables":{
"refreshToken":"%s"
},
"operationName":"RefreshToken"
}''' % password
token_json = self.download_gql('refresh token', data, "Getting the Access token")
self._ACCESS_TOKEN = try_get(token_json, lambda x: x['data']['refreshToken']['accessToken'])
if self._ACCESS_TOKEN is None:
self.report_warning('Failed to get Access token')
else:
self.headers.update({'Authorization': 'Bearer %s' % self._ACCESS_TOKEN})
elif username is not None:
if username != 'refresh':
self.report_warning(f'Login using username and password is not currently supported. {self._LOGIN_HINT}')
def _real_initialize(self):
self._login()
self.report_login()
data = '''{
"query":"mutation RefreshToken($refreshToken: String\\u0021) { refreshToken(refreshToken: $refreshToken) { accessToken }}",
"variables":{
"refreshToken":"%s"
},
"operationName":"RefreshToken"
}''' % password
token_json = self.download_gql('refresh token', data, "Getting the Access token")
self._ACCESS_TOKEN = try_get(token_json, lambda x: x['data']['refreshToken']['accessToken'])
if self._ACCESS_TOKEN is None:
self.report_warning('Failed to get Access token')
else:
self.headers.update({'Authorization': 'Bearer %s' % self._ACCESS_TOKEN})
def _check_login_required(self, is_available, is_premium):
msg = None

@ -28,14 +28,7 @@ class FrontendMastersBaseIE(InfoExtractor):
'high': {'width': 1920, 'height': 1080}
}
def _real_initialize(self):
self._login()
def _login(self):
(username, password) = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')

@ -36,9 +36,8 @@ class FunimationBaseIE(InfoExtractor):
note='Checking geo-location', errnote='Unable to fetch geo-location information'),
'region') or 'US'
def _login(self):
username, password = self._get_login_info()
if username is None:
def _perform_login(self, username, password):
if self._TOKEN:
return
try:
data = self._download_json(
@ -47,7 +46,7 @@ class FunimationBaseIE(InfoExtractor):
'username': username,
'password': password,
}))
return data['token']
FunimationBaseIE._TOKEN = data['token']
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 401:
error = self._parse_json(e.cause.read().decode(), None)['error']
@ -90,8 +89,6 @@ class FunimationPageIE(FunimationBaseIE):
def _real_initialize(self):
if not self._REGION:
FunimationBaseIE._REGION = self._get_region()
if not self._TOKEN:
FunimationBaseIE._TOKEN = self._login()
def _real_extract(self, url):
locale, show, episode = self._match_valid_url(url).group('lang', 'show', 'episode')
@ -154,10 +151,6 @@ class FunimationIE(FunimationBaseIE):
},
}]
def _real_initialize(self):
if not self._TOKEN:
FunimationBaseIE._TOKEN = self._login()
@staticmethod
def _get_experiences(episode):
for lang, lang_data in episode.get('languages', {}).items():

@ -56,24 +56,22 @@ class GaiaIE(InfoExtractor):
def _real_initialize(self):
auth = self._get_cookies('https://www.gaia.com/').get('auth')
if auth:
auth = self._parse_json(
compat_urllib_parse_unquote(auth.value),
None, fatal=False)
if not auth:
username, password = self._get_login_info()
if username is None:
return
auth = self._download_json(
'https://auth.gaia.com/v1/login',
None, data=urlencode_postdata({
'username': username,
'password': password
}))
if auth.get('success') is False:
raise ExtractorError(', '.join(auth['messages']), expected=True)
if auth:
auth = self._parse_json(compat_urllib_parse_unquote(auth.value), None, fatal=False)
self._jwt = auth.get('jwt')
def _perform_login(self, username, password):
if self._jwt:
return
auth = self._download_json(
'https://auth.gaia.com/v1/login',
None, data=urlencode_postdata({
'username': username,
'password': password
}))
if auth.get('success') is False:
raise ExtractorError(', '.join(auth['messages']), expected=True)
self._jwt = auth.get('jwt')
def _real_extract(self, url):
display_id, vtype = self._match_valid_url(url).groups()
node_id = self._download_json(

@ -153,6 +153,7 @@ class GenericIE(InfoExtractor):
IE_DESC = 'Generic downloader that works on some sites'
_VALID_URL = r'.*'
IE_NAME = 'generic'
_NETRC_MACHINE = False # Supress username warning
_TESTS = [
# Direct link to a video
{

@ -35,18 +35,14 @@ class HiDiveIE(InfoExtractor):
'skip': 'Requires Authentication',
}]
def _real_initialize(self):
email, password = self._get_login_info()
if email is None:
return
def _perform_login(self, username, password):
webpage = self._download_webpage(self._LOGIN_URL, None)
form = self._search_regex(
r'(?s)<form[^>]+action="/account/login"[^>]*>(.+?)</form>',
webpage, 'login form')
data = self._hidden_inputs(form)
data.update({
'Email': email,
'Email': username,
'Password': password,
})
self._download_webpage(

@ -27,8 +27,9 @@ class HRTiBaseIE(InfoExtractor):
_APP_VERSION = '1.1'
_APP_PUBLICATION_ID = 'all_in_one'
_API_URL = 'http://clientapi.hrt.hr/client_api.php/config/identify/format/json'
_token = None
def _initialize_api(self):
def _initialize_pre_login(self):
init_data = {
'application_publication_id': self._APP_PUBLICATION_ID
}
@ -64,12 +65,7 @@ class HRTiBaseIE(InfoExtractor):
self._logout_url = modules['user']['resources']['logout']['uri']
def _login(self):
username, password = self._get_login_info()
# TODO: figure out authentication with cookies
if username is None or password is None:
self.raise_login_required()
def _perform_login(self, username, password):
auth_data = {
'username': username,
'password': password,
@ -94,8 +90,9 @@ class HRTiBaseIE(InfoExtractor):
self._token = auth_info['secure_streaming_token']
def _real_initialize(self):
self._initialize_api()
self._login()
if not self._token:
# TODO: figure out authentication with cookies
self.raise_login_required(method='password')
class HRTiIE(HRTiBaseIE):

@ -21,25 +21,26 @@ class ImgGamingBaseIE(InfoExtractor):
_REALM = None
_VALID_URL_TEMPL = r'https?://(?P<domain>%s)/(?P<type>live|playlist|video)/(?P<id>\d+)(?:\?.*?\bplaylistId=(?P<playlist_id>\d+))?'
def _real_initialize(self):
def _initialize_pre_login(self):
self._HEADERS = {
'Realm': 'dce.' + self._REALM,
'x-api-key': self._API_KEY,
}
email, password = self._get_login_info()
if email is None:
self.raise_login_required()
def _perform_login(self, username, password):
p_headers = self._HEADERS.copy()
p_headers['Content-Type'] = 'application/json'
self._HEADERS['Authorization'] = 'Bearer ' + self._download_json(
self._API_BASE + 'login',
None, 'Logging in', data=json.dumps({
'id': email,
'id': username,
'secret': password,
}).encode(), headers=p_headers)['authorisationToken']
def _real_initialize(self):
if not self._HEADERS.get('Authorization'):
self.raise_login_required(method='password')
def _call_api(self, path, media_id):
return self._download_json(
self._API_BASE + path + media_id, media_id, headers=self._HEADERS)

@ -29,9 +29,8 @@ class InstagramBaseIE(InfoExtractor):
_NETRC_MACHINE = 'instagram'
_IS_LOGGED_IN = False
def _login(self):
username, password = self._get_login_info()
if username is None or self._IS_LOGGED_IN:
def _perform_login(self, username, password):
if self._IS_LOGGED_IN:
return
login_webpage = self._download_webpage(
@ -72,9 +71,6 @@ class InstagramBaseIE(InfoExtractor):
raise ExtractorError('Unable to login')
InstagramBaseIE._IS_LOGGED_IN = True
def _real_initialize(self):
self._login()
def _get_count(self, media, kind, *keys):
return traverse_obj(
media, (kind, 'count'), *((f'edge_media_{key}', 'count') for key in keys),

@ -65,11 +65,9 @@ class IPrimaIE(InfoExtractor):
'only_matching': True,
}]
def _login(self):
username, password = self._get_login_info()
if username is None or password is None:
self.raise_login_required('Login is required to access any iPrima content', method='password')
def _perform_login(self, username, password):
if self.access_token:
return
login_page = self._download_webpage(
self._LOGIN_URL, None, note='Downloading login page',
@ -105,16 +103,16 @@ class IPrimaIE(InfoExtractor):
if self.access_token is None:
raise ExtractorError('Getting token failed', expected=True)
def _real_initialize(self):
if not self.access_token:
self.raise_login_required('Login is required to access any iPrima content', method='password')
def _raise_access_error(self, error_code):
if error_code == 'PLAY_GEOIP_DENIED':
self.raise_geo_restricted(countries=['CZ'], metadata_available=True)
elif error_code is not None:
self.raise_no_formats('Access to stream infos forbidden', expected=True)
def _real_initialize(self):
if not self.access_token:
self._login()
def _real_extract(self, url):
video_id = self._match_id(url)

@ -241,9 +241,6 @@ class IqiyiIE(InfoExtractor):
'18': 7, # 1080p
}
def _real_initialize(self):
self._login()
@staticmethod
def _rsa_fun(data):
# public key extracted from http://static.iqiyi.com/js/qiyiV2/20160129180840/jobs/i18n/i18nIndex.js
@ -252,12 +249,7 @@ class IqiyiIE(InfoExtractor):
return ohdave_rsa_encrypt(data, e, N)
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
def _perform_login(self, username, password):
data = self._download_json(
'http://kylin.iqiyi.com/get_token', None,

@ -22,14 +22,7 @@ class LecturioBaseIE(InfoExtractor):
_LOGIN_URL = 'https://app.lecturio.com/en/login'
_NETRC_MACHINE = 'lecturio'
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
# Sets some cookies
_, urlh = self._download_webpage_handle(
self._LOGIN_URL, None, 'Downloading login popup')

@ -25,12 +25,9 @@ class LinkedInBaseIE(InfoExtractor):
_NETRC_MACHINE = 'linkedin'
_logged_in = False
def _real_initialize(self):
def _perform_login(self, username, password):
if self._logged_in:
return
email, password = self._get_login_info()
if email is None:
return
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')
@ -39,7 +36,7 @@ class LinkedInBaseIE(InfoExtractor):
default='https://www.linkedin.com/uas/login-submit', group='url'))
data = self._hidden_inputs(login_page)
data.update({
'session_key': email,
'session_key': username,
'session_password': password,
})
login_submit_page = self._download_webpage(

@ -75,14 +75,7 @@ class LinuxAcademyIE(InfoExtractor):
_CLIENT_ID = 'KaWxNn1C2Gc7n83W9OFeXltd8Utb5vvx'
_NETRC_MACHINE = 'linuxacademy'
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
def random_string():
return ''.join([
random.choice('0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~')

@ -21,9 +21,6 @@ class LyndaBaseIE(InfoExtractor):
_ACCOUNT_CREDENTIALS_HINT = 'Use --username and --password options to provide lynda.com account credentials.'
_NETRC_MACHINE = 'lynda'
def _real_initialize(self):
self._login()
@staticmethod
def _check_error(json_string, key_or_keys):
keys = [key_or_keys] if isinstance(key_or_keys, compat_str) else key_or_keys
@ -32,7 +29,7 @@ class LyndaBaseIE(InfoExtractor):
if error:
raise ExtractorError('Unable to login: %s' % error, expected=True)
def _login_step(self, form_html, fallback_action_url, extra_form_data, note, referrer_url):
def _perform_login_step(self, form_html, fallback_action_url, extra_form_data, note, referrer_url):
action_url = self._search_regex(
r'<form[^>]+action=(["\'])(?P<url>.+?)\1', form_html,
'post url', default=fallback_action_url, group='url')
@ -55,11 +52,7 @@ class LyndaBaseIE(InfoExtractor):
return response, action_url
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
# Step 1: download signin page
signin_page = self._download_webpage(
self._SIGNIN_URL, None, 'Downloading signin page')

@ -148,14 +148,12 @@ class NebulaBaseIE(InfoExtractor):
'creator': episode['channel_title'],
}
def _login(self):
def _perform_login(self, username=None, password=None):
# FIXME: username should be passed from here to inner functions
self._nebula_api_token = self._retrieve_nebula_api_token()
self._nebula_bearer_token = self._fetch_nebula_bearer_token()
self._zype_access_token = self._fetch_zype_access_token()
def _real_initialize(self):
self._login()
class NebulaIE(NebulaBaseIE):
_VALID_URL = r'https?://(?:www\.)?(?:watchnebula\.com|nebula\.app)/videos/(?P<id>[-\w]+)'

@ -183,16 +183,7 @@ class NiconicoIE(InfoExtractor):
'Origin': 'https://www.nicovideo.jp',
}
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
# Log in
def _perform_login(self, username, password):
login_ok = True
login_form_strs = {
'mail_tel': username,

@ -43,15 +43,7 @@ class NJPWWorldIE(InfoExtractor):
_LOGIN_URL = 'https://front.njpwworld.com/auth/login'
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
# No authentication to be performed
if not username:
return True
def _perform_login(self, username, password):
# Setup session (will set necessary cookies)
self._request_webpage(
'https://njpwworld.com/', None, note='Setting up session')

@ -61,14 +61,7 @@ class NocoIE(InfoExtractor):
}
]
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login = self._download_json(
self._LOGIN_URL, None, 'Logging in',
data=urlencode_postdata({

@ -47,10 +47,7 @@ class PacktPubIE(PacktPubBaseIE):
_NETRC_MACHINE = 'packtpub'
_TOKEN = None
def _real_initialize(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
try:
self._TOKEN = self._download_json(
'https://services.packtpub.com/auth-v1/users/tokens', None,

@ -88,11 +88,7 @@ class PatreonIE(InfoExtractor):
# Currently Patreon exposes download URL via hidden CSS, so login is not
# needed. Keeping this commented for when this inevitably changes.
'''
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_form = {
'redirectUrl': 'http://www.patreon.com/',
'email': username,
@ -108,8 +104,6 @@ class PatreonIE(InfoExtractor):
if re.search(r'onLoginFailed', login_page):
raise ExtractorError('Unable to login, incorrect username and/or password', expected=True)
def _real_initialize(self):
self._login()
'''
def _real_extract(self, url):

@ -29,13 +29,9 @@ class PiaproIE(InfoExtractor):
}
}]
def _real_initialize(self):
self._login_status = self._login()
_login_status = False
def _login(self):
username, password = self._get_login_info()
if not username:
return False
def _perform_login(self, username, password):
login_ok = True
login_form_strs = {
'_username': username,
@ -57,7 +53,7 @@ class PiaproIE(InfoExtractor):
if not login_ok:
self.report_warning(
'unable to log in: bad username or password')
return login_ok
self._login_status = login_ok
def _real_extract(self, url):
video_id = self._match_id(url)

@ -22,14 +22,7 @@ class PlatziBaseIE(InfoExtractor):
_LOGIN_URL = 'https://platzi.com/login/'
_NETRC_MACHINE = 'platzi'
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')

@ -38,14 +38,10 @@ class PlayPlusTVIE(InfoExtractor):
'Authorization': 'Bearer ' + self._token,
}, query=query)
def _real_initialize(self):
email, password = self._get_login_info()
if email is None:
self.raise_login_required()
def _perform_login(self, username, password):
req = PUTRequest(
'https://api.playplus.tv/api/web/login', json.dumps({
'email': email,
'email': username,
'password': password,
}).encode(), {
'Content-Type': 'application/json; charset=utf-8',
@ -61,6 +57,10 @@ class PlayPlusTVIE(InfoExtractor):
self._profile = self._call_api('Profiles')['list'][0]['_id']
def _real_initialize(self):
if not self._token:
self.raise_login_required(method='password')
def _real_extract(self, url):
project_id, media_id = self._match_valid_url(url).groups()
media = self._call_api(

@ -162,14 +162,7 @@ query viewClip {
}
}'''
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')

@ -15,11 +15,9 @@ class PokerGoBaseIE(InfoExtractor):
_AUTH_TOKEN = None
_PROPERTY_ID = '1dfb3940-7d53-4980-b0b0-f28b369a000d'
def _login(self):
username, password = self._get_login_info()
if not username:
self.raise_login_required(method='password')
def _perform_login(self, username, password):
if self._AUTH_TOKEN:
return
self.report_login()
PokerGoBaseIE._AUTH_TOKEN = self._download_json(
f'https://subscription.pokergo.com/properties/{self._PROPERTY_ID}/sign-in', None,
@ -30,7 +28,7 @@ class PokerGoBaseIE(InfoExtractor):
def _real_initialize(self):
if not self._AUTH_TOKEN:
self._login()
self.raise_login_required(method='password')
class PokerGoIE(PokerGoBaseIE):

@ -21,10 +21,7 @@ class RoosterTeethBaseIE(InfoExtractor):
_API_BASE = 'https://svod-be.roosterteeth.com'
_API_BASE_URL = f'{_API_BASE}/api/v1'
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
if self._get_cookies(self._API_BASE_URL).get('rt_access_token'):
return
@ -47,9 +44,6 @@ class RoosterTeethBaseIE(InfoExtractor):
msg += ': ' + error
self.report_warning(msg)
def _real_initialize(self):
self._login()
def _extract_video_info(self, data):
thumbnails = []
for image in traverse_obj(data, ('included', 'images')):

@ -25,14 +25,7 @@ class SafariBaseIE(InfoExtractor):
LOGGED_IN = False
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
_, urlh = self._download_webpage_handle(
'https://learning.oreilly.com/accounts/login-check/', None,
'Downloading login page')

@ -14,14 +14,7 @@ class SCTEBaseIE(InfoExtractor):
_LOGIN_URL = 'https://www.scte.org/SCTE/Sign_In.aspx'
_NETRC_MACHINE = 'scte'
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_popup = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login popup')

@ -79,16 +79,12 @@ class ShahidIE(ShahidBaseIE):
'only_matching': True
}]
def _real_initialize(self):
email, password = self._get_login_info()
if email is None:
return
def _perform_login(self, username, password):
try:
user_data = self._download_json(
'https://shahid.mbc.net/wd/service/users/login',
None, 'Logging in', data=json.dumps({
'email': email,
'email': username,
'password': password,
'basic': 'false',
}).encode('utf-8'), headers={

@ -75,9 +75,12 @@ class SonyLIVIE(InfoExtractor):
t[i] = '{:x}'.format(3 & n | 8)
return ''.join(t) + '-' + str(int(time.time() * 1000))
def _login(self, username, password):
def _perform_login(self, username, password):
self._HEADERS['device_id'] = self._get_device_id()
self._HEADERS['content-type'] = 'application/json'
if username.lower() == 'token' and len(password) > 1198:
return password
self._HEADERS['authorization'] = password
elif len(username) != 10 or not username.isdigit():
raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}')
@ -99,7 +102,7 @@ class SonyLIVIE(InfoExtractor):
None, note='Verifying OTP', data=data.encode(), headers=self._HEADERS)
if otp_verify_json['resultCode'] == 'KO':
raise ExtractorError(otp_request_json['message'], expected=True)
return otp_verify_json['resultObj']['accessToken']
self._HEADERS['authorization'] = otp_verify_json['resultObj']['accessToken']
def _call_api(self, version, path, video_id):
try:
@ -118,13 +121,8 @@ class SonyLIVIE(InfoExtractor):
raise ExtractorError(message)
raise
def _real_initialize(self):
def _initialize_pre_login(self):
self._HEADERS['security_token'] = self._call_api('1.4', 'ALL/GETTOKEN', None)
username, password = self._get_login_info()
if username:
self._HEADERS['device_id'] = self._get_device_id()
self._HEADERS['content-type'] = 'application/json'
self._HEADERS['authorization'] = self._login(username, password)
def _real_extract(self, url):
video_id = self._match_id(url)

@ -107,30 +107,24 @@ class SoundcloudBaseIE(InfoExtractor):
return False
raise
def _real_initialize(self):
def _initialize_pre_login(self):
self._CLIENT_ID = self._downloader.cache.load('soundcloud', 'client_id') or 'a3e059563d7fd3372b49b37f00a00bcf'
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
if username == 'oauth' and password is not None:
self._access_token = password
query = self._API_AUTH_QUERY_TEMPLATE % self._CLIENT_ID
payload = {'session': {'access_token': self._access_token}}
token_verification = sanitized_Request(self._API_VERIFY_AUTH_TOKEN % query, json.dumps(payload).encode('utf-8'))
response = self._download_json(token_verification, None, note='Verifying login token...', fatal=False)
if response is not False:
self._HEADERS = {'Authorization': 'OAuth ' + self._access_token}
self.report_login()
else:
self.report_warning('Provided authorization token seems to be invalid. Continue as guest')
elif username is not None:
def _perform_login(self, username, password):
if username != 'oauth':
self.report_warning(
'Login using username and password is not currently supported. '
'Use "--username oauth --password <oauth_token>" to login using an oauth token')
self._access_token = password
query = self._API_AUTH_QUERY_TEMPLATE % self._CLIENT_ID
payload = {'session': {'access_token': self._access_token}}
token_verification = sanitized_Request(self._API_VERIFY_AUTH_TOKEN % query, json.dumps(payload).encode('utf-8'))
response = self._download_json(token_verification, None, note='Verifying login token...', fatal=False)
if response is not False:
self._HEADERS = {'Authorization': 'OAuth ' + self._access_token}
self.report_login()
else:
self.report_warning('Provided authorization token seems to be invalid. Continue as guest')
r'''
def genDevId():

@ -40,8 +40,7 @@ class TeachableBaseIE(InfoExtractor):
if self._logged_in:
return
username, password = self._get_login_info(
netrc_machine=self._SITES.get(site, site))
username, password = self._get_login_info(netrc_machine=self._SITES.get(site, site))
if username is None:
return

@ -51,17 +51,14 @@ class TeamTreeHouseIE(InfoExtractor):
}]
_NETRC_MACHINE = 'teamtreehouse'
def _real_initialize(self):
email, password = self._get_login_info()
if email is None:
return
def _perform_login(self, username, password):
signin_page = self._download_webpage(
'https://teamtreehouse.com/signin',
None, 'Downloading signin page')
data = self._form_hidden_inputs('new_user_session', signin_page)
data.update({
'user_session[email]': email,
'user_session[email]': username,
'user_session[password]': password,
})
error_message = get_element_by_class('error-message', self._download_webpage(

@ -30,11 +30,9 @@ class TennisTVIE(InfoExtractor):
'skip': 'Requires email and password of a subscribed account',
}
_NETRC_MACHINE = 'tennistv'
_session_token = None
def _login(self):
username, password = self._get_login_info()
if not username or not password:
raise ExtractorError('No login info available, needed for using %s.' % self.IE_NAME, expected=True)
def _perform_login(self, username, password):
login_form = {
'Email': username,
@ -63,7 +61,8 @@ class TennisTVIE(InfoExtractor):
self._session_token = login_result['sessionToken']
def _real_initialize(self):
self._login()
if not self._session_token:
raise self.raise_login_required('Login info is needed for this website', method='password')
def _real_extract(self, url):
video_id = self._match_id(url)

@ -40,17 +40,14 @@ class TouTvIE(RadioCanadaIE):
}]
_CLIENT_KEY = '90505c8d-9c34-4f34-8da1-3a85bdc6d4f4'
def _real_initialize(self):
email, password = self._get_login_info()
if email is None:
return
def _perform_login(self, username, password):
try:
self._access_token = self._download_json(
'https://services.radio-canada.ca/toutv/profiling/accounts/login',
None, 'Logging in', data=json.dumps({
'ClientId': self._CLIENT_KEY,
'ClientSecret': '34026772-244b-49b6-8b06-317b30ac9a20',
'Email': email,
'Email': username,
'Password': password,
'Scope': 'id.write media-validation.read',
}).encode(), headers={

@ -54,10 +54,7 @@ class TubiTvIE(InfoExtractor):
},
}]
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
self.report_login()
form_data = {
'username': username,
@ -72,9 +69,6 @@ class TubiTvIE(InfoExtractor):
raise ExtractorError(
'Login failed (invalid username/password)', expected=True)
def _real_initialize(self):
self._login()
def _real_extract(self, url):
video_id = self._match_id(url)
video_data = self._download_json(

@ -247,11 +247,7 @@ class TumblrIE(InfoExtractor):
_ACCESS_TOKEN = None
def _real_initialize(self):
self.get_access_token()
self._login()
def get_access_token(self):
def _initialize_pre_login(self):
login_page = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page', fatal=False)
if login_page:
@ -260,11 +256,7 @@ class TumblrIE(InfoExtractor):
if not self._ACCESS_TOKEN:
self.report_warning('Failed to get access token; metadata will be missing and some videos may not work')
def _login(self):
username, password = self._get_login_info()
if not username:
return
def _perform_login(self, username, password):
if not self._ACCESS_TOKEN:
return

@ -57,14 +57,7 @@ class TwitchBaseIE(InfoExtractor):
'VideoPlayer_ChapterSelectButtonVideo': '8d2793384aac3773beab5e59bd5d6f585aedb923d292800119e03d40cd0f9b41',
}
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
def fail(message):
raise ExtractorError(
'Unable to login. Twitch said: %s' % message, expected=True)

@ -168,14 +168,7 @@ class UdemyIE(InfoExtractor):
self._handle_error(response)
return response
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_popup = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login popup')

@ -23,11 +23,7 @@ class VidioBaseIE(InfoExtractor):
_LOGIN_URL = 'https://www.vidio.com/users/login'
_NETRC_MACHINE = 'vidio'
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
def is_logged_in():
res = self._download_json(
'https://www.vidio.com/interactions.json', None, 'Checking if logged in', fatal=False) or {}
@ -63,10 +59,9 @@ class VidioBaseIE(InfoExtractor):
'Unable to log in: %s. %s' % (reason, clean_html(subreason)), expected=True)
raise ExtractorError('Unable to log in')
def _real_initialize(self):
def _initialize_pre_login(self):
self._api_key = self._download_json(
'https://www.vidio.com/auth', None, data=b'')['api_key']
self._login()
def _call_api(self, url, video_id, note=None):
return self._download_json(url, video_id, note=note, headers={

@ -36,9 +36,6 @@ class ViewLiftBaseIE(InfoExtractor):
def _fetch_token(self, site, url):
if self._TOKENS.get(site):
return
email, password = self._get_login_info(netrc_machine=site)
if email:
self.report_warning('Logging in using username and password is broken. %s' % self._LOGIN_HINTS['cookies'])
cookies = self._get_cookies(url)
if cookies and cookies.get('token'):

@ -99,14 +99,7 @@ class VikiBaseIE(InfoExtractor):
self.raise_login_required(message)
self._raise_error(message)
def _real_initialize(self):
self._login()
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
self._token = self._call_api(
'sessions.json', None, 'Logging in', fatal=False,
data={'username': username, 'password': password}).get('token')

@ -44,12 +44,7 @@ class VimeoBaseInfoExtractor(InfoExtractor):
_LOGIN_REQUIRED = False
_LOGIN_URL = 'https://vimeo.com/log_in'
def _login(self):
username, password = self._get_login_info()
if username is None:
if self._LOGIN_REQUIRED:
raise ExtractorError('No login info available, needed for using %s.' % self.IE_NAME, expected=True)
return
def _perform_login(self, username, password):
webpage = self._download_webpage(
self._LOGIN_URL, None, 'Downloading login page')
token, vuid = self._extract_xsrft_and_vuid(webpage)
@ -75,6 +70,10 @@ class VimeoBaseInfoExtractor(InfoExtractor):
expected=True)
raise ExtractorError('Unable to log in')
def _real_initialize(self):
if self._LOGIN_REQUIRED and not self._get_cookies('https://vimeo.com').get('vuid'):
self._raise_login_required()
def _get_video_password(self):
password = self.get_param('videopassword')
if password is None:
@ -701,9 +700,6 @@ class VimeoIE(VimeoBaseInfoExtractor):
raise ExtractorError('Wrong video password', expected=True)
return checked
def _real_initialize(self):
self._login()
def _extract_from_api(self, video_id, unlisted_hash=None):
token = self._download_json(
'https://vimeo.com/_rv/jwt', video_id, headers={
@ -1231,9 +1227,6 @@ class VimeoReviewIE(VimeoBaseInfoExtractor):
'skip': 'video gone',
}]
def _real_initialize(self):
self._login()
def _real_extract(self, url):
page_url, video_id = self._match_valid_url(url).groups()
data = self._download_json(
@ -1275,9 +1268,6 @@ class VimeoWatchLaterIE(VimeoChannelIE):
'only_matching': True,
}]
def _real_initialize(self):
self._login()
def _page_url(self, base_url, pagenum):
url = '%s/page:%d/' % (base_url, pagenum)
request = sanitized_Request(url)

@ -29,11 +29,7 @@ from .youtube import YoutubeIE
class VKBaseIE(InfoExtractor):
_NETRC_MACHINE = 'vk'
def _login(self):
username, password = self._get_login_info()
if username is None:
return
def _perform_login(self, username, password):
login_page, url_handle = self._download_webpage_handle(
'https://vk.com', None, 'Downloading login page')
@ -57,9 +53,6 @@ class VKBaseIE(InfoExtractor):
raise ExtractorError(
'Unable to login, incorrect username and/or password', expected=True)
def _real_initialize(self):
self._login()
def _download_payload(self, path, video_id, data, fatal=True):
data['al'] = 1
code, payload = self._download_json(

@ -26,22 +26,16 @@ class VLiveBaseIE(NaverBaseIE):
_NETRC_MACHINE = 'vlive'
_logged_in = False
def _real_initialize(self):
if not self._logged_in:
VLiveBaseIE._logged_in = self._login()
def _login(self):
email, password = self._get_login_info()
if email is None:
return False
def _perform_login(self, username, password):
if self._logged_in:
return
LOGIN_URL = 'https://www.vlive.tv/auth/email/login'
self._request_webpage(
LOGIN_URL, None, note='Downloading login cookies')
self._download_webpage(
LOGIN_URL, None, note='Logging in',
data=urlencode_postdata({'email': email, 'pwd': password}),
data=urlencode_postdata({'email': username, 'pwd': password}),
headers={
'Referer': LOGIN_URL,
'Content-Type': 'application/x-www-form-urlencoded'
@ -54,7 +48,7 @@ class VLiveBaseIE(NaverBaseIE):
if not try_get(login_info, lambda x: x['message']['login'], bool):
raise ExtractorError('Unable to log in', expected=True)
return True
VLiveBaseIE._logged_in = True
def _call_api(self, path_template, video_id, fields=None, query_add={}, note=None):
if note is None:

@ -85,7 +85,7 @@ class VRVBaseIE(InfoExtractor):
'resource_key': resource_key,
})['__links__']['cms_resource']['href']
def _real_initialize(self):
def _initialize_pre_login(self):
webpage = self._download_webpage(
'https://vrv.co/', None, headers=self.geo_verification_headers())
self._API_PARAMS = self._parse_json(self._search_regex(
@ -124,16 +124,10 @@ class VRVIE(VRVBaseIE):
}]
_NETRC_MACHINE = 'vrv'
def _real_initialize(self):
super(VRVIE, self)._real_initialize()
email, password = self._get_login_info()
if email is None:
return
def _perform_login(self, username, password):
token_credentials = self._call_api(
'authenticate/by:credentials', None, 'Token Credentials', data={
'email': email,
'email': username,
'password': password,
})
self._TOKEN = token_credentials['oauth_token']

@ -263,7 +263,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
_PLAYLIST_ID_RE = r'(?:(?:PL|LL|EC|UU|FL|RD|UL|TL|PU|OLAK5uy_)[0-9A-Za-z-_]{10,}|RDMM|WL|LL|LM)'
_NETRC_MACHINE = 'youtube'
# _NETRC_MACHINE = 'youtube'
# If True it will raise an error if no login info is provided
_LOGIN_REQUIRED = False
@ -334,21 +334,6 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
r'(?:www\.)?hpniueoejy4opn7bc4ftgazyqjoeqwlvh2uiku2xqku6zpoa4bf5ruid\.onion',
)
def _login(self):
"""
Attempt to log in to YouTube.
If _LOGIN_REQUIRED is set and no authentication was provided, an error is raised.
"""
if (self._LOGIN_REQUIRED
and self.get_param('cookiefile') is None
and self.get_param('cookiesfrombrowser') is None):
self.raise_login_required(
'Login details are needed to download this content', method='cookies')
username, password = self._get_login_info()
if username:
self.report_warning(f'Cannot login to YouTube using username and password. {self._LOGIN_HINTS["cookies"]}')
def _initialize_consent(self):
cookies = self._get_cookies('https://www.youtube.com/')
if cookies.get('__Secure-3PSID'):
@ -379,7 +364,10 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
def _real_initialize(self):
self._initialize_pref()
self._initialize_consent()
self._login()
if (self._LOGIN_REQUIRED
and self.get_param('cookiefile') is None
and self.get_param('cookiesfrombrowser') is None):
self.raise_login_required('Login details are needed to download this content', method='cookies')
_YT_INITIAL_DATA_RE = r'(?:window\s*\[\s*["\']ytInitialData["\']\s*\]|ytInitialData)\s*=\s*({.+?})\s*;'
_YT_INITIAL_PLAYER_RESPONSE_RE = r'ytInitialPlayerResponse\s*=\s*({.+?})\s*;'
@ -3928,6 +3916,7 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
if entry:
yield entry
'''
def _extract_entries(self, parent_renderer, continuation_list):
# continuation_list is modified in-place with continuation_list = [continuation_token]
continuation_list[:] = [None]

@ -25,13 +25,11 @@ class ZattooPlatformBaseIE(InfoExtractor):
def _host_url(self):
return 'https://%s' % (self._API_HOST if hasattr(self, '_API_HOST') else self._HOST)
def _login(self):
username, password = self._get_login_info()
if not username or not password:
self.raise_login_required(
'A valid %s account is needed to access this media.'
% self._NETRC_MACHINE)
def _real_initialize(self):
if not self._power_guide_hash:
self.raise_login_required('An account is needed to access this media', method='password')
def _perform_login(self, username, password):
try:
data = self._download_json(
'%s/zapi/v2/account/login' % self._host_url(), None, 'Logging in',
@ -52,7 +50,7 @@ class ZattooPlatformBaseIE(InfoExtractor):
self._power_guide_hash = data['session']['power_guide_hash']
def _real_initialize(self):
def _initialize_pre_login(self):
webpage = self._download_webpage(
self._host_url(), None, 'Downloading app token')
app_token = self._html_search_regex(
@ -72,8 +70,6 @@ class ZattooPlatformBaseIE(InfoExtractor):
'format': 'json',
}))
self._login()
def _extract_cid(self, video_id, channel_name):
channel_groups = self._download_json(
'%s/zapi/v2/cached/channels/%s' % (self._host_url(),

@ -93,32 +93,27 @@ class Zee5IE(InfoExtractor):
_NETRC_MACHINE = 'zee5'
_GEO_COUNTRIES = ['IN']
def _login(self):
username, password = self._get_login_info()
if username:
if len(username) == 10 and username.isdigit() and self._USER_TOKEN is None:
self.report_login()
otp_request_json = self._download_json('https://b2bapi.zee5.com/device/sendotp_v1.php?phoneno=91{}'.format(username),
None, note='Sending OTP')
if otp_request_json['code'] == 0:
self.to_screen(otp_request_json['message'])
else:
raise ExtractorError(otp_request_json['message'], expected=True)
otp_code = self._get_tfa_info('OTP')
otp_verify_json = self._download_json('https://b2bapi.zee5.com/device/verifyotp_v1.php?phoneno=91{}&otp={}&guest_token={}&platform=web'.format(username, otp_code, self._DEVICE_ID),
None, note='Verifying OTP', fatal=False)
if not otp_verify_json:
raise ExtractorError('Unable to verify OTP.', expected=True)
self._USER_TOKEN = otp_verify_json.get('token')
if not self._USER_TOKEN:
raise ExtractorError(otp_request_json['message'], expected=True)
elif username.lower() == 'token' and len(password) > 1198:
self._USER_TOKEN = password
def _perform_login(self, username, password):
if len(username) == 10 and username.isdigit() and self._USER_TOKEN is None:
self.report_login()
otp_request_json = self._download_json('https://b2bapi.zee5.com/device/sendotp_v1.php?phoneno=91{}'.format(username),
None, note='Sending OTP')
if otp_request_json['code'] == 0:
self.to_screen(otp_request_json['message'])
else:
raise ExtractorError(self._LOGIN_HINT, expected=True)
def _real_initialize(self):
self._login()
raise ExtractorError(otp_request_json['message'], expected=True)
otp_code = self._get_tfa_info('OTP')
otp_verify_json = self._download_json('https://b2bapi.zee5.com/device/verifyotp_v1.php?phoneno=91{}&otp={}&guest_token={}&platform=web'.format(username, otp_code, self._DEVICE_ID),
None, note='Verifying OTP', fatal=False)
if not otp_verify_json:
raise ExtractorError('Unable to verify OTP.', expected=True)
self._USER_TOKEN = otp_verify_json.get('token')
if not self._USER_TOKEN:
raise ExtractorError(otp_request_json['message'], expected=True)
elif username.lower() == 'token' and len(password) > 1198:
self._USER_TOKEN = password
else:
raise ExtractorError(self._LOGIN_HINT, expected=True)
def _real_extract(self, url):
video_id, display_id = self._match_valid_url(url).group('id', 'display_id')

Loading…
Cancel
Save