Exemple #1
0
    def updateShows(self):
        sickrage.LOGGER.debug(
            "SHOW_WATCHLIST::CHECK::START - Trakt Show Watchlist")

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

        indexer = int(sickrage.TRAKT_DEFAULT_INDEXER)
        trakt_id = sickrage.INDEXER_API(indexer).config[b'trakt_id']

        for show_el in self.ShowWatchlist[trakt_id]:
            indexer_id = int(str(show_el))
            show = self.ShowWatchlist[trakt_id][show_el]

            # sickrage.LOGGER.debug(u"Checking Show: %s %s %s" % (trakt_id, indexer_id, show[b'title']))
            if int(sickrage.TRAKT_METHOD_ADD) != 2:
                self.addDefaultShow(indexer, indexer_id, show[b'title'],
                                    SKIPPED)
            else:
                self.addDefaultShow(indexer, indexer_id, show[b'title'],
                                    WANTED)

            if int(sickrage.TRAKT_METHOD_ADD) == 1:
                newShow = findCertainShow(sickrage.showList, indexer_id)

                if newShow is not None:
                    setEpisodeToWanted(newShow, 1, 1)
                else:
                    self.todoWanted.append((indexer_id, 1, 1))
        sickrage.LOGGER.debug(
            "SHOW_WATCHLIST::CHECK::FINISH - Trakt Show Watchlist")
Exemple #2
0
    def removeShowFromTraktLibrary(self, show_obj):
        if self.findShow(show_obj.indexer, show_obj.indexerid):
            trakt_id = sickrage.INDEXER_API(
                show_obj.indexer).config[b'trakt_id']

            # URL parameters
            data = {
                'shows': [{
                    'title': show_obj.name,
                    'year': show_obj.startyear,
                    'ids': {}
                }]
            }

            if trakt_id == 'tvdb_id':
                data[b'shows'][0][b'ids'][b'tvdb'] = show_obj.indexerid
            else:
                data[b'shows'][0][b'ids'][b'tvrage'] = show_obj.indexerid

            sickrage.LOGGER.debug("Removing %s from tv library" %
                                  show_obj.name)

            try:
                self.trakt_api.traktRequest("sync/collection/remove",
                                            data,
                                            method='POST')
            except traktException as e:
                sickrage.LOGGER.warning(
                    "Could not connect to Trakt service. Aborting removing show %s from Trakt library. Error: %s"
                    % (show_obj.name, repr(e)))
Exemple #3
0
    def updateEpisodes(self):
        """
        Sets episodes to wanted that are in trakt watchlist
        """
        sickrage.LOGGER.debug(
            "SHOW_WATCHLIST::CHECK::START - Trakt Episode Watchlist")

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

        managed_show = []

        indexer = int(sickrage.TRAKT_DEFAULT_INDEXER)
        trakt_id = sickrage.INDEXER_API(indexer).config[b'trakt_id']

        for show_el in self.EpisodeWatchlist[trakt_id]:
            indexer_id = int(show_el)
            show = self.EpisodeWatchlist[trakt_id][show_el]

            newShow = findCertainShow(sickrage.showList, indexer_id)

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

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

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

                            for episode_el in show[b'seasons'][season_el][
                                    b'episodes']:
                                setEpisodeToWanted(newShow, season,
                                                   int(episode_el))
            except TypeError:
                sickrage.LOGGER.debug(
                    "Could not parse the output from trakt for %s " %
                    show[b"title"])
        sickrage.LOGGER.debug(
            "SHOW_WATCHLIST::CHECK::FINISH - Trakt Episode Watchlist")
def _xem_exceptions_fetcher():
    if shouldRefresh('xem'):
        for indexer in sickrage.INDEXER_API().indexers:
            sickrage.LOGGER.info(
                "Checking for XEM scene exception updates for " +
                sickrage.INDEXER_API(indexer).name)

            url = "http://thexem.de/map/allNames?origin=%s&seasonNumbers=1" % sickrage.INDEXER_API(
                indexer).config['xem_origin']

            parsedJSON = getURL(url,
                                session=xem_session,
                                timeout=90,
                                json=True)
            if not parsedJSON:
                sickrage.LOGGER.debug(
                    "Check scene exceptions update failed for " +
                    sickrage.INDEXER_API(indexer).name +
                    ", Unable to get URL: " + url)
                continue

            if parsedJSON[b'result'] == 'failure':
                continue

            for indexerid, names in parsedJSON[b'data'].iteritems():
                try:
                    xem_exception_dict[int(indexerid)] = names
                except Exception as e:
                    sickrage.LOGGER.warning(
                        "XEM: Rejected entry: indexerid:{0}; names:{1}".format(
                            indexerid, names))
                    sickrage.LOGGER.debug(
                        "XEM: Rejected entry error message:{0}".format(str(e)))

        setLastRefresh('xem')

    return xem_exception_dict
Exemple #5
0
    def trakt_bulk_data_generate(data):
        """
        Build the JSON structure to send back to Trakt
        """
        uniqueShows = {}
        uniqueSeasons = {}

        for showid, indexerid, show_name, startyear, season, episode in data:
            if showid not in uniqueShows:
                uniqueShows[showid] = {
                    'title': show_name,
                    'year': startyear,
                    'ids': {},
                    'seasons': []
                }
                trakt_id = sickrage.INDEXER_API(indexerid).config[b'trakt_id']

                if trakt_id == 'tvdb_id':
                    uniqueShows[showid][b'ids'][b"tvdb"] = showid
                else:
                    uniqueShows[showid][b'ids'][b"tvrage"] = showid
                uniqueSeasons[showid] = []

        # Get the unique seasons per Show
        for showid, indexerid, show_name, startyear, season, episode in data:
            if season not in uniqueSeasons[showid]:
                uniqueSeasons[showid].append(season)

        # build the query
        traktShowList = []
        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})
                show = uniqueShows[searchedShow]
                show[b'seasons'].append({
                    'number': searchedSeason,
                    'episodes': episodesList
                })
                traktShowList.append(show)
        post_data = {'shows': traktShowList}
        return post_data
