示例#1
0
def make_http_call_cache(callname, params, data):
    """Make an IPC call via HTTP and wait for it to return.
    The contents of data will be expanded to kwargs and passed into the target function."""
    try:  # Python 3
        from urllib.request import build_opener, install_opener, ProxyHandler, HTTPError, URLError, Request, urlopen
    except ImportError:  # Python 2
        from urllib2 import build_opener, install_opener, ProxyHandler, HTTPError, URLError, Request, urlopen
    import json
    # debug('Handling HTTP IPC call to {}'.format(callname))
    # Note: On python 3, using 'localhost' slowdown the call (Windows OS is affected) not sure if it is an urllib issue
    url = 'http://127.0.0.1:{}/{}'.format(G.LOCAL_DB.get_value('cache_service_port', 8002), callname)
    install_opener(build_opener(ProxyHandler({})))  # don't use proxy for localhost
    r = Request(url=url, data=data, headers={'Params': json.dumps(params)})
    try:
        result = urlopen(r, timeout=IPC_TIMEOUT_SECS).read()
    except HTTPError as exc:
        if exc.reason in exceptions.__dict__:
            raise_from(exceptions.__dict__[exc.reason], exc)
        raise_from(Exception('The service has returned: {}'.format(exc.reason)), exc)
    except URLError as exc:
        # On PY2 the exception message have to be decoded with latin-1 for system with symbolic characters
        err_msg = G.py2_decode(str(exc), 'latin-1')
        if '10049' in err_msg:
            err_msg += '\r\nPossible cause is wrong localhost settings in your operative system.'
        LOG.error(err_msg)
        raise_from(exceptions.BackendNotReady(G.py2_encode(err_msg, encoding='latin-1')), exc)
    return result
示例#2
0
def _log(msg, level, *args, **kwargs):
    """Log a message to the Kodi logfile."""
    if args or kwargs:
        msg = msg.format(*args, **kwargs)
    xbmc.log(
        G.py2_encode('[{identifier} ({handle})] {msg}'.format(
            identifier=G.ADDON_ID, handle=G.PLUGIN_HANDLE, msg=msg)), level)
示例#3
0
def make_http_call(callname, data):
    """Make an IPC call via HTTP and wait for it to return.
    The contents of data will be expanded to kwargs and passed into the target function."""
    from collections import OrderedDict
    try:  # Python 3
        from urllib.request import build_opener, install_opener, ProxyHandler, HTTPError, URLError, urlopen
    except ImportError:  # Python 2
        from urllib2 import build_opener, install_opener, ProxyHandler, HTTPError, URLError, urlopen
    import json
    LOG.debug('Handling HTTP IPC call to {}'.format(callname))
    # Note: On python 3, using 'localhost' slowdown the call (Windows OS is affected) not sure if it is an urllib issue
    url = 'http://127.0.0.1:{}/{}'.format(G.LOCAL_DB.get_value('ns_service_port', 8001), callname)
    install_opener(build_opener(ProxyHandler({})))  # don't use proxy for localhost
    try:
        result = json.loads(
            urlopen(url=url, data=json.dumps(data).encode('utf-8'), timeout=IPC_TIMEOUT_SECS).read(),
            object_pairs_hook=OrderedDict)
    except HTTPError as exc:
        result = json.loads(exc.reason)
    except URLError as exc:
        # On PY2 the exception message have to be decoded with latin-1 for system with symbolic characters
        err_msg = G.py2_decode(str(exc), 'latin-1')
        if '10049' in err_msg:
            err_msg += '\r\nPossible cause is wrong localhost settings in your operative system.'
        LOG.error(err_msg)
        raise_from(exceptions.BackendNotReady(G.py2_encode(err_msg, encoding='latin-1')),
                   exc)
    _raise_for_error(result)
    return result
