Beispiel #1
0
    def test_notify(username, blacklist_name=None):
        """
        Sends a test notification to trakt with the given authentication info and returns a boolean
        representing success.

        api: The api string to use
        username: The username to use
        blacklist_name: slug of trakt list used to hide not interested show

        Returns: True if the request succeeded, False otherwise
        """
        try:
            trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)
            trakt_api.validateAccount()
            if blacklist_name and blacklist_name is not None:
                trakt_lists = trakt_api.traktRequest("users/" + username +
                                                     "/lists")
                found = False
                for trakt_list in trakt_lists:
                    if trakt_list['ids']['slug'] == blacklist_name:
                        return "Test notice sent successfully to Trakt"
                if not found:
                    return "Trakt blacklist doesn't exists"
            else:
                return "Test notice sent successfully to Trakt"
        except (traktException, traktAuthException, traktServerBusy) as e:
            logger.warning("Could not connect to Trakt service: {0}".format(
                str(e)))
            return "Test notice failed to Trakt: {0}".format(str(e))
Beispiel #2
0
 def __init__(self):
     self.trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)
     self.todoBacklog = []
     self.todoWanted = []
     self.ShowWatchlist = {}
     self.EpisodeWatchlist = {}
     self.Collectionlist = {}
     self.amActive = False
Beispiel #3
0
    def addShowToBlacklist(self):
        # URL parameters

        indexer_id = self.get_query_argument('indexer_id')
        if not indexer_id:
            raise HTTPError(404)

        data = {'shows': [{'ids': {'tvdb': indexer_id}}]}

        trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)

        trakt_api.traktRequest("users/" + settings.TRAKT_USERNAME + "/lists/" + settings.TRAKT_BLACKLIST_NAME + "/items", data, method='POST')

        return self.redirect('/addShows/trendingShows/')
Beispiel #4
0
    def update_library(ep_obj):
        """
        Sends a request to trakt indicating that the given episode is part of our library.

        ep_obj: The TVEpisode object to add to trakt
        """

        trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)

        if settings.USE_TRAKT:
            try:
                # URL parameters
                data = {
                    'shows': [{
                        'title': ep_obj.show.name,
                        'year': ep_obj.show.startyear,
                        'ids': {
                            ep_obj.idxr.slug: ep_obj.show.indexerid
                        },
                    }]
                }

                if settings.TRAKT_SYNC_WATCHLIST and settings.TRAKT_REMOVE_SERIESLIST:
                    trakt_api.traktRequest("sync/watchlist/remove",
                                           data,
                                           method='POST')

                # Add Season and Episode + Related Episodes
                data['shows'][0]['seasons'] = [{
                    'number': ep_obj.season,
                    'episodes': []
                }]

                for relEp_Obj in [ep_obj] + ep_obj.relatedEps:
                    data['shows'][0]['seasons'][0]['episodes'].append(
                        {'number': relEp_Obj.episode})

                if settings.TRAKT_SYNC_WATCHLIST and settings.TRAKT_REMOVE_WATCHLIST:
                    trakt_api.traktRequest("sync/watchlist/remove",
                                           data,
                                           method='POST')

                # update library
                trakt_api.traktRequest("sync/collection", data, method='POST')

            except (traktException, traktAuthException, traktServerBusy) as e:
                logger.warning(
                    "Could not connect to Trakt service: {0}".format(str(e)))
Beispiel #5
0
    def fetch_trending_shows(self, trakt_list, page_url):
        """Get trending show information from Trakt"""

        trending_shows = []

        trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)

        try:
            not_liked_show = ""
            if settings.TRAKT_ACCESS_TOKEN != '':
                library_shows = trakt_api.traktRequest(
                    "sync/collection/shows?extended=full") or []
                if settings.TRAKT_BLACKLIST_NAME:
                    not_liked_show = trakt_api.traktRequest(
                        "users/" + settings.TRAKT_USERNAME + "/lists/" +
                        settings.TRAKT_BLACKLIST_NAME + "/items") or []
                else:
                    logger.debug("Trakt blacklist name is empty")

            if trakt_list not in ["recommended", "newshow", "newseason"]:
                limit_show = "?limit=" + str(100 + len(not_liked_show)) + "&"
            else:
                limit_show = "?"

            shows = trakt_api.traktRequest(page_url + limit_show +
                                           "extended=full") or []

            if settings.TRAKT_ACCESS_TOKEN != '':
                library_shows = trakt_api.traktRequest(
                    "sync/collection/shows?extended=full") or []

            for show in shows:
                try:
                    if 'show' not in show:
                        show['show'] = show

                    if settings.TRAKT_ACCESS_TOKEN != '':
                        if show['show']['ids']['tvdb'] not in (
                                lshow['show']['ids']['tvdb']
                                for lshow in library_shows):
                            if not_liked_show:
                                if show['show']['ids']['tvdb'] not in (
                                        show['show']['ids']['tvdb']
                                        for show in not_liked_show
                                        if show['type'] == 'show'):
                                    trending_shows += [show]
                            else:
                                trending_shows += [show]
                    else:
                        if not_liked_show:
                            if show['show']['ids']['tvdb'] not in (
                                    show['show']['ids']['tvdb']
                                    for show in not_liked_show
                                    if show['type'] == 'show'):
                                trending_shows += [show]
                        else:
                            trending_shows += [show]

                except MultipleShowObjectsException:
                    continue

            if settings.TRAKT_BLACKLIST_NAME != '':
                black_list = True
            else:
                black_list = False

        except traktException as e:
            logger.warning("Could not connect to Trakt service: {0}".format(
                str(e)))

        for trending_show in trending_shows:
            # get indexer id
            indexer_id = trending_show['show']['ids']['tvdb']
            trending_show['indexer_id'] = indexer_id
            # set image path to show (needed to show it on the screen from the cache)
            image_name = self.get_image_name(indexer_id)
            image_path_relative = posixpath.join('images', 'trakt_trending',
                                                 image_name)
            trending_show['image_path'] = image_path_relative
            # clear indexer_id if we already have the image in the cache so we don't retrieve it again
            image_path = self.get_image_path(image_name)
            if os.path.isfile(image_path):
                trending_show['indexer_id'] = ''

        return trending_shows, black_list
