Пример #1
0
    def _do_search_request(self, request_params):
        censored_params = request_params.copy()
        censored_key = censored_params['apikey']
        censored_params['apikey'] = "{}{}{}".format(censored_key[0:2],
                                                    "*" * 26,
                                                    censored_key[-4:])
        log.debug('Making a request to Jackett using params %s',
                  repr(censored_params))

        search_resp = self._session.get("all/results/torznab",
                                        params=request_params)
        if search_resp.status_code != httplib.OK:
            notify(translation(32700).format(search_resp.reason),
                   image=get_icon_path())
            log.error("Jackett returned %s", search_resp.reason)
            return []

        err = self.get_error(search_resp.content)
        if err is not None:
            notify(translation(32700).format(err["description"]),
                   image=get_icon_path())
            log.error("got code %s: %s", err["code"], err["description"])
            return []

        log.debug("Jackett returned below response")
        log.debug("===============================")
        log.debug(search_resp.content)
        log.debug("===============================")

        return self._parse_items(search_resp.content)
Пример #2
0
    def search_movie(self, title, year, imdb_id):
        if "search_tags" not in self._caps:
            notify(translation(32701), image=get_icon_path())
            return []

        movie_search_caps = self._caps["search_tags"]['movie-search']
        if not movie_search_caps['enabled']:
            notify(translation(32702).format("movie"), image=get_icon_path())
            log.warning(
                "Jackett has no movie capabilities, please add a indexer that has movie capabilities. "
                "Falling back to query search...")
            return self.search_query(title + u' ' + year)

        # todo what values are possible for imdb_id?
        movie_params = movie_search_caps["params"]
        request_params = {"t": "movie", "apikey": self._api_key}

        has_imdb_caps = 'imdbid' in movie_params
        log.debug("movie search; imdb_id=%s, has_imdb_caps=%s", imdb_id,
                  has_imdb_caps)
        if imdb_id and has_imdb_caps:
            request_params["imdbid"] = imdb_id
        else:
            request_params["q"] = title + u' ' + year
            log.debug("searching movie with query=%s", request_params["q"])

        return self._do_search_request(request_params)
Пример #3
0
    def search_shows(self, title, season=None, episode=None, imdb_id=None):
        if "search_tags" not in self._caps:
            notify(translation(32701), image=get_icon_path())
            return []

        tv_search_caps = self._caps["search_tags"]['tv-search']
        if not tv_search_caps['enabled']:
            notify(translation(32702).format("show"), image=get_icon_path())
            log.warning(
                "Jackett has no tvsearch capabilities, please add a indexer that has tvsearch capabilities. "
                "Falling back to query search...")

            title_ep = title
            if bool(season):
                title_ep = "{} S{:0>2}".format(title_ep, season)
                if bool(episode):
                    title_ep = "{}E{:0>2}".format(title_ep, episode)

            results = self.search_query(title_ep)
            if get_setting("search_season_on_episode",
                           bool) and bool(season) and bool(episode):
                season_query = re.escape("{:0>2}".format(season))
                results = results + self._filter_season(
                    self.search_query("{} S{}".format(title, season_query)),
                    season)

            return results

        # todo what values are possible for imdb_id?
        tv_params = tv_search_caps["params"]
        request_params = {"t": "tvsearch", "apikey": self._api_key}
        has_imdb_caps = 'imdbid' in tv_params
        log.debug("movie search; imdb_id=%s, has_imdb_caps=%s", imdb_id,
                  has_imdb_caps)
        if imdb_id and has_imdb_caps:
            request_params["imdbid"] = imdb_id
        else:
            log.debug("searching tv show with query=%s, season=%s, episode=%s",
                      title, season, episode)
            request_params["q"] = title
            if bool(season) and 'season' in tv_params:
                request_params["season"] = season
            if bool(episode) and 'ep' in tv_params:
                request_params["ep"] = episode

        results = self._do_search_request(request_params)
        if get_setting(
                "search_season_on_episode", bool
        ) and 'season' in request_params and 'ep' in request_params:
            del request_params['ep']
            results = results + self._filter_season(
                self._do_search_request(request_params), season)

        return results
