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
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")
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
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
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
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)))
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")
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")
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")
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")
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")
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")
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)))
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")
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")
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")
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
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
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)
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
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")
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
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}
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" )
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" )
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
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" )
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)
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
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")
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}
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
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)
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
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
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
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
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
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()
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())
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
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
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
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())
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
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
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
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
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
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
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))
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
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
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)
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