diff --git a/yt_dlp/extractor/niconico.py b/yt_dlp/extractor/niconico.py index 2c41268354..23435c6b50 100644 --- a/yt_dlp/extractor/niconico.py +++ b/yt_dlp/extractor/niconico.py @@ -23,7 +23,6 @@ from ..utils import ( qualities, remove_start, str_or_none, - traverse_obj, try_get, unescapeHTML, unified_timestamp, @@ -33,13 +32,72 @@ from ..utils import ( urlencode_postdata, urljoin, ) +from ..utils.traversal import find_element, traverse_obj -class NiconicoIE(InfoExtractor): +class NiconicoBaseIE(InfoExtractor): + _GEO_BYPASS = False + _GEO_COUNTRIES = ['JP'] + _LOGIN_BASE = 'https://account.nicovideo.jp' + _NETRC_MACHINE = 'niconico' + + def raise_login_error(self, error, default, expected=True): + raise ExtractorError(f'Unable to login: {error or default}', expected=expected) + + def _perform_login(self, username, password): + if self._get_cookies('https://www.nicovideo.jp').get('user_session'): + return + + self._request_webpage( + f'{self._LOGIN_BASE}/login', None, 'Requesting session cookies') + webpage = self._download_webpage( + f'{self._LOGIN_BASE}/login/redirector', None, + 'Logging in', headers={ + 'Content-Type': 'application/x-www-form-urlencoded', + 'Referer': f'{self._LOGIN_BASE}/login', + }, data=urlencode_postdata({ + 'mail_tel': username, + 'password': password, + }), + ) + + if traverse_obj(self._search_json( + r'NicoGoogleTagManagerDataLayer\s*=\s*\[', + webpage, 'data layer', None, fatal=False, + ), ('user', 'login_status', {lambda x: x == 'login'})): + return + + if err_msg := traverse_obj(webpage, ( + {find_element(cls='notice error')}, {find_element(cls='notice__text')}, {clean_html}, + )): + self.raise_login_error(err_msg, 'Invalid username or password') + elif 'oneTimePw' in webpage: + post_url = self._search_regex( + r'