def run(argv):
    # pylint: disable=broad-except,ungrouped-imports
    # Initialize globals right away to avoid stale values from the last addon invocation.
    # Otherwise Kodi's reuseLanguageInvoker will cause some really quirky behavior!
    # PR: https://github.com/xbmc/xbmc/pull/13814
    g.init_globals(argv)

    reset_log_level_global_var()
    info('Started (Version {})'.format(g.VERSION_RAW))
    info('URL is {}'.format(g.URL))
    success = True

    window_cls = Window(10000)  # Kodi home window

    # If you use multiple Kodi profiles you need to distinguish the property of current profile
    prop_nf_service_status = g.py2_encode('nf_service_status_' +
                                          get_current_kodi_profile_name())
    is_external_call = _check_addon_external_call(window_cls,
                                                  prop_nf_service_status)
    service_status = _get_service_status(window_cls, prop_nf_service_status)

    if service_status.get('status') != 'running':
        if not is_external_call:
            if service_status.get('status') == 'error':
                # The services are not started due to an error exception
                from resources.lib.kodi.ui import show_error_info
                show_error_info(
                    get_local_string(30105),
                    get_local_string(30240).format(
                        service_status.get('message')), False, False)
            else:
                # The services are not started yet
                from resources.lib.kodi.ui import show_backend_not_ready
                show_backend_not_ready()
        success = False

    if success:
        try:
            if _check_valid_credentials():
                if g.IS_ADDON_FIRSTRUN:
                    if check_addon_upgrade():
                        from resources.lib.config_wizard import run_addon_configuration
                        run_addon_configuration()
                route([part for part in g.PATH.split('/') if part])
            else:
                success = False
        except BackendNotReady:
            from resources.lib.kodi.ui import show_backend_not_ready
            show_backend_not_ready()
            success = False
        except Exception as exc:
            import traceback
            from resources.lib.kodi.ui import show_addon_error_info
            error(g.py2_decode(traceback.format_exc(), 'latin-1'))
            show_addon_error_info(exc)
            success = False

    if not success:
        _handle_endofdirectory()
    log_time_trace()
Beispiel #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 error_catching_wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         ui.show_error_info(common.get_local_string(30028), unicode(exc),
                            unknown_error=not(unicode(exc)),
                            netflix_error=isinstance(exc, MSLError))
         raise
Beispiel #4
0
def search_query(row_id, perpetual_range_start, dir_update_listing):
    """Perform the research"""
    # Get item from database
    search_item = G.LOCAL_DB.get_search_item(row_id)
    if not search_item:
        ui.show_error_info('Search error', 'Item not found in the database.')
        return False
    # Update the last access data (move on top last used items)
    if not perpetual_range_start:
        G.LOCAL_DB.update_search_item_last_access(row_id)
    # Perform the path call
    menu_data = G.MAIN_MENU_ITEMS['search']
    search_type = search_item['Type']
    if search_type == 'text':
        call_args = {
            'menu_data': menu_data,
            'search_term': search_item['Value'],
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start
        }
        list_data, extra_data = common.make_call('get_video_list_search', call_args)
    elif search_type == 'audio_lang':
        call_args = {
            'menu_data': menu_data,
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start,
            'context_name': 'spokenAudio',
            'context_id': common.convert_from_string(search_item['Parameters'], dict)['lang_code']
        }
        list_data, extra_data = common.make_call('get_video_list_sorted_sp', call_args)
    elif search_type == 'subtitles_lang':
        call_args = {
            'menu_data': menu_data,
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start,
            'context_name': 'subtitles',
            'context_id': common.convert_from_string(search_item['Parameters'], dict)['lang_code']
        }
        list_data, extra_data = common.make_call('get_video_list_sorted_sp', call_args)
    elif search_type == 'genre_id':
        call_args = {
            'menu_data': menu_data,
            'pathitems': ['search', 'search', row_id],
            'perpetual_range_start': perpetual_range_start,
            'context_name': 'genres',
            'context_id': common.convert_from_string(search_item['Parameters'], dict)['genre_id']
        }
        list_data, extra_data = common.make_call('get_video_list_sorted_sp', call_args)
    else:
        raise NotImplementedError('Search type {} not implemented'.format(search_type))
    # Show the results
    if not list_data:
        ui.show_notification(common.get_local_string(30407))
        return False
    _search_results_directory(search_item['Value'], menu_data, list_data, extra_data, dir_update_listing)
    return True
 def error_catching_wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         message = f'{exc.__class__.__name__}: {exc}'
         ui.show_error_info(common.get_local_string(30028),
                            message,
                            unknown_error=not message,
                            netflix_error=isinstance(exc, MSLError))
         raise
