示例#1
0
def _xem_exceptions_fetcher():
    if shouldRefresh('xem'):
        sickrage.srCore.srLogger.info("Checking for XEM scene exception updates")

        for indexer in srIndexerApi().indexers:

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

            try:
                parsedJSON = sickrage.srCore.srWebSession.get(url, timeout=90).json()
            except Exception:
                sickrage.srCore.srLogger.debug("Check scene exceptions update failed for " + srIndexerApi(
                    indexer).name + ", Unable to get URL: " + url)
                continue

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

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

        setLastRefresh('xem')

    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]

    return xem_exception_dict
示例#2
0
    def _retrieve_season_banner_image(show_obj, season, which=0):
        """
        Should return a dict like:

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

        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 = srIndexerApi(show_obj.indexer).api_params.copy()

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

            t = srIndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)
            indexer_show_obj = t[show_obj.indexerid]

            # Give us just the normal season graphics
            try:
                return indexer_show_obj['_images']['seasonwide'][season][which]['filename']
            except KeyError:
                pass
        except (indexer_error, IOError) as e:
            sickrage.srCore.srLogger.warning("{}: Unable to look up show on ".format(show_obj.indexerid) + srIndexerApi(
                show_obj.indexer).name + ", not downloading images: {}".format(e.message))
            sickrage.srCore.srLogger.debug("Indexer " + srIndexerApi(
                show_obj.indexer).name + " maybe experiencing some problems. Try again later")
示例#3
0
    def _season_posters_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 = srIndexerApi(show_obj.indexer).api_params.copy()

            lINDEXER_API_PARMS['banners'] = True

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

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

            t = srIndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)
            indexer_show_obj = t[show_obj.indexerid]
        except (indexer_error, IOError) as e:
            sickrage.srCore.srLogger.warning("Unable to look up show on " + srIndexerApi(
                show_obj.indexer).name + ", not downloading images: {}".format(e.message))
            sickrage.srCore.srLogger.debug("Indexer " + srIndexerApi(
                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 'season' not in indexer_show_obj['_banners'] or 'season' not in indexer_show_obj['_banners']['season']:
            return result

        # Give us just the normal poster-style season graphics
        seasonsArtObj = indexer_show_obj['_banners']['season']['season']

        # 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]['season']) == season and \
                            seasonsArtObj[seasonArtID]['language'] == sickrage.srCore.srConfig.INDEXER_DEFAULT_LANGUAGE:
                result[season][seasonArtID] = seasonsArtObj[seasonArtID]['_bannerpath']

        return result
示例#4
0
    def run(self, force=False):
        if self.amActive:
            return

        self.amActive = True

        # set thread name
        threading.currentThread().setName(self.name)

        update_timestamp = long(
            time.mktime(datetime.datetime.now().timetuple()))

        try:
            dbData = sickrage.srCore.cacheDB.db.get('lastUpdate',
                                                    'theTVDB',
                                                    with_doc=True)['doc']
            last_update = long(dbData['time'])
        except RecordNotFound:
            last_update = long(time.mktime(datetime.datetime.min.timetuple()))
            dbData = sickrage.srCore.cacheDB.db.insert({
                '_t':
                'lastUpdate',
                'provider':
                'theTVDB',
                'time':
                long(last_update)
            })

        # get indexer updated show ids
        updated_shows = set(d["id"] for d in srIndexerApi().indexer(
            **srIndexerApi().api_params.copy()).updated(long(last_update))
                            or {})

        # start update process
        pi_list = []
        for curShow in sickrage.srCore.SHOWLIST:
            try:
                curShow.nextEpisode()

                if curShow.indexerid in updated_shows:
                    pi_list.append(
                        sickrage.srCore.SHOWQUEUE.updateShow(curShow, True))
                else:
                    pi_list.append(
                        sickrage.srCore.SHOWQUEUE.refreshShow(curShow, False))
            except (CantUpdateShowException, CantRefreshShowException) as e:
                sickrage.srCore.srLogger.debug(
                    "Automatic update failed: {}".format(e.message))

        ProgressIndicators.setIndicator(
            'dailyShowUpdates',
            QueueProgressIndicator("Daily Show Updates", pi_list))

        dbData['time'] = long(update_timestamp)
        sickrage.srCore.cacheDB.db.update(dbData)

        self.amActive = False
示例#5
0
    def run(self, force=False):
        if self.amActive:
            return

        self.amActive = True

        # set thread name
        threading.currentThread().setName(self.name)

        update_timestamp = time.mktime(datetime.datetime.now().timetuple())

        try:
            dbData = CacheDB().db.get('lastUpdate', 'theTVDB',
                                      with_doc=True)['doc']
            last_update = dbData['time']
        except RecordNotFound:
            last_update = time.mktime(datetime.datetime.min.timetuple())
            dbData = CacheDB().db.insert({
                '_t': 'lastUpdate',
                'provider': 'theTVDB',
                'time': long(last_update)
            })

        # get indexer updated show ids
        updated_shows = srIndexerApi().indexer(
            **srIndexerApi().api_params.copy()).updated(long(last_update))

        # start update process
        piList = []
        for curShow in sickrage.srCore.SHOWLIST:
            try:
                curShow.nextEpisode()

                if not os.path.isdir(curShow.location):
                    continue

                if curShow.indexerid in set(d["id"]
                                            for d in updated_shows or {}):
                    piList.append(
                        sickrage.srCore.SHOWQUEUE.updateShow(curShow, True))
                elif datetime.date.fromordinal(
                        curShow.last_refresh) > datetime.timedelta(days=1):
                    piList.append(
                        sickrage.srCore.SHOWQUEUE.refreshShow(curShow, False))
            except (CantUpdateShowException, CantRefreshShowException):
                continue

        ProgressIndicators.setIndicator(
            'dailyShowUpdates',
            QueueProgressIndicator("Daily Show Updates", piList))

        dbData['time'] = long(update_timestamp)
        CacheDB().db.update(dbData)

        self.amActive = False
示例#6
0
    def removeShowFromTraktLibrary(self, show_obj):
        if self.findShow(show_obj.indexer, show_obj.indexerid):
            trakt_id = srIndexerApi(show_obj.indexer).config['trakt_id']

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

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

            sickrage.srCore.srLogger.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.srCore.srLogger.warning(
                        "Could not connect to Trakt service. Aborting removing show %s from Trakt library. Error: %s" % (
                            show_obj.name, repr(e)))
示例#7
0
    def addShowToTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::ADD::START - Look for Shows to Add to Trakt Watchlist")

            if sickrage.srCore.SHOWLIST is not None:
                trakt_data = []

                for show in sickrage.srCore.SHOWLIST:
                    trakt_id = srIndexerApi(show.indexer).config['trakt_id']

                    if not self._checkInList(trakt_id, str(show.indexerid), '0', '0', List='Show'):
                        sickrage.srCore.srLogger.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['ids']['tvdb'] = show.indexerid
                        else:
                            show_el['ids']['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.srCore.srLogger.warning("Could not connect to Trakt service. Error: %s" % e)

            sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::ADD::FINISH - Look for Shows to Add to Trakt Watchlist")
示例#8
0
    def updateShows(self):
        sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::CHECK::START - Trakt Show Watchlist")

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

        indexer = int(sickrage.srCore.srConfig.TRAKT_DEFAULT_INDEXER)
        trakt_id = srIndexerApi(indexer).config['trakt_id']

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

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

            if int(sickrage.srCore.srConfig.TRAKT_METHOD_ADD) == 1:
                newShow = findCertainShow(sickrage.srCore.SHOWLIST, indexer_id)

                if newShow is not None:
                    setEpisodeToWanted(newShow, 1, 1)
                else:
                    self.todoWanted.append((indexer_id, 1, 1))
        sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::CHECK::FINISH - Trakt Show Watchlist")
示例#9
0
    def removeEpisodeFromTraktCollection(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_REMOVE and sickrage.srCore.srConfig.TRAKT_SYNC and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.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 = srIndexerApi(cur_episode["indexer"]).config['trakt_id']

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

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

            sickrage.srCore.srLogger.debug("COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection")
示例#10
0
    def addShowToTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::ADD::START - Look for Shows to Add to Trakt Watchlist")

            if sickrage.srCore.SHOWLIST is not None:
                trakt_data = []

                for show in sickrage.srCore.SHOWLIST:
                    trakt_id = srIndexerApi(show.indexer).config['trakt_id']

                    if not self._checkInList(trakt_id, str(show.indexerid), '0', '0', List='Show'):
                        sickrage.srCore.srLogger.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['ids']['tvdb'] = show.indexerid
                        else:
                            show_el['ids']['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.srCore.srLogger.warning("Could not connect to Trakt service. Error: %s" % e)

            sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::ADD::FINISH - Look for Shows to Add to Trakt Watchlist")
示例#11
0
    def removeEpisodeFromTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.debug(
                "WATCHLIST::REMOVE::START - Look for Episodes to Remove from Trakt Watchlist")

            trakt_data = []
            for s in [x['doc'] for x in sickrage.srCore.mainDB.db.all('tv_shows', with_doc=True)]:
                for e in [e['doc'] for e in
                          sickrage.srCore.mainDB.db.get_many('tv_episodes', s['indexer_id'], with_doc=True)]:
                    trakt_id = srIndexerApi(s["indexer"]).config['trakt_id']

                    if self._checkInList(trakt_id, str(e["showid"]), str(e["season"]),
                                         str(e["episode"])) and e[
                        "status"] not in Quality.SNATCHED + Quality.SNATCHED_PROPER + [UNKNOWN] + [WANTED]:
                        sickrage.srCore.srLogger.debug("Removing Episode %s S%02dE%02d from watchlist" %
                                                       (s["show_name"], e["season"],
                                                        e["episode"]))
                        trakt_data.append((e["showid"], s["indexer"], s["show_name"],
                                           s["startyear"], e["season"], e["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.srCore.srLogger.warning("Could not connect to Trakt service. Error: %s" % e)

            sickrage.srCore.srLogger.debug(
                "WATCHLIST::REMOVE::FINISH - Look for Episodes to Remove from Trakt Watchlist")
示例#12
0
    def addEpisodeToTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.debug("WATCHLIST::ADD::START - Look for Episodes to Add to Trakt Watchlist")

            trakt_data = []
            for s in [x['doc'] for x in sickrage.srCore.mainDB.db.all('tv_shows', with_doc=True)]:
                for e in [e['doc'] for e in
                          sickrage.srCore.mainDB.db.get_many('tv_episodes', s['indexer_id'], with_doc=True)]:
                    trakt_id = srIndexerApi(s["indexer"]).config['trakt_id']

                    if not self._checkInList(trakt_id, str(e["showid"]), str(e["season"]), str(e["episode"])):
                        sickrage.srCore.srLogger.debug("Adding Episode %s S%02dE%02d to watchlist" %
                                                       (s["show_name"], e["season"], e["episode"]))
                        trakt_data.append(
                            (e["showid"], s["indexer"], s["show_name"], s["startyear"], e["season"], e["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.srCore.srLogger.warning("Could not connect to Trakt service. Error %s" % e)

            sickrage.srCore.srLogger.debug("WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist")
示例#13
0
    def removeEpisodeFromTraktCollection(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_REMOVE and sickrage.srCore.srConfig.TRAKT_SYNC and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.debug(
                "COLLECTION::REMOVE::START - Look for Episodes to Remove From Trakt Collection")

            trakt_data = []
            for s in [x['doc'] for x in sickrage.srCore.mainDB.db.all('tv_shows', with_doc=True)]:
                for e in [e['doc'] for e in
                          sickrage.srCore.mainDB.db.get_many('tv_episodes', s['indexer_id'], with_doc=True)]:
                    trakt_id = srIndexerApi(s["indexer"]).config['trakt_id']

                    if self._checkInList(trakt_id, str(e["showid"]), str(e["season"]), str(e["episode"]),
                                         List='Collection'):

                        if e["location"] == '':
                            sickrage.srCore.srLogger.debug("Removing Episode %s S%02dE%02d from collection" %
                                                           (s["show_name"], e["season"], e["episode"]))
                            trakt_data.append(
                                (e["showid"], s["indexer"], s["show_name"], s["startyear"], e["season"], e["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.srCore.srLogger.warning("Could not connect to Trakt service. Error: %s" % e)

            sickrage.srCore.srLogger.debug(
                "COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection")
示例#14
0
    def removeShowFromTraktLibrary(self, show_obj):
        if self.findShow(show_obj.indexer, show_obj.indexerid):
            trakt_id = srIndexerApi(show_obj.indexer).config['trakt_id']

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

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

            sickrage.srCore.srLogger.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.srCore.srLogger.warning(
                    "Could not connect to Trakt service. Aborting removing show %s from Trakt library. Error: %s"
                    % (show_obj.name, repr(e)))
示例#15
0
    def updateShows(self):
        sickrage.srCore.srLogger.debug(
            "SHOW_WATCHLIST::CHECK::START - Trakt Show Watchlist")

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

        indexer = int(sickrage.srCore.srConfig.TRAKT_DEFAULT_INDEXER)
        trakt_id = srIndexerApi(indexer).config['trakt_id']

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

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

            if int(sickrage.srCore.srConfig.TRAKT_METHOD_ADD) == 1:
                newShow = findCertainShow(sickrage.srCore.SHOWLIST, indexer_id)

                if newShow is not None:
                    setEpisodeToWanted(newShow, 1, 1)
                else:
                    self.todoWanted.append((indexer_id, 1, 1))
        sickrage.srCore.srLogger.debug(
            "SHOW_WATCHLIST::CHECK::FINISH - Trakt Show Watchlist")
示例#16
0
    def addEpisodeToTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.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 = srIndexerApi(cur_episode["indexer"]).config['trakt_id']

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

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

            sickrage.srCore.srLogger.debug("WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist")
示例#17
0
    def removeEpisodeFromTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.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 = srIndexerApi(cur_episode["indexer"]).config['trakt_id']

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

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

                sickrage.srCore.srLogger.debug("WATCHLIST::REMOVE::FINISH - Look for Episodes to Remove from Trakt Watchlist")
示例#18
0
    def run(self, force=False):
        if self.amActive:
            return

        self.amActive = True

        # set thread name
        threading.currentThread().setName(self.name)

        update_timestamp = time.mktime(datetime.datetime.now().timetuple())

        sqlResult = cache_db.CacheDB().select('SELECT `time` FROM lastUpdate WHERE provider = ?', ['theTVDB'])
        if sqlResult:
            last_update = sqlResult[0]['time']
        else:
            last_update = time.mktime(datetime.datetime.min.timetuple())
            cache_db.CacheDB().action('INSERT INTO lastUpdate (provider, `time`) VALUES (?, ?)',
                                      ['theTVDB', long(last_update)])

        if sickrage.srCore.srConfig.USE_FAILED_DOWNLOADS:
            FailedHistory.trimHistory()

        # get indexer updated show ids
        updated_shows = srIndexerApi(1).indexer(**srIndexerApi(1).api_params.copy()).updated(long(last_update))

        # start update process
        piList = []
        for curShow in sickrage.srCore.SHOWLIST:
            try:
                curShow.nextEpisode()
                if curShow.indexerid in set(d["id"] for d in updated_shows or {}):
                    piList.append(sickrage.srCore.SHOWQUEUE.updateShow(curShow, True))
                else:
                    piList.append(sickrage.srCore.SHOWQUEUE.refreshShow(curShow, False))
            except (CantUpdateShowException, CantRefreshShowException) as e:
                continue

        ProgressIndicators.setIndicator('dailyShowUpdates', QueueProgressIndicator("Daily Show Updates", piList))

        cache_db.CacheDB().action('UPDATE lastUpdate SET `time` = ? WHERE provider=?',
                                  [long(update_timestamp), 'theTVDB'])

        self.amActive = False
示例#19
0
    def validateShow(show, season=None, episode=None):
        indexer_lang = show.lang

        try:
            lINDEXER_API_PARMS = srIndexerApi(show.indexer).api_params.copy()

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

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

            t = srIndexerApi(show.indexer).indexer(**lINDEXER_API_PARMS)
            if season is None and episode is None:
                return t

            return t[show.indexerid][season][episode]
        except (indexer_episodenotfound, indexer_seasonnotfound):
            pass
示例#20
0
    def validateShow(show, season=None, episode=None):
        indexer_lang = show.lang

        try:
            lINDEXER_API_PARMS = srIndexerApi(show.indexer).api_params.copy()

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

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

            t = srIndexerApi(show.indexer).indexer(**lINDEXER_API_PARMS)
            if season is None and episode is None:
                return t

            return t[show.indexerid][season][episode]
        except (indexer_episodenotfound, indexer_seasonnotfound):
            pass
示例#21
0
    def update_library(self, ep_obj):
        """
        Sends a request to trakt indicating that the given episode is part of our library.

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

        trakt_id = srIndexerApi(ep_obj.show.indexer).config['trakt_id']
        trakt_api = TraktAPI(sickrage.srCore.srConfig.SSL_VERIFY,
                             sickrage.srCore.srConfig.TRAKT_TIMEOUT)

        if sickrage.srCore.srConfig.USE_TRAKT:
            try:
                # URL parameters
                data = {
                    'shows': [{
                        'title': ep_obj.show.name,
                        'year': ep_obj.show.startyear,
                        'ids': {},
                    }]
                }

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

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

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

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

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

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

            except (traktException, traktAuthException, traktServerBusy) as e:
                sickrage.srCore.srLogger.warning(
                    "Could not connect to Trakt service: %s" % e)