Beispiel #6
0
class TraktChecker(object):
    def __init__(self):
        self.trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)
        self.todoBacklog = []
        self.todoWanted = []
        self.ShowWatchlist = {}
        self.EpisodeWatchlist = {}
        self.Collectionlist = {}
        self.amActive = False

    def run(self, force=False):
        self.amActive = True

        # add shows from trakt.tv watchlist
        if settings.TRAKT_SYNC_WATCHLIST:
            self.todoWanted = []  # its about to all get re-added
            if len(settings.ROOT_DIRS.split("|")) < 2:
                logger.warning("No default root directory")
                return

            try:
                self.syncWatchlist()
            except Exception:
                logger.debug(traceback.format_exc())

            try:
                # sync trakt.tv library with sickchill library
                self.syncLibrary()
            except Exception:
                logger.debug(traceback.format_exc())

        self.amActive = False

    def findShow(self, indexer, indexerid):
        traktShow = None

        try:
            library = self.trakt_api.traktRequest(
                "sync/collection/shows") or []
            if not library:
                logger.debug(
                    "No shows found in your library, aborting library update")
                return

            traktShow = [
                x for x in library if int(indexerid) == int(
                    x["show"]["ids"][sickchill.indexer.slug(indexer)] or -1)
            ]
        except traktException as e:
            logger.warning(
                "Could not connect to Trakt service. Aborting library check. Error: {0}"
                .format(repr(e)))

        return traktShow

    def removeShowFromTraktLibrary(self, show_obj):
        if self.findShow(show_obj.indexer, show_obj.indexerid):

            # URL parameters
            data = {
                "shows": [{
                    "title": show_obj.name,
                    "year": show_obj.startyear,
                    "ids": {
                        show_obj.idxr.slug: show_obj.indexerid
                    }
                }]
            }

            logger.debug("Removing {0} from trakt.tv library".format(
                show_obj.name))

            try:
                self.trakt_api.traktRequest("sync/collection/remove",
                                            data,
                                            method="POST")
            except traktException as e:
                logger.warning(
                    "Could not connect to Trakt service. Aborting removing show {0} from Trakt library. Error: {1}"
                    .format(show_obj.name, repr(e)))

    def addShowToTraktLibrary(self, show_obj):
        """
        Sends a request to trakt indicating that the given show and all its episodes is part of our library.

        show_obj: The TVShow object to add to trakt
        """
        if not self.findShow(show_obj.indexer, show_obj.indexerid):
            # URL parameters
            data = {
                "shows": [{
                    "title": show_obj.name,
                    "year": show_obj.startyear,
                    "ids": {
                        show_obj.idxr.slug: show_obj.indexerid
                    }
                }]
            }

            logger.debug("Adding {0} to trakt.tv library".format(
                show_obj.name))

            try:
                self.trakt_api.traktRequest("sync/collection",
                                            data,
                                            method="POST")
            except traktException as e:
                logger.warning(
                    "Could not connect to Trakt service. Aborting adding show {0} to Trakt library. Error: {1}"
                    .format(show_obj.name, repr(e)))
                return

    def syncLibrary(self):
        if settings.TRAKT_SYNC and settings.USE_TRAKT:
            logger.debug("Sync SickChill with Trakt Collection")

            if self._getShowCollection():
                self.addEpisodeToTraktCollection()
                if settings.TRAKT_SYNC_REMOVE:
                    self.removeEpisodeFromTraktCollection()

    def removeEpisodeFromTraktCollection(self):
        if settings.TRAKT_SYNC_REMOVE and settings.TRAKT_SYNC and settings.USE_TRAKT:
            logger.debug(
                "COLLECTION::REMOVE::START - Look for Episodes to Remove From Trakt Collection"
            )

            main_db_con = db.DBConnection()
            sql_selection = "select tv_shows.indexer, tv_shows.startyear, showid, show_name, season, episode, tv_episodes.status, tv_episodes.location from tv_episodes,tv_shows where tv_shows.indexer_id = tv_episodes.showid"
            episodes = main_db_con.select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    if self._checkInList(
                            sickchill.indexer.slug(cur_episode["indexer"]),
                            str(cur_episode["showid"]),
                            str(cur_episode["season"]),
                            str(cur_episode["episode"]),
                            List="Collection",
                    ):
                        if cur_episode["location"] == "":
                            logger.debug(
                                "Removing Episode {show} {ep} from collection".
                                format(show=cur_episode["show_name"],
                                       ep=episode_num(cur_episode["season"],
                                                      cur_episode["episode"])))
                            trakt_data.append((
                                cur_episode["showid"],
                                cur_episode["indexer"],
                                cur_episode["show_name"],
                                cur_episode["startyear"],
                                cur_episode["season"],
                                cur_episode["episode"],
                            ))

                if trakt_data:
                    try:
                        data = self.trakt_bulk_data_generate(trakt_data)
                        self.trakt_api.traktRequest("sync/collection/remove",
                                                    data,
                                                    method="POST")
                        self._getShowCollection()
                    except traktException as e:
                        logger.warning(
                            "Could not connect to Trakt service. Error: {0}".
                            format(str(e)))

            logger.debug(
                "COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection"
            )

    def addEpisodeToTraktCollection(self):
        if settings.TRAKT_SYNC and settings.USE_TRAKT:
            logger.debug(
                "COLLECTION::ADD::START - Look for Episodes to Add to Trakt Collection"
            )

            main_db_con = db.DBConnection()
            sql_selection = (
                "select tv_shows.indexer, tv_shows.startyear, showid, show_name, season, episode from tv_episodes,tv_shows where tv_shows.indexer_id = tv_episodes.showid and tv_episodes.status in ("
                + ",".join(
                    [str(x)
                     for x in Quality.DOWNLOADED + Quality.ARCHIVED]) + ")")
            episodes = main_db_con.select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    if not self._checkInList(
                            sickchill.indexer.slug(cur_episode["indexer"]),
                            str(cur_episode["showid"]),
                            str(cur_episode["season"]),
                            str(cur_episode["episode"]),
                            List="Collection",
                    ):
                        logger.debug(
                            "Adding Episode {show} {ep} to collection".format(
                                show=cur_episode["show_name"],
                                ep=episode_num(cur_episode["season"],
                                               cur_episode["episode"])))
                        trakt_data.append((
                            cur_episode["showid"],
                            cur_episode["indexer"],
                            cur_episode["show_name"],
                            cur_episode["startyear"],
                            cur_episode["season"],
                            cur_episode["episode"],
                        ))

                if trakt_data:
                    try:
                        data = self.trakt_bulk_data_generate(trakt_data)
                        self.trakt_api.traktRequest("sync/collection",
                                                    data,
                                                    method="POST")
                        self._getShowCollection()
                    except traktException as e:
                        logger.warning(
                            "Could not connect to Trakt service. Error: {0}".
                            format(str(e)))

            logger.debug(
                "COLLECTION::ADD::FINISH - Look for Episodes to Add to Trakt Collection"
            )

    def syncWatchlist(self):
        if settings.TRAKT_SYNC_WATCHLIST and settings.USE_TRAKT:
            logger.debug("Sync SickChill with Trakt Watchlist")

            self.removeShowFromSickChill()

            if self._getShowWatchlist():
                self.addShowToTraktWatchList()
                self.updateShows()

            if self._getEpisodeWatchlist():
                self.removeEpisodeFromTraktWatchList()
                self.addEpisodeToTraktWatchList()
                self.updateEpisodes()

    def removeEpisodeFromTraktWatchList(self):
        if settings.TRAKT_SYNC_WATCHLIST and settings.USE_TRAKT:
            logger.debug(
                "WATCHLIST::REMOVE::START - Look for Episodes to Remove from Trakt Watchlist"
            )

            main_db_con = db.DBConnection()
            sql_selection = "select tv_shows.indexer, tv_shows.startyear, showid, show_name, season, episode, tv_episodes.status from tv_episodes,tv_shows where tv_shows.indexer_id = tv_episodes.showid"
            episodes = main_db_con.select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    if self._checkInList(
                            sickchill.indexer.slug(cur_episode["indexer"]),
                            str(cur_episode["showid"]),
                            str(cur_episode["season"]),
                            str(cur_episode["episode"])):
                        if cur_episode[
                                "status"] not in Quality.SNATCHED + Quality.SNATCHED_PROPER + [
                                    UNKNOWN
                                ] + [WANTED]:
                            logger.debug(
                                "Removing Episode {show} {ep} from watchlist".
                                format(show=cur_episode["show_name"],
                                       ep=episode_num(cur_episode["season"],
                                                      cur_episode["episode"])))
                            trakt_data.append((
                                cur_episode["showid"],
                                cur_episode["indexer"],
                                cur_episode["show_name"],
                                cur_episode["startyear"],
                                cur_episode["season"],
                                cur_episode["episode"],
                            ))

                if trakt_data:
                    try:
                        data = self.trakt_bulk_data_generate(trakt_data)
                        self.trakt_api.traktRequest("sync/watchlist/remove",
                                                    data,
                                                    method="POST")
                        self._getEpisodeWatchlist()
                    except traktException as e:
                        logger.warning(
                            "Could not connect to Trakt service. Error: {0}".
                            format(str(e)))

                logger.debug(
                    "WATCHLIST::REMOVE::FINISH - Look for Episodes to Remove from Trakt Watchlist"
                )

    def addEpisodeToTraktWatchList(self):
        if settings.TRAKT_SYNC_WATCHLIST and settings.USE_TRAKT:
            logger.debug(
                "WATCHLIST::ADD::START - Look for Episodes to Add to Trakt Watchlist"
            )

            main_db_con = db.DBConnection()
            sql_selection = (
                "select tv_shows.indexer, tv_shows.startyear, showid, show_name, season, episode from tv_episodes,tv_shows where tv_shows.indexer_id = tv_episodes.showid and tv_episodes.status in ("
                + ",".join([
                    str(x) for x in Quality.SNATCHED +
                    Quality.SNATCHED_PROPER + [WANTED]
                ]) + ")")
            episodes = main_db_con.select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    if not self._checkInList(
                            sickchill.indexer.slug(cur_episode["indexer"]),
                            str(cur_episode["showid"]),
                            str(cur_episode["season"]),
                            str(cur_episode["episode"])):
                        logger.debug(
                            "Adding Episode {show} {ep} to watchlist".format(
                                show=cur_episode["show_name"],
                                ep=episode_num(cur_episode["season"],
                                               cur_episode["episode"])))
                        trakt_data.append((
                            cur_episode["showid"],
                            cur_episode["indexer"],
                            cur_episode["show_name"],
                            cur_episode["startyear"],
                            cur_episode["season"],
                            cur_episode["episode"],
                        ))

                if trakt_data:
                    try:
                        data = self.trakt_bulk_data_generate(trakt_data)
                        self.trakt_api.traktRequest("sync/watchlist",
                                                    data,
                                                    method="POST")
                        self._getEpisodeWatchlist()
                    except traktException as e:
                        logger.warning(
                            "Could not connect to Trakt service. Error {0}".
                            format(str(e)))

            logger.debug(
                "WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist"
            )

    def addShowToTraktWatchList(self):
        if settings.TRAKT_SYNC_WATCHLIST and settings.USE_TRAKT:
            logger.debug(
                "SHOW_WATCHLIST::ADD::START - Look for Shows to Add to Trakt Watchlist"
            )

            if settings.showList is not None:
                trakt_data = []

                for show in settings.showList:
                    if not self._checkInList(show.idxr.slug,
                                             str(show.indexerid),
                                             "0",
                                             "0",
                                             List="Show"):
                        logger.debug(
                            "Adding Show: Indexer {0} {1} - {2} to Watchlist".
                            format(show.idxr.name, str(show.indexerid),
                                   show.name))
                        show_el = {
                            "title": show.name,
                            "year": show.startyear,
                            "ids": {
                                show.idxr.slug: show.indexerid
                            }
                        }

                        trakt_data.append(show_el)

                if trakt_data:
                    try:
                        data = {"shows": trakt_data}
                        self.trakt_api.traktRequest("sync/watchlist",
                                                    data,
                                                    method="POST")
                        self._getShowWatchlist()
                    except traktException as e:
                        logger.warning(
                            "Could not connect to Trakt service. Error: {0}".
                            format(str(e)))

            logger.debug(
                "SHOW_WATCHLIST::ADD::FINISH - Look for Shows to Add to Trakt Watchlist"
            )

    def removeShowFromSickChill(self):
        if settings.TRAKT_SYNC_WATCHLIST and settings.USE_TRAKT and settings.TRAKT_REMOVE_SHOW_FROM_SICKCHILL:
            logger.debug(
                "SHOW_SICKCHILL::REMOVE::START - Look for Shows to remove from SickChill"
            )

            if settings.showList:
                for show in settings.showList:
                    if show.status in ("Ended", "Canceled"):
                        if not show.imdb_id:
                            logger.warning(
                                "Could not check trakt progress for {0} because the imdb id is missing from {} data, skipping"
                                .format(show.name, show.idxr.name))
                            continue

                        try:
                            progress = self.trakt_api.traktRequest(
                                "shows/" + show.imdb_id +
                                "/progress/watched") or {}
                        except traktException as e:
                            logger.warning(
                                "Could not connect to Trakt service. Aborting removing show {0} from SickChill. Error: {1}"
                                .format(show.name, repr(e)))
                            continue

                        if not progress:
                            continue

                        if progress.get("aired", True) == progress.get(
                                "completed", False):
                            settings.showQueueScheduler.action.remove_show(
                                show, full=True)
                            logger.debug(
                                "Show: {0} has been removed from SickChill".
                                format(show.name))

            logger.debug(
                "SHOW_SICKCHILL::REMOVE::FINISH - Trakt Show Watchlist")

    def updateShows(self):
        logger.debug("SHOW_WATCHLIST::CHECK::START - Trakt Show Watchlist")

        self._getShowWatchlist()
        if not self.ShowWatchlist:
            logger.debug(
                "No shows found in your watchlist, aborting watchlist update")
            return

        for index, indexer in sickchill.indexer:
            if indexer.slug in self.ShowWatchlist:
                for show_el in self.ShowWatchlist[indexer.slug]:
                    indexer_id = int(str(show_el))
                    show = self.ShowWatchlist[indexer.slug][show_el]

                    # logger.debug("Checking Show: %s %s %s" % (slug, indexer_id, show['title']))
                    if int(settings.TRAKT_METHOD_ADD) != 2:
                        self.addDefaultShow(index, indexer_id, show["title"],
                                            SKIPPED)
                    else:
                        self.addDefaultShow(index, indexer_id, show["title"],
                                            WANTED)

                    if int(settings.TRAKT_METHOD_ADD) == 1:
                        newShow = Show.find(settings.showList, indexer_id)

                        if newShow is not None:
                            setEpisodeToWanted(newShow, 1, 1)
                        else:
                            self.todoWanted.append((indexer_id, 1, 1))
        logger.debug("SHOW_WATCHLIST::CHECK::FINISH - Trakt Show Watchlist")

    def updateEpisodes(self):
        """
        Sets episodes to wanted that are in trakt watchlist
        """
        logger.debug("SHOW_WATCHLIST::CHECK::START - Trakt Episode Watchlist")

        self._getEpisodeWatchlist()
        if not self.EpisodeWatchlist:
            logger.debug(
                "No episode found in your watchlist, aborting episode update")
            return

        managed_show = []

        for index, indexer in sickchill.indexer:
            if indexer.slug in self.EpisodeWatchlist:
                for show_el in self.EpisodeWatchlist[indexer.slug]:
                    indexer_id = int(show_el)
                    show = self.EpisodeWatchlist[indexer.slug][show_el]

                    newShow = Show.find(settings.showList, indexer_id)

                    try:
                        if newShow is None:
                            if indexer_id not in managed_show:
                                self.addDefaultShow(index, indexer_id,
                                                    show["title"], SKIPPED)
                                managed_show.append(indexer_id)

                                for season_el in show["seasons"]:
                                    season = int(season_el)

                                    for episode_el in show["seasons"][
                                            season_el]["episodes"]:
                                        self.todoWanted.append(
                                            (indexer_id, season,
                                             int(episode_el)))
                        else:
                            if newShow.indexer == indexer:
                                for season_el in show["seasons"]:
                                    season = int(season_el)

                                    for episode_el in show["seasons"][
                                            season_el]["episodes"]:
                                        setEpisodeToWanted(
                                            newShow, season, int(episode_el))
                    except TypeError:
                        logger.debug(
                            "Could not parse the output from trakt for {0} ".
                            format(show["title"]))
        logger.debug("SHOW_WATCHLIST::CHECK::FINISH - Trakt Episode Watchlist")

    @staticmethod
    def addDefaultShow(indexer, indexer_id, name, status):
        """
        Adds a new show with the default settings
        """
        if not Show.find(settings.showList, int(indexer_id)):
            logger.info("Adding show " + str(indexer_id))
            root_dirs = settings.ROOT_DIRS.split("|")

            try:
                location = root_dirs[int(root_dirs[0]) + 1]
            except Exception:
                location = None

            if location:
                showPath = os.path.join(location, sanitize_filename(name))
                dir_exists = helpers.makeDir(showPath)

                if not dir_exists:
                    logger.warning(
                        "Unable to create the folder {0} , can't add the show".
                        format(showPath))
                    return
                else:
                    helpers.chmodAsParent(showPath)

                settings.showQueueScheduler.action.add_show(
                    int(indexer),
                    int(indexer_id),
                    showPath,
                    default_status=status,
                    quality=int(settings.QUALITY_DEFAULT),
                    season_folders=int(settings.SEASON_FOLDERS_DEFAULT),
                    paused=settings.TRAKT_START_PAUSED,
                    default_status_after=status,
                )
            else:
                logger.warning(
                    "There was an error creating the show, no root directory setting found"
                )
                return

    def manageNewShow(self, show):
        logger.debug(
            "Checking if trakt watch list wants to search for episodes from new show "
            + show.name)
        episodes = [i for i in self.todoWanted if i[0] == show.indexerid]

        for episode in episodes:
            self.todoWanted.remove(episode)
            setEpisodeToWanted(show, episode[1], episode[2])

    def _checkInList(self, slug, showid, season, episode, List=None):
        """
        Check in the Watchlist or CollectionList for Show
        Is the Show, Season and Episode in the slug list
        """
        # logger.debug("Checking Show: %s %s %s " % (slug, showid, List))

        if "Collection" == List:
            try:
                if self.Collectionlist[slug][showid]["seasons"][season][
                        "episodes"][episode] == episode:
                    return True
            except Exception:
                return False
        elif "Show" == List:
            try:
                if self.ShowWatchlist[slug][showid]["id"] == showid:
                    return True
            except Exception:
                return False
        else:
            try:
                if self.EpisodeWatchlist[slug][showid]["seasons"][season][
                        "episodes"][episode] == episode:
                    return True
            except Exception:
                return False

    def _getShowWatchlist(self):
        """
        Get Watchlist and parse once into addressable structure
        """
        try:
            self.ShowWatchlist = {
                indexer.slug: {}
                for index, indexer in sickchill.indexer
            }
            TraktShowWatchlist = self.trakt_api.traktRequest(
                "sync/watchlist/shows")
            for slug in self.ShowWatchlist:
                for watchlist_el in TraktShowWatchlist:
                    if watchlist_el["show"]["ids"][slug]:

                        title = watchlist_el["show"]["title"]
                        year = str(watchlist_el["show"]["year"])

                        showid = str(watchlist_el["show"]["ids"][slug])
                        self.ShowWatchlist[slug][showid] = {
                            "id": showid,
                            "title": title,
                            "year": year
                        }
        except traktException as e:
            logger.warning(
                "Could not connect to trakt service, cannot download Show Watchlist: {0}"
                .format(repr(e)))
            return False
        return True

    def _getEpisodeWatchlist(self):
        """
        Get Watchlist and parse once into addressable structure
        """
        try:
            self.EpisodeWatchlist = {
                indexer.slug: {}
                for index, indexer in sickchill.indexer
            }
            TraktEpisodeWatchlist = self.trakt_api.traktRequest(
                "sync/watchlist/episodes")
            for slug in self.EpisodeWatchlist:
                for watchlist_el in TraktEpisodeWatchlist:
                    if watchlist_el["show"]["ids"][slug]:

                        title = watchlist_el["show"]["title"]
                        year = str(watchlist_el["show"]["year"])
                        season = str(watchlist_el["episode"]["season"])
                        episode = str(watchlist_el["episode"]["number"])

                        showid = str(watchlist_el["show"]["ids"][slug])

                        if showid not in self.EpisodeWatchlist[slug]:
                            self.EpisodeWatchlist[slug][showid] = {
                                "id": showid,
                                "title": title,
                                "year": year,
                                "seasons": {}
                            }

                        if season not in self.EpisodeWatchlist[slug][showid][
                                "seasons"]:
                            self.EpisodeWatchlist[slug][showid]["seasons"][
                                season] = {
                                    "s": season,
                                    "episodes": {}
                                }

                        if episode not in self.EpisodeWatchlist[slug][showid][
                                "seasons"][season]["episodes"]:
                            self.EpisodeWatchlist[slug][showid]["seasons"][
                                season]["episodes"][episode] = episode

        except traktException as e:
            logger.warning(
                "Could not connect to trakt service, cannot download Episode Watchlist: {0}"
                .format(repr(e)))
            return False
        return True

    def _getShowCollection(self):
        """
        Get Collection and parse once into addressable structure
        """
        try:
            self.Collectionlist = {
                indexer.slug: {}
                for index, indexer in sickchill.indexer
            }
            logger.debug("Getting Show Collection")
            TraktCollectionList = self.trakt_api.traktRequest(
                "sync/collection/shows")
            for slug in self.Collectionlist:
                for watchlist_el in TraktCollectionList:
                    if "seasons" in watchlist_el:
                        for season_el in watchlist_el["seasons"]:
                            for episode_el in season_el["episodes"]:
                                season = str(season_el["number"])
                                episode = str(episode_el["number"])

                                if watchlist_el["show"]["ids"][
                                        slug] is not None:
                                    title = watchlist_el["show"]["title"]
                                    year = str(watchlist_el["show"]["year"])
                                    showid = str(
                                        watchlist_el["show"]["ids"][slug])

                                    if showid not in self.Collectionlist[slug]:
                                        self.Collectionlist[slug][showid] = {
                                            "id": showid,
                                            "title": title,
                                            "year": year,
                                            "seasons": {}
                                        }

                                    if season not in self.Collectionlist[slug][
                                            showid]["seasons"]:
                                        self.Collectionlist[slug][showid][
                                            "seasons"][season] = {
                                                "s": season,
                                                "episodes": {}
                                            }

                                    if episode not in self.Collectionlist[
                                            slug][showid]["seasons"][season][
                                                "episodes"]:
                                        self.Collectionlist[slug][showid][
                                            "seasons"][season]["episodes"][
                                                episode] = episode
        except traktException as e:
            logger.warning(
                "Could not connect to trakt service, cannot download Show Collection: {0}"
                .format(repr(e)))
            return False
        return True

    @staticmethod
    def trakt_bulk_data_generate(data):
        """
        Build the JSON structure to send back to Trakt
        """
        uniqueShows = {}
        uniqueSeasons = {}

        for showid, indexer, show_name, startyear, season, episode in data:
            slug = sickchill.indexer.slug(indexer)
            if showid not in uniqueShows:
                uniqueShows[showid] = {
                    "title": show_name,
                    "year": startyear,
                    "ids": {
                        slug: showid
                    },
                    "seasons": []
                }
                uniqueSeasons[showid] = []

            if season not in uniqueSeasons[showid]:
                uniqueSeasons[showid].append(season)

        # build the query
        showList = []
        seasonsList = {}

        for searchedShow in uniqueShows:
            seasonsList[searchedShow] = []

            for searchedSeason in uniqueSeasons[searchedShow]:
                episodesList = []

                for showid, indexerid, show_name, startyear, season, episode in data:
                    if season == searchedSeason and showid == searchedShow:
                        episodesList.append({"number": episode})
                uniqueShows[searchedShow]["seasons"].append({
                    "number":
                    searchedSeason,
                    "episodes":
                    episodesList
                })
            showList.append(uniqueShows[searchedShow])
        post_data = {"shows": showList}
        return post_data