Пример #4
0
def search_jackett(payload, method):
    jackett = get_client()
    if jackett is None:
        utils.notify(utils.translation(32603), image=utils.get_icon_path())
        return []

    log.debug("Processing %s with Jackett", method)
    if method == 'movie':
        res = jackett.search_movie(payload["search_title"], payload['year'],
                                   payload["imdb_id"])
    elif method == 'season':
        res = jackett.search_season(payload["search_title"], payload["season"],
                                    payload["imdb_id"])
    elif method == 'episode':
        res = jackett.search_episode(payload["search_title"],
                                     payload["season"], payload["episode"],
                                     payload["imdb_id"])
    elif method == 'anime':
        log.warning("jackett provider does not yet support anime search")
        res = []
        log.info("anime payload=%s", repr(payload))
    #     client.search_query(payload["search_title"], payload["season"], payload["episode"], payload["imdb_id"])
    else:
        res = jackett.search_query(payload["search_title"])

    log.debug("%s search returned %d results", method, len(res))

    res = filter_results(method, res)

    return sort_results(res)
Пример #5
0
def get_client():
    host = urlparse(get_setting('host'))
    if host.netloc == '' or host.scheme == '':
        log.warning("Host %s is invalid. Can't return anything",
                    get_setting('host'))
        utils.notify(utils.translation(32600), image=utils.get_icon_path())
        return None

    api_key = get_setting('api_key')

    if len(api_key) != 32:
        utils.notify(utils.translation(32601), image=utils.get_icon_path())
        return None
    else:
        log.debug("jackett host: %s", host)
        log.debug("jackett api_key: %s%s%s", api_key[0:2], "*" * 26,
                  api_key[-4:])

    return Jackett(host=host.geturl(), api_key=api_key)
Пример #6
0
def tray():
    app = QtGui.QApplication(['NSAway'])
    style = app.style()
    ico = QtGui.QIcon(get_icon_path("good.ico"))
    w = QtGui.QWidget()

    trayIcon = SystemTrayIcon(ico, w)
    trayIcon.show()

    sys.exit(app.exec_())
Пример #7
0
def tray():
  app = QtGui.QApplication(['NSAway'])
  style = app.style()
  ico = QtGui.QIcon(get_icon_path("good.ico"))
  w = QtGui.QWidget()

  trayIcon = SystemTrayIcon(ico, w)
  trayIcon.show()

  sys.exit(app.exec_())
Пример #8
0
    def search_query(self, query):
        if not self._caps["search_tags"]['search']:
            notify(translation(32702).format("query"), image=get_icon_path())
            log.warning(
                "Jackett has no search capabilities, please add a indexer that has search capabilities."
            )
            return []

        request_params = {"apikey": self._api_key, "q": query}

        return self._do_search_request(request_params)
Пример #9
0
    def get_caps(self):
        caps_resp = self._session.get("all/results/torznab",
                                      params={
                                          "t": "caps",
                                          "apikey": self._api_key
                                      })

        if caps_resp.status_code != httplib.OK:
            notify(translation(32700).format(caps_resp.reason),
                   image=get_icon_path())
            log.error("Jackett return %s", caps_resp.reason)
            set_setting('settings_validated', caps_resp.reason)
            return

        err = self.get_error(caps_resp.content)
        if err is not None:
            notify(translation(32700).format(err["description"]),
                   image=get_icon_path())
            log.error("got code %s: %s", err["code"], err["description"])
            set_setting('settings_validated', err["description"])
            return

        set_setting('settings_validated', 'Success')

        xml = ET.ElementTree(ET.fromstring(caps_resp.content)).getroot()

        # todo handle gracefully, doesn't exist for individual trackers
        # self._caps["limits"] = xml.find("limits").attrib

        self._caps["search_tags"] = {}
        for type_tag in xml.findall('searching/*'):
            self._caps["search_tags"][type_tag.tag] = {
                "enabled":
                type_tag.attrib["available"] == "yes",
                "params": [
                    p for p in type_tag.attrib['supportedParams'].split(",")
                    if p
                ],
            }

        log.info("Found capabilities: %s", repr(self._caps))
Пример #10
0
def validate_client():
    p_dialog = xbmcgui.DialogProgressBG()
    try:
        p_dialog.create('Elementum [COLOR FFFF6B00]Jackett[/COLOR]',
                        utils.translation(32005))
        get_client()
        if get_setting("settings_validated") == "Success":
            utils.notify(utils.translation(32006), image=utils.get_icon_path())
        utils.ADDON.openSettings()
    finally:
        p_dialog.close()
        del p_dialog