Beispiel #6
0
def run(argv):
    # Initialize globals right away to avoid stale values from the last addon invocation.
    # Otherwise Kodi's reuseLanguageInvoker will cause some really quirky behavior!
    # PR: https://github.com/xbmc/xbmc/pull/13814
    G.init_globals(argv)

    LOG.info('Started (Version {})'.format(G.VERSION_RAW))
    LOG.info('URL is {}'.format(G.URL))
    success = True

    window_cls = Window(10000)  # Kodi home window

    # If you use multiple Kodi profiles you need to distinguish the property of current profile
    prop_nf_service_status = G.py2_encode('nf_service_status_' +
                                          get_current_kodi_profile_name())
    is_external_call = _check_addon_external_call(window_cls,
                                                  prop_nf_service_status)
    service_status = _get_service_status(window_cls, prop_nf_service_status)

    if service_status.get('status') != 'running':
        if not is_external_call:
            if service_status.get('status') == 'error':
                # The services are not started due to an error exception
                from resources.lib.kodi.ui import show_error_info
                show_error_info(
                    get_local_string(30105),
                    get_local_string(30240).format(
                        service_status.get('message')), False, False)
            else:
                # The services are not started yet
                from resources.lib.kodi.ui import show_backend_not_ready
                show_backend_not_ready()
        success = False
    if success:
        cancel_playback = False
        pathitems = [part for part in G.REQUEST_PATH.split('/') if part]
        if G.IS_ADDON_FIRSTRUN:
            is_first_run_install, cancel_playback = check_addon_upgrade()
            if is_first_run_install:
                from resources.lib.config_wizard import run_addon_configuration
                run_addon_configuration()
        if cancel_playback and G.MODE_PLAY in pathitems[:1]:
            # Temporary for migration library STRM to new format. todo: to be removed in future releases
            # When a user do the add-on upgrade, the first time that the add-on will be opened will be executed
            # the library migration. But if a user instead to open the add-on, try to play a video from Kodi
            # library, Kodi will open the old STRM file because the migration is executed after.
            success = False
        else:
            success = route(pathitems)
    if not success:
        from xbmcplugin import endOfDirectory
        endOfDirectory(handle=G.PLUGIN_HANDLE, succeeded=False)
    LOG.log_time_trace()
Beispiel #7
0
 def error_catching_wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         if isinstance(exc, MSLError):
             message = g.py2_decode(str(exc))
         else:
             message = str(exc)
         ui.show_error_info(common.get_local_string(30028), message,
                            unknown_error=not message,
                            netflix_error=isinstance(exc, MSLError))
         raise
def search_query(row_id, perpetual_range_start, dir_update_listing):
    """Perform the research"""
    # Get item from database
    search_item = G.LOCAL_DB.get_search_item(row_id)
    if not search_item:
        ui.show_error_info('Search error', 'Item not found in the database.')
        return False
    # Update the last access data (move on top last used items)
    if not perpetual_range_start:
        G.LOCAL_DB.update_search_item_last_access(row_id)
    return exec_query(row_id, search_item['Type'], search_item['Parameters'],
                      search_item['Value'], perpetual_range_start,
                      dir_update_listing)
Beispiel #9
0
def rate_thumb(videoid, rating, track_id_jaw):
    """Rate a video on Netflix"""
    common.debug('Thumb rating {} as {}', videoid.value, rating)
    event_uuid = common.get_random_uuid()
    response = common.make_call(
        'post',
        {'component': 'set_thumb_rating',
         'data': {
             'eventUuid': event_uuid,
             'titleId': int(videoid.value),
             'trackId': track_id_jaw,
             'rating': rating,
         }})
    if response.get('status', '') == 'success':
        ui.show_notification(common.get_local_string(30045).split('|')[rating])
    else:
        common.error('Rating thumb error, response detail: {}', response)
        ui.show_error_info('Rating error', 'Error type: {}' + response.get('status', '--'),
                           True, True)