Beispiel #7
0
    def run(self):

        super(QueueItemAdd, self).run()

        logger.info(_('Starting to add show {0}').format(_('by ShowDir: {0}').format(self.showDir) if self.showDir else _('by Indexer Id: {0}').format(self.indexer_id)))
        # make sure the Indexer IDs are valid
        try:
            s = sickchill.indexer.series_by_id(indexerid=self.indexer_id, indexer=self.indexer, language=self.lang)
            if not s:
                error_string = _('Could not find show with id:{0} on {1}, skipping').format(
                    self.indexer_id, sickchill.indexer.name(self.indexer))

                logger.info(error_string)
                ui.notifications.error(_('Unable to add show'), error_string)

                self._finish_early()
                return

            # Let's try to create the show Dir if it's not provided. This way we force the show dir to build build using the
            # Indexers provided series name
            if self.root_dir and not self.showDir:
                if not s.seriesName:
                    logger.info(_('Unable to get a show {0}, can\'t add the show').format(self.showDir))
                    self._finish_early()
                    return

                show_dir = s.seriesName
                if settings.ADD_SHOWS_WITH_YEAR and s.firstAired:
                    try:
                        year = '({0})'.format(dateutil.parser.parse(s.firstAired).year)
                        if year not in show_dir:
                            show_dir = '{0} {1}'.format(s.seriesName, year)
                    except (TypeError, ValueError):
                        logger.info(_('Could not append the show year folder for the show: {0}').format(show_dir))

                self.showDir = os.path.join(self.root_dir, sanitize_filename(show_dir))

                if settings.ADD_SHOWS_WO_DIR:
                    logger.info(_("Skipping initial creation of {0} due to config.ini setting").format(self.showDir))
                else:
                    dir_exists = makeDir(self.showDir)
                    if not dir_exists:
                        logger.info(_('Unable to create the folder {0}, can\'t add the show').format(self.showDir))
                        self._finish_early()
                        return

                    chmodAsParent(self.showDir)

            # this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show
            if getattr(s, 'seriesName', None) is None:
                # noinspection PyPep8
                error_string = _('Show in {0} has no name on {1}, probably searched with the wrong language. Delete .nfo and add manually in the correct language.').format(
                    self.showDir, sickchill.indexer.name(self.indexer))

                logger.warning(error_string)
                ui.notifications.error(_('Unable to add show'), error_string)

                self._finish_early()
                return
        except Exception as error:
            error_string = 'Unable to look up the show in {0} on {1} using ID {2}, not using the NFO. Delete .nfo and try adding manually again.'.format(
                self.showDir, sickchill.indexer.name(self.indexer), self.indexer_id)

            logger.exception('{0}: {1}'.format(error_string, error))
            ui.notifications.error(_('Unable to add show'), error_string)

            if settings.USE_TRAKT:
                trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)

                title = self.showDir.split('/')[-1]
                data = {
                    'shows': [
                        {
                            'title': title,
                            'ids': {sickchill.indexer.slug(self.indexer): self.indexer_id}
                        }
                    ]
                }
                trakt_api.traktRequest('sync/watchlist/remove', data, method='POST')

            self._finish_early()
            return

        try:
            try:
                newShow = TVShow(self.indexer, self.indexer_id, self.lang)
            except MultipleShowObjectsException as error:
                # If we have the show in our list, but the location is wrong, lets fix it and refresh!
                existing_show = Show.find(settings.showList, self.indexer_id)
                # noinspection PyProtectedMember
                if existing_show and not os.path.isdir(existing_show._location):
                    newShow = existing_show
                else:
                    raise error

            newShow.loadFromIndexer()

            self.show = newShow

            # set up initial values
            self.show.location = self.showDir
            self.show.subtitles = self.subtitles if self.subtitles is not None else settings.SUBTITLES_DEFAULT
            self.show.subtitles_sr_metadata = self.subtitles_sr_metadata
            self.show.quality = self.quality if self.quality else settings.QUALITY_DEFAULT
            self.show.season_folders = self.season_folders if self.season_folders is not None else settings.SEASON_FOLDERS_DEFAULT
            self.show.anime = self.anime if self.anime is not None else settings.ANIME_DEFAULT
            self.show.scene = self.scene if self.scene is not None else settings.SCENE_DEFAULT
            self.show.paused = self.paused if self.paused is not None else False

            # set up default new/missing episode status
            logger.info(_('Setting all episodes to the specified default status: {0}') .format(self.show.default_ep_status))
            self.show.default_ep_status = self.default_status

            if self.show.anime:
                self.show.release_groups = BlackAndWhiteList(self.show.indexerid)
                if self.blacklist:
                    self.show.release_groups.set_black_keywords(self.blacklist)
                if self.whitelist:
                    self.show.release_groups.set_white_keywords(self.whitelist)

            # # be smart-ish about this
            # if self.show.genre and 'talk show' in self.show.genre.lower():
            #     self.show.air_by_date = 1
            # if self.show.genre and 'documentary' in self.show.genre.lower():
            #     self.show.air_by_date = 0
            # if self.show.classification and 'sports' in self.show.classification.lower():
            #     self.show.sports = 1

        except Exception as error:
            error_string = 'Unable to add {0} due to an error with {1}'.format(
                self.show.name if self.show else 'show', sickchill.indexer.name(self.indexer))

            logger.exception('{0}: {1}'.format(error_string, error))

            logger.exception('Error trying to add show: {0}'.format(error))
            logger.debug(traceback.format_exc())

            ui.notifications.error(_('Unable to add show'), error_string)

            self._finish_early()
            return

        except MultipleShowObjectsException:
            error_string = _('The show in {0} is already in your show list, skipping').format(self.showDir)
            logger.warning(error_string)
            ui.notifications.error(_('Show skipped'), error_string)

            self._finish_early()
            return

        self.show.load_imdb_imfo()

        try:
            self.show.saveToDB()
        except Exception as error:
            logger.exception('Error saving the show to the database: {0}'.format(error))
            logger.debug(traceback.format_exc())
            self._finish_early()
            raise

        # add it to the show list
        if not Show.find(settings.showList, self.indexer_id):
            settings.showList.append(self.show)

        try:
            self.show.loadEpisodesFromIndexer()
        except Exception as error:
            logger.exception('Error with {0}, not creating episode list: {1}'.format(self.show.idxr.name, error))
            logger.debug(traceback.format_exc())

        # update internal name cache
        name_cache.build_name_cache(self.show)

        try:
            self.show.loadEpisodesFromDir()
        except Exception as error:
            logger.exception('Error searching dir for episodes: {0}'.format(error))
            logger.debug(traceback.format_exc())

        # if they set default ep status to WANTED then run the backlog to search for episodes
        # FIXME: This needs to be a backlog queue item!!!
        if self.show.default_ep_status == WANTED:
            logger.info('Launching backlog for this show since its episodes are WANTED')
            settings.backlogSearchScheduler.action.searchBacklog([self.show])

        self.show.writeMetadata()
        self.show.updateMetadata()
        self.show.populateCache()

        self.show.flushEpisodes()

        if settings.USE_TRAKT:
            # if there are specific episodes that need to be added by trakt
            settings.traktCheckerScheduler.action.manageNewShow(self.show)
            # add show to trakt.tv library
            if settings.TRAKT_SYNC:
                settings.traktCheckerScheduler.action.addShowToTraktLibrary(self.show)

            if settings.TRAKT_SYNC_WATCHLIST:
                logger.info('update watchlist')
                notifiers.trakt_notifier.update_watchlist(show_obj=self.show)

        # Load XEM data to DB for show
        scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer, force=True)

        # check if show has XEM mapping so we can determine if searches should go by scene numbering or indexer numbering.
        if not self.scene and scene_numbering.get_xem_numbering_for_show(self.show.indexerid, self.show.indexer):
            self.show.scene = 1

        # After initial add, set to default_status_after.
        self.show.default_ep_status = self.default_status_after

        super(QueueItemAdd, self).finish()
        self.finish()