def _get_error_details(decoded_response):
    err_message = 'Unhandled error check log.'
    err_number = None
    # Catch a chunk error
    if 'errordata' in decoded_response:
        err_data = json.loads(
            base64.standard_b64decode(decoded_response['errordata']))
        err_message = err_data['errormsg']
        err_number = err_data['internalcode']
    # Catch a manifest error
    elif 'error' in decoded_response:
        if decoded_response['error'].get('errorDisplayMessage'):
            err_message = decoded_response['error']['errorDisplayMessage']
            err_number = decoded_response['error'].get('bladeRunnerCode')
    # Catch a license error
    elif 'result' in decoded_response and isinstance(
            decoded_response.get('result'), list):
        if 'error' in decoded_response['result'][0]:
            if decoded_response['result'][0]['error'].get(
                    'errorDisplayMessage'):
                err_message = decoded_response['result'][0]['error'][
                    'errorDisplayMessage']
                err_number = decoded_response['result'][0]['error'].get(
                    'bladeRunnerCode')
    return G.py2_encode(err_message), err_number
示例#5
0
 def __getitem__(self, key):
     try:
         # If you use multiple Kodi profiles you need to distinguish the property of current profile
         return G.WND_KODI_HOME.getProperty(
             G.py2_encode('netflix_{}_{}'.format(
                 get_current_kodi_profile_name(), key)))
     except Exception:  # pylint: disable=broad-except
         return ''
示例#6
0
 def __init__(self):
     self.window_cls = Window(10000)  # Kodi home window
     # If you use multiple Kodi profiles you need to distinguish the property of current profile
     self.prop_nf_service_status = G.py2_encode(
         'nf_service_status_' + get_current_kodi_profile_name())
     self.controller = None
     self.library_updater = None
     self.settings_monitor = None
def _get_error_details(decoded_response):
    # Catch a chunk error
    if 'errordata' in decoded_response:
        return G.py2_encode(
            json.loads(base64.standard_b64decode(
                decoded_response['errordata']))['errormsg'])
    # Catch a manifest error
    if 'error' in decoded_response:
        if decoded_response['error'].get('errorDisplayMessage'):
            return G.py2_encode(
                decoded_response['error']['errorDisplayMessage'])
    # Catch a license error
    if 'result' in decoded_response and isinstance(
            decoded_response.get('result'), list):
        if 'error' in decoded_response['result'][0]:
            if decoded_response['result'][0]['error'].get(
                    'errorDisplayMessage'):
                return G.py2_encode(decoded_response['result'][0]['error']
                                    ['errorDisplayMessage'])
    return G.py2_encode('Unhandled error check log.')
示例#8
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()
示例#9
0
def convert_language_iso(from_value, iso_format=xbmc.ISO_639_1, use_fallback=True):
    """
    Convert language code from an English name or three letter code (ISO 639-2) to two letter code (ISO 639-1)

    :param iso_format: specify the iso format (ISO_639_1 or ISO_639_2)
    :param use_fallback: if True when the conversion fails, is returned the current Kodi active language
    """
    converted_lang = xbmc.convertLanguage(G.py2_encode(from_value), iso_format)
    if not use_fallback:
        return converted_lang
    converted_lang = converted_lang if converted_lang else xbmc.getLanguage(iso_format, False)  # Get lang. active
    return converted_lang if converted_lang else 'en' if iso_format == xbmc.ISO_639_1 else 'eng'
示例#10
0
def _convert_season(value):
    if isinstance(value, int):
        return str(value)
    # isdigit is needed to filter out non numeric characters from 'shortName' key
    return ''.join([n for n in G.py2_encode(value) if n.isdigit()])
示例#11
0
def show_notification(msg, title='Netflix', time=3000):
    """Show a notification"""
    xbmc.executebuiltin(
        G.py2_encode('Notification({}, {}, {}, {})'.format(
            title, msg, time, G.ICON)))
示例#12
0
 def __setitem__(self, key, newvalue):
     # If you use multiple Kodi profiles you need to distinguish the property of current profile
     G.WND_KODI_HOME.setProperty(
         G.py2_encode('netflix_{}_{}'.format(
             get_current_kodi_profile_name(), key)), newvalue)
示例#13
0
def play_media(media):
    """Play a media in Kodi"""
    xbmc.executebuiltin(G.py2_encode('PlayMedia({})'.format(media)))
示例#14
0
def convert_language_iso(from_value, iso_format=xbmc.ISO_639_1):
    """
    Convert given value (English name or two/three letter code) to the specified format
    :param iso_format: specify the iso format (two letter code ISO_639_1 or three letter code ISO_639_2)
    """
    return xbmc.convertLanguage(G.py2_encode(from_value), iso_format)
示例#15
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()