예제 #1
0
    def search_by_id(self, media_id: str, id_type: str, media_type: str):
        if id_type == "tvdb" and media_type == "movie":
            # Skip invalid search.
            # The Trakt API states that tvdb is only for shows and episodes:
            # https://trakt.docs.apiary.io/#reference/search/id-lookup/get-id-lookup-results
            logger.debug("tvdb does not support movie provider")
            return None

        if not self.valid_trakt_id(media_id):
            logger.error(f"Ignoring invalid id: '{media_id}'")

            return None

        search = trakt.sync.search_by_id(media_id,
                                         id_type=id_type,
                                         media_type=media_type)
        # look for the first wanted type in the results
        # NOTE: this is not needed, kept around for caution
        for m in search:
            if m.media_type != f"{media_type}s":
                logger.error(
                    f"Internal error, wrong media type: {m.media_type}. Please report this to PlexTraktSync developers"
                )
                continue
            return m

        return None
예제 #2
0
    def resolve_guid(self, guid: PlexGuid, show: Media = None):
        if guid.provider in ["local", "none", "agents.none"]:
            logger.warning(
                f"{guid.pm.item}: Skipping guid {guid} because provider {guid.provider} has no external Id"
            )

            return None

        if guid.provider not in ["imdb", "tmdb", "tvdb"]:
            logger.error(
                f"{guid.pm.item}: Unable to parse a valid provider from guid {guid}"
            )
            return None

        try:
            if show:
                tm = self.trakt.find_episode_guid(guid, show.seasons)
            else:
                tm = self.trakt.find_by_guid(guid)
        except (TraktException, RequestException) as e:
            logger.warning(
                f"{guid.pm.item}: Skipping guid {guid} Trakt errors: {e}")
            return None

        if tm is None:
            logger.warning(
                f"{guid.pm.item}: Skipping guid {guid} not found on Trakt")
            return None

        return Media(guid.pm, tm, plex_api=self.plex, trakt_api=self.trakt)
예제 #3
0
    def resolve_any(self, pm: PlexLibraryItem, show: Media = None):
        try:
            guids = pm.guids
        except (PlexApiException, RequestException) as e:
            logger.error(f"Skipping {pm}: {e}")
            return None

        for guid in guids:
            m = self.resolve_guid(guid, show)
            if m:
                return m

        return None
예제 #4
0
        def wrapper(*args, **kwargs):
            retry = 0
            while True:
                try:
                    return fn(*args, **kwargs)
                except (
                        RateLimitException,
                        RequestException,
                        TraktInternalException,
                        LockedUserAccountException,
                ) as e:
                    if retry == retries:
                        logger.error(f"Error: {e}")
                        logger.error(
                            "API didn't respond properly, script will abort now. Please try again later."
                        )
                        logger.error(
                            f"Last call: {fn.__module__}.{fn.__name__}({args[1:]}, {kwargs})"
                        )
                        exit(1)

                    if isinstance(e, RateLimitException):
                        seconds = int(e.response.headers.get("Retry-After", 1))
                    else:
                        seconds = 1 + retry
                    retry += 1
                    logger.warning(
                        f"{e} for {fn.__module__}.{fn.__name__}(), retrying after {seconds} seconds (try: {retry}/{retries})"
                    )
                    sleep(seconds)
예제 #5
0
    def error(self, message: str):
        logger.error(message)
        self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR, explain=message)

        return False
예제 #6
0
def _get_plex_server():
    CONFIG = factory.config()
    plex_token = CONFIG["PLEX_TOKEN"]
    plex_baseurl = CONFIG["PLEX_BASEURL"]
    plex_fallbackurl = CONFIG["PLEX_FALLBACKURL"]
    if plex_token == "-":
        plex_token = ""
    server = None

    plexapi.X_PLEX_PLATFORM = PLEX_PLATFORM
    plexapi.BASE_HEADERS["X-Plex-Platform"] = plexapi.X_PLEX_PLATFORM

    session = factory.session()
    PlexServer = partial(plexapi.server.PlexServer, session=session)

    # if connection fails, it will try :
    # 1. url expected by new ssl certificate
    # 2. url without ssl
    # 3. fallback url (localhost)

    try:
        server = PlexServer(token=plex_token, baseurl=plex_baseurl)
    except plexapi.server.requests.exceptions.SSLError as e:
        m = "Plex connection error: {}, fallback url {} didn't respond either.".format(
            str(e), plex_fallbackurl)
        excep_msg = str(e.__context__)
        if "doesn't match '*." in excep_msg:
            hash_pos = excep_msg.find("*.") + 2
            new_hash = excep_msg[hash_pos:hash_pos + 32]
            end_pos = plex_baseurl.find(".plex.direct")
            new_plex_baseurl = (plex_baseurl[:end_pos - 32] + new_hash +
                                plex_baseurl[end_pos:])
            try:  # 1
                server = PlexServer(token=plex_token, baseurl=new_plex_baseurl)
                # save new url to .env
                CONFIG["PLEX_TOKEN"] = plex_token
                CONFIG["PLEX_BASEURL"] = new_plex_baseurl
                CONFIG["PLEX_FALLBACKURL"] = plex_fallbackurl
                CONFIG.save()
                logger.info(
                    "Plex server url changed to {}".format(new_plex_baseurl))
            except Exception:
                pass
        if server is None and plex_baseurl[:5] == "https":
            new_plex_baseurl = plex_baseurl.replace("https", "http")
            try:  # 2
                server = PlexServer(token=plex_token, baseurl=new_plex_baseurl)
                logger.warning(
                    "Switched to Plex unsecure connection because of SSLError."
                )
            except Exception:
                pass
    except Exception as e:
        m = "Plex connection error: {}, fallback url {} didn't respond either.".format(
            str(e), plex_fallbackurl)
    if server is None:
        try:  # 3
            server = PlexServer(token=plex_token, baseurl=plex_fallbackurl)
            logger.warning("No response from {}, fallback to {}".format(
                plex_baseurl, plex_fallbackurl))
        except Exception:
            logger.error(m)
            print(m)
            exit(1)
    return server