Пример #11
0
def search(payload, method="general"):
    """ Main search entrypoint

    Args:
        payload (dict): Search payload from Quasar.
        method   (str): Type of search, can be ``general``, ``movie``, ``show``, ``season`` or ``anime``

    Returns:
        list: All filtered results in the format Quasar expects
    """
    log.debug("Searching with payload (%s): %s" % (method, repr(payload)))

    if method == 'general':
        payload = {'title': payload}

    global request_time
    global provider_names
    global provider_results
    global available_providers

    provider_names = []
    provider_results = []
    available_providers = 0
    request_time = time.time()

    providers = get_enabled_providers()

    if len(providers) == 0:
        notify(translation(32060), image=get_icon_path())
        log.error("No providers enabled")
        return []

    log.info(
        "Burstin' with %s" %
        ", ".join([definitions[provider]['name'] for provider in providers]))

    if get_setting("use_cloudhole", bool):
        clearance, user_agent = get_cloudhole_clearance(get_cloudhole_key())
        set_setting('clearance', clearance)
        set_setting('user_agent', user_agent)

    if get_setting('kodi_language', bool):
        kodi_language = xbmc.getLanguage(xbmc.ISO_639_1)
        if not kodi_language:
            log.warning("Kodi returned empty language code...")
        elif 'titles' not in payload or not payload['titles']:
            log.info("No translations available...")
        elif payload['titles'] and kodi_language not in payload['titles']:
            log.info("No '%s' translation available..." % kodi_language)

    p_dialog = xbmcgui.DialogProgressBG()
    p_dialog.create('Quasar [COLOR FFFF6B00]Burst[/COLOR]', translation(32061))
    for provider in providers:
        available_providers += 1
        provider_names.append(definitions[provider]['name'])
        task = Thread(target=run_provider, args=(provider, payload, method))
        task.start()

    providers_time = time.time()
    total = float(available_providers)

    # Exit if all providers have returned results or timeout reached, check every 100ms
    while time.time() - providers_time < timeout and available_providers > 0:
        timer = time.time() - providers_time
        log.debug("Timer: %ds / %ds" % (timer, timeout))
        if timer > timeout:
            break
        message = translation(
            32062
        ) % available_providers if available_providers > 1 else translation(
            32063)
        p_dialog.update(int((total - available_providers) / total * 100),
                        message=message)
        time.sleep(0.25)

    p_dialog.close()
    del p_dialog

    if available_providers > 0:
        message = u', '.join(provider_names)
        message = message + translation(32064)
        log.warning(message.encode('utf-8'))
        notify(message, ADDON_ICON)

    log.debug("all provider_results: %s" % repr(provider_results))

    filtered_results = apply_filters(provider_results)

    log.debug("all filtered_results: %s" % repr(filtered_results))

    log.info("Providers returned %d results in %s seconds" %
             (len(filtered_results), round(time.time() - request_time, 2)))

    return filtered_results
Пример #12
0
def search(payload, method="general"):
    """ Main search entrypoint

    Args:
        payload (dict): Search payload from Quasar.
        method   (str): Type of search, can be ``general``, ``movie``, ``show``, ``season`` or ``anime``

    Returns:
        list: All filtered results in the format Quasar expects
    """
    log.debug("Searching with payload (%s): %s" % (method, repr(payload)))

    if method == 'general':
        payload = {
            'title': payload
        }

    global request_time
    global provider_names
    global provider_results
    global available_providers

    provider_names = []
    provider_results = []
    available_providers = 0
    request_time = time.time()

    providers = get_enabled_providers()

    if len(providers) == 0:
        notify(translation(32060), image=get_icon_path())
        log.error("No providers enabled")
        return []

    log.info("Burstin' with %s" % ", ".join([definitions[provider]['name'] for provider in providers]))

    if get_setting("use_cloudhole", bool):
        clearance, user_agent = get_cloudhole_clearance(get_cloudhole_key())
        set_setting('clearance', clearance)
        set_setting('user_agent', user_agent)

    if get_setting('kodi_language', bool):
        kodi_language = xbmc.getLanguage(xbmc.ISO_639_1)
        if not kodi_language:
            log.warning("Kodi returned empty language code...")
        elif 'titles' not in payload or not payload['titles']:
            log.info("No translations available...")
        elif payload['titles'] and kodi_language not in payload['titles']:
            log.info("No '%s' translation available..." % kodi_language)

    p_dialog = xbmcgui.DialogProgressBG()
    p_dialog.create('Quasar [COLOR FFFF6B00]Burst[/COLOR]', translation(32061))
    for provider in providers:
        available_providers += 1
        provider_names.append(definitions[provider]['name'])
        task = Thread(target=run_provider, args=(provider, payload, method))
        task.start()

    providers_time = time.time()
    total = float(available_providers)

    # Exit if all providers have returned results or timeout reached, check every 100ms
    while time.time() - providers_time < timeout and available_providers > 0:
        timer = time.time() - providers_time
        log.debug("Timer: %ds / %ds" % (timer, timeout))
        if timer > timeout:
            break
        message = translation(32062) % available_providers if available_providers > 1 else translation(32063)
        p_dialog.update(int((total - available_providers) / total * 100), message=message)
        time.sleep(0.25)

    p_dialog.close()
    del p_dialog

    if available_providers > 0:
        message = u', '.join(provider_names)
        message = message + translation(32064)
        log.warning(message.encode('utf-8'))
        notify(message, ADDON_ICON)

    log.debug("all provider_results: %s" % repr(provider_results))

    filtered_results = apply_filters(provider_results)

    log.debug("all filtered_results: %s" % repr(filtered_results))

    log.info("Providers returned %d results in %s seconds" % (len(filtered_results), round(time.time() - request_time, 2)))

    return filtered_results
