예제 #1
0
    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
예제 #2
0
 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)
예제 #4
0
    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
예제 #5
0
 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
예제 #6
0
 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()
예제 #7
0
 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)
예제 #9
0
 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
예제 #10
0
 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
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
 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
예제 #15
0
 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
예제 #16
0
    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
예제 #17
0
    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)
예제 #18
0
    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)
예제 #19
0
 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