示例#22
0
def _xem_exceptions_fetcher():
    if shouldRefresh('xem'):
        sickrage.srCore.srLogger.info(
            "Checking for XEM scene exception updates")

        for indexer in srIndexerApi().indexers:

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

            try:
                parsedJSON = sickrage.srCore.srWebSession.get(
                    url, timeout=90).json()
            except Exception:
                sickrage.srCore.srLogger.debug(
                    "Check scene exceptions update failed for " +
                    srIndexerApi(indexer).name + ", Unable to get URL: " + url)
                continue

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

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

        setLastRefresh('xem')

    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]

    return xem_exception_dict
示例#23
0
    def updateEpisodes(self):
        """
        Sets episodes to wanted that are in trakt watchlist
        """
        sickrage.srCore.srLogger.debug(
            "SHOW_WATCHLIST::CHECK::START - Trakt Episode Watchlist")

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

        managed_show = []

        indexer = int(sickrage.srCore.srConfig.TRAKT_DEFAULT_INDEXER)
        trakt_id = srIndexerApi(indexer).config['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.srCore.SHOWLIST, indexer_id)

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

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

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

                            for episode_el in show['seasons'][season_el][
                                    'episodes']:
                                setEpisodeToWanted(newShow, season,
                                                   int(episode_el))
            except TypeError:
                sickrage.srCore.srLogger.debug(
                    "Could not parse the output from trakt for %s " %
                    show["title"])
        sickrage.srCore.srLogger.debug(
            "SHOW_WATCHLIST::CHECK::FINISH - Trakt Episode Watchlist")
示例#24
0
    def trakt_show_data_generate(self, data):

        showList = []
        for indexer, indexerid, title, year in data:
            show = {'title': title,
                    'year': year,
                    'ids': {srIndexerApi(indexer).trakt_id: indexerid}}

            showList.append(show)

        post_data = {'shows': showList}

        return post_data
示例#25
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 = srIndexerApi(indexerid).config['trakt_id']

                if trakt_id == 'tvdb_id':
                    uniqueShows[showid]['ids']["tvdb"] = showid
                else:
                    uniqueShows[showid]['ids']["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['seasons'].append({
                    'number': searchedSeason,
                    'episodes': episodesList
                })
                traktShowList.append(show)

        return {'shows': traktShowList}