Пример #13
0
def update_tray_icon(tray,status):
  # status can only be (good, alert)
  tray.setIcon(QtGui.QIcon(get_icon_path(status+".ico")))
Пример #14
0
def process(provider,
            generator,
            filtering,
            has_special,
            verify_name=True,
            verify_size=True):
    """ Method for processing provider results using its generator and Filtering class instance

    Args:
        provider        (str): Provider ID
        generator  (function): Generator method, can be either ``extract_torrents`` or ``extract_from_api``
        filtering (Filtering): Filtering class instance
        has_special    (bool): Whether title contains special chars
        verify_name    (bool): Whether to double-check the results' names match the query or not
        verify_size    (bool): Whether to check the results' file sizes
    """
    log.debug("execute_process for %s with %s" % (provider, repr(generator)))
    definition = definitions[provider]
    definition = get_alias(definition, get_setting("%s_alias" % provider))

    client = Client()
    token = None
    logged_in = False
    token_auth = False

    if get_setting("use_cloudhole", bool):
        client.clearance = get_setting('clearance')
        client.user_agent = get_setting('user_agent')

    if get_setting('kodi_language', bool):
        kodi_language = xbmc.getLanguage(xbmc.ISO_639_1)
        if kodi_language:
            filtering.kodi_language = kodi_language
        language_exceptions = get_setting('language_exceptions')
        if language_exceptions.strip().lower():
            filtering.language_exceptions = re.split(r',\s?',
                                                     language_exceptions)

    log.debug("[%s] Queries: %s" % (provider, filtering.queries))
    log.debug("[%s] Extras:  %s" % (provider, filtering.extras))

    for query, extra in zip(filtering.queries, filtering.extras):
        log.debug("[%s] Before keywords - Query: %s - Extra: %s" %
                  (provider, repr(query), repr(extra)))
        if has_special:
            # Removing quotes, surrounding {title*} keywords, when title contains special chars
            query = re.sub("[\"']({title.*?})[\"']", '\\1', query)

        query = filtering.process_keywords(provider, query)
        extra = filtering.process_keywords(provider, extra)
        if 'charset' in definition and 'utf' not in definition[
                'charset'].lower():
            try:
                query = urllib.quote(query.encode(definition['charset']))
                extra = urllib.quote(extra.encode(definition['charset']))
            except:
                pass

        log.debug("[%s] After keywords  - Query: %s - Extra: %s" %
                  (provider, repr(query), repr(extra)))
        if not query:
            return filtering.results

        url_search = filtering.url.replace('QUERY', query)
        if extra:
            url_search = url_search.replace('EXTRA', extra)
        else:
            url_search = url_search.replace('EXTRA', '')
        url_search = url_search.replace(' ', definition['separator'])

        # MagnetDL fix...
        url_search = url_search.replace('FIRSTLETTER', query[:1])

        # Creating the payload for POST method
        payload = dict()
        for key, value in filtering.post_data.iteritems():
            if 'QUERY' in value:
                payload[key] = filtering.post_data[key].replace('QUERY', query)
            else:
                payload[key] = filtering.post_data[key]

        # Creating the payload for GET method
        data = None
        if filtering.get_data:
            data = dict()
            for key, value in filtering.get_data.iteritems():
                if 'QUERY' in value:
                    data[key] = filtering.get_data[key].replace('QUERY', query)
                else:
                    data[key] = filtering.get_data[key]

        log.debug("-   %s query: %s" % (provider, repr(query)))
        log.debug("--  %s url_search before token: %s" %
                  (provider, repr(url_search)))
        log.debug("--- %s using POST payload: %s" % (provider, repr(payload)))
        log.debug("----%s filtering with post_data: %s" %
                  (provider, repr(filtering.post_data)))

        # Set search's "title" in filtering to double-check results' names
        if 'filter_title' in definition and definition['filter_title']:
            filtering.filter_title = True
            filtering.title = query

        if token:
            log.info('[%s] Reusing existing token' % provider)
            url_search = url_search.replace('TOKEN', token)
        elif 'token' in definition:
            token_url = definition['base_url'] + definition['token']
            log.debug("Getting token for %s at %s" %
                      (provider, repr(token_url)))
            client.open(token_url.encode('utf-8'))
            try:
                token_data = json.loads(client.content)
            except:
                log.error('%s: Failed to get token for %s' %
                          (provider, repr(url_search)))
                return filtering.results
            log.debug("Token response for %s: %s" %
                      (provider, repr(token_data)))
            if 'token' in token_data:
                token = token_data['token']
                log.debug("Got token for %s: %s" % (provider, repr(token)))
                url_search = url_search.replace('TOKEN', token)
            else:
                log.warning('%s: Unable to get token for %s' %
                            (provider, repr(url_search)))

        if logged_in:
            log.info("[%s] Reusing previous login" % provider)
        elif token_auth:
            log.info("[%s] Reusing previous token authorization" % provider)
        elif 'private' in definition and definition['private']:
            username = get_setting('%s_username' % provider)
            password = get_setting('%s_password' % provider)
            passkey = get_setting('%s_passkey' % provider)
            if not username and not password and not passkey:
                for addon_name in ('script.magnetic.%s' % provider,
                                   'script.magnetic.%s-mc' % provider):
                    for setting in ('username', 'password'):
                        try:
                            value = xbmcaddon.Addon(addon_name).getSetting(
                                setting)
                            set_setting('%s_%s' % (provider, setting), value)
                            if setting == 'username':
                                username = value
                            if setting == 'password':
                                password = value
                        except:
                            pass

            if passkey:
                logged_in = True
                client.passkey = passkey
                url_search = url_search.replace('PASSKEY', passkey)

            elif 'login_object' in definition and definition['login_object']:
                logged_in = False
                login_object = definition['login_object'].replace(
                    'USERNAME',
                    '"%s"' % username).replace('PASSWORD', '"%s"' % password)

                # TODO generic flags in definitions for those...
                if provider == 'lostfilm':
                    client.open(definition['root_url'] +
                                '/v_search.php?c=110&s=1&e=1')
                    if client.content == 'log in first':
                        pass
                    else:
                        log.info('[%s] Login successful' % provider)
                        logged_in = True

                if 'token_auth' in definition:
                    # log.debug("[%s] logging in with: %s" % (provider, login_object))
                    if client.open(definition['root_url'] +
                                   definition['token_auth'],
                                   post_data=eval(login_object)):
                        try:
                            token_data = json.loads(client.content)
                        except:
                            log.error('%s: Failed to get token from %s' %
                                      (provider, definition['token_auth']))
                            return filtering.results
                        log.debug("Token response for %s: %s" %
                                  (provider, repr(token_data)))
                        if 'token' in token_data:
                            client.token = token_data['token']
                            log.debug("Auth token for %s: %s" %
                                      (provider, repr(client.token)))
                        else:
                            log.error('%s: Unable to get auth token for %s' %
                                      (provider, repr(url_search)))
                            return filtering.results
                        log.info('[%s] Token auth successful' % provider)
                        token_auth = True
                    else:
                        log.error("[%s] Token auth failed with response: %s" %
                                  (provider, repr(client.content)))
                        return filtering.results
                elif not logged_in and client.login(
                        definition['root_url'] + definition['login_path'],
                        eval(login_object), definition['login_failed']):
                    log.info('[%s] Login successful' % provider)
                    logged_in = True
                elif not logged_in:
                    log.error("[%s] Login failed: %s", provider, client.status)
                    log.debug("[%s] Failed login content: %s", provider,
                              repr(client.content))
                    notify(translation(32089), image=get_icon_path())
                    return filtering.results

                if logged_in:
                    if provider == 'lostfilm':
                        log.info('[%s] Search lostfilm serial ID...', provider)
                        url_search = fix_lf(url_search)
                        client.open(url_search.encode('utf-8'),
                                    post_data=payload,
                                    get_data=data)
                        search_info = re.search(r'PlayEpisode\((.*?)\)">',
                                                client.content)
                        if search_info:
                            series_details = re.search(
                                '\'(\d+)\',\'(\d+)\',\'(\d+)\'',
                                search_info.group(1))
                            client.open(definition['root_url'] +
                                        '/v_search.php?c=%s&s=%s&e=%s' %
                                        (series_details.group(1),
                                         series_details.group(2),
                                         series_details.group(3)))
                            redirect_url = re.search(ur'url=(.*?)">',
                                                     client.content)
                            if redirect_url is not None:
                                url_search = redirect_url.group(1)
                        else:
                            log.info('[%s] Not found ID in %s' %
                                     (provider, url_search))
                            return filtering.results

        log.info(">  %s search URL: %s" %
                 (definition['name'].rjust(longest), url_search))

        client.open(url_search.encode('utf-8'),
                    post_data=payload,
                    get_data=data)
        filtering.results.extend(
            generate_payload(provider, generator(provider, client), filtering,
                             verify_name, verify_size))
    return filtering.results
