def request(url, params={}, headers={}, data=None, method=None):
    if params:
        url = "".join([url, "?", urllib_parse.urlencode(params)])

    req = urllib_request.Request(url)
    if method:
        req.get_method = lambda: method
    req.add_header("User-Agent", USER_AGENT)
    req.add_header("Accept-Encoding", "gzip")
    for k, v in headers.items():
        req.add_header(k, v)
    if data:
        req.data = data
    try:
        with closing(urllib_request.urlopen(req)) as response:
            data = response.read()
            if response.headers.get("Content-Encoding", "") == "gzip":
                import zlib
                data = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(data)
            response.data = data
            response.json = lambda: parse_json(data)
            response.xml = lambda: parse_xml(data)
            return response
    except Exception as e:
        import traceback
        map(log.error, traceback.format_exc().split("\n"))
        notify("%s: %s" % (getLocalizedString(30224), repr(e).encode('utf-8')))
        return None, None
    def AddonFailure(self, addonId):
        if ADDON.getSetting("provider_disable_failing") == u"false":
            return 0

        if addonId in self._failures:
            self._failures[addonId] += 1
        else:
            self._failures[addonId] = 1

        log.warning("Recorded failure %d for %s" %
                    (self._failures[addonId], addonId))

        if self._failures[addonId] > int(
                ADDON.getSetting("provider_allowed_failures")):
            try:
                time.sleep(10)
                notify(getLocalizedString(30111))
                urllib_request.urlopen("%s/provider/%s/disable" %
                                       (projectxD_HOST, addonId))
            except:
                notify(getLocalizedString(30112))
                return 0
        return self._failures[addonId]
def register(search, search_movie, search_episode, search_season=None):
    try:
        payload = json.loads(base64.b64decode(sys.argv[1]))
    except:
        notify(getLocalizedString(30102), time=1000)
        return

    results = ()
    method = {
        "search": search,
        "search_movie": search_movie,
        "search_season": search_season,
        "search_episode": search_episode,
    }.get(payload["method"]) or (lambda *a, **kw: [])
    try:
        results = ()
        try:
            objects = method(payload["search_object"])
            if objects is not None:
                results = tuple(objects)
        except Exception as e:
            import traceback
            map(log.error, traceback.format_exc().split("\n"))
            notify("%s: %s" % (getLocalizedString(30224), repr(e).encode('utf-8')))
            try:
                urllib_request.urlopen("%s/provider/%s/failure" % (projectxD_HOST, ADDON_ID))
            except:
                pass
    finally:
        try:
            req = urllib_request.Request(payload["callback_url"], data=json.dumps(results))
            with closing(urllib_request.urlopen(req)) as response:
                log.debug("callback returned: %d" % response.getcode())
        except Exception as e:
            import traceback
            map(log.error, traceback.format_exc().split("\n"))
            notify("%s: %s" % (getLocalizedString(30224), repr(e).encode('utf-8')))
            try:
                urllib_request.urlopen("%s/provider/%s/failure" % (projectxD_HOST, ADDON_ID))
            except:
                pass