示例#26
0
    def removeEpisodeFromTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.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 = srIndexerApi(
                        cur_episode["indexer"]).config['trakt_id']

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

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

                sickrage.srCore.srLogger.debug(
                    "WATCHLIST::REMOVE::FINISH - Look for Episodes to Remove from Trakt Watchlist"
                )
示例#27
0
    def removeEpisodeFromTraktCollection(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_REMOVE and sickrage.srCore.srConfig.TRAKT_SYNC and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.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 = srIndexerApi(
                        cur_episode["indexer"]).config['trakt_id']

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

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

            sickrage.srCore.srLogger.debug(
                "COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection"
            )
示例#28
0
    def trakt_show_data_generate(self, data):

        showList = []
        for indexer, indexerid, title, year in data:
            trakt_id = srIndexerApi(indexer).config['trakt_id']
            show = {'title': title, 'year': year, 'ids': {}}
            if trakt_id == 'tvdb_id':
                show['ids']['tvdb'] = indexerid
            else:
                show['ids']['tvrage'] = indexerid
            showList.append(show)

        post_data = {'shows': showList}

        return post_data
示例#29
0
    def addEpisodeToTraktWatchList(self):
        if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST and sickrage.srCore.srConfig.USE_TRAKT:
            sickrage.srCore.srLogger.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 = srIndexerApi(
                        cur_episode["indexer"]).config['trakt_id']

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

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

            sickrage.srCore.srLogger.debug(
                "WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist"
            )
示例#30
0
文件: trakt.py 项目: afctim/SiCKRAGE
    def update_library(self, ep_obj):
        """
        Sends a request to trakt indicating that the given episode is part of our library.

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

        trakt_id = srIndexerApi(ep_obj.show.indexer).config['trakt_id']
        trakt_api = TraktAPI(sickrage.srCore.srConfig.SSL_VERIFY, sickrage.srCore.srConfig.TRAKT_TIMEOUT)

        if sickrage.srCore.srConfig.USE_TRAKT:
            try:
                # URL parameters
                data = {
                    'shows': [
                        {
                            'title': ep_obj.show.name,
                            'year': ep_obj.show.startyear,
                            'ids': {},
                        }
                    ]
                }

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

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

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

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

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

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

            except (traktException, traktAuthException, traktServerBusy) as e:
                sickrage.srCore.srLogger.warning("Could not connect to Trakt service: %s" % e)
示例#31
0
    def get_show(self, name):
        show = None
        show_id = 0
        fromCache = False

        if not all([name, sickrage.srCore.SHOWLIST]): return show, show_id

        try:
            # check cache for show
            cache = sickrage.srCore.NAMECACHE.get(name)
            if cache:
                fromCache = True
                show_id = cache

            # try indexers
            if not show_id and self.tryIndexers:
                try:
                    show_id1 = int(srIndexerApi().searchForShowID(
                        full_sanitizeSceneName(name))[2])
                    show_id2 = int(srTraktAPI()['search'].query(
                        full_sanitizeSceneName(name), 'show')[0].ids['tvdb'])
                    show_id = (show_id, show_id1)[show_id1 == show_id2]
                except Exception:
                    pass

            # try scene exceptions
            if not show_id:
                try:
                    show_id = get_scene_exception_by_name(name)[0]
                except Exception:
                    pass

            # create show object
            show = findCertainShow(sickrage.srCore.SHOWLIST,
                                   int(show_id)) if show_id else None

            # add show to cache
            if show and not fromCache:
                sickrage.srCore.NAMECACHE.put(name, show.indexerid)
        except Exception as e:
            sickrage.srCore.srLogger.debug(
                "Error when attempting to find show: %s in SiCKRAGE. Error: %r "
                % (name, repr(e)))

        return show, show_id
示例#32
0
    def updateEpisodes(self):
        """
        Sets episodes to wanted that are in trakt watchlist
        """
        sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::CHECK::START - Trakt Episode Watchlist")

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

        managed_show = []

        indexer = int(sickrage.srCore.srConfig.TRAKT_DEFAULT_INDEXER)
        trakt_id = srIndexerApi(indexer).config['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.srCore.SHOWLIST, indexer_id)

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

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

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

                            for episode_el in show['seasons'][season_el]['episodes']:
                                setEpisodeToWanted(newShow, season, int(episode_el))
            except TypeError:
                sickrage.srCore.srLogger.debug("Could not parse the output from trakt for %s " % show["title"])
        sickrage.srCore.srLogger.debug("SHOW_WATCHLIST::CHECK::FINISH - Trakt Episode Watchlist")
示例#33
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 = srIndexerApi(indexerid).config['trakt_id']

                if trakt_id == 'tvdb_id':
                    uniqueShows[showid]['ids']["tvdb"] = showid
                else:
                    uniqueShows[showid]['ids']["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['seasons'].append({'number': searchedSeason, 'episodes': episodesList})
                traktShowList.append(show)

        return {'shows': traktShowList}
示例#34
0
    def get_show(self, name, tryIndexers=False):
        if not sickrage.srCore.SHOWLIST:
            return

        showObj = None
        fromCache = False

        if not name:
            return showObj

        try:
            # check cache for show
            cache = sickrage.srCore.NAMECACHE.get(name)
            if cache:
                fromCache = True
                showObj = findCertainShow(sickrage.srCore.SHOWLIST, int(cache))

            # try indexers
            if not showObj and tryIndexers:
                showObj = findCertainShow(
                    sickrage.srCore.SHOWLIST,
                    srIndexerApi().searchForShowID(
                        full_sanitizeSceneName(name))[2])

            # try scene exceptions
            if not showObj:
                ShowID = get_scene_exception_by_name(name)[0]
                if ShowID:
                    showObj = findCertainShow(sickrage.srCore.SHOWLIST,
                                              int(ShowID))

            # add show to cache
            if showObj and not fromCache:
                sickrage.srCore.NAMECACHE.put(name, showObj.indexerid)
        except Exception as e:
            sickrage.srCore.srLogger.debug(
                "Error when attempting to find show: %s in SiCKRAGE. Error: %r "
                % (name, repr(e)))

        return showObj
示例#35
0
    def update_library(self, ep_obj):
        """
        Sends a request to trakt indicating that the given episode is part of our library.

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

        if sickrage.srCore.srConfig.USE_TRAKT:
            try:
                # URL parameters
                data = {
                    'shows': [
                        {
                            'title': ep_obj.show.name,
                            'year': ep_obj.show.startyear,
                            'ids': {srIndexerApi(ep_obj.show.indexer).trakt_id: ep_obj.show.indexerid},
                        }
                    ]
                }

                if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST:
                    if sickrage.srCore.srConfig.TRAKT_REMOVE_SERIESLIST:
                        srTraktAPI()["sync/watchlist"].remove(data)

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

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

                if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST:
                    if sickrage.srCore.srConfig.TRAKT_REMOVE_WATCHLIST:
                        srTraktAPI()["sync/watchlist"].remove(data)

                # update library
                srTraktAPI()["sync/collection"].add(data)

            except Exception as e:
                sickrage.srCore.srLogger.warning("Could not connect to Trakt service: %s" % e)
示例#36
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 = srIndexerApi(show_obj.indexer).config['trakt_id']
            # URL parameters
            data = {
                'shows': [{
                    'title': show_obj.name,
                    'year': show_obj.startyear,
                    'ids': {}
                }]
            }

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

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

            try:
                self.trakt_api.traktRequest("sync/collection",
                                            data,
                                            method='POST')
            except traktException as e:
                sickrage.srCore.srLogger.warning(
                    "Could not connect to Trakt service. Aborting adding show %s to Trakt library. Error: %s"
                    % (show_obj.name, repr(e)))
                return
示例#37
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 = srIndexerApi(show_obj.indexer).config['trakt_id']
            # URL parameters
            data = {
                'shows': [
                    {
                        'title': show_obj.name,
                        'year': show_obj.startyear,
                        'ids': {}
                    }
                ]
            }

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

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

            try:
                self.trakt_api.traktRequest("sync/collection", data, method='POST')
            except traktException as e:
                sickrage.srCore.srLogger.warning(
                        "Could not connect to Trakt service. Aborting adding show %s to Trakt library. Error: %s" % (
                            show_obj.name, repr(e)))
                return
示例#38
0
    def get_show(self, name, tryIndexers=False):
        if not sickrage.srCore.SHOWLIST:
            return

        showObj = None
        fromCache = False

        if not name:
            return showObj

        try:
            # check cache for show
            cache = sickrage.srCore.NAMECACHE.retrieveNameFromCache(name)
            if cache:
                fromCache = True
                showObj = findCertainShow(sickrage.srCore.SHOWLIST, int(cache))

            # try indexers
            if not showObj and tryIndexers:
                showObj = findCertainShow(sickrage.srCore.SHOWLIST,
                                          srIndexerApi().searchForShowID(full_sanitizeSceneName(name))[2])

            # try scene exceptions
            if not showObj:
                ShowID = get_scene_exception_by_name(name)[0]
                if ShowID:
                    showObj = findCertainShow(sickrage.srCore.SHOWLIST, int(ShowID))

            # add show to cache
            if showObj and not fromCache:
                sickrage.srCore.NAMECACHE.addNameToCache(name, showObj.indexerid)
        except Exception as e:
            sickrage.srCore.srLogger.debug(
                "Error when attempting to find show: %s in SiCKRAGE. Error: %r " % (name, repr(e)))

        return showObj
示例#39
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 = srIndexerApi(show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS['actors'] = True

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

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

        t = srIndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)

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

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

        except indexer_error:
            sickrage.srCore.srLogger.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.srCore.srLogger.info("Incomplete info for show with id " + str(show_obj.indexerid) + " on " + srIndexerApi(
                    show_obj.indexer).name + ", skipping it")
            return False

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

        if getattr(myShow, "genre", None):
            Genres = SubElement(tv_node, "genres")
            for genre in myShow['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['firstaired']

        if getattr(myShow, "firstaired", None):
            try:
                year_text = str(datetime.datetime.strptime(myShow["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["overview"]

        if getattr(myShow, 'rating', None):
            try:
                rating = int(float(myShow['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['status']

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

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

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

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

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

        indentXML(rootNode)

        data = ElementTree(rootNode)

        return data
示例#40
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'))
                result.score += 1

                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]

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

                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]

            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:
                airdate = bestResult.air_date.toordinal()

                dbData = [
                    x['doc'] for x in sickrage.srCore.mainDB.db.get_many(
                        'tv_episodes',
                        bestResult.show.indexerid,
                        with_doc=True)
                    if x['doc']['indexer'] == bestResult.show.indexer
                    and x['doc']['airdate'] == airdate
                ]

                season_number = None
                episode_numbers = []

                if dbData:
                    season_number = int(dbData[0]['season'])
                    episode_numbers = [int(dbData[0]['episode'])]

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

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

                        t = srIndexerApi(bestResult.show.indexer).indexer(
                            **lINDEXER_API_PARMS)

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

                        season_number = int(epObj["seasonnumber"])
                        episode_numbers = [int(epObj["episodenumber"])]
                    except indexer_episodenotfound:
                        sickrage.srCore.srLogger.warning(
                            "Unable to find episode with date " +
                            bestResult.air_date + " for show " +
                            bestResult.show.name + ", skipping")
                        episode_numbers = []
                    except indexer_error as e:
                        sickrage.srCore.srLogger.warning(
                            "Unable to contact " +
                            srIndexerApi(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.srCore.srLogger.debug(
                    "Converted parsed result {} into {}".format(
                        bestResult.original_name, bestResult))

        # CPU sleep
        time.sleep(0.02)

        return bestResult
示例#41
0
def retrieve_exceptions(get_xem=True, get_anidb=True):
    """
    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 srIndexerApi().indexers:
        indexer_name = srIndexerApi(indexer).name

        if shouldRefresh(indexer_name):
            sickrage.srCore.srLogger.info("Checking for SiCKRAGE scene exception updates on {}".format(indexer_name))
            loc = srIndexerApi(indexer).config['scene_loc']

            try:
                # each exception is on one line with the format indexer_id: 'show name 1', 'show name 2', etc
                cur_line = None
                for cur_line in sickrage.srCore.srWebSession.get(loc).text.splitlines():
                    indexer_id, _, aliases = cur_line.partition(':')  # @UnusedVariable
                    if not aliases:
                        continue

                    # regex out the list of shows, taking \' into account
                    exception_dict[int(indexer_id)] = [{re.sub(r'\\(.)', r'\1', x): -1} for x in
                                                       re.findall(r"'(.*?)(?<!\\)',?", aliases)]
                if cur_line is None:
                    sickrage.srCore.srLogger.debug(
                        "Check scene exceptions update failed. Unable to update from: {}".format(loc))
                    continue

                # refreshed successfully
                setLastRefresh(indexer_name)
            except Exception:
                continue

    # XEM scene exceptions
    if get_xem:
        _xem_exceptions_fetcher()

    # AniDB scene exceptions
    if get_anidb:
        _anidb_exceptions_fetcher()

    sql_l = []
    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["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.items():
                cur_exception, curSeason = ex
                if cur_exception not in existing_exceptions:
                    sql_l.append(
                        ["INSERT OR IGNORE INTO scene_exceptions (indexer_id, show_name, season) VALUES (?,?,?);",
                         [cur_indexer_id, cur_exception, curSeason]])
    if len(sql_l) > 0:
        cache_db.CacheDB().mass_action(sql_l)
        sickrage.srCore.srLogger.debug("Updated scene exceptions")
        del sql_l  # cleanup
    else:
        sickrage.srCore.srLogger.debug("No scene exceptions update needed")

    # cleanup
    exception_dict.clear()
    anidb_exception_dict.clear()
    xem_exception_dict.clear()
示例#42
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]['last_refreshed'])
        refresh = int(time.mktime(datetime.datetime.today().timetuple())) > lastRefresh + MAX_REFRESH_AGE_SECS
    else:
        refresh = True

    if refresh or force:
        sickrage.srCore.srLogger.debug(
            'Looking up XEM scene mapping for show %s on %s' % (indexer_id, srIndexerApi(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:
            # XEM MAP URL
            url = "http://thexem.de/map/havemap?origin=%s" % srIndexerApi(indexer).config['xem_origin']
            parsedJSON = sickrage.srCore.srWebSession.get(url).json()
            if not parsedJSON or 'result' not in parsedJSON or 'success' not in parsedJSON['result'] \
                    or 'data' not in parsedJSON or str(indexer_id) not in parsedJSON['data']:
                return

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

            parsedJSON = sickrage.srCore.srWebSession.get(url).json()
            if not ((parsedJSON and 'result' in parsedJSON) and 'success' in parsedJSON['result']):
                sickrage.srCore.srLogger.info(
                    'No XEM data for show "%s on %s"' % (indexer_id, srIndexerApi(indexer).name,))
                return

            cl = []
            for entry in parsedJSON['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['scene']['season'],
                         entry['scene']['episode'],
                         entry['scene']['absolute'],
                         indexer_id,
                         entry[srIndexerApi(indexer).config['xem_origin']]['season'],
                         entry[srIndexerApi(indexer).config['xem_origin']]['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['scene_2']['season'],
                         entry['scene_2']['episode'],
                         entry['scene_2']['absolute'],
                         indexer_id,
                         entry[srIndexerApi(indexer).config['xem_origin']]['season'],
                         entry[srIndexerApi(indexer).config['xem_origin']]['episode']
                         ]])

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

        except Exception as e:
            sickrage.srCore.srLogger.warning(
                "Exception while refreshing XEM data for show " + str(
                    indexer_id) + " on " + srIndexerApi(
                    indexer).name + ": {}".format(e.message))
            sickrage.srCore.srLogger.debug(traceback.format_exc())
示例#43
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 = srIndexerApi(show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS['actors'] = True

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

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

        t = srIndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)

        tv_node = Element("Series")

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

        except indexer_error:
            sickrage.srCore.srLogger.error(
                "" + srIndexerApi(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.srCore.srLogger.info(
                "Incomplete info for show with id " + str(show_obj.indexerid) + " on " + srIndexerApi(
                    show_obj.indexer).name + ", skipping it")
            return False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if getattr(myShow, 'firstaired', None):
            try:
                year_text = str(datetime.datetime.strptime(myShow['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['runtime']

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

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

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

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

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

        if getattr(myShow, 'genre', None) and isinstance(myShow["genre"], basestring):
            Genres = SubElement(tv_node, "Genres")
            for genre in myShow['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["genre"].split('|') if x.strip()])

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

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

                cur_actor = SubElement(Persons, "Person")

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

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

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

        indentXML(tv_node)

        data = ElementTree(tv_node)

        return data
示例#44
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.srCore.srLogger.debug(
        'Fixing any XEM scene mapping issues for show %s on %s' % (
        indexer_id, srIndexerApi(indexer).name))

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

        if not int(row['scene_season']) and last_scene_season:
            scene_season = last_scene_season + 1
            update_scene_season = True
        else:
            scene_season = int(row['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['scene_episode']) and last_scene_episode:
            scene_episode = last_scene_episode + 1
            update_scene_episode = True
        else:
            scene_episode = int(row['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['absolute_number']) and last_absolute_number:
            absolute_number = last_absolute_number + 1
            update_absolute_number = True
        else:
            absolute_number = int(row['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['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['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)
        del cl  # cleanup
示例#45
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 = srIndexerApi(ep_obj.show.indexer).api_params.copy()

            lINDEXER_API_PARMS['actors'] = True

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

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

            t = srIndexerApi(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.srCore.srLogger.error("Unable to connect to " + srIndexerApi(
                ep_obj.show.indexer).name + " while creating meta files - skipping - {}".format(e.message))
            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.srCore.srLogger.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" %
                    (curEpToWrite.season, curEpToWrite.episode, srIndexerApi(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['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['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['rating']

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

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

                        IMDbId = SubElement(episode, "IMDbId")
                        IMDbId.text = myShow['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.items():
                    # 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['_actors']:
                        if not ('name' in actor and actor['name'].strip()):
                            continue

                        cur_actor = SubElement(Persons, "Person")

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

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

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

                Language = SubElement(episode, "Language")
                try:
                    Language.text = myEp['language']
                except Exception:
                    Language.text = sickrage.srCore.srConfig.INDEXER_DEFAULT_LANGUAGE

                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['Director'] += [x.strip() for x in myEp['director'].split('|') if x.strip()]
            if getattr(myEp, 'gueststars', None):
                persons_dict['GuestStar'] += [x.strip() for x in myEp['gueststars'].split('|') if x.strip()]
            if getattr(myEp, 'writer', None):
                persons_dict['Writer'] += [x.strip() for x in myEp['writer'].split('|') if x.strip()]

        indentXML(rootNode)
        data = ElementTree(rootNode)

        return data
示例#46
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

    try:
        dbData = MainDB().db.get('xem_refresh', indexer_id,
                                 with_doc=True)['doc']
        lastRefresh = int(dbData['last_refreshed'])
        refresh = int(time.mktime(datetime.datetime.today().timetuple())
                      ) > lastRefresh + MAX_REFRESH_AGE_SECS
    except RecordNotFound:
        refresh = True

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

        # mark refreshed
        try:
            dbData = MainDB().db.get('xem_refresh', indexer_id,
                                     with_doc=True)['doc']
            dbData['last_refreshed'] = int(
                time.mktime(datetime.datetime.today().timetuple()))
            MainDB().db.update(dbData)
        except RecordNotFound:
            MainDB().db.insert({
                '_t':
                'xem_refresh',
                'indexer':
                indexer,
                'last_refreshed':
                int(time.mktime(datetime.datetime.today().timetuple())),
                'indexer_id':
                indexer_id
            })

        try:
            # XEM MAP URL
            url = "http://thexem.de/map/havemap?origin=%s" % srIndexerApi(
                indexer).config['xem_origin']

            try:
                parsedJSON = sickrage.srCore.srWebSession.get(url).json()
                if indexer_id not in map(int, parsedJSON['data']):
                    raise
            except:
                return

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

            try:
                parsedJSON = sickrage.srCore.srWebSession.get(url).json()
                if 'success' not in parsedJSON['result']:
                    raise
            except:
                sickrage.srCore.srLogger.info(
                    'No XEM data for show "%s on %s"' % (
                        indexer_id,
                        srIndexerApi(indexer).name,
                    ))
                return

            for entry in parsedJSON['data']:
                try:
                    dbData = [
                        x['doc'] for x in MainDB().db.get_many(
                            'tv_episodes', indexer_id, with_doc=True)
                        if x['doc']['season'] == entry[srIndexerApi(
                            indexer).config['xem_origin']]['season']
                        and x['doc']['episode'] == entry[srIndexerApi(
                            indexer).config['xem_origin']]['episode']
                    ][0]
                except:
                    continue

                if 'scene' in entry:
                    dbData['scene_season'] = entry['scene']['season']
                    dbData['scene_episode'] = entry['scene']['episode']
                    dbData['scene_absolute_number'] = entry['scene'][
                        'absolute']
                if 'scene_2' in entry:  # for doubles
                    dbData['scene_season'] = entry['scene_2']['season']
                    dbData['scene_episode'] = entry['scene_2']['episode']
                    dbData['scene_absolute_number'] = entry['scene_2'][
                        'absolute']

                MainDB().db.update(dbData)

        except Exception as e:
            sickrage.srCore.srLogger.warning(
                "Exception while refreshing XEM data for show {} on {}: {}".
                format(indexer_id,
                       srIndexerApi(indexer).name, e.message))
            sickrage.srCore.srLogger.debug(traceback.format_exc())
示例#47
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 = srIndexerApi(ep_obj.show.indexer).api_params.copy()

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

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

            t = srIndexerApi(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.srCore.srLogger.error("Unable to connect to TVDB while creating meta files - skipping - {}".format(e.message))
            return False

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

        movie.attrib["isExtra"] = "false"
        movie.attrib["isSet"] = "false"
        movie.attrib["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.srCore.srLogger.info("Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" %
                                            (curEpToWrite.season, curEpToWrite.episode, srIndexerApi(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['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["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["overview"]

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

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

                if not ep_obj.relatedEps and getattr(myEp, "rating", None):
                    try:
                        rating = int((float(myEp['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['director']

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

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

                    if getattr(myShow, '_actors', None):
                        for actor in myShow['_actors']:
                            if 'name' in actor and actor['name'].strip():
                                cur_actor = SubElement(cast, "actor")
                                cur_actor.text = actor['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
示例#48
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 = srIndexerApi(show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS['actors'] = True

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

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

        t = srIndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)

        tv_node = Element("tvshow")

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

        except indexer_error:
            sickrage.srCore.srLogger.error(
                "" + srIndexerApi(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.srCore.srLogger.info("Incomplete info for show with id " + str(show_ID) + " on " + srIndexerApi(
                show_obj.indexer).name + ", skipping it")
            return False

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

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

        if getattr(myShow, 'firstaired', None):
            try:
                year_text = str(datetime.datetime.strptime(myShow["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["overview"]

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

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

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

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

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

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

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

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

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

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

        # Make it purdy
        indentXML(tv_node)

        data = ElementTree(tv_node)

        return data
示例#49
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 or sickrage.srCore.srConfig.INDEXER_DEFAULT_LANGUAGE

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

            lINDEXER_API_PARMS['language'] = indexer_lang

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

            t = srIndexerApi(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.srCore.srLogger.error(
                "Unable to connect to TVDB while creating meta files - skipping - {}"
                .format(e.message))
            return False

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

        movie.attrib["isExtra"] = "false"
        movie.attrib["isSet"] = "false"
        movie.attrib["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.srCore.srLogger.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?"
                    % (curEpToWrite.season, curEpToWrite.episode,
                       srIndexerApi(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['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["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["overview"]

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

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

                if not ep_obj.relatedEps and getattr(myEp, "rating", None):
                    try:
                        rating = int((float(myEp['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['director']

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

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

                    if getattr(myShow, '_actors', None):
                        for actor in myShow['_actors']:
                            if 'name' in actor and actor['name'].strip():
                                cur_actor = SubElement(cast, "actor")
                                cur_actor.text = actor['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
示例#50
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'))
                result.score += 1

                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]

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

                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]

            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 = srIndexerApi(bestResult.show.indexer).api_params.copy()

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

                        t = srIndexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS)

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

                        season_number = int(epObj["seasonnumber"])
                        episode_numbers = [int(epObj["episodenumber"])]
                    except indexer_episodenotfound:
                        sickrage.srCore.srLogger.warning(
                            "Unable to find episode with date " + bestResult.air_date + " for show " + bestResult.show.name + ", skipping")
                        episode_numbers = []
                    except indexer_error as e:
                        sickrage.srCore.srLogger.warning(
                            "Unable to contact " + srIndexerApi(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.srCore.srLogger.debug(
                    "Converted parsed result {} into {}".format(bestResult.original_name, bestResult))

        # CPU sleep
        time.sleep(1)

        return bestResult
示例#51
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 or sickrage.srCore.srConfig.INDEXER_DEFAULT_LANGUAGE
        lINDEXER_API_PARMS = srIndexerApi(show_obj.indexer).api_params.copy()

        lINDEXER_API_PARMS['language'] = indexer_lang

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

        t = srIndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)

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

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

        except indexer_error:
            sickrage.srCore.srLogger.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.srCore.srLogger.info("Incomplete info for show with id " +
                                          str(show_obj.indexerid) + " on " +
                                          srIndexerApi(show_obj.indexer).name +
                                          ", skipping it")
            return False

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

        if getattr(myShow, "genre", None):
            Genres = SubElement(tv_node, "genres")
            for genre in myShow['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['firstaired']

        if getattr(myShow, "firstaired", None):
            try:
                year_text = str(
                    datetime.datetime.strptime(myShow["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["overview"]

        if getattr(myShow, 'rating', None):
            try:
                rating = int(float(myShow['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['status']

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

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

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

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

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

        indentXML(rootNode)

        data = ElementTree(rootNode)

        return data
示例#52
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 = srIndexerApi(ep_obj.show.indexer).api_params.copy()

        lINDEXER_API_PARMS['actors'] = True

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

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

        try:
            t = srIndexerApi(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.srCore.srLogger.error("Unable to connect to {} while creating meta files - skipping - {}".format(
                srIndexerApi(
                    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.srCore.srLogger.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" %
                    (curEpToWrite.season, curEpToWrite.episode, srIndexerApi(ep_obj.show.indexer).name))
                return None

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

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

            sickrage.srCore.srLogger.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['episodename']

            if getattr(myShow, 'seriesname', None):
                showtitle = SubElement(episode, "showtitle")
                showtitle.text = myShow['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['overview']

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

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

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

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

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

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

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

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

            if getattr(myEp, 'gueststars', None) and isinstance(myEp['gueststars'], basestring):
                for actor in (x.strip() for x in myEp['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['_actors']:
                    cur_actor = SubElement(episode, "actor")

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

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

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

        # Make it purdy
        indentXML(rootNode)
        data = ElementTree(rootNode)
        return data
示例#53
0
文件: show.py 项目: afctim/SiCKRAGE
    def run(self):
        super(QueueItemAdd, self).run()

        sickrage.srCore.srLogger.info("Started adding show {}".format(self.showDir))

        index_name = srIndexerApi(self.indexer).name

        # make sure the Indexer IDs are valid
        try:

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

            sickrage.srCore.srLogger.info("{}: {}".format(index_name, repr(lINDEXER_API_PARMS)))

            t = srIndexerApi(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 not getattr(s, 'seriesname'):
                sickrage.srCore.srLogger.error(
                    "Show in {} has no name on {}, probably the wrong language used to search with".format(self.showDir,
                                                                                                           index_name))
                sickrage.srCore.srNotifications.error("Unable to add show",
                                                      "Show in {} has no name on {}, probably the wrong language. Delete .nfo and add manually in the correct language".format(
                                                          self.showDir, index_name))
                return self._finishEarly()

            # if the show has no episodes/seasons
            if not len(s):
                sickrage.srCore.srLogger.error("Show " + str(s['seriesname']) + " is on " + str(
                    srIndexerApi(self.indexer).name) + " but contains no season/episode data.")
                sickrage.srCore.srNotifications.error("Unable to add show",
                                                      "Show " + str(s['seriesname']) + " is on " + str(srIndexerApi(
                                                          self.indexer).name) + " but contains no season/episode data.")
                return self._finishEarly()
        except Exception as e:
            sickrage.srCore.srLogger.error(
                "{}: Error while loading information from indexer {}. Error: {}".format(self.indexer_id, index_name,
                                                                                        e.message))

            sickrage.srCore.srNotifications.error(
                "Unable to add show",
                "Unable to look up the show in {} on {} using ID {}, not using the NFO. Delete .nfo and try adding manually again.".format(
                    self.showDir, index_name, self.indexer_id)
            )

            if sickrage.srCore.srConfig.USE_TRAKT:

                trakt_id = srIndexerApi(self.indexer).config['trakt_id']
                trakt_api = TraktAPI(sickrage.srCore.srConfig.SSL_VERIFY, sickrage.srCore.srConfig.TRAKT_TIMEOUT)

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

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

            return self._finishEarly()

        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 or sickrage.srCore.srConfig.SUBTITLES_DEFAULT
            self.show.quality = self.quality or sickrage.srCore.srConfig.QUALITY_DEFAULT
            self.show.flatten_folders = self.flatten_folders or sickrage.srCore.srConfig.FLATTEN_FOLDERS_DEFAULT
            self.show.anime = self.anime or sickrage.srCore.srConfig.ANIME_DEFAULT
            self.show.scene = self.scene or sickrage.srCore.srConfig.SCENE_DEFAULT
            self.show.archive_firstmatch = self.archive or sickrage.srCore.srConfig.ARCHIVE_DEFAULT
            self.show.paused = self.paused or False

            # set up default new/missing episode status
            sickrage.srCore.srLogger.info(
                "Setting all current episodes to the specified default status: " + str(self.default_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.srCore.srLogger.error(
                "Unable to add show due to an error with " + srIndexerApi(
                    self.indexer).name + ": {}".format(e.message))
            if self.show:
                sickrage.srCore.srNotifications.error(
                    "Unable to add " + str(self.show.name) + " due to an error with " + srIndexerApi(
                        self.indexer).name + "")
            else:
                sickrage.srCore.srNotifications.error(
                    "Unable to add show due to an error with " + srIndexerApi(self.indexer).name + "")
            return self._finishEarly()

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

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

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

        # 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

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

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

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

        try:
            self.show.loadEpisodesFromDir()
        except Exception as e:
            sickrage.srCore.srLogger.debug("Error searching dir for episodes: {}".format(e.message))
            sickrage.srCore.srLogger.debug(traceback.format_exc())

        # if they set default ep status to WANTED then run the backlog to search for episodes
        if self.show.default_ep_status == WANTED:
            sickrage.srCore.srLogger.info("Launching backlog for this show since its episodes are WANTED")
            sickrage.srCore.BACKLOGSEARCHER.searchBacklog([self.show])

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

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

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

            if sickrage.srCore.srConfig.TRAKT_SYNC_WATCHLIST:
                sickrage.srCore.srLogger.info("update watchlist")
                sickrage.srCore.notifiersDict.trakt_notifier.update_watchlist(show_obj=self.show)

        # After initial add, set to default_status_after.
        sickrage.srCore.srLogger.info(
            "Setting all future episodes to the specified default status: " + str(self.default_status_after))
        self.show.default_ep_status = self.default_status_after

        self.show.saveToDB()

        sickrage.srCore.NAMECACHE.buildNameCache(self.show)

        sickrage.srCore.srLogger.info("Finished adding show {}".format(self.showDir))
示例#54
0
文件: tivo.py 项目: afctim/SiCKRAGE
    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 = srIndexerApi(ep_obj.show.indexer).api_params.copy()

            lINDEXER_API_PARMS['actors'] = True

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

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

            t = srIndexerApi(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.srCore.srLogger.error("Unable to connect to " + srIndexerApi(
                    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.srCore.srLogger.info("Unable to find episode %dx%d on %s, has it been removed? Should I delete from db?" % (curEpToWrite.season, curEpToWrite.episode, srIndexerApi(ep_obj.show.indexer).name))
                return None

            if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None):
                myEp["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["seriesname"] + "\n")
                data += ("seriesTitle : " + myShow["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["zap2it_id"] + "\n")

            # This is the call sign of the channel the episode was recorded from.
            if getattr(myShow, 'network', None):
                data += ("callsign : " + myShow["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["_actors"]:
                    if 'name' in actor and actor['name'].strip():
                        data += ("vActor : " + actor['name'].strip() + "\n")

            # This is shown on both the Program screen and the Details screen.
            if getattr(myEp, 'rating', None):
                try:
                    rating = float(myEp['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["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
示例#55
0
文件: trakt.py 项目: afctim/SiCKRAGE
    def update_watchlist(self, show_obj=None, s=None, e=None, data_show=None, data_episode=None, update="add"):

        """
        Sends a request to trakt indicating that the given episode is part of our library.

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

        trakt_api = TraktAPI(sickrage.srCore.srConfig.SSL_VERIFY, sickrage.srCore.srConfig.TRAKT_TIMEOUT)

        if sickrage.srCore.srConfig.USE_TRAKT:

            data = {}
            try:
                # URL parameters
                if show_obj is not None:
                    trakt_id = srIndexerApi(show_obj.indexer).config['trakt_id']
                    data = {
                        'shows': [
                            {
                                'title': show_obj.name,
                                'year': show_obj.startyear,
                                'ids': {},
                            }
                        ]
                    }

                    if trakt_id == 'tvdb_id':
                        data['shows'][0]['ids']['tvdb'] = show_obj.indexerid
                    else:
                        data['shows'][0]['ids']['tvrage'] = show_obj.indexerid
                elif data_show is not None:
                    data.update(data_show)
                else:
                    sickrage.srCore.srLogger.warning(
                        "there's a coding problem contact developer. It's needed to be provided at lest one of the two: data_show or show_obj")
                    return False

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

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

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

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

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

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

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

            except (traktException, traktAuthException, traktServerBusy) as e:
                sickrage.srCore.srLogger.warning("Could not connect to Trakt service: %s" % e)
                return False

        return True
示例#56
0
文件: show.py 项目: afctim/SiCKRAGE
    def run(self):
        super(QueueItemUpdate, self).run()

        sickrage.srCore.srLogger.info("Performing updates for show: {}".format(self.show.name))

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

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

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

        # get episode list from DB
        DBEpList = self.show.loadEpisodesFromDB() if not self.force else {}

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

        if IndexerEpList is None:
            sickrage.srCore.srLogger.error("No data returned from " + srIndexerApi(
                self.show.indexer).name + ", unable to update this show")
        else:
            # for each ep we found on the Indexer not in the DB list add to DB
            sql_l = []
            for curSeason in IndexerEpList:
                for curEpisode in set(IndexerEpList[curSeason]).difference(DBEpList.get(curSeason, {})):
                    sql_q = self.show.getEpisode(curSeason, curEpisode, forceIndexer=True).saveToDB(False)
                    if sql_q:
                        sql_l.append(sql_q)

            if len(sql_l) > 0:
                main_db.MainDB().mass_upsert(sql_l)
                del sql_l  # cleanup

            # remaining episodes in the DB list are not on the indexer, just delete them from the DB
            for curSeason in DBEpList:
                for curEpisode in set(DBEpList[curSeason]).difference(IndexerEpList.get(curSeason, {})):
                    sickrage.srCore.srLogger.info("Permanently deleting episode " + str(curSeason) + "x" + str(
                        curEpisode) + " from the database")

                    try:
                        self.show.getEpisode(curSeason, curEpisode).deleteEpisode()
                    except EpisodeDeletedException:
                        pass

        # cleanup
        scrub(DBEpList)
        scrub(IndexerEpList)

        sickrage.srCore.srLogger.info("Finished updates for show: {}".format(self.show.name))

        # refresh show
        sickrage.srCore.SHOWQUEUE.refreshShow(self.show, self.force)
示例#57
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 = srIndexerApi(ep_obj.show.indexer).api_params.copy()

            lINDEXER_API_PARMS['actors'] = True

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

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

            t = srIndexerApi(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.srCore.srLogger.error("Unable to connect to " + srIndexerApi(
                ep_obj.show.indexer).name + " while creating meta files - skipping - {}".format(e.message))
            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.srCore.srLogger.info(
                    "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" %
                    (curEpToWrite.season, curEpToWrite.episode, srIndexerApi(ep_obj.show.indexer).name))
                return None

            if ep_obj.season == 0 and not getattr(myEp, 'firstaired', None):
                myEp["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["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["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["runtime"]

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

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

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

                    cur_actor = SubElement(episode, "actor")

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

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

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

        # Make it purdy
        indentXML(rootNode)
        data = ElementTree(rootNode)
        return data