Пример #15
0
    def _parse_item(self, item):
        result = {
            "name": None,
            "provider": "Unknown",
            "size": "Unknown",
            "uri": None,
            "seeds": "0",
            "peers": "0",
            "info_hash": "",
            "language": None,

            # todo would be nice to assign correct icons but that can be very time consuming due to the number
            #  of indexers in Jackett
            "icon": get_icon_path(),
            "_size_bytes": -1
        }

        for ref in item:
            tag = ref.tag
            attrib = ref.attrib
            if tag == "{" + self._torznab_ns + "}attr":
                val = attrib["value"]
                if isinstance(val, str):
                    val = val.decode("utf-8")
                if "name" in attrib and "value" in attrib and attrib["name"] and val and \
                        attrib["name"] in self._torznab_elementum_mappings["torznab_attrs"]:
                    json = self._torznab_elementum_mappings["torznab_attrs"][
                        attrib["name"]]
                    result[json] = val
                continue

            if ref.tag in self._torznab_elementum_mappings[
                    "tags"] and ref.text is not None:
                json = self._torznab_elementum_mappings["tags"][ref.tag]
                val = ref.text.strip()

                if isinstance(val, str):
                    val = val.decode("utf-8")

                result[json] = val

        # if we didn't get a magnet uri, attempt to resolve the magnet uri.
        # todo for some reason Elementum cannot resolve the link that gets proxied through Jackett.
        #  So we will resolve it manually for Elementum for now.
        #  In actuality, this should be fixed within Elementum
        if result["uri"] is None:
            link = item.find('link')
            jackett_uri = ""
            if link is not None:
                jackett_uri = link.text
            else:
                enclosure = item.find('enclosure')
                if enclosure is not None:
                    jackett_uri = enclosure.attrib['url']

            if jackett_uri != "":
                result["uri"] = get_magnet_from_jackett(jackett_uri)

        if result["name"] is None or result["uri"] is None:
            log.warning("Could not parse item; name = %s; uri = %s",
                        result["name"], result["uri"])
            log.debug("Failed item is: %s",
                      ElementTree.tostring(item, encoding='utf8'))
            return None

        # result["name"] = result["name"].decode("utf-8") # might be needed for non-english items
        result["seeds"] = int(result["seeds"])
        result["peers"] = int(result["peers"])
        resolution = get_resolution(result["name"])
        result["resolution"] = utils.resolutions.keys()[::-1].index(resolution)
        result["_resolution"] = resolution
        result["release_type"] = get_release_type(result["name"])

        if result["size"] != "Unknown":
            result["_size_bytes"] = int(result["size"])
            result["size"] = human_size(result["_size_bytes"])

        return result