def run(url_suffix="", retry=0):
    try:
        buffer_timeout = int(ADDON.getSetting("buffer_timeout"))
        if buffer_timeout < 60:
            buffer_timeout = 60
    except:
        buffer_timeout = 60
    buffer_timeout = buffer_timeout * 2

    try:
        preload_timeout = int(ADDON.getSetting("preload_timeout"))
        if preload_timeout < 1:
            preload_timeout = 1
    except:
        preload_timeout = 1

    socket.setdefaulttimeout(buffer_timeout)
    urllib_request.install_opener(
        urllib_request.build_opener(NoRedirectHandler()))

    # Pause currently playing projectx file to avoid doubling requests
    try:
        if xbmc.Player().isPlaying() and ADDON_ID in xbmc.Player(
        ).getPlayingFile():
            xbmc.Player().pause()
    except:
        pass

    url = sys.argv[0].replace("plugin://%s" % ADDON_ID,
                              projectxD_HOST + url_suffix) + sys.argv[2]
    query_add = ""

    if len(sys.argv) > 3:
        app = sys.argv[3].replace(":", "=")

        # Replacing resume=false with resume=true if item is launched from main window
        title = xbmc.getInfoLabel('ListItem.Title')
        label = xbmc.getInfoLabel('ListItem.Label')
        # if "resume" in app and not title and not label:
        #     app = app.replace("resume=false", "resume=true")
        # if "resume" not in app and not title and not label:
        if not title and not label:
            if app:
                app = app.replace("resume=false", "")
                app += "&"
            if app and "resume" not in app:
                app += "resume=true"
        query_add = app
    elif "play" in url or "links" in url:
        query_add = "resume=true"

    if query_add and "resume" not in url:
        query_add = query_add.replace("resume=", "doresume=")
        if "?" in url:
            url += "&" + query_add
        else:
            url += "?" + query_add

    log.debug("Requesting %s from %s" % (url, repr(sys.argv)))

    try:
        data = _json(url)
    except PlayerException as e:
        redirect_url = e.__str__()
        log.debug("Launching player with %s" % (redirect_url))
        xbmcplugin.endOfDirectory(HANDLE, succeeded=True)
        xbmc.sleep(500)
        xbmc.executeJSONRPC(
            '{"jsonrpc":"2.0","method":"Player.Open","params":{"item":{"file":"%s"}},"id":"1"}'
            % (redirect_url))
        return
    except RedirectException as e:
        redirect_url = e.__str__()
        log.debug("Redirecting Kodi with %s" % (redirect_url))
        xbmcplugin.endOfDirectory(HANDLE, succeeded=True)
        xbmc.sleep(500)
        if "keyboard=1" in sys.argv[0]:
            xbmc.executebuiltin('Container.Update(%s,replace)' %
                                (redirect_url))
        else:
            xbmc.executebuiltin('Container.Update(%s)' % (redirect_url))
        return
    except urllib_error.URLError as e:
        # We can retry the request if connection is refused.
        # For example when plugin has not yet started but is requested by someone.
        if retry <= 2:
            time.sleep(preload_timeout)
            return run(retry=retry + 1)

        if isinstance(e.reason, IOError) or isinstance(
                e.reason, OSError) or 'Connection refused' in e.reason:
            notify(getLocalizedString(30116), time=7000)
        else:
            import traceback
            map(log.error, traceback.format_exc().split("\n"))
            notify(e.reason, time=7000)
        return
    except Exception as e:
        import traceback
        map(log.error, traceback.format_exc().split("\n"))
        try:
            msg = six.ensure_text(e.__str__(), errors='ignore')
        except:
            try:
                msg = six.ensure_binary(e.__str__(), errors='ignore')
            except:
                msg = repr(e)
        notify(getLocalizedLabel(msg), time=7000)
        return

    if not data:
        return

    if data["content_type"]:
        content_type = data["content_type"]
        if data["content_type"].startswith("menus"):
            content_type = data["content_type"].split("_")[1]

        xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_UNSORTED)
        if content_type != "tvshows":
            xbmcplugin.addSortMethod(HANDLE,
                                     xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
        else:
            xbmcplugin.addSortMethod(HANDLE,
                                     xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE)
        xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_DATE)
        xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_GENRE)
        xbmcplugin.setContent(HANDLE, content_type)

    listitems = list(range(len(data["items"])))
    for i, item in enumerate(data["items"]):
        # Translate labels
        if item["label"][0:8] == "LOCALIZE":
            item["label"] = getLocalizedLabel(item["label"])
            if isinstance(item["label"], str):
                item["label"] = six.ensure_text(item["label"], 'utf-8')
        if item["label2"][0:8] == "LOCALIZE":
            item["label2"] = getLocalizedLabel(item["label2"])

        if PLATFORM['kodi'] >= 19:
            listItem = xbmcgui.ListItem(label=item["label"],
                                        label2=item["label2"])
            listItem.setArt({'icon': item["icon"]})
            listItem.setArt({'thumb': item["thumbnail"]})
        else:
            listItem = xbmcgui.ListItem(label=item["label"],
                                        label2=item["label2"],
                                        iconImage=item["icon"],
                                        thumbnailImage=item["thumbnail"])

        if item.get("info"):
            listItem.setInfo("video", item["info"])
        if item.get("stream_info"):
            for type_, values in item["stream_info"].items():
                listItem.addStreamInfo(type_, values)
        if item.get("art"):
            listItem.setArt(item["art"])
        elif ADDON.getSetting('default_fanart'
                              ) == 'true' and item["label"] != six.ensure_text(
                                  getLocalizedString(30218), 'utf-8'):
            fanart = os.path.join(ADDON_PATH, "fanart.png")
            listItem.setArt({'fanart': fanart})
        if item.get("context_menu"):
            # Translate context menus
            for m, menu in enumerate(item["context_menu"]):
                if menu[0][0:8] == "LOCALIZE":
                    menu[0] = getLocalizedLabel(menu[0])
            listItem.addContextMenuItems(item["context_menu"])
        listItem.setProperty("isPlayable", item["is_playable"] and "true"
                             or "false")
        if item.get("properties"):
            for k, v in item["properties"].items():
                listItem.setProperty(k, v)
        listitems[i] = (item["path"], listItem, not item["is_playable"])

    xbmcplugin.addDirectoryItems(HANDLE, listitems, totalItems=len(listitems))

    # Set ViewMode
    if data["content_type"]:
        viewMode = ADDON.getSetting("viewmode_%s" % data["content_type"])
        if viewMode:
            try:
                xbmc.executebuiltin('Container.SetViewMode(%s)' % viewMode)
            except Exception as e:
                log.warning("Unable to SetViewMode(%s): %s" %
                            (viewMode, repr(e)))

    xbmcplugin.endOfDirectory(HANDLE,
                              succeeded=True,
                              updateListing=False,
                              cacheToDisc=False)
