def _login(self, modal_error_message=False): """Perform account login""" # If exists get the current esn value before extract a new session data current_esn = g.get_esn() try: # First we get the authentication url without logging in, required for login API call react_context = website.extract_json(self._get('profiles'), 'reactContext') auth_url = website.extract_api_data(react_context)['auth_url'] common.debug('Logging in...') login_response = self._post('login', data=_login_payload( common.get_credentials(), auth_url)) validate_msg = website.validate_login(login_response) if validate_msg: self.session.cookies.clear() common.purge_credentials() if modal_error_message: ui.show_ok_dialog(common.get_local_string(30008), validate_msg) else: ui.show_notification(common.get_local_string(30009)) return False website.extract_session_data(login_response) except Exception as exc: common.error(traceback.format_exc()) self.session.cookies.clear() raise exc common.info('Login successful') ui.show_notification(common.get_local_string(30109)) self.update_session_data(current_esn) return True
def _login(self, modal_error_message=False): """Perform account login""" # If exists get the current esn value before extract a new session data current_esn = g.get_esn() try: # First we get the authentication url without logging in, required for login API call react_context = website.extract_json(self._get('login'), 'reactContext') auth_url = website.extract_api_data(react_context)['auth_url'] common.debug('Logging in...') login_response = self._post( 'login', data=_login_payload(common.get_credentials(), auth_url)) try: website.extract_session_data(login_response, validate=True, update_profiles=True) common.info('Login successful') ui.show_notification(common.get_local_string(30109)) self.update_session_data(current_esn) return True except (LoginValidateError, LoginValidateErrorIncorrectPassword) as exc: self.session.cookies.clear() common.purge_credentials() if not modal_error_message: raise ui.show_ok_dialog(common.get_local_string(30008), unicode(exc)) except InvalidMembershipStatusError: ui.show_error_info(common.get_local_string(30008), common.get_local_string(30180), False, True) except Exception: # pylint: disable=broad-except import traceback common.error(g.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() raise return False
def _refresh_session_data(self): """Refresh session_data from the Netflix website""" # pylint: disable=broad-except try: website.extract_session_data(self._get('profiles')) self.update_session_data() except InvalidMembershipStatusError: raise except WebsiteParsingError: # it is possible that cookies may not work anymore, # it should be due to updates in the website, # this can happen when opening the addon while executing update_profiles_data import traceback common.debug(traceback.format_exc()) common.warn( 'Failed to refresh session data, login expired (WebsiteParsingError)' ) self.session.cookies.clear() return self._login() except Exception: import traceback common.debug(traceback.format_exc()) common.warn( 'Failed to refresh session data, login expired (Exception)') self.session.cookies.clear() return False common.debug('Successfully refreshed session data') return True
def _refresh_session_data(self): """Refresh session_data from the Netflix website""" # pylint: disable=broad-except try: website.extract_session_data(self._get('profiles')) self.update_session_data() except Exception: common.debug(traceback.format_exc()) common.info('Failed to refresh session data, login expired') self.session.cookies.clear() return False common.debug('Successfully refreshed session data') return True
def _activate_profile(self, guid, ignore_update_lolomo_data=False): """Set the profile identified by guid as active""" common.debug('Switching to profile {}', guid) current_active_guid = g.LOCAL_DB.get_active_profile_guid() if self.is_profile_session_active and guid == current_active_guid: common.info( 'The profile session of guid {} is still active, activation not needed.', guid) if not self.is_profile_session_active or ( self.is_profile_session_active and guid != current_active_guid): common.info('Activating profile {}', guid) # 20/05/2020 - The method 1 not more working for switching PIN locked profiles # INIT Method 1 - HTTP mode # response = self._get('switch_profile', params={'tkn': guid}) # self.auth_url = self.website_extract_session_data(response)['auth_url'] # END Method 1 # INIT Method 2 - API mode import time self._get(endpoint='activate_profile', params={ 'switchProfileGuid': guid, '_': int(time.time()), 'authURL': self.auth_url }) # Retrieve browse page to update authURL response = self._get('browse') self.auth_url = website.extract_session_data(response)['auth_url'] # END Method 2 self.is_profile_session_active = True g.LOCAL_DB.switch_active_profile(guid) g.CACHE_MANAGEMENT.identifier_prefix = guid self.update_session_data() if not ignore_update_lolomo_data: self.update_lolomo_data()
def __init__(self): super(NFSessionOperations, self).__init__() # Slot allocation for IPC self.slots = [ self.get_safe, self.post_safe, self.login, self.logout, self.path_request, self.perpetual_path_request, self.callpath_request, self.fetch_initial_page, self.activate_profile, self.parental_control_data, self.get_metadata, self.update_loco_context, self.update_videoid_bookmark ] # Share the activate profile function to SessionBase class self.external_func_activate_profile = self.activate_profile self.dt_initial_page_prefetch = None # Try prefetch login if self.prefetch_login(): try: # Try prefetch initial page response = self.get_safe('browse') api_data = website.extract_session_data(response, update_profiles=True) self.auth_url = api_data['auth_url'] self.dt_initial_page_prefetch = datetime.now() except Exception as exc: # pylint: disable=broad-except common.warn('Prefetch initial page failed: {}', exc)
def _activate_profile(self, guid): """Set the profile identified by guid as active""" common.debug('Switching to profile {}', guid) current_active_guid = g.LOCAL_DB.get_active_profile_guid() if self.is_profile_session_active and guid == current_active_guid: common.info( 'The profile session of guid {} is still active, activation not needed.', guid) import time timestamp = time.time() common.info('Activating profile {}', guid) # 20/05/2020 - The method 1 not more working for switching PIN locked profiles # INIT Method 1 - HTTP mode # response = self._get('switch_profile', params={'tkn': guid}) # self.auth_url = self.website_extract_session_data(response)['auth_url'] # END Method 1 # INIT Method 2 - API mode self._get(endpoint='activate_profile', params={ 'switchProfileGuid': guid, '_': int(timestamp * 1000), 'authURL': self.auth_url }) # Retrieve browse page to update authURL response = self._get('browse') self.auth_url = website.extract_session_data(response)['auth_url'] # END Method 2 self.is_profile_session_active = True # Update the session profile cookie (only a test, see 'Profile idle timeout' in website.py) # expires = int(timestamp) + (g.LOCAL_DB.get_value('profile_gate_idle_timer', 30, TABLE_SESSION) * 60) # self.session.cookies.set('profilesNewSession', '0', domain='.netflix.com', path='/', expires=expires) g.LOCAL_DB.switch_active_profile(guid) g.CACHE_MANAGEMENT.identifier_prefix = guid cookies.save(self.account_hash, self.session.cookies)
def website_extract_session_data(self, content, **kwargs): """Extract session data and handle errors""" try: return website.extract_session_data(content, **kwargs) except (WebsiteParsingError, InvalidMembershipStatusAnonymous, LoginValidateErrorIncorrectPassword) as exc: common.warn('Session data not valid, login can be expired or the password has been changed ({})', type(exc).__name__) if isinstance(exc, (InvalidMembershipStatusAnonymous, LoginValidateErrorIncorrectPassword)): common.purge_credentials() self.session.cookies.clear() common.send_signal(signal=common.Signals.CLEAR_USER_ID_TOKENS) raise NotLoggedInError raise
def website_extract_session_data(self, content, **kwargs): """Extract session data and handle errors""" try: return website.extract_session_data(content, **kwargs) except WebsiteParsingError as exc: common.error('An error occurs in extract session data: {}', exc) raise except (LoginValidateError, MbrStatusAnonymousError) as exc: common.warn('The session data is not more valid ({})', type(exc).__name__) common.purge_credentials() self.session.cookies.clear() common.send_signal(signal=common.Signals.CLEAR_USER_ID_TOKENS) raise NotLoggedInError
def login(self, modal_error_message=True): """Perform account login""" try: # First we get the authentication url without logging in, required for login API call react_context = website.extract_json(self.get('login'), 'reactContext') auth_url = website.extract_api_data(react_context)['auth_url'] common.debug('Logging in...') login_response = self.post('login', data=_login_payload( common.get_credentials(), auth_url)) try: website.extract_session_data(login_response, validate=True, update_profiles=True) common.info('Login successful') ui.show_notification(common.get_local_string(30109)) cookies.save(self.account_hash, self.session.cookies) return True except LoginValidateError as exc: self.session.cookies.clear() common.purge_credentials() if not modal_error_message: raise ui.show_ok_dialog(common.get_local_string(30008), unicode(exc)) except (MbrStatusNeverMemberError, MbrStatusFormerMemberError): if not modal_error_message: raise ui.show_error_info(common.get_local_string(30008), common.get_local_string(30180), False, True) except Exception: # pylint: disable=broad-except import traceback common.error(G.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() raise return False
def try_refresh_session_data(self, raise_exception=False): """Refresh session_data from the Netflix website""" # pylint: disable=broad-except try: self.auth_url = website.extract_session_data( self._get('browse'))['auth_url'] self.update_session_data() common.debug('Successfully refreshed session data') return True except InvalidMembershipStatusError: raise except (WebsiteParsingError, InvalidMembershipStatusAnonymous, LoginValidateErrorIncorrectPassword) as exc: # Possible known causes: # -Cookies may not work anymore most likely due to updates in the website # -Login password has been changed # -Expired cookie profiles? might cause InvalidMembershipStatusAnonymous (i am not really sure) import traceback common.warn( 'Failed to refresh session data, login can be expired or the password has been changed ({})', type(exc).__name__) common.debug(g.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() if isinstance(exc, (InvalidMembershipStatusAnonymous, LoginValidateErrorIncorrectPassword)): # This prevent the MSL error: No entity association record found for the user common.send_signal(signal=common.Signals.CLEAR_USER_ID_TOKENS) return self._login() except requests.exceptions.RequestException: import traceback common.warn( 'Failed to refresh session data, request error (RequestException)' ) common.warn(g.py2_decode(traceback.format_exc(), 'latin-1')) if raise_exception: raise except Exception: import traceback common.warn( 'Failed to refresh session data, login expired (Exception)') common.debug(g.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() if raise_exception: raise return False
def _login(self): """Perform account login""" try: auth_url = website.extract_userdata( self._get('profiles'))['authURL'] common.debug('Logging in...') login_response = self._post( 'login', data=_login_payload(common.get_credentials(), auth_url)) session_data = website.extract_session_data(login_response) except Exception: common.debug(traceback.format_exc()) self.session.cookies.clear() raise LoginFailedError common.info('Login successful') ui.show_notification(common.get_local_string(30109)) self.session_data = session_data
def try_refresh_session_data(self, raise_exception=False): """Refresh session_data from the Netflix website""" from requests import exceptions try: self.auth_url = website.extract_session_data( self._get('browse'))['auth_url'] cookies.save(self.account_hash, self.session.cookies) common.debug('Successfully refreshed session data') return True except InvalidMembershipStatusError: raise except (WebsiteParsingError, InvalidMembershipStatusAnonymous, LoginValidateErrorIncorrectPassword) as exc: import traceback common.warn( 'Failed to refresh session data, login can be expired or the password has been changed ({})', type(exc).__name__) common.debug(g.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() if isinstance(exc, (InvalidMembershipStatusAnonymous, LoginValidateErrorIncorrectPassword)): # This prevent the MSL error: No entity association record found for the user common.send_signal(signal=common.Signals.CLEAR_USER_ID_TOKENS) return self._login() except exceptions.RequestException: import traceback common.warn( 'Failed to refresh session data, request error (RequestException)' ) common.warn(g.py2_decode(traceback.format_exc(), 'latin-1')) if raise_exception: raise except Exception: # pylint: disable=broad-except import traceback common.warn( 'Failed to refresh session data, login expired (Exception)') common.debug(g.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() if raise_exception: raise return False
def activate_profile(self, guid): """Set the profile identified by guid as active""" common.debug('Switching to profile {}', guid) current_active_guid = G.LOCAL_DB.get_active_profile_guid() if guid == current_active_guid: common.info( 'The profile guid {} is already set, activation not needed.', guid) return timestamp = time.time() common.info('Activating profile {}', guid) # 20/05/2020 - The method 1 not more working for switching PIN locked profiles # INIT Method 1 - HTTP mode # response = self._get('switch_profile', params={'tkn': guid}) # self.nfsession.auth_url = self.website_extract_session_data(response)['auth_url'] # END Method 1 # INIT Method 2 - API mode try: self.get_safe(endpoint='activate_profile', params={ 'switchProfileGuid': guid, '_': int(timestamp * 1000), 'authURL': self.auth_url }) except HttpError401: # Profile guid not more valid raise InvalidProfilesError( 'Unable to access to the selected profile.') # Retrieve browse page to update authURL response = self.get_safe('browse') self.auth_url = website.extract_session_data(response)['auth_url'] # END Method 2 G.LOCAL_DB.switch_active_profile(guid) G.CACHE_MANAGEMENT.identifier_prefix = guid cookies.save(self.account_hash, self.session.cookies)