Beispiel #8
0
    def update_watchlist(show_obj=None,
                         s=None,
                         e=None,
                         data_show=None,
                         data_episode=None,
                         update="add"):
        """
        Sends a request to trakt indicating that the given episode is part of our library.

        show_obj: The TVShow object to add to trakt
        s: season number
        e: episode number
        data_show: structured object of shows trakt type
        data_episode: structured object of episodes trakt type
        update: type o action add or remove
        """

        trakt_api = TraktAPI(settings.SSL_VERIFY, settings.TRAKT_TIMEOUT)

        if settings.USE_TRAKT:

            data = {}
            try:
                # URL parameters
                if show_obj is not None:
                    data = {
                        'shows': [{
                            'title': show_obj.name,
                            'year': show_obj.startyear,
                            'ids': {
                                show_obj.idxr.slug: show_obj.indexerid
                            },
                        }]
                    }
                elif data_show is not None:
                    data.update(data_show)
                else:
                    logger.warning(
                        "there's a coding problem contact developer. It's needed to be provided at lest one of the two: data_show or show_obj"
                    )
                    return False

                if data_episode is not None:
                    data['shows'][0].update(data_episode)

                elif s is not None:
                    # trakt URL parameters
                    season = {
                        'season': [{
                            'number': s,
                        }]
                    }

                    if e is not None:
                        # trakt URL parameters
                        episode = {'episodes': [{'number': e}]}

                        season['season'][0].update(episode)

                    data['shows'][0].update(season)

                trakt_url = "sync/watchlist"
                if update == "remove":
                    trakt_url += "/remove"

                trakt_api.traktRequest(trakt_url, data, method='POST')

            except (traktException, traktAuthException, traktServerBusy) as e:
                logger.warning(
                    "Could not connect to Trakt service: {0}".format(str(e)))
                return False

        return True