def projectxd_thread(monitor):
    crash_count = 0
    try:
        monitor_abort = xbmc.Monitor()  # For Kodi >= 14
        while not monitor_abort.abortRequested():
            log.info("projectxd: starting projectxd")
            proc = None
            if hasSubprocess:
                proc = start_projectxd(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                if not proc:
                    break
            else:
                log.info("projectxd: current system is unable to run the binary")
                break

            threading.Thread(target=wait_for_abortRequested, args=[proc, monitor]).start()

            if not hasSubprocess:
                break

            if binary_platform["os"] == "windows":
                while proc.poll() is None:
                    log.info(proc.stdout.readline())
            else:
                # Kodi hangs on some Android (sigh...) systems when doing a blocking
                # read. We count on the fact that projectx daemon flushes its log
                # output on \n, creating a pretty clean output
                import fcntl
                import select
                fd = proc.stdout.fileno()
                fl = fcntl.fcntl(fd, fcntl.F_GETFL)
                fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
                while proc.poll() is None:
                    try:
                        to_read, _, _ = select.select([proc.stdout], [], [])
                        for ro in to_read:
                            line = ro.readline()
                            if line == "":  # write end is closed
                                break
                            log.info(line)
                    except IOError:
                        time.sleep(1)  # nothing to read, sleep

            if proc.returncode == 0 or proc.returncode == -9 or monitor_abort.abortRequested():
                break

            if proc.returncode == 5:
                notify(getLocalizedString(30332), time=3000)
            else:
                crash_count += 1
                notify(getLocalizedString(30100), time=3000)

            xbmc.executebuiltin("Dialog.Close(all, true)")
            system_information()
            time.sleep(5)
            if crash_count >= 3:
                notify(getLocalizedString(30110), time=3000)
                break

    except Exception as e:
        import traceback
        map(log.error, traceback.format_exc().split("\n"))
        notify("%s: %s" % (getLocalizedString(30226), repr(e).encode('utf-8')))
        raise
 def Notify(self, header, message, image):
     return notify(getLocalizedLabel(message), header, 3000, image)