aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpukkandan <pukkandan.ytdlp@gmail.com>2022-03-19 02:23:33 +0530
committerGitHub <noreply@github.com>2022-03-18 13:53:33 -0700
commit52efa4b31200119adaa8acf33e50b84fcb6948f0 (patch)
treef1963a4ade1111db9db8edea8fff0a7c58923cf9
parent028f6437f1cb45bb9b3b286cba173b0588337feb (diff)
downloadhypervideo-pre-52efa4b31200119adaa8acf33e50b84fcb6948f0.tar.lz
hypervideo-pre-52efa4b31200119adaa8acf33e50b84fcb6948f0.tar.xz
hypervideo-pre-52efa4b31200119adaa8acf33e50b84fcb6948f0.zip
[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
-rw-r--r--test/test_iqiyi_sdk_interpreter.py9
-rw-r--r--test/test_netrc.py13
-rw-r--r--yt_dlp/extractor/abematv.py10
-rw-r--r--yt_dlp/extractor/adn.py5
-rw-r--r--yt_dlp/extractor/afreecatv.py9
-rw-r--r--yt_dlp/extractor/alura.py9
-rw-r--r--yt_dlp/extractor/animelab.py35
-rw-r--r--yt_dlp/extractor/animeondemand.py9
-rw-r--r--yt_dlp/extractor/atresplayer.py9
-rw-r--r--yt_dlp/extractor/bbc.py9
-rw-r--r--yt_dlp/extractor/bilibili.py9
-rw-r--r--yt_dlp/extractor/canvas.py9
-rw-r--r--yt_dlp/extractor/common.py42
-rw-r--r--yt_dlp/extractor/crunchyroll.py8
-rw-r--r--yt_dlp/extractor/curiositystream.py7
-rw-r--r--yt_dlp/extractor/digitalconcerthall.py8
-rw-r--r--yt_dlp/extractor/eroprofile.py9
-rw-r--r--yt_dlp/extractor/facebook.py11
-rw-r--r--yt_dlp/extractor/fancode.py38
-rw-r--r--yt_dlp/extractor/frontendmasters.py9
-rw-r--r--yt_dlp/extractor/funimation.py13
-rw-r--r--yt_dlp/extractor/gaia.py30
-rw-r--r--yt_dlp/extractor/generic.py1
-rw-r--r--yt_dlp/extractor/hidive.py8
-rw-r--r--yt_dlp/extractor/hrti.py15
-rw-r--r--yt_dlp/extractor/imggaming.py13
-rw-r--r--yt_dlp/extractor/instagram.py8
-rw-r--r--yt_dlp/extractor/iprima.py16
-rw-r--r--yt_dlp/extractor/iqiyi.py10
-rw-r--r--yt_dlp/extractor/lecturio.py9
-rw-r--r--yt_dlp/extractor/linkedin.py7
-rw-r--r--yt_dlp/extractor/linuxacademy.py9
-rw-r--r--yt_dlp/extractor/lynda.py11
-rw-r--r--yt_dlp/extractor/nebula.py6
-rw-r--r--yt_dlp/extractor/niconico.py11
-rw-r--r--yt_dlp/extractor/njpwworld.py10
-rw-r--r--yt_dlp/extractor/noco.py9
-rw-r--r--yt_dlp/extractor/packtpub.py5
-rw-r--r--yt_dlp/extractor/patreon.py8
-rw-r--r--yt_dlp/extractor/piapro.py10
-rw-r--r--yt_dlp/extractor/platzi.py9
-rw-r--r--yt_dlp/extractor/playplustv.py12
-rw-r--r--yt_dlp/extractor/pluralsight.py9
-rw-r--r--yt_dlp/extractor/pokergo.py10
-rw-r--r--yt_dlp/extractor/roosterteeth.py8
-rw-r--r--yt_dlp/extractor/safari.py9
-rw-r--r--yt_dlp/extractor/scte.py9
-rw-r--r--yt_dlp/extractor/shahid.py8
-rw-r--r--yt_dlp/extractor/sonyliv.py16
-rw-r--r--yt_dlp/extractor/soundcloud.py34
-rw-r--r--yt_dlp/extractor/teachable.py3
-rw-r--r--yt_dlp/extractor/teamtreehouse.py7
-rw-r--r--yt_dlp/extractor/tennistv.py9
-rw-r--r--yt_dlp/extractor/toutv.py7
-rw-r--r--yt_dlp/extractor/tubitv.py8
-rw-r--r--yt_dlp/extractor/tumblr.py12
-rw-r--r--yt_dlp/extractor/twitch.py9
-rw-r--r--yt_dlp/extractor/udemy.py9
-rw-r--r--yt_dlp/extractor/vidio.py9
-rw-r--r--yt_dlp/extractor/viewlift.py3
-rw-r--r--yt_dlp/extractor/viki.py9
-rw-r--r--yt_dlp/extractor/vimeo.py20
-rw-r--r--yt_dlp/extractor/vk.py9
-rw-r--r--yt_dlp/extractor/vlive.py16
-rw-r--r--yt_dlp/extractor/vrv.py12
-rw-r--r--yt_dlp/extractor/youtube.py23
-rw-r--r--yt_dlp/extractor/zattoo.py14
-rw-r--r--yt_dlp/extractor/zee5.py45
68 files changed, 254 insertions, 570 deletions
diff --git a/test/test_iqiyi_sdk_interpreter.py b/test/test_iqiyi_sdk_interpreter.py
index ee039f898..adbae4690 100644
--- a/test/test_iqiyi_sdk_interpreter.py
+++ b/test/test_iqiyi_sdk_interpreter.py
@@ -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])
diff --git a/test/test_netrc.py b/test/test_netrc.py
index 36b943591..94a703406 100644
--- a/test/test_netrc.py
+++ b/test/test_netrc.py
@@ -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)
diff --git a/yt_dlp/extractor/abematv.py b/yt_dlp/extractor/abematv.py
index 360fa4699..a839f0c1f 100644
--- a/yt_dlp/extractor/abematv.py
+++ b/yt_dlp/extractor/abematv.py
@@ -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:
diff --git a/yt_dlp/extractor/adn.py b/yt_dlp/extractor/adn.py
index 0863e0d85..fca6e605d 100644
--- a/yt_dlp/extractor/adn.py
+++ b/yt_dlp/extractor/adn.py
@@ -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,
diff --git a/yt_dlp/extractor/afreecatv.py b/yt_dlp/extractor/afreecatv.py
index e8118d931..77f0e3c10 100644
--- a/yt_dlp/extractor/afreecatv.py
+++ b/yt_dlp/extractor/afreecatv.py
@@ -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',
diff --git a/yt_dlp/extractor/alura.py b/yt_dlp/extractor/alura.py
index f5325de2f..d2e2df270 100644
--- a/yt_dlp/extractor/alura.py
+++ b/yt_dlp/extractor/alura.py
@@ -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')
diff --git a/yt_dlp/extractor/animelab.py b/yt_dlp/extractor/animelab.py
index 4fb7ee424..1c2cc47dd 100644
--- a/yt_dlp/extractor/animelab.py
+++ b/yt_dlp/extractor/animelab.py
@@ -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):
diff --git a/yt_dlp/extractor/animeondemand.py b/yt_dlp/extractor/animeondemand.py
index 5694f7240..2e674d58f 100644
--- a/yt_dlp/extractor/animeondemand.py
+++ b/yt_dlp/extractor/animeondemand.py
@@ -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)
diff --git a/yt_dlp/extractor/atresplayer.py b/yt_dlp/extractor/atresplayer.py
index 6d843966a..465af4ed3 100644
--- a/yt_dlp/extractor/atresplayer.py
+++ b/yt_dlp/extractor/atresplayer.py
@@ -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')
diff --git a/yt_dlp/extractor/bbc.py b/yt_dlp/extractor/bbc.py
index b664a7007..823155730 100644
--- a/yt_dlp/extractor/bbc.py
+++ b/yt_dlp/extractor/bbc.py
@@ -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
diff --git a/yt_dlp/extractor/bilibili.py b/yt_dlp/extractor/bilibili.py
index 1bbf7ca1c..b4eb20642 100644
--- a/yt_dlp/extractor/bilibili.py
+++ b/yt_dlp/extractor/bilibili.py
@@ -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+)'
diff --git a/yt_dlp/extractor/canvas.py b/yt_dlp/extractor/canvas.py
index 82fded4e1..31e7d7de6 100644
--- a/yt_dlp/extractor/canvas.py
+++ b/yt_dlp/extractor/canvas.py
@@ -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',
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index 345da9a72..f3ae3fd4c 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -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):
diff --git a/yt_dlp/extractor/crunchyroll.py b/yt_dlp/extractor/crunchyroll.py
index b6ba5ef56..bf1bf8c1c 100644
--- a/yt_dlp/extractor/crunchyroll.py
+++ b/yt_dlp/extractor/crunchyroll.py
@@ -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)
diff --git a/yt_dlp/extractor/curiositystream.py b/yt_dlp/extractor/curiositystream.py
index 485b6031f..b8abcf7a5 100644
--- a/yt_dlp/extractor/curiositystream.py
+++ b/yt_dlp/extractor/curiositystream.py
@@ -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)
diff --git a/yt_dlp/extractor/digitalconcerthall.py b/yt_dlp/extractor/digitalconcerthall.py
index 9b302a9a0..8398ae30e 100644
--- a/yt_dlp/extractor/digitalconcerthall.py
+++ b/yt_dlp/extractor/digitalconcerthall.py
@@ -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:
diff --git a/yt_dlp/extractor/eroprofile.py b/yt_dlp/extractor/eroprofile.py
index a8396f1d3..5d5e7f244 100644
--- a/yt_dlp/extractor/eroprofile.py
+++ b/yt_dlp/extractor/eroprofile.py
@@ -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)
diff --git a/yt_dlp/extractor/facebook.py b/yt_dlp/extractor/facebook.py
index ef57b221c..2deed585f 100644
--- a/yt_dlp/extractor/facebook.py
+++ b/yt_dlp/extractor/facebook.py
@@ -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)
diff --git a/yt_dlp/extractor/fancode.py b/yt_dlp/extractor/fancode.py
index 978df31ff..7ea16c61d 100644
--- a/yt_dlp/extractor/fancode.py
+++ b/yt_dlp/extractor/fancode.py
@@ -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
diff --git a/yt_dlp/extractor/frontendmasters.py b/yt_dlp/extractor/frontendmasters.py
index 0d29da29b..fc67a8437 100644
--- a/yt_dlp/extractor/frontendmasters.py
+++ b/yt_dlp/extractor/frontendmasters.py
@@ -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')
diff --git a/yt_dlp/extractor/funimation.py b/yt_dlp/extractor/funimation.py
index 96dad2ca3..36a9c4772 100644
--- a/yt_dlp/extractor/funimation.py
+++ b/yt_dlp/extractor/funimation.py
@@ -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():
diff --git a/yt_dlp/extractor/gaia.py b/yt_dlp/extractor/gaia.py
index 7821fb783..5b0195c63 100644
--- a/yt_dlp/extractor/gaia.py
+++ b/yt_dlp/extractor/gaia.py
@@ -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(
diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py
index 6a8b8543b..97e34808f 100644
--- a/yt_dlp/extractor/generic.py
+++ b/yt_dlp/extractor/generic.py
@@ -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
{
diff --git a/yt_dlp/extractor/hidive.py b/yt_dlp/extractor/hidive.py
index 15bd444f9..46d7d62ab 100644
--- a/yt_dlp/extractor/hidive.py
+++ b/yt_dlp/extractor/hidive.py
@@ -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(
diff --git a/yt_dlp/extractor/hrti.py b/yt_dlp/extractor/hrti.py
index dc5b9670c..36d600773 100644
--- a/yt_dlp/extractor/hrti.py
+++ b/yt_dlp/extractor/hrti.py
@@ -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):
diff --git a/yt_dlp/extractor/imggaming.py b/yt_dlp/extractor/imggaming.py
index 230dc86d3..ce7b21ab2 100644
--- a/yt_dlp/extractor/imggaming.py
+++ b/yt_dlp/extractor/imggaming.py
@@ -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)
diff --git a/yt_dlp/extractor/instagram.py b/yt_dlp/extractor/instagram.py
index 3bb786d6a..970f2c8ab 100644
--- a/yt_dlp/extractor/instagram.py
+++ b/yt_dlp/extractor/instagram.py
@@ -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),
diff --git a/yt_dlp/extractor/iprima.py b/yt_dlp/extractor/iprima.py
index 347fec1d5..1a2038453 100644
--- a/yt_dlp/extractor/iprima.py
+++ b/yt_dlp/extractor/iprima.py
@@ -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)
diff --git a/yt_dlp/extractor/iqiyi.py b/yt_dlp/extractor/iqiyi.py
index fdcf14469..dc4667744 100644
--- a/yt_dlp/extractor/iqiyi.py
+++ b/yt_dlp/extractor/iqiyi.py
@@ -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,
diff --git a/yt_dlp/extractor/lecturio.py b/yt_dlp/extractor/lecturio.py
index 9d2228700..0ee1eeb4d 100644
--- a/yt_dlp/extractor/lecturio.py
+++ b/yt_dlp/extractor/lecturio.py
@@ -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')
diff --git a/yt_dlp/extractor/linkedin.py b/yt_dlp/extractor/linkedin.py
index bd76ae166..bf549e164 100644
--- a/yt_dlp/extractor/linkedin.py
+++ b/yt_dlp/extractor/linkedin.py
@@ -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(
diff --git a/yt_dlp/extractor/linuxacademy.py b/yt_dlp/extractor/linuxacademy.py
index 2053970d1..6aff88e13 100644
--- a/yt_dlp/extractor/linuxacademy.py
+++ b/yt_dlp/extractor/linuxacademy.py
@@ -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-._~')
diff --git a/yt_dlp/extractor/lynda.py b/yt_dlp/extractor/lynda.py
index 58cf17239..ce304743f 100644
--- a/yt_dlp/extractor/lynda.py
+++ b/yt_dlp/extractor/lynda.py
@@ -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')
diff --git a/yt_dlp/extractor/nebula.py b/yt_dlp/extractor/nebula.py
index d235805c3..b77ef5f28 100644
--- a/yt_dlp/extractor/nebula.py
+++ b/yt_dlp/extractor/nebula.py
@@ -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]+)'
diff --git a/yt_dlp/extractor/niconico.py b/yt_dlp/extractor/niconico.py
index 77c07417b..74828f833 100644
--- a/yt_dlp/extractor/niconico.py
+++ b/yt_dlp/extractor/niconico.py
@@ -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,
diff --git a/yt_dlp/extractor/njpwworld.py b/yt_dlp/extractor/njpwworld.py
index 89380d039..68c8c8e52 100644
--- a/yt_dlp/extractor/njpwworld.py
+++ b/yt_dlp/extractor/njpwworld.py
@@ -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')
diff --git a/yt_dlp/extractor/noco.py b/yt_dlp/extractor/noco.py
index 78c4952f4..28af909d5 100644
--- a/yt_dlp/extractor/noco.py
+++ b/yt_dlp/extractor/noco.py
@@ -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({
diff --git a/yt_dlp/extractor/packtpub.py b/yt_dlp/extractor/packtpub.py
index c06fca795..62c52cd6e 100644
--- a/yt_dlp/extractor/packtpub.py
+++ b/yt_dlp/extractor/packtpub.py
@@ -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,
diff --git a/yt_dlp/extractor/patreon.py b/yt_dlp/extractor/patreon.py
index d3ee071e0..963a0d6fb 100644
--- a/yt_dlp/extractor/patreon.py
+++ b/yt_dlp/extractor/patreon.py
@@ -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):
diff --git a/yt_dlp/extractor/piapro.py b/yt_dlp/extractor/piapro.py
index 497e1edbc..c4eb4913f 100644
--- a/yt_dlp/extractor/piapro.py
+++ b/yt_dlp/extractor/piapro.py
@@ -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)
diff --git a/yt_dlp/extractor/platzi.py b/yt_dlp/extractor/platzi.py
index 23c8256b5..17f52e7f4 100644
--- a/yt_dlp/extractor/platzi.py
+++ b/yt_dlp/extractor/platzi.py
@@ -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')
diff --git a/yt_dlp/extractor/playplustv.py b/yt_dlp/extractor/playplustv.py
index fd72a3717..cad2c3a0f 100644
--- a/yt_dlp/extractor/playplustv.py
+++ b/yt_dlp/extractor/playplustv.py
@@ -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(
diff --git a/yt_dlp/extractor/pluralsight.py b/yt_dlp/extractor/pluralsight.py
index 801057ee1..2a5e0e488 100644
--- a/yt_dlp/extractor/pluralsight.py
+++ b/yt_dlp/extractor/pluralsight.py
@@ -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')
diff --git a/yt_dlp/extractor/pokergo.py b/yt_dlp/extractor/pokergo.py
index d27031c91..c9e2fed12 100644
--- a/yt_dlp/extractor/pokergo.py
+++ b/yt_dlp/extractor/pokergo.py
@@ -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):
diff --git a/yt_dlp/extractor/roosterteeth.py b/yt_dlp/extractor/roosterteeth.py
index 652fdd116..a55dd4f8b 100644
--- a/yt_dlp/extractor/roosterteeth.py
+++ b/yt_dlp/extractor/roosterteeth.py
@@ -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')):
diff --git a/yt_dlp/extractor/safari.py b/yt_dlp/extractor/safari.py
index cca4464ca..7b4571daa 100644
--- a/yt_dlp/extractor/safari.py
+++ b/yt_dlp/extractor/safari.py
@@ -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')
diff --git a/yt_dlp/extractor/scte.py b/yt_dlp/extractor/scte.py
index ca1de63b6..7215cf5d1 100644
--- a/yt_dlp/extractor/scte.py
+++ b/yt_dlp/extractor/scte.py
@@ -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')
diff --git a/yt_dlp/extractor/shahid.py b/yt_dlp/extractor/shahid.py
index 42de41a11..ab45d9ce4 100644
--- a/yt_dlp/extractor/shahid.py
+++ b/yt_dlp/extractor/shahid.py
@@ -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={
diff --git a/yt_dlp/extractor/sonyliv.py b/yt_dlp/extractor/sonyliv.py
index a5026b2e0..5b6849fc9 100644
--- a/yt_dlp/extractor/sonyliv.py
+++ b/yt_dlp/extractor/sonyliv.py
@@ -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)
diff --git a/yt_dlp/extractor/soundcloud.py b/yt_dlp/extractor/soundcloud.py
index 64b8a71b6..bbc79c2be 100644
--- a/yt_dlp/extractor/soundcloud.py
+++ b/yt_dlp/extractor/soundcloud.py
@@ -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():
diff --git a/yt_dlp/extractor/teachable.py b/yt_dlp/extractor/teachable.py
index 37eae82bc..232eaa521 100644
--- a/yt_dlp/extractor/teachable.py
+++ b/yt_dlp/extractor/teachable.py
@@ -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
diff --git a/yt_dlp/extractor/teamtreehouse.py b/yt_dlp/extractor/teamtreehouse.py
index d347e97ef..64522ec4c 100644
--- a/yt_dlp/extractor/teamtreehouse.py
+++ b/yt_dlp/extractor/teamtreehouse.py
@@ -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(
diff --git a/yt_dlp/extractor/tennistv.py b/yt_dlp/extractor/tennistv.py
index a39a2fc60..58fdecebe 100644
--- a/yt_dlp/extractor/tennistv.py
+++ b/yt_dlp/extractor/tennistv.py
@@ -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)
diff --git a/yt_dlp/extractor/toutv.py b/yt_dlp/extractor/toutv.py
index 6c84c211c..1d5da1040 100644
--- a/yt_dlp/extractor/toutv.py
+++ b/yt_dlp/extractor/toutv.py
@@ -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={
diff --git a/yt_dlp/extractor/tubitv.py b/yt_dlp/extractor/tubitv.py
index e9b66ec77..31feb9a70 100644
--- a/yt_dlp/extractor/tubitv.py
+++ b/yt_dlp/extractor/tubitv.py
@@ -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(
diff --git a/yt_dlp/extractor/tumblr.py b/yt_dlp/extractor/tumblr.py
index a3e0e15f2..8086f613d 100644
--- a/yt_dlp/extractor/tumblr.py
+++ b/yt_dlp/extractor/tumblr.py
@@ -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
diff --git a/yt_dlp/extractor/twitch.py b/yt_dlp/extractor/twitch.py
index bee26c3a3..10de74c8e 100644
--- a/yt_dlp/extractor/twitch.py
+++ b/yt_dlp/extractor/twitch.py
@@ -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)
diff --git a/yt_dlp/extractor/udemy.py b/yt_dlp/extractor/udemy.py
index 25b28e98e..235f89713 100644
--- a/yt_dlp/extractor/udemy.py
+++ b/yt_dlp/extractor/udemy.py
@@ -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')
diff --git a/yt_dlp/extractor/vidio.py b/yt_dlp/extractor/vidio.py
index e99dbdefa..6bfb8d442 100644
--- a/yt_dlp/extractor/vidio.py
+++ b/yt_dlp/extractor/vidio.py
@@ -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={
diff --git a/yt_dlp/extractor/viewlift.py b/yt_dlp/extractor/viewlift.py
index 5b558d890..4627f66fd 100644
--- a/yt_dlp/extractor/viewlift.py
+++ b/yt_dlp/extractor/viewlift.py
@@ -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'):
diff --git a/yt_dlp/extractor/viki.py b/yt_dlp/extractor/viki.py
index 19b09121c..8234ba7df 100644
--- a/yt_dlp/extractor/viki.py
+++ b/yt_dlp/extractor/viki.py
@@ -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')
diff --git a/yt_dlp/extractor/vimeo.py b/yt_dlp/extractor/vimeo.py
index 458a751fe..051cf1b17 100644
--- a/yt_dlp/extractor/vimeo.py
+++ b/yt_dlp/extractor/vimeo.py
@@ -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)
diff --git a/yt_dlp/extractor/vk.py b/yt_dlp/extractor/vk.py
index 18eb33b57..cbc315961 100644
--- a/yt_dlp/extractor/vk.py
+++ b/yt_dlp/extractor/vk.py
@@ -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(
diff --git a/yt_dlp/extractor/vlive.py b/yt_dlp/extractor/vlive.py
index 74dc349d5..ae35c976c 100644
--- a/yt_dlp/extractor/vlive.py
+++ b/yt_dlp/extractor/vlive.py
@@ -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:
diff --git a/yt_dlp/extractor/vrv.py b/yt_dlp/extractor/vrv.py
index 7bc55f333..10e6be7ed 100644
--- a/yt_dlp/extractor/vrv.py
+++ b/yt_dlp/extractor/vrv.py
@@ -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']
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index d6c74f455..d74d5b0e9 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -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]
diff --git a/yt_dlp/extractor/zattoo.py b/yt_dlp/extractor/zattoo.py
index 9435920b2..c02b4ca14 100644
--- a/yt_dlp/extractor/zattoo.py
+++ b/yt_dlp/extractor/zattoo.py
@@ -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(),
diff --git a/yt_dlp/extractor/zee5.py b/yt_dlp/extractor/zee5.py
index ebe393ec7..3e3f11b15 100644
--- a/yt_dlp/extractor/zee5.py
+++ b/yt_dlp/extractor/zee5.py
@@ -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')