Exemple #6
0
    def removeEpisodeFromTraktWatchList(self):
        if sickrage.TRAKT_SYNC_WATCHLIST and sickrage.USE_TRAKT:
            sickrage.LOGGER.debug(
                "WATCHLIST::REMOVE::START - Look for Episodes to Remove from Trakt Watchlist"
            )

            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.MainDB().select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    trakt_id = sickrage.INDEXER_API(
                        cur_episode[b"indexer"]).config[b'trakt_id']

                    if self._checkInList(
                            trakt_id, str(cur_episode[b"showid"]),
                            str(cur_episode[b"season"]),
                            str(cur_episode[b"episode"])
                    ) and cur_episode[
                            b"status"] not in Quality.SNATCHED + Quality.SNATCHED_PROPER + [
                                UNKNOWN
                            ] + [WANTED]:
                        sickrage.LOGGER.debug(
                            "Removing Episode %s S%02dE%02d from watchlist" %
                            (cur_episode[b"show_name"], cur_episode[b"season"],
                             cur_episode[b"episode"]))
                        trakt_data.append(
                            (cur_episode[b"showid"], cur_episode[b"indexer"],
                             cur_episode[b"show_name"],
                             cur_episode[b"startyear"], cur_episode[b"season"],
                             cur_episode[b"episode"]))

                if len(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:
                        sickrage.LOGGER.warning(
                            "Could not connect to Trakt service. Error: %s" %
                            e)

                sickrage.LOGGER.debug(
                    "WATCHLIST::REMOVE::FINISH - Look for Episodes to Remove from Trakt Watchlist"
                )
Exemple #7
0
    def removeEpisodeFromTraktCollection(self):
        if sickrage.TRAKT_SYNC_REMOVE and sickrage.TRAKT_SYNC and sickrage.USE_TRAKT:
            sickrage.LOGGER.debug(
                "COLLECTION::REMOVE::START - Look for Episodes to Remove From Trakt Collection"
            )

            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.MainDB().select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    trakt_id = sickrage.INDEXER_API(
                        cur_episode[b"indexer"]).config[b'trakt_id']

                    if self._checkInList(trakt_id,
                                         str(cur_episode[b"showid"]),
                                         str(cur_episode[b"season"]),
                                         str(cur_episode[b"episode"]),
                                         List='Collection'):
                        if cur_episode[b"location"] == '':
                            sickrage.LOGGER.debug(
                                "Removing Episode %s S%02dE%02d from collection"
                                % (cur_episode[b"show_name"],
                                   cur_episode[b"season"],
                                   cur_episode[b"episode"]))
                            trakt_data.append((cur_episode[b"showid"],
                                               cur_episode[b"indexer"],
                                               cur_episode[b"show_name"],
                                               cur_episode[b"startyear"],
                                               cur_episode[b"season"],
                                               cur_episode[b"episode"]))

                if len(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:
                        sickrage.LOGGER.warning(
                            "Could not connect to Trakt service. Error: %s" %
                            e)

            sickrage.LOGGER.debug(
                "COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection"
            )
Exemple #8
0
    def addEpisodeToTraktWatchList(self):
        if sickrage.TRAKT_SYNC_WATCHLIST and sickrage.USE_TRAKT:
            sickrage.LOGGER.debug(
                "WATCHLIST::ADD::START - Look for Episodes to Add to Trakt Watchlist"
            )

            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.MainDB().select(sql_selection)

            if episodes is not None:
                trakt_data = []

                for cur_episode in episodes:
                    trakt_id = sickrage.INDEXER_API(
                        cur_episode[b"indexer"]).config[b'trakt_id']

                    if not self._checkInList(trakt_id,
                                             str(cur_episode[b"showid"]),
                                             str(cur_episode[b"season"]),
                                             str(cur_episode[b"episode"])):
                        sickrage.LOGGER.debug(
                            "Adding Episode %s S%02dE%02d to watchlist" %
                            (cur_episode[b"show_name"], cur_episode[b"season"],
                             cur_episode[b"episode"]))
                        trakt_data.append(
                            (cur_episode[b"showid"], cur_episode[b"indexer"],
                             cur_episode[b"show_name"],
                             cur_episode[b"startyear"], cur_episode[b"season"],
                             cur_episode[b"episode"]))

                if len(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:
                        sickrage.LOGGER.warning(
                            "Could not connect to Trakt service. Error %s" % e)

            sickrage.LOGGER.debug(
                "WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist"
            )
Exemple #9
0
    def addShowToTraktWatchList(self):
        if sickrage.TRAKT_SYNC_WATCHLIST and sickrage.USE_TRAKT:
            sickrage.LOGGER.debug(
                "SHOW_WATCHLIST::ADD::START - Look for Shows to Add to Trakt Watchlist"
            )

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

                for show in sickrage.showList:
                    trakt_id = sickrage.INDEXER_API(
                        show.indexer).config[b'trakt_id']

                    if not self._checkInList(
                            trakt_id, str(
                                show.indexerid), '0', '0', List='Show'):
                        sickrage.LOGGER.debug(
                            "Adding Show: Indexer %s %s - %s to Watchlist" %
                            (trakt_id, str(show.indexerid), show.name))
                        show_el = {
                            'title': show.name,
                            'year': show.startyear,
                            'ids': {}
                        }
                        if trakt_id == 'tvdb_id':
                            show_el[b'ids'][b'tvdb'] = show.indexerid
                        else:
                            show_el[b'ids'][b'tvrage'] = show.indexerid
                        trakt_data.append(show_el)

                if len(trakt_data):
                    try:
                        data = {'shows': trakt_data}
                        self.trakt_api.traktRequest("sync/watchlist",
                                                    data,
                                                    method='POST')
                        self._getShowWatchlist()
                    except traktException as e:
                        sickrage.LOGGER.warning(
                            "Could not connect to Trakt service. Error: %s" %
                            e)

            sickrage.LOGGER.debug(
                "SHOW_WATCHLIST::ADD::FINISH - Look for Shows to Add to Trakt Watchlist"
            )
Exemple #10
0
    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
        """
        data = {}

        if not self.findShow(show_obj.indexer, show_obj.indexerid):
            trakt_id = sickrage.INDEXER_API(
                show_obj.indexer).config[b'trakt_id']
            # URL parameters
            data = {
                'shows': [{
                    'title': show_obj.name,
                    'year': show_obj.startyear,
                    'ids': {}
                }]
            }

            if trakt_id == 'tvdb_id':
                data[b'shows'][0][b'ids'][b'tvdb'] = show_obj.indexerid
            else:
                data[b'shows'][0][b'ids'][b'tvrage'] = show_obj.indexerid

        if len(data):
            sickrage.LOGGER.debug("Adding %s to tv library" % show_obj.name)

            try:
                self.trakt_api.traktRequest("sync/collection",
                                            data,
                                            method='POST')
            except traktException as e:
                sickrage.LOGGER.warning(
                    "Could not connect to Trakt service. Aborting adding show %s to Trakt library. Error: %s"
                    % (show_obj.name, repr(e)))
                return
Exemple #11
0
    def _ep_data(self, ep_obj):
        """
        Creates an elementTree XML structure for a MediaBrowser style episode.xml
        and returns the resulting data object.

        show_obj: a TVShow instance to create the NFO for
        """

        eps_to_write = [ep_obj] + ep_obj.relatedEps

        indexer_lang = ep_obj.show.lang

        try:
            # There's gotta be a better way of doing this but we don't wanna
            # change the language value elsewhere
            lINDEXER_API_PARMS = sickrage.INDEXER_API(
                ep_obj.show.indexer).api_params.copy()

            if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
                lINDEXER_API_PARMS[b'language'] = indexer_lang

            if ep_obj.show.dvdorder != 0:
                lINDEXER_API_PARMS[b'dvdorder'] = True

            t = sickrage.INDEXER_API(
                ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS)
            myShow = t[ep_obj.show.indexerid]
        except indexer_shownotfound as e:
            raise ShowNotFoundException(e.message)
        except indexer_error as e:
            sickrage.LOGGER.error(
                "Unable to connect to TVDB while creating meta files - skipping - {}"
                .format(e))
            return False

        rootNode = Element("details")
        movie = SubElement(rootNode, "movie")

        movie.attrib[b"isExtra"] = "false"
        movie.attrib[b"isSet"] = "false"
        movie.attrib[b"isTV"] = "true"

        # write an MediaBrowser XML containing info for all matching episodes
        for curEpToWrite in eps_to_write:

            try:
                myEp = myShow[curEpToWrite.season][curEpToWrite.episode]
            except (indexer_episodenotfound, indexer_seasonnotfound):
                sickrage.LOGGER.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?"
                    % (curEpToWrite.season, curEpToWrite.episode,
                       sickrage.INDEXER_API(ep_obj.show.indexer).name))
                return None

            if curEpToWrite == ep_obj:
                # root (or single) episode

                # default to today's date for specials if firstaired is not set
                if curEpToWrite.season == 0 and not getattr(
                        myEp, 'firstaired', None):
                    myEp[b'firstaired'] = str(datetime.date.fromordinal(1))

                if not (getattr(myEp, 'episodename', None)
                        and getattr(myEp, 'firstaired', None)):
                    return None

                episode = movie

                if curEpToWrite.name:
                    EpisodeName = SubElement(episode, "title")
                    EpisodeName.text = curEpToWrite.name

                SeasonNumber = SubElement(episode, "season")
                SeasonNumber.text = str(curEpToWrite.season)

                EpisodeNumber = SubElement(episode, "episode")
                EpisodeNumber.text = str(curEpToWrite.episode)

                if getattr(myShow, "firstaired", None):
                    try:
                        year_text = str(
                            datetime.datetime.strptime(myShow[b"firstaired"],
                                                       dateFormat).year)
                        if year_text:
                            year = SubElement(episode, "year")
                            year.text = year_text
                    except:
                        pass

                if getattr(myShow, "overview", None):
                    plot = SubElement(episode, "plot")
                    plot.text = myShow[b"overview"]

                if curEpToWrite.description:
                    Overview = SubElement(episode, "episodeplot")
                    Overview.text = curEpToWrite.description

                if getattr(myShow, 'contentrating', None):
                    mpaa = SubElement(episode, "mpaa")
                    mpaa.text = myShow[b"contentrating"]

                if not ep_obj.relatedEps and getattr(myEp, "rating", None):
                    try:
                        rating = int((float(myEp[b'rating']) * 10))
                    except ValueError:
                        rating = 0

                    if rating:
                        Rating = SubElement(episode, "rating")
                        Rating.text = str(rating)

                if getattr(myEp, 'director', None):
                    director = SubElement(episode, "director")
                    director.text = myEp[b'director']

                if getattr(myEp, 'writer', None):
                    writer = SubElement(episode, "credits")
                    writer.text = myEp[b'writer']

                if getattr(myShow, '_actors', None) or getattr(
                        myEp, 'gueststars', None):
                    cast = SubElement(episode, "cast")
                    if getattr(myEp, 'gueststars', None) and isinstance(
                            myEp[b'gueststars'], basestring):
                        for actor in (x.strip()
                                      for x in myEp[b'gueststars'].split('|')
                                      if x.strip()):
                            cur_actor = SubElement(cast, "actor")
                            cur_actor.text = actor

                    if getattr(myShow, '_actors', None):
                        for actor in myShow[b'_actors']:
                            if 'name' in actor and actor[b'name'].strip():
                                cur_actor = SubElement(cast, "actor")
                                cur_actor.text = actor[b'name'].strip()

            else:
                # append data from (if any) related episodes

                if curEpToWrite.name:
                    if not EpisodeName.text:
                        EpisodeName.text = curEpToWrite.name
                    else:
                        EpisodeName.text = EpisodeName.text + ", " + curEpToWrite.name

                if curEpToWrite.description:
                    if not Overview.text:
                        Overview.text = curEpToWrite.description
                    else:
                        Overview.text = Overview.text + "\r" + curEpToWrite.description

        indentXML(rootNode)
        data = ElementTree(rootNode)

        return data
Exemple #12
0
    def _ep_data(self, ep_obj):
        """
        Creates an elementTree XML structure for a MediaBrowser style episode.xml
        and returns the resulting data object.

        show_obj: a TVShow instance to create the NFO for
        """

        eps_to_write = [ep_obj] + ep_obj.relatedEps

        persons_dict = {
            'Director': [],
            'GuestStar': [],
            'Writer': []
        }

        indexer_lang = ep_obj.show.lang

        try:
            lINDEXER_API_PARMS = sickrage.INDEXER_API(ep_obj.show.indexer).api_params.copy()

            lINDEXER_API_PARMS[b'actors'] = True

            if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
                lINDEXER_API_PARMS[b'language'] = indexer_lang

            if ep_obj.show.dvdorder != 0:
                lINDEXER_API_PARMS[b'dvdorder'] = True

            t = sickrage.INDEXER_API(ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS)

            myShow = t[ep_obj.show.indexerid]
        except indexer_shownotfound as e:
            raise ShowNotFoundException(e.message)
        except indexer_error as e:
            sickrage.LOGGER.error("Unable to connect to " + sickrage.INDEXER_API(
                    ep_obj.show.indexer).name + " while creating meta files - skipping - {}".format(e))
            return False

        rootNode = Element("Item")

        # write an MediaBrowser XML containing info for all matching episodes
        for curEpToWrite in eps_to_write:

            try:
                myEp = myShow[curEpToWrite.season][curEpToWrite.episode]
            except (indexer_episodenotfound, indexer_seasonnotfound):
                sickrage.LOGGER.info("Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" %
                             (curEpToWrite.season, curEpToWrite.episode, sickrage.INDEXER_API(ep_obj.show.indexer).name))
                return None

            if curEpToWrite == ep_obj:
                # root (or single) episode

                # default to today's date for specials if firstaired is not set
                if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None):
                    myEp[b'firstaired'] = str(datetime.date.fromordinal(1))

                if not (getattr(myEp, 'episodename', None) and getattr(myEp, 'firstaired', None)):
                    return None

                episode = rootNode

                if curEpToWrite.name:
                    EpisodeName = SubElement(episode, "EpisodeName")
                    EpisodeName.text = curEpToWrite.name

                EpisodeNumber = SubElement(episode, "EpisodeNumber")
                EpisodeNumber.text = str(ep_obj.episode)

                if ep_obj.relatedEps:
                    EpisodeNumberEnd = SubElement(episode, "EpisodeNumberEnd")
                    EpisodeNumberEnd.text = str(curEpToWrite.episode)

                SeasonNumber = SubElement(episode, "SeasonNumber")
                SeasonNumber.text = str(curEpToWrite.season)

                if not ep_obj.relatedEps and getattr(myEp, 'absolute_number', None):
                    absolute_number = SubElement(episode, "absolute_number")
                    absolute_number.text = str(myEp[b'absolute_number'])

                if curEpToWrite.airdate != datetime.date.fromordinal(1):
                    FirstAired = SubElement(episode, "FirstAired")
                    FirstAired.text = str(curEpToWrite.airdate)

                MetadataType = SubElement(episode, "Type")
                MetadataType.text = "Episode"

                if curEpToWrite.description:
                    Overview = SubElement(episode, "Overview")
                    Overview.text = curEpToWrite.description

                if not ep_obj.relatedEps:
                    if getattr(myEp, 'rating', None):
                        Rating = SubElement(episode, "Rating")
                        Rating.text = myEp[b'rating']

                    if getattr(myShow, 'imdb_id', None):
                        IMDB_ID = SubElement(episode, "IMDB_ID")
                        IMDB_ID.text = myShow[b'imdb_id']

                        IMDB = SubElement(episode, "IMDB")
                        IMDB.text = myShow[b'imdb_id']

                        IMDbId = SubElement(episode, "IMDbId")
                        IMDbId.text = myShow[b'imdb_id']

                indexerid = SubElement(episode, "id")
                indexerid.text = str(curEpToWrite.indexerid)

                # fill in Persons section with collected directors, guest starts and writers
                Persons = SubElement(episode, "Persons")
                for person_type, names in persons_dict.iteritems():
                    # remove doubles
                    names = list(set(names))
                    for cur_name in names:
                        Person = SubElement(Persons, "Person")
                        cur_person_name = SubElement(Person, "Name")
                        cur_person_name.text = cur_name
                        cur_person_type = SubElement(Person, "Type")
                        cur_person_type.text = person_type

                if getattr(myShow, '_actors', None):
                    for actor in myShow[b'_actors']:
                        if not ('name' in actor and actor[b'name'].strip()):
                            continue

                        cur_actor = SubElement(Persons, "Person")

                        cur_actor_name = SubElement(cur_actor, "Name")
                        cur_actor_name.text = actor[b'name'].strip()

                        cur_actor_type = SubElement(cur_actor, "Type")
                        cur_actor_type.text = "Actor"

                        if 'role' in actor and actor[b'role'].strip():
                            cur_actor_role = SubElement(cur_actor, "Role")
                            cur_actor_role.text = actor[b'role'].strip()

                Language = SubElement(episode, "Language")
                try:
                    Language.text = myEp[b'language']
                except Exception:
                    Language.text = sickrage.INDEXER_DEFAULT_LANGUAGE  # tvrage api doesn't provide language so we must assume a value here

                thumb = SubElement(episode, "filename")
                # TODO: See what this is needed for.. if its still needed
                # just write this to the NFO regardless of whether it actually exists or not
                # note: renaming files after nfo generation will break this, tough luck
                thumb_text = self.get_episode_thumb_path(ep_obj)
                if thumb_text:
                    thumb.text = thumb_text

            else:
                # append data from (if any) related episodes
                if curEpToWrite.episode:
                    if not EpisodeNumberEnd.text:
                        EpisodeNumberEnd.text = curEpToWrite.episode
                    else:
                        EpisodeNumberEnd.text = EpisodeNumberEnd.text + ", " + curEpToWrite.episode

                if curEpToWrite.name:
                    if not EpisodeName.text:
                        EpisodeName.text = curEpToWrite.name
                    else:
                        EpisodeName.text = EpisodeName.text + ", " + curEpToWrite.name

                if curEpToWrite.description:
                    if not Overview.text:
                        Overview.text = curEpToWrite.description
                    else:
                        Overview.text = Overview.text + "\r" + curEpToWrite.description

            # collect all directors, guest stars and writers
            if getattr(myEp, 'director', None):
                persons_dict[b'Director'] += [x.strip() for x in myEp[b'director'].split('|') if x.strip()]
            if getattr(myEp, 'gueststars', None):
                persons_dict[b'GuestStar'] += [x.strip() for x in myEp[b'gueststars'].split('|') if x.strip()]
            if getattr(myEp, 'writer', None):
                persons_dict[b'Writer'] += [x.strip() for x in myEp[b'writer'].split('|') if x.strip()]

        indentXML(rootNode)
        data = ElementTree(rootNode)

        return data
Exemple #13
0
 def __str__(self):
     return str(self.date) + " " + self.name + " " + str(
         self.season) + "x" + str(self.episode) + " of " + str(
             self.indexerid) + " from " + str(
                 sickrage.INDEXER_API(self.indexer).name)
Exemple #14
0
def xem_refresh(indexer_id, indexer, force=False):
    """
    Refresh data from xem for a tv show

    :param indexer_id: int
    """
    if not indexer_id or indexer_id < 1:
        return

    indexer_id = int(indexer_id)
    indexer = int(indexer)

    MAX_REFRESH_AGE_SECS = 86400  # 1 day

    rows = main_db.MainDB().select(
        "SELECT last_refreshed FROM xem_refresh WHERE indexer = ? AND indexer_id = ?",
        [indexer, indexer_id])
    if rows:
        lastRefresh = int(rows[0][b'last_refreshed'])
        refresh = int(time.mktime(datetime.datetime.today().timetuple())
                      ) > lastRefresh + MAX_REFRESH_AGE_SECS
    else:
        refresh = True

    if refresh or force:
        sickrage.LOGGER.debug(
            'Looking up XEM scene mapping for show %s on %s' %
            (indexer_id, sickrage.INDEXER_API(indexer).name))

        # mark refreshed
        main_db.MainDB().upsert(
            "xem_refresh", {
                'indexer':
                indexer,
                'last_refreshed':
                int(time.mktime(datetime.datetime.today().timetuple()))
            }, {'indexer_id': indexer_id})

        try:
            from scene_exceptions import xem_session

            # XEM MAP URL
            url = "http://thexem.de/map/havemap?origin=%s" % sickrage.INDEXER_API(
                indexer).config[b'xem_origin']
            parsedJSON = getURL(url, session=xem_session, json=True)
            if not parsedJSON or 'result' not in parsedJSON or 'success' not in parsedJSON[
                    b'result'] or 'data' not in parsedJSON or str(
                        indexer_id) not in parsedJSON[b'data']:
                return

            # XEM API URL
            url = "http://thexem.de/map/all?id={}&origin={}&destination=scene".format(
                indexer_id,
                sickrage.INDEXER_API(indexer).config[b'xem_origin'])

            parsedJSON = getURL(url, session=xem_session, json=True)
            if not ((parsedJSON and 'result' in parsedJSON)
                    and 'success' in parsedJSON[b'result']):
                sickrage.LOGGER.info('No XEM data for show "%s on %s"' % (
                    indexer_id,
                    sickrage.INDEXER_API(indexer).name,
                ))
                return

            cl = []
            for entry in parsedJSON[b'data']:
                if 'scene' in entry:
                    cl.append([
                        "UPDATE tv_episodes SET scene_season = ?, scene_episode = ?, scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?",
                        [
                            entry[b'scene'][b'season'],
                            entry[b'scene'][b'episode'],
                            entry[b'scene'][b'absolute'], indexer_id,
                            entry[sickrage.INDEXER_API(
                                indexer).config[b'xem_origin']][b'season'],
                            entry[sickrage.INDEXER_API(
                                indexer).config[b'xem_origin']][b'episode']
                        ]
                    ])
                if 'scene_2' in entry:  # for doubles
                    cl.append([
                        "UPDATE tv_episodes SET scene_season = ?, scene_episode = ?, scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?",
                        [
                            entry[b'scene_2'][b'season'],
                            entry[b'scene_2'][b'episode'],
                            entry[b'scene_2'][b'absolute'], indexer_id,
                            entry[sickrage.INDEXER_API(
                                indexer).config[b'xem_origin']][b'season'],
                            entry[sickrage.INDEXER_API(
                                indexer).config[b'xem_origin']][b'episode']
                        ]
                    ])

            if len(cl) > 0:
                main_db.MainDB().mass_action(cl)

        except Exception as e:
            sickrage.LOGGER.warning(
                "Exception while refreshing XEM data for show " +
                str(indexer_id) + " on " + sickrage.INDEXER_API(indexer).name +
                ": {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())
Exemple #15
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []
        bestResult = None

        for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes:
            match = cur_regex.match(name)

            if not match:
                continue

            result = ParseResult(name)
            result.which_regex = [cur_regex_name]
            result.score = 0 - cur_regex_num

            named_groups = match.groupdict().keys()

            if 'series_name' in named_groups:
                result.series_name = match.group('series_name')
                if result.series_name:
                    result.series_name = self.clean_series_name(result.series_name)
                    result.score += 1

            if 'series_num' in named_groups and match.group('series_num'):
                result.score += 1

            if 'season_num' in named_groups:
                tmp_season = int(match.group('season_num'))
                if cur_regex_name == 'bare' and tmp_season in (19, 20):
                    continue
                result.season_number = tmp_season
                result.score += 1

            if 'ep_num' in named_groups:
                ep_num = self._convert_number(match.group('ep_num'))
                if 'extra_ep_num' in named_groups and match.group('extra_ep_num'):
                    result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1)
                    result.score += 1
                else:
                    result.episode_numbers = [ep_num]
                result.score += 1

            if 'ep_ab_num' in named_groups:
                ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'):
                    result.ab_episode_numbers = range(ep_ab_num,
                                                      self._convert_number(match.group('extra_ab_ep_num')) + 1)
                    result.score += 1
                else:
                    result.ab_episode_numbers = [ep_ab_num]
                result.score += 1

            if 'air_date' in named_groups:
                air_date = match.group('air_date')
                try:
                    result.air_date = parser.parse(air_date, fuzzy=True).date()
                    result.score += 1
                except Exception:
                    continue

            if 'extra_info' in named_groups:
                tmp_extra_info = match.group('extra_info')

                # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                if tmp_extra_info and cur_regex_name == 'season_only' and re.search(
                        r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I):
                    continue
                result.extra_info = tmp_extra_info
                result.score += 1

            if 'release_group' in named_groups:
                result.release_group = match.group('release_group')
                result.score += 1

            if 'version' in named_groups:
                # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                version = match.group('version')
                if version:
                    result.version = version
                else:
                    result.version = 1
            else:
                result.version = -1

            matches.append(result)

        if len(matches):
            # pick best match with highest score based on placement
            bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

            show = None
            if not self.naming_pattern:
                # try and create a show object for this result
                show = self.get_show(bestResult.series_name, self.tryIndexers)

            # confirm passed in show object indexer id matches result show object indexer id
            if show:
                if self.showObj and show.indexerid != self.showObj.indexerid:
                    show = None
                bestResult.show = show
            elif not show and self.showObj:
                bestResult.show = self.showObj

            # if this is a naming pattern test or result doesn't have a show object then return best result
            if not bestResult.show or self.naming_pattern:
                return bestResult

            # get quality
            bestResult.quality = Quality.nameQuality(name, bestResult.show.is_anime)

            new_episode_numbers = []
            new_season_numbers = []
            new_absolute_numbers = []

            # if we have an air-by-date show then get the real season/episode numbers
            if bestResult.is_air_by_date:
                from sickrage.core.databases import main_db
                airdate = bestResult.air_date.toordinal()
                sql_result = main_db.MainDB().select(
                        "SELECT season, episode FROM tv_episodes WHERE showid = ? AND indexer = ? AND airdate = ?",
                        [bestResult.show.indexerid, bestResult.show.indexer, airdate])

                season_number = None
                episode_numbers = []

                if sql_result:
                    season_number = int(sql_result[0][0])
                    episode_numbers = [int(sql_result[0][1])]

                if not season_number or not len(episode_numbers):
                    try:
                        lINDEXER_API_PARMS = sickrage.INDEXER_API(bestResult.show.indexer).api_params.copy()

                        if bestResult.show.lang:
                            lINDEXER_API_PARMS[b'language'] = bestResult.show.lang

                        t = sickrage.INDEXER_API(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS)

                        epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0]

                        season_number = int(epObj[b"seasonnumber"])
                        episode_numbers = [int(epObj[b"episodenumber"])]
                    except indexer_episodenotfound:
                        sickrage.LOGGER.warning(
                                "Unable to find episode with date " + bestResult.air_date + " for show " + bestResult.show.name + ", skipping")
                        episode_numbers = []
                    except indexer_error as e:
                        sickrage.LOGGER.warning(
                                "Unable to contact " + sickrage.INDEXER_API(bestResult.show.indexer).name + ": {}".format(
                                        e))
                        episode_numbers = []

                for epNo in episode_numbers:
                    s = season_number
                    e = epNo

                    if bestResult.show.is_scene:
                        (s, e) = get_indexer_numbering(bestResult.show.indexerid,
                                                       bestResult.show.indexer,
                                                       season_number,
                                                       epNo)
                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers):
                scene_season = get_scene_exception_by_name(bestResult.series_name)[1]
                for epAbsNo in bestResult.ab_episode_numbers:
                    a = epAbsNo

                    if bestResult.show.is_scene:
                        a = get_indexer_absolute_numbering(bestResult.show.indexerid,
                                                           bestResult.show.indexer, epAbsNo,
                                                           True, scene_season)

                    (s, e) = get_all_episodes_from_absolute_number(bestResult.show, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

            elif bestResult.season_number and len(bestResult.episode_numbers):
                for epNo in bestResult.episode_numbers:
                    s = bestResult.season_number
                    e = epNo

                    if bestResult.show.is_scene:
                        (s, e) = get_indexer_numbering(bestResult.show.indexerid,
                                                       bestResult.show.indexer,
                                                       bestResult.season_number,
                                                       epNo)
                    if bestResult.show.is_anime:
                        a = get_absolute_number_from_season_and_episode(bestResult.show, s, e)
                        if a:
                            new_absolute_numbers.append(a)

                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            # need to do a quick sanity check heregex.  It's possible that we now have episodes
            # from more than one season (by tvdb numbering), and this is just too much
            # for sickrage, so we'd need to flag it.
            new_season_numbers = list(set(new_season_numbers))  # remove duplicates
            if len(new_season_numbers) > 1:
                raise InvalidNameException("Scene numbering results episodes from "
                                           "seasons %s, (i.e. more than one) and "
                                           "sickrage does not support this.  "
                                           "Sorry." % (new_season_numbers))

            # I guess it's possible that we'd have duplicate episodes too, so lets
            # eliminate them
            new_episode_numbers = list(set(new_episode_numbers))
            new_episode_numbers.sort()

            # maybe even duplicate absolute numbers so why not do them as well
            new_absolute_numbers = list(set(new_absolute_numbers))
            new_absolute_numbers.sort()

            if len(new_absolute_numbers):
                bestResult.ab_episode_numbers = new_absolute_numbers

            if len(new_season_numbers) and len(new_episode_numbers):
                bestResult.episode_numbers = new_episode_numbers
                bestResult.season_number = new_season_numbers[0]

            if bestResult.show.is_scene:
                sickrage.LOGGER.debug("Converted parsed result {} into {}".format(bestResult.original_name, bestResult))

        # CPU sleep
        gen.sleep(1)

        return bestResult
Exemple #16
0
    def _ep_data(self, ep_obj):
        """
        Creates a key value structure for a Tivo episode metadata file and
        returns the resulting data object.

        ep_obj: a TVEpisode instance to create the metadata file for.

        Lookup the show in http://thetvdb.com/ using the python library:

        https://github.com/dbr/indexer_api/

        The results are saved in the object myShow.

        The key values for the tivo metadata file are from:

        http://pytivo.sourceforge.net/wiki/index.php/Metadata
        """

        data = ""

        eps_to_write = [ep_obj] + ep_obj.relatedEps

        indexer_lang = ep_obj.show.lang

        try:
            lINDEXER_API_PARMS = sickrage.INDEXER_API(
                ep_obj.show.indexer).api_params.copy()

            lINDEXER_API_PARMS[b'actors'] = True

            if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
                lINDEXER_API_PARMS[b'language'] = indexer_lang

            if ep_obj.show.dvdorder != 0:
                lINDEXER_API_PARMS[b'dvdorder'] = True

            t = sickrage.INDEXER_API(
                ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS)
            myShow = t[ep_obj.show.indexerid]
        except indexer_shownotfound as e:
            raise ShowNotFoundException(str(e))
        except indexer_error as e:
            sickrage.LOGGER.error(
                "Unable to connect to " +
                sickrage.INDEXER_API(ep_obj.show.indexer).name +
                " while creating meta files - skipping - " + str(e))
            return False

        for curEpToWrite in eps_to_write:

            try:
                myEp = myShow[curEpToWrite.season][curEpToWrite.episode]
            except (indexer_episodenotfound, indexer_seasonnotfound):
                sickrage.LOGGER.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?"
                    % (curEpToWrite.season, curEpToWrite.episode,
                       sickrage.INDEXER_API(ep_obj.show.indexer).name))
                return None

            if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None):
                myEp[b"firstaired"] = str(datetime.date.fromordinal(1))

            if not (getattr(myEp, 'episodename', None)
                    and getattr(myEp, 'firstaired', None)):
                return None

            if getattr(myShow, 'seriesname', None):
                data += ("title : " + myShow[b"seriesname"] + "\n")
                data += ("seriesTitle : " + myShow[b"seriesname"] + "\n")

            data += ("episodeTitle : " +
                     curEpToWrite._format_pattern('%Sx%0E %EN') + "\n")

            # This should be entered for episodic shows and omitted for movies. The standard tivo format is to enter
            # the season number followed by the episode number for that season. For example, enter 201 for season 2
            # episode 01.

            # This only shows up if you go into the Details from the Program screen.

            # This seems to disappear once the video is transferred to TiVo.

            # NOTE: May not be correct format, missing season, but based on description from wiki leaving as is.
            data += ("episodeNumber : " + str(curEpToWrite.episode) + "\n")

            # Must be entered as true or false. If true, the year from originalAirDate will be shown in parentheses
            # after the episode's title and before the description on the Program screen.

            # FIXME: Hardcode isEpisode to true for now, not sure how to handle movies
            data += "isEpisode : true\n"

            # Write the synopsis of the video here
            # Micrsoft Word's smartquotes can die in a fire.
            sanitizedDescription = curEpToWrite.description
            # Replace double curly quotes
            sanitizedDescription = sanitizedDescription.replace(
                "\u201c", "\"").replace("\u201d", "\"")
            # Replace single curly quotes
            sanitizedDescription = sanitizedDescription.replace(
                "\u2018", "'").replace("\u2019", "'").replace("\u02BC", "'")

            data += ("description : " + sanitizedDescription + "\n")

            # Usually starts with "SH" and followed by 6-8 digits.
            # Tivo uses zap2it for thier data, so the series id is the zap2it_id.
            if getattr(myShow, 'zap2it_id', None):
                data += ("seriesId : " + myShow[b"zap2it_id"] + "\n")

            # This is the call sign of the channel the episode was recorded from.
            if getattr(myShow, 'network', None):
                data += ("callsign : " + myShow[b"network"] + "\n")

            # This must be entered as yyyy-mm-ddThh:mm:ssZ (the t is capitalized and never changes, the Z is also
            # capitalized and never changes). This is the original air date of the episode.
            # NOTE: Hard coded the time to T00:00:00Z as we really don't know when during the day the first run happened.
            if curEpToWrite.airdate != datetime.date.fromordinal(1):
                data += ("originalAirDate : " + str(curEpToWrite.airdate) +
                         "T00:00:00Z\n")

            # This shows up at the beginning of the description on the Program screen and on the Details screen.
            if getattr(myShow, '_actors', None):
                for actor in myShow[b"_actors"]:
                    if 'name' in actor and actor[b'name'].strip():
                        data += ("vActor : " + actor[b'name'].strip() + "\n")

            # This is shown on both the Program screen and the Details screen.
            if getattr(myEp, 'rating', None):
                try:
                    rating = float(myEp[b'rating'])
                except ValueError:
                    rating = 0.0
                # convert 10 to 4 star rating. 4 * rating / 10
                # only whole numbers or half numbers work. multiply by 2, round, divide by 2.0
                rating = round(8 * rating / 10) / 2.0
                data += ("starRating : " + str(rating) + "\n")

            # This is shown on both the Program screen and the Details screen.
            # It uses the standard TV rating system of: TV-Y7, TV-Y, TV-G, TV-PG, TV-14, TV-MA and TV-NR.
            if getattr(myShow, 'contentrating', None):
                data += ("tvRating : " + str(myShow[b"contentrating"]) + "\n")

            # This field can be repeated as many times as necessary or omitted completely.
            if ep_obj.show.genre:
                for genre in ep_obj.show.genre.split('|'):
                    if genre:
                        data += ("vProgramGenre : " + str(genre) + "\n")

                        # NOTE: The following are metadata keywords are not used
                        # displayMajorNumber
                        # showingBits
                        # displayMinorNumber
                        # colorCode
                        # vSeriesGenre
                        # vGuestStar, vDirector, vExecProducer, vProducer, vWriter, vHost, vChoreographer
                        # partCount
                        # partIndex

        return data
Exemple #17
0
    def run(self):
        ShowQueueItem.run(self)

        sickrage.LOGGER.debug("Beginning update of " + self.show.name)

        sickrage.LOGGER.debug("Retrieving show info from " +
                              sickrage.INDEXER_API(self.show.indexer).name +
                              "")
        try:
            self.show.loadFromIndexer(cache=not self.force)
        except indexer_error as e:
            sickrage.LOGGER.warning(
                "Unable to contact " +
                sickrage.INDEXER_API(self.show.indexer).name +
                ", aborting: {}".format(e))
            return
        except indexer_attributenotfound as e:
            sickrage.LOGGER.error(
                "Data retrieved from " +
                sickrage.INDEXER_API(self.show.indexer).name +
                " was incomplete, aborting: {}".format(e))
            return

        sickrage.LOGGER.debug("Retrieving show info from TMDb")
        try:
            self.show.loadTMDbInfo()
        except Exception as e:
            sickrage.LOGGER.error("Error loading TMDb info: {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())
            try:
                sickrage.LOGGER.debug(
                    "Attempting to retrieve show info from IMDb")
                self.show.loadIMDbInfo()
            except Exception as e:
                sickrage.LOGGER.error("Error loading IMDb info: {}".format(e))
                sickrage.LOGGER.debug(traceback.format_exc())

        # have to save show before reading episodes from db
        try:
            self.show.saveToDB()
        except Exception as e:
            sickrage.LOGGER.error(
                "Error saving show info to the database: {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())

        # get episode list from DB
        sickrage.LOGGER.debug("Loading all episodes from the database")
        DBEpList = self.show.loadEpisodesFromDB()

        # get episode list from TVDB
        sickrage.LOGGER.debug("Loading all episodes from " +
                              sickrage.INDEXER_API(self.show.indexer).name +
                              "")
        try:
            IndexerEpList = self.show.loadEpisodesFromIndexer(
                cache=not self.force)
        except indexer_exception as e:
            sickrage.LOGGER.error(
                "Unable to get info from " +
                sickrage.INDEXER_API(self.show.indexer).name +
                ", the show info will not be refreshed: {}".format(e))
            IndexerEpList = None

        if IndexerEpList is None:
            sickrage.LOGGER.error(
                "No data returned from " +
                sickrage.INDEXER_API(self.show.indexer).name +
                ", unable to update this show")
        else:
            # for each ep we found on the Indexer delete it from the DB list
            for curSeason in IndexerEpList:
                for curEpisode in IndexerEpList[curSeason]:
                    curEp = self.show.getEpisode(curSeason, curEpisode)
                    curEp.saveToDB()

                    if curSeason in DBEpList and curEpisode in DBEpList[
                            curSeason]:
                        del DBEpList[curSeason][curEpisode]

            # remaining episodes in the DB list are not on the indexer, just delete them from the DB
            for curSeason in DBEpList:
                for curEpisode in DBEpList[curSeason]:
                    sickrage.LOGGER.info("Permanently deleting episode " +
                                         str(curSeason) + "x" +
                                         str(curEpisode) +
                                         " from the database")
                    curEp = self.show.getEpisode(curSeason, curEpisode)
                    try:
                        curEp.deleteEpisode()
                    except EpisodeDeletedException:
                        pass

        # save show again, in case episodes have changed
        try:
            self.show.saveToDB()
        except Exception as e:
            sickrage.LOGGER.error(
                "Error saving show info to the database: {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())

        sickrage.LOGGER.debug("Finished update of " + self.show.name)

        sickrage.SHOWQUEUE.refreshShow(self.show, self.force)
        self.finish()
Exemple #18
0
    def run(self):

        ShowQueueItem.run(self)

        sickrage.LOGGER.info("Starting to add show {}".format(self.showDir))
        # make sure the Indexer IDs are valid
        try:

            lINDEXER_API_PARMS = sickrage.INDEXER_API(
                self.indexer).api_params.copy()
            if self.lang:
                lINDEXER_API_PARMS[b'language'] = self.lang

            sickrage.LOGGER.info("" +
                                 str(sickrage.INDEXER_API(self.indexer).name) +
                                 ": " + repr(lINDEXER_API_PARMS))

            t = sickrage.INDEXER_API(
                self.indexer).indexer(**lINDEXER_API_PARMS)
            s = t[self.indexer_id]

            # 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:
                sickrage.LOGGER.error(
                    "Show in " + self.showDir + " has no name on " +
                    str(sickrage.INDEXER_API(self.indexer).name) +
                    ", probably the wrong language used to search with.")
                notifications.error(
                    "Unable to add show",
                    "Show in " + self.showDir + " has no name on " +
                    str(sickrage.INDEXER_API(self.indexer).name) +
                    ", probably the wrong language. Delete .nfo and add manually in the correct language."
                )
                self._finishEarly()
                return
            # if the show has no episodes/seasons
            if not s:
                sickrage.LOGGER.error(
                    "Show " + str(s[b'seriesname']) + " is on " +
                    str(sickrage.INDEXER_API(self.indexer).name) +
                    " but contains no season/episode data.")
                notifications.error(
                    "Unable to add show", "Show " + str(s[b'seriesname']) +
                    " is on " + str(sickrage.INDEXER_API(self.indexer).name) +
                    " but contains no season/episode data.")
                self._finishEarly()
                return
        except Exception as e:
            sickrage.LOGGER.error(
                "%s Error while loading information from indexer %s. Error: %r"
                %
                (self.indexer_id, sickrage.INDEXER_API(self.indexer).name, e))

            notifications.error(
                "Unable to add show",
                "Unable to look up the show in %s on %s using ID %s, not using the NFO. Delete .nfo and try adding manually again."
                % (self.showDir, sickrage.INDEXER_API(
                    self.indexer).name, self.indexer_id))

            if sickrage.USE_TRAKT:

                trakt_id = sickrage.INDEXER_API(
                    self.indexer).config[b'trakt_id']
                trakt_api = TraktAPI(sickrage.SSL_VERIFY,
                                     sickrage.TRAKT_TIMEOUT)

                title = self.showDir.split("/")[-1]
                data = {'shows': [{'title': title, 'ids': {}}]}
                if trakt_id == 'tvdb_id':
                    data[b'shows'][0][b'ids'][b'tvdb'] = self.indexer_id
                else:
                    data[b'shows'][0][b'ids'][b'tvrage'] = self.indexer_id

                trakt_api.traktRequest("sync/watchlist/remove",
                                       data,
                                       method='POST')

            self._finishEarly()
            return

        try:
            self.show = TVShow(self.indexer, self.indexer_id, self.lang)
            self.show.loadFromIndexer()

            # set up initial values
            self.show.location = self.showDir
            self.show.subtitles = self.subtitles if self.subtitles is not None else sickrage.SUBTITLES_DEFAULT
            self.show.quality = self.quality if self.quality else sickrage.QUALITY_DEFAULT
            self.show.flatten_folders = self.flatten_folders if self.flatten_folders is not None else sickrage.FLATTEN_FOLDERS_DEFAULT
            self.show.anime = self.anime if self.anime is not None else sickrage.ANIME_DEFAULT
            self.show.scene = self.scene if self.scene is not None else sickrage.SCENE_DEFAULT
            self.show.archive_firstmatch = self.archive if self.archive is not None else sickrage.ARCHIVE_DEFAULT
            self.show.paused = self.paused if self.paused is not None else False

            # set up default new/missing episode status
            sickrage.LOGGER.info(
                "Setting all episodes to the specified default status: " +
                str(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 smartish 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 indexer_exception as e:
            sickrage.LOGGER.error("Unable to add show due to an error with " +
                                  sickrage.INDEXER_API(self.indexer).name +
                                  ": {}".format(e))
            if self.show:
                notifications.error("Unable to add " + str(self.show.name) +
                                    " due to an error with " +
                                    sickrage.INDEXER_API(self.indexer).name +
                                    "")
            else:
                notifications.error(
                    "Unable to add show due to an error with " +
                    sickrage.INDEXER_API(self.indexer).name + "")
            self._finishEarly()
            return

        except MultipleShowObjectsException:
            sickrage.LOGGER.warning("The show in " + self.showDir +
                                    " is already in your show list, skipping")
            notifications.error(
                'Show skipped', "The show in " + self.showDir +
                " is already in your show list")
            self._finishEarly()
            return

        except Exception as e:
            sickrage.LOGGER.error("Error trying to add show: {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())
            self._finishEarly()
            raise

        sickrage.LOGGER.debug("Retrieving show info from TMDb")
        try:
            self.show.loadTMDbInfo()
        except Exception as e:
            sickrage.LOGGER.error("Error loading TMDb info: {}".format(e))
            try:
                sickrage.LOGGER.debug(
                    "Attempting to retrieve show info from IMDb")
                self.show.loadIMDbInfo()
            except Exception as e:
                sickrage.LOGGER.error("Error loading IMDb info: {}".format(e))

        try:
            self.show.saveToDB()
        except Exception as e:
            sickrage.LOGGER.error(
                "Error saving the show to the database: {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())
            self._finishEarly()
            raise

        # add it to the show list
        sickrage.showList.append(self.show)

        try:
            self.show.loadEpisodesFromIndexer()
        except Exception as e:
            sickrage.LOGGER.error(
                "Error with " + sickrage.INDEXER_API(self.show.indexer).name +
                ", not creating episode list: {}".format(e))
            sickrage.LOGGER.debug(traceback.format_exc())

        # update internal name cache
        sickrage.NAMECACHE.buildNameCache()

        try:
            self.show.loadEpisodesFromDir()
        except Exception as e:
            sickrage.LOGGER.error(
                "Error searching dir for episodes: {}".format(e))
            sickrage.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:
            sickrage.LOGGER.info(
                "Launching backlog for this show since its episodes are WANTED"
            )
            sickrage.BACKLOGSEARCHER.searchBacklog([self.show])

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

        self.show.flushEpisodes()

        if sickrage.USE_TRAKT:
            # if there are specific episodes that need to be added by trakt
            sickrage.TRAKTSEARCHER.manageNewShow(self.show)

            # add show to trakt.tv library
            if sickrage.TRAKT_SYNC:
                sickrage.TRAKTSEARCHER.addShowToTraktLibrary(self.show)

            if sickrage.TRAKT_SYNC_WATCHLIST:
                sickrage.LOGGER.info("update watchlist")
                sickrage.NOTIFIERS.trakt_notifier.update_watchlist(
                    show_obj=self.show)

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

        # check if show has XEM mapping so we can determin if searches should go by scene numbering or indexer numbering.
        if not self.scene and 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

        self.finish()
Exemple #19
0
    def _season_banners_dict(show_obj, season):
        """
        Should return a dict like:

        result = {<season number>:
                    {1: '<url 1>', 2: <url 2>, ...},}
        """

        # This holds our resulting dictionary of season art
        result = {}

        indexer_lang = show_obj.lang

        try:
            # There's gotta be a better way of doing this but we don't wanna
            # change the language value elsewhere
            lINDEXER_API_PARMS = sickrage.INDEXER_API(
                show_obj.indexer).api_params.copy()

            lINDEXER_API_PARMS[b'banners'] = True

            if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
                lINDEXER_API_PARMS[b'language'] = indexer_lang

            t = sickrage.INDEXER_API(
                show_obj.indexer).indexer(**lINDEXER_API_PARMS)
            indexer_show_obj = t[show_obj.indexerid]
        except (indexer_error, IOError) as e:
            sickrage.LOGGER.warning(
                "Unable to look up show on " +
                sickrage.INDEXER_API(show_obj.indexer).name +
                ", not downloading images: {}".format(e))
            sickrage.LOGGER.debug(
                "Indexer " + sickrage.INDEXER_API(show_obj.indexer).name +
                " maybe experiencing some problems. Try again later")
            return result

        # if we have no season banners then just finish
        if not getattr(indexer_show_obj, '_banners', None):
            return result

        # if we have no season banners then just finish
        if 'season' not in indexer_show_obj[
                b'_banners'] or 'seasonwide' not in indexer_show_obj[
                    b'_banners'][b'season']:
            return result

        # Give us just the normal season graphics
        seasonsArtObj = indexer_show_obj[b'_banners'][b'season'][b'seasonwide']

        # Returns a nested dictionary of season art with the season
        # number as primary key. It's really overkill but gives the option
        # to present to user via ui to pick down the road.

        result[season] = {}

        # find the correct season in the TVDB object and just copy the dict into our result dict
        for seasonArtID in seasonsArtObj.keys():
            if int(seasonsArtObj[seasonArtID]
                   [b'season']) == season and seasonsArtObj[seasonArtID][
                       b'language'] == sickrage.INDEXER_DEFAULT_LANGUAGE:
                result[season][seasonArtID] = seasonsArtObj[seasonArtID][
                    b'_bannerpath']

        return result
Exemple #20
0
    def _retrieve_show_image(self, image_type, show_obj, which=None):
        """
        Gets an image URL from theTVDB.com and TMDB.com, downloads it and returns the data.

        image_type: type of image to retrieve (currently supported: fanart, poster, banner)
        show_obj: a TVShow object to use when searching for the image
        which: optional, a specific numbered poster to look for

        Returns: the binary image data if available, or else None
        """
        image_url = None
        indexer_lang = show_obj.lang

        try:
            # There's gotta be a better way of doing this but we don't wanna
            # change the language value elsewhere
            lINDEXER_API_PARMS = sickrage.INDEXER_API(
                show_obj.indexer).api_params.copy()

            lINDEXER_API_PARMS[b'banners'] = True

            if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
                lINDEXER_API_PARMS[b'language'] = indexer_lang

            if show_obj.dvdorder != 0:
                lINDEXER_API_PARMS[b'dvdorder'] = True

            t = sickrage.INDEXER_API(
                show_obj.indexer).indexer(**lINDEXER_API_PARMS)
            indexer_show_obj = t[show_obj.indexerid]
        except (indexer_error, IOError) as e:
            sickrage.LOGGER.warning(
                "Unable to look up show on " +
                sickrage.INDEXER_API(show_obj.indexer).name +
                ", not downloading images: {}".format(e))
            sickrage.LOGGER.debug(
                "Indexer " + sickrage.INDEXER_API(show_obj.indexer).name +
                " maybe experiencing some problems. Try again later")
            return None

        if image_type not in ('fanart', 'poster', 'banner', 'poster_thumb',
                              'banner_thumb'):
            sickrage.LOGGER.error("Invalid image type " + str(image_type) +
                                  ", couldn't find it in the " +
                                  sickrage.INDEXER_API(show_obj.indexer).name +
                                  " object")
            return None

        if image_type == 'poster_thumb':
            if getattr(indexer_show_obj, 'poster', None):
                image_url = re.sub('posters', '_cache/posters',
                                   indexer_show_obj[b'poster'])
            if not image_url:
                # Try and get images from Fanart.TV
                image_url = self._retrieve_show_images_from_fanart(
                    show_obj, image_type)
            if not image_url:
                # Try and get images from TMDB
                image_url = self._retrieve_show_images_from_tmdb(
                    show_obj, image_type)
        elif image_type == 'banner_thumb':
            if getattr(indexer_show_obj, 'banner', None):
                image_url = re.sub('graphical', '_cache/graphical',
                                   indexer_show_obj[b'banner'])
            if not image_url:
                # Try and get images from Fanart.TV
                image_url = self._retrieve_show_images_from_fanart(
                    show_obj, image_type)
        else:
            if getattr(indexer_show_obj, image_type, None):
                image_url = indexer_show_obj[image_type]
            if not image_url:
                # Try and get images from Fanart.TV
                image_url = self._retrieve_show_images_from_fanart(
                    show_obj, image_type)
            if not image_url:
                # Try and get images from TMDB
                image_url = self._retrieve_show_images_from_tmdb(
                    show_obj, image_type)

        if image_url:
            image_data = metadata_helpers.getShowImage(image_url, which)
            return image_data

        return None
Exemple #21
0
def retrieve_exceptions():
    """
    Looks up the exceptions on github, parses them into a dict, and inserts them into the
    scene_exceptions table in cache.db. Also clears the scene name cache.
    """

    for indexer in sickrage.INDEXER_API().indexers:
        if shouldRefresh(sickrage.INDEXER_API(indexer).name):
            sickrage.LOGGER.info("Checking for scene exception updates for " +
                                 sickrage.INDEXER_API(indexer).name + "")

            loc = sickrage.INDEXER_API(indexer).config[b'scene_loc']
            try:
                data = getURL(loc,
                              session=sickrage.INDEXER_API(indexer).session)
            except Exception:
                continue

            if data is None:
                # When data is None, trouble connecting to github, or reading file failed
                sickrage.LOGGER.debug(
                    "Check scene exceptions update failed. Unable to update from: "
                    + loc)
                continue

            setLastRefresh(sickrage.INDEXER_API(indexer).name)

            # each exception is on one line with the format indexer_id: 'show name 1', 'show name 2', etc
            for cur_line in data.splitlines():
                indexer_id, _, aliases = cur_line.partition(
                    ':')  # @UnusedVariable

                if not aliases:
                    continue

                indexer_id = int(indexer_id)

                # regex out the list of shows, taking \' into account
                # alias_list = [re.sub(r'\\(.)', r'\1', x) for x in re.findall(r"'(.*?)(?<!\\)',?", aliases)]
                alias_list = [{
                    re.sub(r'\\(.)', r'\1', x): -1
                } for x in re.findall(r"'(.*?)(?<!\\)',?", aliases)]
                exception_dict[indexer_id] = alias_list
                del alias_list

            # cleanup
            del data

    # XEM scene exceptions
    _xem_exceptions_fetcher()
    for xem_ex in xem_exception_dict:
        if xem_ex in exception_dict:
            exception_dict[
                xem_ex] = exception_dict[xem_ex] + xem_exception_dict[xem_ex]
        else:
            exception_dict[xem_ex] = xem_exception_dict[xem_ex]

    # AniDB scene exceptions
    _anidb_exceptions_fetcher()
    for anidb_ex in anidb_exception_dict:
        if anidb_ex in exception_dict:
            exception_dict[anidb_ex] = exception_dict[
                anidb_ex] + anidb_exception_dict[anidb_ex]
        else:
            exception_dict[anidb_ex] = anidb_exception_dict[anidb_ex]

    queries = []
    for cur_indexer_id in exception_dict:
        sql_ex = cache_db.CacheDB().select(
            "SELECT * FROM scene_exceptions WHERE indexer_id = ?;",
            [cur_indexer_id])
        existing_exceptions = [x[b"show_name"] for x in sql_ex]
        if not cur_indexer_id in exception_dict:
            continue

        for cur_exception_dict in exception_dict[cur_indexer_id]:
            for ex in cur_exception_dict.iteritems():
                cur_exception, curSeason = ex
                if cur_exception not in existing_exceptions:
                    queries.append([
                        "INSERT OR IGNORE INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?);",
                        [cur_indexer_id, cur_exception, curSeason]
                    ])
    if queries:
        cache_db.CacheDB().mass_action(queries)
        sickrage.LOGGER.debug("Updated scene exceptions")
    else:
        sickrage.LOGGER.debug("No scene exceptions update needed")

    # cleanup
    exception_dict.clear()
    anidb_exception_dict.clear()
    xem_exception_dict.clear()
Exemple #22
0
    def _ep_data(self, ep_obj):
        """
        Creates an elementTree XML structure for a WDTV style episode.xml
        and returns the resulting data object.

        ep_obj: a TVShow instance to create the NFO for
        """

        eps_to_write = [ep_obj] + ep_obj.relatedEps

        indexer_lang = ep_obj.show.lang

        try:
            lINDEXER_API_PARMS = sickrage.INDEXER_API(
                ep_obj.show.indexer).api_params.copy()

            lINDEXER_API_PARMS[b'actors'] = True

            if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
                lINDEXER_API_PARMS[b'language'] = indexer_lang

            if ep_obj.show.dvdorder != 0:
                lINDEXER_API_PARMS[b'dvdorder'] = True

            t = sickrage.INDEXER_API(
                ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS)
            myShow = t[ep_obj.show.indexerid]
        except indexer_shownotfound as e:
            raise ShowNotFoundException(e.message)
        except indexer_error as e:
            sickrage.LOGGER.error(
                "Unable to connect to " +
                sickrage.INDEXER_API(ep_obj.show.indexer).name +
                " while creating meta files - skipping - {}".format(e))
            return False

        rootNode = Element("details")

        # write an WDTV XML containing info for all matching episodes
        for curEpToWrite in eps_to_write:

            try:
                myEp = myShow[curEpToWrite.season][curEpToWrite.episode]
            except (indexer_episodenotfound, indexer_seasonnotfound):
                sickrage.LOGGER.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?"
                    % (curEpToWrite.season, curEpToWrite.episode,
                       sickrage.INDEXER_API(ep_obj.show.indexer).name))
                return None

            if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None):
                myEp[b"firstaired"] = str(datetime.date.fromordinal(1))

            if not (getattr(myEp, 'episodename', None)
                    and getattr(myEp, 'firstaired', None)):
                return None

            if len(eps_to_write) > 1:
                episode = SubElement(rootNode, "details")
            else:
                episode = rootNode

            # TODO: get right EpisodeID
            episodeID = SubElement(episode, "id")
            episodeID.text = str(curEpToWrite.indexerid)

            title = SubElement(episode, "title")
            title.text = ep_obj.prettyName()

            if getattr(myShow, 'seriesname', None):
                seriesName = SubElement(episode, "series_name")
                seriesName.text = myShow[b"seriesname"]

            if curEpToWrite.name:
                episodeName = SubElement(episode, "episode_name")
                episodeName.text = curEpToWrite.name

            seasonNumber = SubElement(episode, "season_number")
            seasonNumber.text = str(curEpToWrite.season)

            episodeNum = SubElement(episode, "episode_number")
            episodeNum.text = str(curEpToWrite.episode)

            firstAired = SubElement(episode, "firstaired")

            if curEpToWrite.airdate != datetime.date.fromordinal(1):
                firstAired.text = str(curEpToWrite.airdate)

            if getattr(myShow, 'firstaired', None):
                try:
                    year_text = str(
                        datetime.datetime.strptime(myShow[b"firstaired"],
                                                   dateFormat).year)
                    if year_text:
                        year = SubElement(episode, "year")
                        year.text = year_text
                except Exception:
                    pass

            if curEpToWrite.season != 0 and getattr(myShow, 'runtime', None):
                runtime = SubElement(episode, "runtime")
                runtime.text = myShow[b"runtime"]

            if getattr(myShow, 'genre', None):
                genre = SubElement(episode, "genre")
                genre.text = " / ".join([
                    x.strip() for x in myShow[b"genre"].split('|')
                    if x.strip()
                ])

            if getattr(myEp, 'director', None):
                director = SubElement(episode, "director")
                director.text = myEp[b'director']

            if getattr(myShow, '_actors', None):
                for actor in myShow[b'_actors']:
                    if not ('name' in actor and actor[b'name'].strip()):
                        continue

                    cur_actor = SubElement(episode, "actor")

                    cur_actor_name = SubElement(cur_actor, "name")
                    cur_actor_name.text = actor[b'name']

                    if 'role' in actor and actor[b'role'].strip():
                        cur_actor_role = SubElement(cur_actor, "role")
                        cur_actor_role.text = actor[b'role'].strip()

            if curEpToWrite.description:
                overview = SubElement(episode, "overview")
                overview.text = curEpToWrite.description

        # Make it purdy
        indentXML(rootNode)
        data = ElementTree(rootNode)
        return data
Exemple #23
0
def fix_xem_numbering(indexer_id, indexer):
    """
    Returns a dict of (season, episode) : (sceneSeason, sceneEpisode) mappings
    for an entire show.  Both the keys and values of the dict are tuples.
    Will be empty if there are no scene numbers set in xem
    """
    if indexer_id is None:
        return {}

    indexer_id = int(indexer_id)
    indexer = int(indexer)

    rows = main_db.MainDB().select(
        'SELECT season, episode, absolute_number, scene_season, scene_episode, scene_absolute_number FROM tv_episodes WHERE indexer = ? AND showid = ?',
        [indexer, indexer_id])

    last_absolute_number = None
    last_scene_season = None
    last_scene_episode = None
    last_scene_absolute_number = None

    update_absolute_number = False
    update_scene_season = False
    update_scene_episode = False
    update_scene_absolute_number = False

    sickrage.LOGGER.debug(
        'Fixing any XEM scene mapping issues for show %s on %s' %
        (indexer_id, sickrage.INDEXER_API(indexer).name))

    cl = []
    for row in rows:
        season = int(row[b'season'])
        episode = int(row[b'episode'])

        if not int(row[b'scene_season']) and last_scene_season:
            scene_season = last_scene_season + 1
            update_scene_season = True
        else:
            scene_season = int(row[b'scene_season'])
            if last_scene_season and scene_season < last_scene_season:
                scene_season = last_scene_season + 1
                update_scene_season = True

        if not int(row[b'scene_episode']) and last_scene_episode:
            scene_episode = last_scene_episode + 1
            update_scene_episode = True
        else:
            scene_episode = int(row[b'scene_episode'])
            if last_scene_episode and scene_episode < last_scene_episode:
                scene_episode = last_scene_episode + 1
                update_scene_episode = True

        # check for unset values and correct them
        if not int(row[b'absolute_number']) and last_absolute_number:
            absolute_number = last_absolute_number + 1
            update_absolute_number = True
        else:
            absolute_number = int(row[b'absolute_number'])
            if last_absolute_number and absolute_number < last_absolute_number:
                absolute_number = last_absolute_number + 1
                update_absolute_number = True

        if not int(
                row[b'scene_absolute_number']) and last_scene_absolute_number:
            scene_absolute_number = last_scene_absolute_number + 1
            update_scene_absolute_number = True
        else:
            scene_absolute_number = int(row[b'scene_absolute_number'])
            if last_scene_absolute_number and scene_absolute_number < last_scene_absolute_number:
                scene_absolute_number = last_scene_absolute_number + 1
                update_scene_absolute_number = True

        # store values for lookup on next iteration
        last_absolute_number = absolute_number
        last_scene_season = scene_season
        last_scene_episode = scene_episode
        last_scene_absolute_number = scene_absolute_number

        if update_absolute_number:
            cl.append([
                "UPDATE tv_episodes SET absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?",
                [absolute_number, indexer_id, season, episode]
            ])
            update_absolute_number = False

        if update_scene_season:
            cl.append([
                "UPDATE tv_episodes SET scene_season = ? WHERE showid = ? AND season = ? AND episode = ?",
                [scene_season, indexer_id, season, episode]
            ])
            update_scene_season = False

        if update_scene_episode:
            cl.append([
                "UPDATE tv_episodes SET scene_episode = ? WHERE showid = ? AND season = ? AND episode = ?",
                [scene_episode, indexer_id, season, episode]
            ])
            update_scene_episode = False

        if update_scene_absolute_number:
            cl.append([
                "UPDATE tv_episodes SET scene_absolute_number = ? WHERE showid = ? AND season = ? AND episode = ?",
                [scene_absolute_number, indexer_id, season, episode]
            ])
            update_scene_absolute_number = False

    if len(cl) > 0:
        main_db.MainDB().mass_action(cl)
Exemple #24
0
    def _show_data(self, show_obj):
        """
        Creates an elementTree XML structure for a MediaBrowser-style series.xml
        returns the resulting data object.

        show_obj: a TVShow instance to create the NFO for
        """

        indexer_lang = show_obj.lang
        # There's gotta be a better way of doing this but we don't wanna
        # change the language value elsewhere
        lINDEXER_API_PARMS = sickrage.INDEXER_API(show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS[b'actors'] = True

        if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
            lINDEXER_API_PARMS[b'language'] = indexer_lang

        if show_obj.dvdorder != 0:
            lINDEXER_API_PARMS[b'dvdorder'] = True

        t = sickrage.INDEXER_API(show_obj.indexer).indexer(**lINDEXER_API_PARMS)

        tv_node = Element("Series")

        try:
            myShow = t[int(show_obj.indexerid)]
        except indexer_shownotfound:
            sickrage.LOGGER.error("Unable to find show with id " + str(show_obj.indexerid) + " on " + sickrage.INDEXER_API(
                    show_obj.indexer).name + ", skipping it")
            raise

        except indexer_error:
            sickrage.LOGGER.error(
                    "" + sickrage.INDEXER_API(show_obj.indexer).name + " is down, can't use its data to make the NFO")
            raise

        # check for title and id
        if not (getattr(myShow, 'seriesname', None) and getattr(myShow, 'id', None)):
            sickrage.LOGGER.info("Incomplete info for show with id " + str(show_obj.indexerid) + " on " + sickrage.INDEXER_API(
                    show_obj.indexer).name + ", skipping it")
            return False

        if getattr(myShow, 'id', None):
            indexerid = SubElement(tv_node, "id")
            indexerid.text = str(myShow[b'id'])

        if getattr(myShow, 'seriesname', None):
            SeriesName = SubElement(tv_node, "SeriesName")
            SeriesName.text = myShow[b'seriesname']

        if getattr(myShow, 'status', None):
            Status = SubElement(tv_node, "Status")
            Status.text = myShow[b'status']

        if getattr(myShow, 'network', None):
            Network = SubElement(tv_node, "Network")
            Network.text = myShow[b'network']

        if getattr(myShow, 'airs_time', None):
            Airs_Time = SubElement(tv_node, "Airs_Time")
            Airs_Time.text = myShow[b'airs_time']

        if getattr(myShow, 'airs_dayofweek', None):
            Airs_DayOfWeek = SubElement(tv_node, "Airs_DayOfWeek")
            Airs_DayOfWeek.text = myShow[b'airs_dayofweek']

        FirstAired = SubElement(tv_node, "FirstAired")
        if getattr(myShow, 'firstaired', None):
            FirstAired.text = myShow[b'firstaired']

        if getattr(myShow, 'contentrating', None):
            ContentRating = SubElement(tv_node, "ContentRating")
            ContentRating.text = myShow[b'contentrating']

            MPAARating = SubElement(tv_node, "MPAARating")
            MPAARating.text = myShow[b'contentrating']

            certification = SubElement(tv_node, "certification")
            certification.text = myShow[b'contentrating']

        MetadataType = SubElement(tv_node, "Type")
        MetadataType.text = "Series"

        if getattr(myShow, 'overview', None):
            Overview = SubElement(tv_node, "Overview")
            Overview.text = myShow[b'overview']

        if getattr(myShow, 'firstaired', None):
            PremiereDate = SubElement(tv_node, "PremiereDate")
            PremiereDate.text = myShow[b'firstaired']

        if getattr(myShow, 'rating', None):
            Rating = SubElement(tv_node, "Rating")
            Rating.text = myShow[b'rating']

        if getattr(myShow, 'firstaired', None):
            try:
                year_text = str(datetime.datetime.strptime(myShow[b'firstaired'], dateFormat).year)
                if year_text:
                    ProductionYear = SubElement(tv_node, "ProductionYear")
                    ProductionYear.text = year_text
            except Exception:
                pass

        if getattr(myShow, 'runtime', None):
            RunningTime = SubElement(tv_node, "RunningTime")
            RunningTime.text = myShow[b'runtime']

            Runtime = SubElement(tv_node, "Runtime")
            Runtime.text = myShow[b'runtime']

        if getattr(myShow, 'imdb_id', None):
            imdb_id = SubElement(tv_node, "IMDB_ID")
            imdb_id.text = myShow[b'imdb_id']

            imdb_id = SubElement(tv_node, "IMDB")
            imdb_id.text = myShow[b'imdb_id']

            imdb_id = SubElement(tv_node, "IMDbId")
            imdb_id.text = myShow[b'imdb_id']

        if getattr(myShow, 'zap2it_id', None):
            Zap2ItId = SubElement(tv_node, "Zap2ItId")
            Zap2ItId.text = myShow[b'zap2it_id']

        if getattr(myShow, 'genre', None) and isinstance(myShow[b"genre"], basestring):
            Genres = SubElement(tv_node, "Genres")
            for genre in myShow[b'genre'].split('|'):
                if genre.strip():
                    cur_genre = SubElement(Genres, "Genre")
                    cur_genre.text = genre.strip()

            Genre = SubElement(tv_node, "Genre")
            Genre.text = "|".join([x.strip() for x in myShow[b"genre"].split('|') if x.strip()])

        if getattr(myShow, 'network', None):
            Studios = SubElement(tv_node, "Studios")
            Studio = SubElement(Studios, "Studio")
            Studio.text = myShow[b'network']

        if getattr(myShow, '_actors', None):
            Persons = SubElement(tv_node, "Persons")
            for actor in myShow[b'_actors']:
                if not ('name' in actor and actor[b'name'].strip()):
                    continue

                cur_actor = SubElement(Persons, "Person")

                cur_actor_name = SubElement(cur_actor, "Name")
                cur_actor_name.text = actor[b'name'].strip()

                cur_actor_type = SubElement(cur_actor, "Type")
                cur_actor_type.text = "Actor"

                if 'role' in actor and actor[b'role'].strip():
                    cur_actor_role = SubElement(cur_actor, "Role")
                    cur_actor_role.text = actor[b'role'].strip()

        indentXML(tv_node)

        data = ElementTree(tv_node)

        return data
Exemple #25
0
    def _ep_data(self, ep_obj):
        """
        Creates an elementTree XML structure for an KODI-style episode.nfo and
        returns the resulting data object.
            show_obj: a TVEpisode instance to create the NFO for
        """

        eps_to_write = [ep_obj] + ep_obj.relatedEps

        indexer_lang = ep_obj.show.lang

        lINDEXER_API_PARMS = sickrage.INDEXER_API(
            ep_obj.show.indexer).api_params.copy()

        lINDEXER_API_PARMS[b'actors'] = True

        if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
            lINDEXER_API_PARMS[b'language'] = indexer_lang

        if ep_obj.show.dvdorder != 0:
            lINDEXER_API_PARMS[b'dvdorder'] = True

        try:
            t = sickrage.INDEXER_API(
                ep_obj.show.indexer).indexer(**lINDEXER_API_PARMS)
            myShow = t[ep_obj.show.indexerid]
        except indexer_shownotfound as e:
            raise ShowNotFoundException(e.message)
        except indexer_error as e:
            sickrage.LOGGER.error(
                "Unable to connect to {} while creating meta files - skipping - {}"
                .format(sickrage.INDEXER_API(ep_obj.show.indexer).name, e))
            return

        if len(eps_to_write) > 1:
            rootNode = Element("kodimultiepisode")
        else:
            rootNode = Element("episodedetails")

        # write an NFO containing info for all matching episodes
        for curEpToWrite in eps_to_write:

            try:
                myEp = myShow[curEpToWrite.season][curEpToWrite.episode]
            except (indexer_episodenotfound, indexer_seasonnotfound):
                sickrage.LOGGER.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?"
                    % (curEpToWrite.season, curEpToWrite.episode,
                       sickrage.INDEXER_API(ep_obj.show.indexer).name))
                return None

            if not getattr(myEp, 'firstaired', None):
                myEp[b"firstaired"] = str(datetime.date.fromordinal(1))

            if not getattr(myEp, 'episodename', None):
                sickrage.LOGGER.debug(
                    "Not generating nfo because the ep has no title")
                return None

            sickrage.LOGGER.debug("Creating metadata for episode " +
                                  str(ep_obj.season) + "x" +
                                  str(ep_obj.episode))

            if len(eps_to_write) > 1:
                episode = SubElement(rootNode, "episodedetails")
            else:
                episode = rootNode

            if getattr(myEp, 'episodename', None):
                title = SubElement(episode, "title")
                title.text = myEp[b'episodename']

            if getattr(myShow, 'seriesname', None):
                showtitle = SubElement(episode, "showtitle")
                showtitle.text = myShow[b'seriesname']

            season = SubElement(episode, "season")
            season.text = str(curEpToWrite.season)

            episodenum = SubElement(episode, "episode")
            episodenum.text = str(curEpToWrite.episode)

            uniqueid = SubElement(episode, "uniqueid")
            uniqueid.text = str(curEpToWrite.indexerid)

            if curEpToWrite.airdate != datetime.date.fromordinal(1):
                aired = SubElement(episode, "aired")
                aired.text = str(curEpToWrite.airdate)

            if getattr(myEp, 'overview', None):
                plot = SubElement(episode, "plot")
                plot.text = myEp[b'overview']

            if curEpToWrite.season and getattr(myShow, 'runtime', None):
                runtime = SubElement(episode, "runtime")
                runtime.text = myShow[b"runtime"]

            if getattr(myEp, 'airsbefore_season', None):
                displayseason = SubElement(episode, "displayseason")
                displayseason.text = myEp[b'airsbefore_season']

            if getattr(myEp, 'airsbefore_episode', None):
                displayepisode = SubElement(episode, "displayepisode")
                displayepisode.text = myEp[b'airsbefore_episode']

            if getattr(myEp, 'filename', None):
                thumb = SubElement(episode, "thumb")
                thumb.text = myEp[b'filename'].strip()

            # watched = SubElement(episode, "watched")
            # watched.text = 'false'

            if getattr(myEp, 'writer', None):
                ep_credits = SubElement(episode, "credits")
                ep_credits.text = myEp[b'writer'].strip()

            if getattr(myEp, 'director', None):
                director = SubElement(episode, "director")
                director.text = myEp[b'director'].strip()

            if getattr(myEp, 'rating', None):
                rating = SubElement(episode, "rating")
                rating.text = myEp[b'rating']

            if getattr(myEp, 'gueststars', None) and isinstance(
                    myEp[b'gueststars'], basestring):
                for actor in (x.strip() for x in myEp[b'gueststars'].split('|')
                              if x.strip()):
                    cur_actor = SubElement(episode, "actor")
                    cur_actor_name = SubElement(cur_actor, "name")
                    cur_actor_name.text = actor

            if getattr(myShow, '_actors', None):
                for actor in myShow[b'_actors']:
                    cur_actor = SubElement(episode, "actor")

                    if 'name' in actor and actor[b'name'].strip():
                        cur_actor_name = SubElement(cur_actor, "name")
                        cur_actor_name.text = actor[b'name'].strip()
                    else:
                        continue

                    if 'role' in actor and actor[b'role'].strip():
                        cur_actor_role = SubElement(cur_actor, "role")
                        cur_actor_role.text = actor[b'role'].strip()

                    if 'image' in actor and actor[b'image'].strip():
                        cur_actor_thumb = SubElement(cur_actor, "thumb")
                        cur_actor_thumb.text = actor[b'image'].strip()

        # Make it purdy
        indentXML(rootNode)
        data = ElementTree(rootNode)
        return data
Exemple #26
0
    def _show_data(self, show_obj):
        """
        Creates an elementTree XML structure for a MediaBrowser-style series.xml
        returns the resulting data object.

        show_obj: a TVShow instance to create the NFO for
        """

        indexer_lang = show_obj.lang
        lINDEXER_API_PARMS = sickrage.INDEXER_API(
            show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS[b'actors'] = True

        if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
            lINDEXER_API_PARMS[b'language'] = indexer_lang

        if show_obj.dvdorder != 0:
            lINDEXER_API_PARMS[b'dvdorder'] = True

        t = sickrage.INDEXER_API(
            show_obj.indexer).indexer(**lINDEXER_API_PARMS)

        rootNode = Element("details")
        tv_node = SubElement(rootNode, "movie")
        tv_node.attrib[b"isExtra"] = "false"
        tv_node.attrib[b"isSet"] = "false"
        tv_node.attrib[b"isTV"] = "true"

        try:
            myShow = t[int(show_obj.indexerid)]
        except indexer_shownotfound:
            sickrage.LOGGER.error("Unable to find show with id " +
                                  str(show_obj.indexerid) +
                                  " on tvdb, skipping it")
            raise

        except indexer_error:
            sickrage.LOGGER.error(
                "TVDB is down, can't use its data to make the NFO")
            raise

        # check for title and id
        if not (getattr(myShow, 'seriesname', None)
                and getattr(myShow, 'id', None)):
            sickrage.LOGGER.info("Incomplete info for show with id " +
                                 str(show_obj.indexerid) + " on " +
                                 sickrage.INDEXER_API(show_obj.indexer).name +
                                 ", skipping it")
            return False

        SeriesName = SubElement(tv_node, "title")
        SeriesName.text = myShow[b'seriesname']

        if getattr(myShow, "genre", None):
            Genres = SubElement(tv_node, "genres")
            for genre in myShow[b'genre'].split('|'):
                if genre and genre.strip():
                    cur_genre = SubElement(Genres, "Genre")
                    cur_genre.text = genre.strip()

        if getattr(myShow, 'firstaired', None):
            FirstAired = SubElement(tv_node, "premiered")
            FirstAired.text = myShow[b'firstaired']

        if getattr(myShow, "firstaired", None):
            try:
                year_text = str(
                    datetime.datetime.strptime(myShow[b"firstaired"],
                                               dateFormat).year)
                if year_text:
                    year = SubElement(tv_node, "year")
                    year.text = year_text
            except Exception:
                pass

        if getattr(myShow, 'overview', None):
            plot = SubElement(tv_node, "plot")
            plot.text = myShow[b"overview"]

        if getattr(myShow, 'rating', None):
            try:
                rating = int(float(myShow[b'rating']) * 10)
            except ValueError:
                rating = 0

            if rating:
                Rating = SubElement(tv_node, "rating")
                Rating.text = str(rating)

        if getattr(myShow, 'status', None):
            Status = SubElement(tv_node, "status")
            Status.text = myShow[b'status']

        if getattr(myShow, "contentrating", None):
            mpaa = SubElement(tv_node, "mpaa")
            mpaa.text = myShow[b"contentrating"]

        if getattr(myShow, 'imdb_id', None):
            imdb_id = SubElement(tv_node, "id")
            imdb_id.attrib[b"moviedb"] = "imdb"
            imdb_id.text = myShow[b'imdb_id']

        if getattr(myShow, 'id', None):
            indexerid = SubElement(tv_node, "indexerid")
            indexerid.text = myShow[b'id']

        if getattr(myShow, 'runtime', None):
            Runtime = SubElement(tv_node, "runtime")
            Runtime.text = myShow[b'runtime']

        if getattr(myShow, '_actors', None):
            cast = SubElement(tv_node, "cast")
            for actor in myShow[b'_actors']:
                if 'name' in actor and actor[b'name'].strip():
                    cur_actor = SubElement(cast, "actor")
                    cur_actor.text = actor[b'name'].strip()

        indentXML(rootNode)

        data = ElementTree(rootNode)

        return data
Exemple #27
0
    def _show_data(self, show_obj):
        """
        Creates an elementTree XML structure for an KODI-style tvshow.nfo and
        returns the resulting data object.

        show_obj: a TVShow instance to create the NFO for
        """

        show_ID = show_obj.indexerid

        indexer_lang = show_obj.lang
        lINDEXER_API_PARMS = sickrage.INDEXER_API(
            show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS[b'actors'] = True

        if indexer_lang and not indexer_lang == sickrage.INDEXER_DEFAULT_LANGUAGE:
            lINDEXER_API_PARMS[b'language'] = indexer_lang

        if show_obj.dvdorder != 0:
            lINDEXER_API_PARMS[b'dvdorder'] = True

        t = sickrage.INDEXER_API(
            show_obj.indexer).indexer(**lINDEXER_API_PARMS)

        tv_node = Element("tvshow")

        try:
            myShow = t[int(show_ID)]
        except indexer_shownotfound:
            sickrage.LOGGER.error("Unable to find show with id " +
                                  str(show_ID) + " on " +
                                  sickrage.INDEXER_API(show_obj.indexer).name +
                                  ", skipping it")
            raise

        except indexer_error:
            sickrage.LOGGER.error(
                "" + sickrage.INDEXER_API(show_obj.indexer).name +
                " is down, can't use its data to add this show")
            raise

        # check for title and id
        if not (getattr(myShow, 'seriesname', None)
                and getattr(myShow, 'id', None)):
            sickrage.LOGGER.info("Incomplete info for show with id " +
                                 str(show_ID) + " on " +
                                 sickrage.INDEXER_API(show_obj.indexer).name +
                                 ", skipping it")
            return False

        title = SubElement(tv_node, "title")
        title.text = myShow[b"seriesname"]

        if getattr(myShow, 'rating', None):
            rating = SubElement(tv_node, "rating")
            rating.text = myShow[b"rating"]

        if getattr(myShow, 'firstaired', None):
            try:
                year_text = str(
                    datetime.datetime.strptime(myShow[b"firstaired"],
                                               dateFormat).year)
                if year_text:
                    year = SubElement(tv_node, "year")
                    year.text = year_text
            except:
                pass

        if getattr(myShow, 'overview', None):
            plot = SubElement(tv_node, "plot")
            plot.text = myShow[b"overview"]

        if getattr(myShow, 'id', None):
            episodeguide = SubElement(tv_node, "episodeguide")
            episodeguideurl = SubElement(episodeguide, "url")
            episodeguideurl.text = sickrage.INDEXER_API(
                show_obj.indexer).config[b'base_url'] + str(
                    myShow[b"id"]) + '/all/en.zip'

        if getattr(myShow, 'contentrating', None):
            mpaa = SubElement(tv_node, "mpaa")
            mpaa.text = myShow[b"contentrating"]

        if getattr(myShow, 'id', None):
            indexerid = SubElement(tv_node, "id")
            indexerid.text = str(myShow[b"id"])

        if getattr(myShow, 'genre', None) and isinstance(
                myShow[b"genre"], basestring):
            genre = SubElement(tv_node, "genre")
            genre.text = " / ".join(x.strip()
                                    for x in myShow[b"genre"].split('|')
                                    if x.strip())

        if getattr(myShow, 'firstaired', None):
            premiered = SubElement(tv_node, "premiered")
            premiered.text = myShow[b"firstaired"]

        if getattr(myShow, 'network', None):
            studio = SubElement(tv_node, "studio")
            studio.text = myShow[b"network"].strip()

        if getattr(myShow, '_actors', None):
            for actor in myShow[b'_actors']:
                cur_actor = SubElement(tv_node, "actor")

                if 'name' in actor and actor[b'name'].strip():
                    cur_actor_name = SubElement(cur_actor, "name")
                    cur_actor_name.text = actor[b'name'].strip()
                else:
                    continue

                if 'role' in actor and actor[b'role'].strip():
                    cur_actor_role = SubElement(cur_actor, "role")
                    cur_actor_role.text = actor[b'role'].strip()

                if 'image' in actor and actor[b'image'].strip():
                    cur_actor_thumb = SubElement(cur_actor, "thumb")
                    cur_actor_thumb.text = actor[b'image'].strip()

        # Make it purdy
        indentXML(tv_node)

        data = ElementTree(tv_node)

        return data
Exemple #28
0
    def loadFromIndexer(self, season=None, episode=None, cache=True, tvapi=None, cachedSeason=None):

        if season is None:
            season = self.season
        if episode is None:
            episode = self.episode

        sickrage.LOGGER.debug("%s: Loading episode details from %s for episode S%02dE%02d" %
                      (self.show.indexerid, sickrage.INDEXER_API(self.show.indexer).name, season or 0, episode or 0))

        indexer_lang = self.show.lang

        try:
            if cachedSeason is None:
                if tvapi is None:
                    lINDEXER_API_PARMS = sickrage.INDEXER_API(self.indexer).api_params.copy()

                    if not cache:
                        lINDEXER_API_PARMS[b'cache'] = False

                    if indexer_lang:
                        lINDEXER_API_PARMS[b'language'] = indexer_lang

                    if self.show.dvdorder != 0:
                        lINDEXER_API_PARMS[b'dvdorder'] = True

                    t = sickrage.INDEXER_API(self.indexer).indexer(**lINDEXER_API_PARMS)
                else:
                    t = tvapi
                myEp = t[self.show.indexerid][season][episode]
            else:
                myEp = cachedSeason[episode]

        except (indexer_error, IOError) as e:
            sickrage.LOGGER.debug("" + sickrage.INDEXER_API(self.indexer).name + " threw up an error: {}".format(e))
            # if the episode is already valid just log it, if not throw it up
            if self.name:
                sickrage.LOGGER.debug("" + sickrage.INDEXER_API(
                        self.indexer).name + " timed out but we have enough info from other sources, allowing the error")
                return
            else:
                sickrage.LOGGER.error("" + sickrage.INDEXER_API(self.indexer).name + " timed out, unable to create the episode")
                return False
        except (indexer_episodenotfound, indexer_seasonnotfound):
            sickrage.LOGGER.debug("Unable to find the episode on " + sickrage.INDEXER_API(
                    self.indexer).name + "... has it been removed? Should I delete from db?")
            # if I'm no longer on the Indexers but I once was then delete myself from the DB
            if self.indexerid != -1:
                self.deleteEpisode()
            return

        if getattr(myEp, 'episodename', None) is None:
            sickrage.LOGGER.info("This episode %s - S%02dE%02d has no name on %s. Setting to an empty string" % (
                self.show.name, season or 0, episode or 0, sickrage.INDEXER_API(self.indexer).name))
            setattr(myEp, 'episodename', '')
            # # if I'm incomplete on TVDB but I once was complete then just delete myself from the DB for now
            # if self.indexerid != -1:
            #     self.deleteEpisode()
            # return False

        if getattr(myEp, 'absolute_number', None) is None:
            sickrage.LOGGER.debug("This episode %s - S%02dE%02d has no absolute number on %s" % (
                self.show.name, season or 0, episode or 0, sickrage.INDEXER_API(self.indexer).name))
        else:
            sickrage.LOGGER.debug("%s: The absolute_number for S%02dE%02d is: %s " % (
                self.show.indexerid, season or 0, episode or 0, myEp[b"absolute_number"]))
            self.absolute_number = int(myEp[b"absolute_number"])

        self.name = getattr(myEp, 'episodename', "")
        self.season = season
        self.episode = episode

        xem_refresh(self.show.indexerid, self.show.indexer)

        self.scene_absolute_number = get_scene_absolute_numbering(
                self.show.indexerid,
                self.show.indexer,
                self.absolute_number
        )

        self.scene_season, self.scene_episode = get_scene_numbering(
                self.show.indexerid,
                self.show.indexer,
                self.season, self.episode
        )

        self.description = getattr(myEp, 'overview', "")

        firstaired = getattr(myEp, 'firstaired', None)
        if not firstaired or firstaired == "0000-00-00":
            firstaired = str(datetime.date.fromordinal(1))
        rawAirdate = [int(x) for x in firstaired.split("-")]

        try:
            self.airdate = datetime.date(rawAirdate[0], rawAirdate[1], rawAirdate[2])
        except (ValueError, IndexError):
            sickrage.LOGGER.warning("Malformed air date of %s retrieved from %s for (%s - S%02dE%02d)" % (
                firstaired, sickrage.INDEXER_API(self.indexer).name, self.show.name, season or 0, episode or 0))
            # if I'm incomplete on the indexer but I once was complete then just delete myself from the DB for now
            if self.indexerid != -1:
                self.deleteEpisode()
            return False

        # early conversion to int so that episode doesn't get marked dirty
        self.indexerid = getattr(myEp, 'id', None)
        if self.indexerid is None:
            sickrage.LOGGER.error("Failed to retrieve ID from " + sickrage.INDEXER_API(self.indexer).name)
            if self.indexerid != -1:
                self.deleteEpisode()
            return False

        # don't update show status if show dir is missing, unless it's missing on purpose
        if not os.path.isdir(
                self.show._location) and not sickrage.CREATE_MISSING_SHOW_DIRS and not sickrage.ADD_SHOWS_WO_DIR:
            sickrage.LOGGER.info(
                    "The show dir %s is missing, not bothering to change the episode statuses since it'd probably be invalid" % self.show._location)
            return

        if self.location:
            sickrage.LOGGER.debug("%s: Setting status for S%02dE%02d based on status %s and location %s" %
                          (self.show.indexerid, season or 0, episode or 0, statusStrings[self.status],
                           self.location))

        if not os.path.isfile(self.location):
            if self.airdate >= datetime.date.today() or self.airdate == datetime.date.fromordinal(1):
                sickrage.LOGGER.debug("Episode airs in the future or has no airdate, marking it %s" % statusStrings[
                    UNAIRED])
                self.status = UNAIRED
            elif self.status in [UNAIRED, UNKNOWN]:
                # Only do UNAIRED/UNKNOWN, it could already be snatched/ignored/skipped, or downloaded/archived to disconnected media
                sickrage.LOGGER.debug(
                    "Episode has already aired, marking it %s" % statusStrings[self.show.default_ep_status])
                self.status = self.show.default_ep_status if self.season > 0 else SKIPPED  # auto-skip specials
            else:
                sickrage.LOGGER.debug(
                        "Not touching status [ %s ] It could be skipped/ignored/snatched/archived" % statusStrings[
                            self.status])

        # if we have a media file then it's downloaded
        elif isMediaFile(self.location):
            # leave propers alone, you have to either post-process them or manually change them back
            if self.status not in Quality.SNATCHED_PROPER + Quality.DOWNLOADED + Quality.SNATCHED + Quality.ARCHIVED:
                sickrage.LOGGER.debug(
                        "5 Status changes from " + str(self.status) + " to " + str(
                                Quality.statusFromName(self.location)))
                self.status = Quality.statusFromName(self.location, anime=self.show.is_anime)

        # shouldn't get here probably
        else:
            sickrage.LOGGER.debug("6 Status changes from " + str(self.status) + " to " + str(UNKNOWN))
            self.status = UNKNOWN