def login(self, credentials=None): """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'] LOG.debug('Logging in...') login_response = self.post( 'login', headers={'Accept-Language': _get_accept_language_string(react_context)}, data=_login_payload(credentials or common.get_credentials(), auth_url, react_context)) website.extract_session_data(login_response, validate=True, update_profiles=True) if credentials: # Save credentials only when login has succeeded common.set_credentials(credentials) LOG.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() raise_from(LoginError(unicode(exc)), exc) except (MbrStatusNeverMemberError, MbrStatusFormerMemberError) as exc: self.session.cookies.clear() LOG.warn('Membership status {} not valid for login', exc) raise_from(LoginError(common.get_local_string(30180)), exc) except Exception: # pylint: disable=broad-except self.session.cookies.clear() import traceback LOG.error(G.py2_decode(traceback.format_exc(), 'latin-1')) raise
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 load_manifest(self, viewable_id): """ Loads the manifests for the given viewable_id and returns a mpd-XML-Manifest :param viewable_id: The id of of the viewable :return: MPD XML Manifest or False if no success """ try: manifest = self._load_manifest(viewable_id, g.get_esn()) except MSLError as exc: if 'Email or password is incorrect' in g.py2_decode(str(exc)): # Known cases when MSL error "Email or password is incorrect." can happen: # - If user change the password when the nf session was still active # - Netflix has reset the password for suspicious activity when the nf session was still active # Then clear the credentials and also user tokens. common.purge_credentials() self.msl_requests.crypto.clear_user_id_tokens() raise # Disable 1080p Unlock for now, as it is broken due to Netflix changes # if (g.ADDON.getSettingBool('enable_1080p_unlock') and # not g.ADDON.getSettingBool('enable_vp9_profiles') and # not has_1080p(manifest)): # common.debug('Manifest has no 1080p viewables, trying unlock') # manifest = self.get_edge_manifest(viewable_id, manifest) return self.__tranform_to_dash(manifest)
def logout(self, url): """Logout of the current account and reset the session""" common.debug('Logging out of current account') g.settings_monitor_suspend(True) # Disable and reset auto-update / auto-sync features g.ADDON.setSettingInt('lib_auto_upd_mode', 0) g.ADDON.setSettingBool('lib_sync_mylist', False) g.SHARED_DB.delete_key('sync_mylist_profile_guid') # Disable and reset the auto-select profile g.LOCAL_DB.set_value('autoselect_profile_guid', '') g.ADDON.setSetting('autoselect_profile_name', '') g.ADDON.setSettingBool('autoselect_profile_enabled', False) g.settings_monitor_suspend(False) # Delete cookie and credentials cookies.delete(self.account_hash) self._get('logout') common.purge_credentials() common.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session() xbmc.executebuiltin('Container.Update(path,replace)' ) # Go to a fake page to clear screen # Open root page xbmc.executebuiltin('Container.Update({},replace)'.format( url)) # replace=reset history
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 logout(self): """Logout of the current account and reset the session""" common.debug('Logging out of current account') cookies.delete(self.account_hash) self._get('logout') common.purge_credentials() common.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session()
def logout(self): """Logout of the current account and reset the session""" common.debug('Logging out of current account') cookies.delete(self.account_hash) self._get('logout') common.purge_credentials() common.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session() xbmc.executebuiltin('XBMC.Container.Update(path,replace)') # Clean path history xbmc.executebuiltin('XBMC.ActivateWindow(Home)')
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: LOG.error('An error occurs in extract session data: {}', exc) raise except (LoginValidateError, MbrStatusAnonymousError) as exc: LOG.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_from(NotLoggedInError, exc)
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: LOG.error('An error occurs in extract session data: {}', exc) raise except (LoginValidateError, MbrStatusAnonymousError) as exc: LOG.warn('The session data is not more valid ({})', type(exc).__name__) common.purge_credentials() self.session.cookies.clear() # Clear the user ID tokens are tied to the credentials self.msl_handler.clear_user_id_tokens() raise NotLoggedInError from exc
def logout(self, url): """Logout of the current account and reset the session""" common.debug('Logging out of current account') # Perform the website logout self._get('logout') g.settings_monitor_suspend(True) # Disable and reset auto-update / auto-sync features g.ADDON.setSettingInt('lib_auto_upd_mode', 1) g.ADDON.setSettingBool('lib_sync_mylist', False) g.SHARED_DB.delete_key('sync_mylist_profile_guid') # Disable and reset the auto-select profile g.LOCAL_DB.set_value('autoselect_profile_guid', '') g.ADDON.setSetting('autoselect_profile_name', '') g.ADDON.setSettingBool('autoselect_profile_enabled', False) # Reset of selected profile guid for library playback g.LOCAL_DB.set_value('library_playback_profile_guid', '') g.ADDON.setSetting('library_playback_profile', '') g.settings_monitor_suspend(False) # Delete cookie and credentials self.session.cookies.clear() cookies.delete(self.account_hash) common.purge_credentials() # Reset the ESN obtained from website/generated g.LOCAL_DB.set_value('esn', '', TABLE_SESSION) # Reinitialize the MSL handler (delete msl data file, then reset everything) common.send_signal(signal=common.Signals.REINITIALIZE_MSL_HANDLER, data=True) g.CACHE.clear(clear_database=True) common.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session() xbmc.executebuiltin('Container.Update(path,replace)' ) # Go to a fake page to clear screen # Open root page xbmc.executebuiltin('Container.Update({},replace)'.format( url)) # replace=reset history
def load_manifest(self, viewable_id): """ Loads the manifests for the given viewable_id and returns a mpd-XML-Manifest :param viewable_id: The id of of the viewable :return: MPD XML Manifest or False if no success """ try: manifest = self._load_manifest(viewable_id, get_esn()) except MSLError as exc: if 'Email or password is incorrect' in G.py2_decode(str(exc)): # Known cases when MSL error "Email or password is incorrect." can happen: # - If user change the password when the nf session was still active # - Netflix has reset the password for suspicious activity when the nf session was still active # Then clear the credentials and also user tokens. common.purge_credentials() self.msl_requests.crypto.clear_user_id_tokens() raise return self.__tranform_to_dash(manifest)
def logout(self): """Logout of the current account and reset the session""" LOG.debug('Logging out of current account') # Perform the website logout self.get('logout') G.settings_monitor_suspend(True) # Disable and reset auto-update / auto-sync features G.ADDON.setSettingInt('lib_auto_upd_mode', 1) G.ADDON.setSettingBool('lib_sync_mylist', False) G.SHARED_DB.delete_key('sync_mylist_profile_guid') # Disable and reset the profile guid of profile auto-selection G.LOCAL_DB.set_value('autoselect_profile_guid', '') # Disable and reset the selected profile guid for library playback G.LOCAL_DB.set_value('library_playback_profile_guid', '') G.settings_monitor_suspend(False) # Delete cookie and credentials self.session.cookies.clear() cookies.delete() common.purge_credentials() # Reset the ESN obtained from website/generated G.LOCAL_DB.set_value('esn', '', TABLE_SESSION) # Reinitialize the MSL handler (delete msl data file, then reset everything) common.send_signal(signal=common.Signals.REINITIALIZE_MSL_HANDLER, data=True) G.CACHE.clear(clear_database=True) LOG.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session() common.container_update('path', True) # Go to a fake page to clear screen # Open root page common.container_update(G.BASE_URL, True)
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.session.cookies) LOG.debug('Successfully refreshed session data') return True except MbrStatusError: raise except (WebsiteParsingError, MbrStatusAnonymousError) as exc: import traceback LOG.warn( 'Failed to refresh session data, login can be expired or the password has been changed ({})', type(exc).__name__) LOG.debug(G.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() if isinstance(exc, MbrStatusAnonymousError): # This prevent the MSL error: No entity association record found for the user common.send_signal(signal=common.Signals.CLEAR_USER_ID_TOKENS) # Needed to do a new login common.purge_credentials() ui.show_notification(common.get_local_string(30008)) raise_from(NotLoggedInError, exc) except exceptions.RequestException: import traceback LOG.warn( 'Failed to refresh session data, request error (RequestException)' ) LOG.warn(G.py2_decode(traceback.format_exc(), 'latin-1')) if raise_exception: raise except Exception: # pylint: disable=broad-except import traceback LOG.warn( 'Failed to refresh session data, login expired (Exception)') LOG.debug(G.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() if raise_exception: raise return False
def try_refresh_session_data(self, raise_exception=False): """Refresh session data from the Netflix website""" try: self.auth_url = website.extract_session_data( self.get('browse'))['auth_url'] cookies.save(self.session.cookies.jar) LOG.debug('Successfully refreshed session data') return True except MbrStatusError: raise except (WebsiteParsingError, MbrStatusAnonymousError) as exc: import traceback LOG.warn( 'Failed to refresh session data, login can be expired or the password has been changed ({})', type(exc).__name__) LOG.debug(traceback.format_exc()) self.session.cookies.clear() if isinstance(exc, MbrStatusAnonymousError): # This prevent the MSL error: No entity association record found for the user self.msl_handler.clear_user_id_tokens() # Needed to do a new login common.purge_credentials() ui.show_notification(common.get_local_string(30008)) raise NotLoggedInError from exc except httpx.RequestError: import traceback LOG.warn( 'Failed to refresh session data, request error (RequestError)') LOG.warn(traceback.format_exc()) if raise_exception: raise except Exception: # pylint: disable=broad-except import traceback LOG.warn( 'Failed to refresh session data, login expired (Exception)') LOG.debug(traceback.format_exc()) self.session.cookies.clear() if raise_exception: raise return False
def logout(self, url): """Logout of the current account and reset the session""" common.debug('Logging out of current account') # Disable and reset auto-update / auto-sync features g.settings_monitor_suspended(True) g.ADDON.setSettingInt('lib_auto_upd_mode', 0) g.ADDON.setSettingBool('lib_sync_mylist', False) g.settings_monitor_suspended(False) g.SHARED_DB.delete_key('sync_mylist_profile_guid') cookies.delete(self.account_hash) self._get('logout') common.purge_credentials() common.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session() xbmc.executebuiltin( 'XBMC.Container.Update(path,replace)') # Clean path history xbmc.executebuiltin( 'Container.Update({})'.format(url)) # Open root page
def get_manifest(self, viewable_id): """ Get the manifests for the given viewable_id and returns a mpd-XML-Manifest :param viewable_id: The id of of the viewable :return: MPD XML Manifest or False if no success """ try: esn = get_esn() # When the add-on is installed from scratch or you logout the account the ESN will be empty if not esn: esn = set_esn() manifest = self._get_manifest(viewable_id, esn) except MSLError as exc: if 'Email or password is incorrect' in str(exc): # Known cases when MSL error "Email or password is incorrect." can happen: # - If user change the password when the nf session was still active # - Netflix has reset the password for suspicious activity when the nf session was still active # Then clear the credentials and also user tokens. common.purge_credentials() self.msl_requests.crypto.clear_user_id_tokens() raise return self.__tranform_to_dash(manifest)
def logout(self): """Logout of the current account and reset the session""" LOG.debug('Logging out of current account') # Perform the website logout self.get('logout') with G.SETTINGS_MONITOR.ignore_events(2): # Disable and reset auto-update / auto-sync features G.ADDON.setSettingInt('lib_auto_upd_mode', 1) G.ADDON.setSettingBool('lib_sync_mylist', False) G.SHARED_DB.delete_key('sync_mylist_profile_guid') # Disable and reset the profile guid of profile auto-selection G.LOCAL_DB.set_value('autoselect_profile_guid', '') # Disable and reset the selected profile guid for library playback G.LOCAL_DB.set_value('library_playback_profile_guid', '') # Delete cookie and credentials self.session.cookies.clear() cookies.delete() common.purge_credentials() # Reinitialize the MSL handler (delete msl data file, then reset everything) self.msl_handler.reinitialize_msl_handler(delete_msl_file=True) G.CACHE.clear(clear_database=True) LOG.info('Logout successful') ui.show_notification(common.get_local_string(30113)) self._init_session() common.container_update('path', True) # Go to a fake page to clear screen # Open root page common.container_update(G.BASE_URL, True)
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'] LOG.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) LOG.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 LOG.error(G.py2_decode(traceback.format_exc(), 'latin-1')) self.session.cookies.clear() raise return False