Пример #16
0
def process(provider,
            generator,
            filtering,
            has_special,
            verify_name=True,
            verify_size=True):
    """ Method for processing provider results using its generator and Filtering class instance

    Args:
        provider        (str): Provider ID
        generator  (function): Generator method, can be either ``extract_torrents`` or ``extract_from_api``
        filtering (Filtering): Filtering class instance
        has_special    (bool): Whether title contains special chars
        verify_name    (bool): Whether to double-check the results' names match the query or not
        verify_size    (bool): Whether to check the results' file sizes
    """
    log.debug("execute_process for %s with %s" % (provider, repr(generator)))
    definition = definitions[provider]
    definition = get_alias(definition, get_setting("%s_alias" % provider))

    client = Client(info=filtering.info)
    logged_in = False

    if get_setting('kodi_language', bool):
        kodi_language = xbmc.getLanguage(xbmc.ISO_639_1)
        if kodi_language:
            filtering.kodi_language = kodi_language
        language_exceptions = get_setting('language_exceptions')
        if language_exceptions.strip().lower():
            filtering.language_exceptions = re.split(r',\s?',
                                                     language_exceptions)

    log.debug("[%s] Queries: %s" % (provider, filtering.queries))
    log.debug("[%s] Extras:  %s" % (provider, filtering.extras))

    for query, extra in zip(filtering.queries, filtering.extras):
        log.debug("[%s] Before keywords - Query: %s - Extra: %s" %
                  (provider, repr(query), repr(extra)))
        if has_special:
            # Removing quotes, surrounding {title*} keywords, when title contains special chars
            query = re.sub("[\"']({title.*?})[\"']", '\\1', query)

        query = filtering.process_keywords(provider, query)
        extra = filtering.process_keywords(provider, extra)
        if 'charset' in definition and 'utf' not in definition[
                'charset'].lower():
            try:
                query = urllib.quote(query.encode(definition['charset']))
                extra = urllib.quote(extra.encode(definition['charset']))
            except:
                pass

        log.debug("[%s] After keywords  - Query: %s - Extra: %s" %
                  (provider, repr(query), repr(extra)))
        if not query:
            return filtering.results

        query = urllib.quote(query.encode('utf-8'))
        url_search = filtering.url.replace('QUERY', query)
        if extra:
            url_search = url_search.replace('EXTRA', extra)
        else:
            url_search = url_search.replace('EXTRA', '')
        url_search = url_search.replace(' ', definition['separator'])

        if 'post_data' in definition and not filtering.post_data:
            filtering.post_data = eval(definition['post_data'])

        # Creating the payload for POST method
        payload = dict()
        for key, value in filtering.post_data.iteritems():
            if 'QUERY' in value:
                payload[key] = filtering.post_data[key].replace('QUERY', query)
            else:
                payload[key] = filtering.post_data[key]

        # Creating the payload for GET method
        data = None
        if filtering.get_data:
            data = dict()
            for key, value in filtering.get_data.iteritems():
                if 'QUERY' in value:
                    data[key] = filtering.get_data[key].replace('QUERY', query)
                else:
                    data[key] = filtering.get_data[key]

        log.debug("-   %s query: %s" % (provider, repr(query)))
        log.debug("--  %s url_search before token: %s" %
                  (provider, repr(url_search)))
        log.debug("--- %s using POST payload: %s" % (provider, repr(payload)))
        log.debug("----%s filtering with post_data: %s" %
                  (provider, repr(filtering.post_data)))

        # Set search's "title" in filtering to double-check results' names
        if 'filter_title' in definition and definition['filter_title']:
            filtering.filter_title = True
            filtering.title = query

        if logged_in:
            log.info("[%s] Reusing previous login" % provider)
        elif 'private' in definition and definition['private']:
            username = get_setting('%s_username' % provider)
            password = get_setting('%s_password' % provider)

            if 'login_object' in definition and definition['login_object']:
                logged_in = False
                try:
                    login_object = definition['login_object'].replace(
                        'USERNAME',
                        '"%s"' % username).replace('PASSWORD',
                                                   '"%s"' % password)
                except Exception, e:
                    log.error("[{0}] Make login_object fail: {1}".format(
                        provider, e))
                    return filtering.results

                # TODO generic flags in definitions for those...
                if provider == 'lostfilm':
                    client.open(definition['root_url'] +
                                '/v_search.php?c=110&s=1&e=1')
                    if u'Вход. – LostFilm.TV.' in client.content:
                        pass
                    else:
                        log.info('[%s] Login successful' % provider)
                        logged_in = True

                if not logged_in and client.login(
                        definition['root_url'] + definition['login_path'],
                        eval(login_object), definition['login_failed']):
                    log.info('[%s] Login successful' % provider)
                    logged_in = True
                elif not logged_in:
                    log.error("[%s] Login failed: %s", provider, client.status)
                    log.debug("[%s] Failed login content: %s", provider,
                              repr(client.content))
                    notify(translation(32089).format(provider),
                           image=get_icon_path())
                    return filtering.results

                if logged_in:
                    if provider == 'lostfilm':
                        log.info('[%s] Search lostfilm serial ID...', provider)
                        url_search = fix_lf(url_search)
                        client.open(url_search.encode('utf-8'),
                                    post_data=payload,
                                    get_data=data)
                        series_details = re.search(
                            r'"mark-rate-pane" rel="(\d+),(\d+),(\d+)">',
                            client.content)
                        if series_details:
                            client.open(definition['root_url'] +
                                        '/v_search.php?a=%s%s%s' %
                                        (series_details.group(1),
                                         series_details.group(2).zfill(3),
                                         series_details.group(3).zfill(3)))
                            redirect_url = re.search(ur'url=(.*?)">',
                                                     client.content)
                            if redirect_url is not None:
                                url_search = redirect_url.group(1)
                        else:
                            log.info('[%s] Not found ID in %s' %
                                     (provider, url_search))
                            return filtering.results

        log.info(">  %s search URL: %s" %
                 (definition['name'].rjust(longest), url_search))

        client.open(url_search, post_data=payload, get_data=data)
        filtering.results.extend(
            generate_payload(provider, generator(provider, client), filtering,
                             verify_name, verify_size))