Beispiel #10
0
 def wrapper(*args, **kwargs):
     # pylint: disable=broad-except, ungrouped-imports
     success = False
     try:
         func(*args, **kwargs)
         success = True
     except BackendNotReady as exc_bnr:
         from resources.lib.kodi.ui import show_backend_not_ready
         show_backend_not_ready(G.py2_decode(str(exc_bnr), 'latin-1'))
     except InputStreamHelperError as exc:
         from resources.lib.kodi.ui import show_ok_dialog
         show_ok_dialog('InputStream Helper Add-on error', (
             'The operation has been cancelled.\r\n'
             'InputStream Helper has generated an internal error:\r\n{}\r\n\r\n'
             'Please report it to InputStream Helper github.'.format(exc)))
     except (
             HttpError401, HttpErrorTimeout
     ) as exc:  # HTTP error 401 Client Error: Unauthorized for url ...
         # HttpError401: This is a generic error, can happen when the http request for some reason has failed.
         # Known causes:
         # - Possible change of data format or wrong data in the http request (also in headers/params)
         # - Some current nf session data are not more valid (authURL/cookies/...)
         # HttpErrorTimeout: This error is raised by Requests ReadTimeout error, unknown causes
         from resources.lib.kodi.ui import show_ok_dialog
         show_ok_dialog(
             get_local_string(30105),
             ('There was a communication problem with Netflix.[CR]'
              'You can try the operation again or exit.[CR]'
              '(Error code: {})').format(exc.__class__.__name__))
     except (MbrStatusNeverMemberError, MbrStatusFormerMemberError):
         from resources.lib.kodi.ui import show_error_info
         show_error_info(get_local_string(30008), get_local_string(30180),
                         False, True)
     except Exception as exc:
         import traceback
         from resources.lib.kodi.ui import show_addon_error_info
         LOG.error(G.py2_decode(traceback.format_exc(), 'latin-1'))
         show_addon_error_info(exc)
     finally:
         if not success:
             from xbmcplugin import endOfDirectory
             endOfDirectory(handle=G.PLUGIN_HANDLE, succeeded=False)
Beispiel #11
0
def run(argv):
    # Initialize globals right away to avoid stale values from the last addon invocation.
    # Otherwise Kodi's reuseLanguageInvoker will cause some really quirky behavior!
    # PR: https://github.com/xbmc/xbmc/pull/13814
    G.init_globals(argv)

    LOG.info('Started (Version {})', G.VERSION_RAW)
    LOG.info('URL is {}', G.URL)
    success = True

    is_external_call = _check_addon_external_call()
    service_status = _get_service_status()

    if service_status.get('status') != 'running':
        if not is_external_call:
            if service_status.get('status') == 'error':
                # The services are not started due to an error exception
                from resources.lib.kodi.ui import show_error_info
                show_error_info(get_local_string(30105), get_local_string(30240).format(service_status.get('message')),
                                False, False)
            else:
                # The services are not started yet
                from resources.lib.kodi.ui import show_backend_not_ready
                show_backend_not_ready()
        success = False
    if success:
        pathitems = [part for part in G.REQUEST_PATH.split('/') if part]
        if G.IS_ADDON_FIRSTRUN:
            is_first_run_install = check_addon_upgrade()
            if is_first_run_install:
                from resources.lib.config_wizard import run_addon_configuration
                run_addon_configuration()
        success = route(pathitems)
    if not success:
        from xbmcplugin import endOfDirectory
        endOfDirectory(handle=G.PLUGIN_HANDLE, succeeded=False)
    LOG.log_time_trace()
Beispiel #12
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
def run(argv):
    # pylint: disable=broad-except,ungrouped-imports,too-many-branches
    # Initialize globals right away to avoid stale values from the last addon invocation.
    # Otherwise Kodi's reuseLanguageInvoker will cause some really quirky behavior!
    # PR: https://github.com/xbmc/xbmc/pull/13814
    g.init_globals(argv)

    reset_log_level_global_var()
    info('Started (Version {})'.format(g.VERSION_RAW))
    info('URL is {}'.format(g.URL))
    success = True

    window_cls = Window(10000)  # Kodi home window

    # If you use multiple Kodi profiles you need to distinguish the property of current profile
    prop_nf_service_status = g.py2_encode('nf_service_status_' +
                                          get_current_kodi_profile_name())
    is_external_call = _check_addon_external_call(window_cls,
                                                  prop_nf_service_status)
    service_status = _get_service_status(window_cls, prop_nf_service_status)

    if service_status.get('status') != 'running':
        if not is_external_call:
            if service_status.get('status') == 'error':
                # The services are not started due to an error exception
                from resources.lib.kodi.ui import show_error_info
                show_error_info(
                    get_local_string(30105),
                    get_local_string(30240).format(
                        service_status.get('message')), False, False)
            else:
                # The services are not started yet
                from resources.lib.kodi.ui import show_backend_not_ready
                show_backend_not_ready()
        success = False

    if success:
        try:
            if _check_valid_credentials():
                if g.IS_ADDON_FIRSTRUN:
                    if check_addon_upgrade():
                        from resources.lib.config_wizard import run_addon_configuration
                        run_addon_configuration()
                route([part for part in g.PATH.split('/') if part])
            else:
                success = False
        except BackendNotReady:
            from resources.lib.kodi.ui import show_backend_not_ready
            show_backend_not_ready()
            success = False
        except InputStreamHelperError as exc:
            from resources.lib.kodi.ui import show_ok_dialog
            show_ok_dialog('InputStream Helper Add-on error', (
                'The operation has been cancelled.\r\n'
                'InputStream Helper has generated an internal error:\r\n{}\r\n\r\n'
                'Please report it to InputStream Helper github.'.format(exc)))
            success = False
        except HttpError401:
            # Http error 401 Client Error: Unauthorized for url ... issue (see _request in nfsession_requests.py)
            from resources.lib.kodi.ui import show_ok_dialog
            show_ok_dialog(get_local_string(30105), (
                'There was a communication problem with Netflix.\r\n'
                'This is a known and unresolvable issue, do not submit reports.\r\n'
                'You can try the operation again or exit.'))
            success = False
        except Exception as exc:
            import traceback
            from resources.lib.kodi.ui import show_addon_error_info
            error(g.py2_decode(traceback.format_exc(), 'latin-1'))
            show_addon_error_info(exc)
            success = False

    if not success:
        _handle_endofdirectory()
    log_time_trace()
Beispiel #14
0
def run(argv):
    # pylint: disable=broad-except,ungrouped-imports,too-many-branches
    # Initialize globals right away to avoid stale values from the last addon invocation.
    # Otherwise Kodi's reuseLanguageInvoker will cause some really quirky behavior!
    # PR: https://github.com/xbmc/xbmc/pull/13814
    G.init_globals(argv)

    reset_log_level_global_var()
    info('Started (Version {})'.format(G.VERSION_RAW))
    info('URL is {}'.format(G.URL))
    success = True

    window_cls = Window(10000)  # Kodi home window

    # If you use multiple Kodi profiles you need to distinguish the property of current profile
    prop_nf_service_status = G.py2_encode('nf_service_status_' +
                                          get_current_kodi_profile_name())
    is_external_call = _check_addon_external_call(window_cls,
                                                  prop_nf_service_status)
    service_status = _get_service_status(window_cls, prop_nf_service_status)

    if service_status.get('status') != 'running':
        if not is_external_call:
            if service_status.get('status') == 'error':
                # The services are not started due to an error exception
                from resources.lib.kodi.ui import show_error_info
                show_error_info(
                    get_local_string(30105),
                    get_local_string(30240).format(
                        service_status.get('message')), False, False)
            else:
                # The services are not started yet
                from resources.lib.kodi.ui import show_backend_not_ready
                show_backend_not_ready()
        success = False
    if success:
        try:
            cancel_playback = False
            pathitems = [part for part in G.REQUEST_PATH.split('/') if part]
            if G.IS_ADDON_FIRSTRUN:
                is_first_run_install, cancel_playback = check_addon_upgrade()
                if is_first_run_install:
                    from resources.lib.config_wizard import run_addon_configuration
                    run_addon_configuration()
            if cancel_playback and G.MODE_PLAY in pathitems[:1]:
                # Temporary for migration library STRM to new format. todo: to be removed in future releases
                # When a user do the add-on upgrade, the first time that the add-on will be opened will be executed
                # the library migration. But if a user instead to open the add-on, try to play a video from Kodi
                # library, Kodi will open the old STRM file because the migration is executed after.
                success = False
            else:
                success = route(pathitems)
        except BackendNotReady as exc_bnr:
            from resources.lib.kodi.ui import show_backend_not_ready
            show_backend_not_ready(G.py2_decode(str(exc_bnr), 'latin-1'))
            success = False
        except InputStreamHelperError as exc:
            from resources.lib.kodi.ui import show_ok_dialog
            show_ok_dialog('InputStream Helper Add-on error', (
                'The operation has been cancelled.\r\n'
                'InputStream Helper has generated an internal error:\r\n{}\r\n\r\n'
                'Please report it to InputStream Helper github.'.format(exc)))
            success = False
        except HttpError401:  # HTTP error 401 Client Error: Unauthorized for url ...
            # This is a generic error, can happen when the http request for some reason has failed.
            # Known causes:
            # - Possible change of data format or wrong data in the http request (also in headers/params)
            # - Some current nf session data are not more valid (authURL/cookies/...)
            from resources.lib.kodi.ui import show_ok_dialog
            show_ok_dialog(
                get_local_string(30105),
                ('There was a communication problem with Netflix.\r\n'
                 'You can try the operation again or exit.'))
            success = False
        except (MbrStatusNeverMemberError, MbrStatusFormerMemberError):
            from resources.lib.kodi.ui import show_error_info
            show_error_info(get_local_string(30008), get_local_string(30180),
                            False, True)
            success = False
        except Exception as exc:
            import traceback
            from resources.lib.kodi.ui import show_addon_error_info
            error(G.py2_decode(traceback.format_exc(), 'latin-1'))
            show_addon_error_info(exc)
            success = False

    if not success:
        from xbmcplugin import endOfDirectory
        endOfDirectory(handle=G.PLUGIN_HANDLE, succeeded=False)
    log_time_trace()