Пример #17
0
def search(payload, method="general"):
    """ Main search entrypoint

    Args:
        payload (dict): Search payload from Elementum.
        method   (str): Type of search, can be ``general``, ``movie``, ``show``, ``season`` or ``anime``

    Returns:
        list: All filtered results in the format Elementum expects
    """
    log.debug("Searching with payload (%s): %s" % (method, repr(payload)))

    if method == 'general':
        if 'query' in payload:
            payload['title'] = payload['query']
            payload['titles'] = {'source': payload['query']}
        else:
            payload = {
                'title': payload,
                'titles': {
                    'source': payload
                },
            }

    payload['titles'] = dict(
        (k.lower(), v) for k, v in payload['titles'].iteritems())

    # If titles[] exists in payload and there are special chars in titles[source]
    #   then we set a flag to possibly modify the search query
    payload['has_special'] = 'titles' in payload and \
                             bool(payload['titles']) and \
                             'source' in payload['titles'] and \
                             any(c in payload['titles']['source'] for c in special_chars)
    if payload['has_special']:
        log.debug(
            "Query title contains special chars, so removing any quotes in the search query"
        )

    if 'proxy_url' not in payload:
        payload['proxy_url'] = ''
    if 'internal_proxy_url' not in payload:
        payload['internal_proxy_url'] = ''
    if 'elementum_url' not in payload:
        payload['elementum_url'] = ''
    if 'silent' not in payload:
        payload['silent'] = False
    if 'skip_auth' not in payload:
        payload['skip_auth'] = False

    global request_time
    global provider_names
    global provider_results
    global available_providers

    provider_names = []
    provider_results = []
    available_providers = 0
    request_time = time.time()

    providers = get_enabled_providers(method)

    if len(providers) == 0:
        if not payload['silent']:
            notify(translation(32060), image=get_icon_path())
        log.error("No providers enabled")
        return []

    log.info(
        "Burstin' with %s" %
        ", ".join([definitions[provider]['name'] for provider in providers]))

    if get_setting('kodi_language', bool):
        kodi_language = xbmc.getLanguage(xbmc.ISO_639_1)
        if not kodi_language:
            log.warning("Kodi returned empty language code...")
        elif 'titles' not in payload or not payload['titles']:
            log.info("No translations available...")
        elif payload['titles'] and kodi_language not in payload['titles']:
            log.info("No '%s' translation available..." % kodi_language)

    p_dialog = xbmcgui.DialogProgressBG()
    if not payload['silent']:
        p_dialog.create('Elementum [COLOR FFFF6B00]Burst[/COLOR]',
                        translation(32061))

    for provider in providers:
        available_providers += 1
        provider_names.append(definitions[provider]['name'])
        task = Thread(target=run_provider, args=(provider, payload, method))
        task.start()

    providers_time = time.time()
    total = float(available_providers)

    # Exit if all providers have returned results or timeout reached, check every 100ms
    while time.time() - providers_time < timeout and available_providers > 0:
        timer = time.time() - providers_time
        log.debug("Timer: %ds / %ds" % (timer, timeout))
        if timer > timeout:
            break
        message = translation(
            32062
        ) % available_providers if available_providers > 1 else translation(
            32063)
        if not payload['silent']:
            p_dialog.update(int((total - available_providers) / total * 100),
                            message=message)
        time.sleep(0.25)

    if not payload['silent']:
        p_dialog.close()
    del p_dialog

    if available_providers > 0:
        message = u', '.join(provider_names)
        message = message + translation(32064)
        log.warning(message.encode('utf-8'))
        if not payload['silent']:
            notify(message, ADDON_ICON)

    log.debug("all provider_results: %s" % repr(provider_results))

    filtered_results = apply_filters(provider_results)

    log.debug("all filtered_results: %s" % repr(filtered_results))

    log.info("Providers returned %d results in %s seconds" %
             (len(filtered_results), round(time.time() - request_time, 2)))

    return filtered_results
Пример #18
0
def update_tray_icon(tray, status):
    # status can only be (good, alert)
    tray.setIcon(QtGui.QIcon(get_icon_path(status + ".ico")))