def addShowToTraktWatchList(self): trakt_data = [] sickrage.app.log.debug("SHOW_WATCHLIST::ADD::START - Look for Shows to Add to Trakt Watchlist") for show in sickrage.app.showlist: if not self._checkInList(IndexerApi(show.indexer).trakt_id, str(show.indexerid), 0, 0, 'Show'): sickrage.app.log.debug( "Adding Show: Indexer %s %s - %s to Watchlist" % ( IndexerApi(show.indexer).trakt_id, str(show.indexerid), show.name)) show_el = {'title': show.name, 'year': show.startyear, 'ids': {IndexerApi(show.indexer).trakt_id: show.indexerid}} trakt_data.append(show_el) if len(trakt_data): try: data = {'shows': trakt_data} srTraktAPI()["sync/watchlist"].add(data) self._getShowWatchlist() except Exception as e: sickrage.app.log.warning("Could not connect to Trakt service. Error: %s" % e) sickrage.app.log.debug("SHOW_WATCHLIST::ADD::FINISH - Look for Shows to Add to Trakt Watchlist")
def _xem_exceptions_fetcher(force=False): if should_refresh('xem') or force: sickrage.app.log.info("Checking for XEM scene exception updates") for indexer in IndexerApi().indexers: url = "http://thexem.de/map/allNames?origin=%s&seasonNumbers=1" % IndexerApi(indexer).config[ 'xem_origin'] try: parsedJSON = WebSession().get(url, timeout=90).json() except Exception: sickrage.app.log.debug("Check scene exceptions update failed for " + IndexerApi( indexer).name + ", Unable to get URL: " + url) continue if parsedJSON['result'] == 'failure': continue for indexer_id, names in parsedJSON['data'].items(): try: xem_exception_dict[int(indexer_id)] = names except Exception as e: sickrage.app.log.warning( "XEM: Rejected entry: indexer_id:{0}; names:{1}".format(indexer_id, names)) sickrage.app.log.debug("XEM: Rejected entry error message:{}".format(e)) set_last_refresh('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 or sickrage.app.config.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 = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang t = IndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) # Give us just the normal season graphics image_data = t.images(show_obj.indexer_id, key_type='seasonwide', season=season) if image_data: return image_data[which]['filename'] sickrage.app.log.debug( "{}: No season {} banner images on {} to download found".format(show_obj.indexer_id, season, IndexerApi(show_obj.indexer).name)) except (KeyError, IndexError): pass
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 or sickrage.app.config.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 = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang t = IndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) # Give us just the normal season graphics return t.images(show_obj.indexerid, key_type='seasonwide', season=season)[which]['filename'] except (indexer_error, IOError) as e: sickrage.app.log.warning("{}: Unable to look up show on ".format(show_obj.indexerid) + IndexerApi( show_obj.indexer).name + ", not downloading images: {}".format(e)) sickrage.app.log.debug("Indexer " + IndexerApi( show_obj.indexer).name + " maybe experiencing some problems. Try again later") except (KeyError, IndexError): pass
def run(self, force=False): if self.amActive: return self.amActive = True # set thread name threading.currentThread().setName(self.name) update_timestamp = int(time.mktime( datetime.datetime.now().timetuple())) try: dbData = sickrage.app.cache_db.db.get('lastUpdate', 'theTVDB', with_doc=True)['doc'] last_update = int(dbData['time']) except RecordNotFound: last_update = update_timestamp dbData = sickrage.app.cache_db.db.insert({ '_t': 'lastUpdate', 'provider': 'theTVDB', 'time': 0 }) # get indexer updated show ids indexer_api = IndexerApi().indexer(**IndexerApi().api_params.copy()) updated_shows = set(s["id"] for s in indexer_api.updated(last_update) or {}) # start update process pi_list = [] for show in sickrage.app.showlist: if show.paused: sickrage.app.log.info( 'Show update skipped, show: {} is paused.'.format( show.name)) try: show.nextEpisode() stale = ( datetime.datetime.now() - datetime.datetime.fromordinal(show.last_update)).days > 7 if show.indexerid in updated_shows or stale: pi_list.append( sickrage.app.show_queue.updateShow(show, False)) else: pi_list.append( sickrage.app.show_queue.refreshShow(show, False)) except (CantUpdateShowException, CantRefreshShowException) as e: sickrage.app.log.debug("Automatic update failed: {}".format( e.message)) ProgressIndicators.setIndicator( 'dailyShowUpdates', QueueProgressIndicator("Daily Show Updates", pi_list)) dbData['time'] = update_timestamp sickrage.app.cache_db.db.update(dbData) self.amActive = False
def updateShows(self): sickrage.app.log.debug("SHOW_WATCHLIST::CHECK::START - Trakt Show Watchlist") if not len(self.ShowWatchlist): sickrage.app.log.debug("No shows found in your watchlist, aborting watchlist update") return for key, show in self.ShowWatchlist.items(): # get traktID and indexerID values trakt_id, indexer_id = key try: # determine indexer = IndexerApi().indexersByTraktID[trakt_id] except KeyError: continue if trakt_id == IndexerApi(indexer).trakt_id: if int(sickrage.app.config.trakt_method_add) != 2: self.addDefaultShow(indexer, indexer_id, show.title, SKIPPED) else: self.addDefaultShow(indexer, indexer_id, show.title, WANTED) if int(sickrage.app.config.trakt_method_add) == 1: newShow = findCertainShow(indexer_id) if newShow is not None: setEpisodeToWanted(newShow, 1, 1) else: self.todoWanted.append((indexer_id, 1, 1)) sickrage.app.log.debug("SHOW_WATCHLIST::CHECK::FINISH - Trakt Show Watchlist")
def load_from_indexer(self, cache=True, tvapi=None): if self.indexer is not INDEXER_TVRAGE: sickrage.app.log.debug( str(self.indexer_id) + ": Loading show info from " + IndexerApi(self.indexer).name) t = tvapi if not t: lINDEXER_API_PARMS = IndexerApi(self.indexer).api_params.copy() lINDEXER_API_PARMS['cache'] = cache lINDEXER_API_PARMS[ 'language'] = self.lang or sickrage.app.config.indexer_default_language if self.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) myEp = t[self.indexer_id] if not myEp: return try: self.name = myEp['seriesname'].strip() except AttributeError: raise indexer_attributenotfound( "Found %s, but attribute 'seriesname' was empty." % self.indexer_id) self.overview = safe_getattr(myEp, 'overview', self.overview) self.classification = safe_getattr(myEp, 'classification', self.classification) self.genre = safe_getattr(myEp, 'genre', self.genre) self.network = safe_getattr(myEp, 'network', self.network) self.runtime = try_int(safe_getattr(myEp, 'runtime', self.runtime)) self.imdb_id = safe_getattr(myEp, 'imdbid', self.imdb_id) try: self.airs = (safe_getattr(myEp, 'airsdayofweek') + " " + safe_getattr(myEp, 'airstime')).strip() except: self.airs = '' try: self.startyear = try_int( str(safe_getattr(myEp, 'firstaired') or datetime.date.min).split('-')[0]) except: self.startyear = 0 self.status = safe_getattr(myEp, 'status', self.status) else: sickrage.app.log.warning( str(self.indexer_id) + ": NOT loading info from " + IndexerApi(self.indexer).name + " as it is temporarily disabled.") object_session(self).commit()
def load_episodes_from_indexer(self, cache=True): scanned_eps = {} l_indexer_api_parms = IndexerApi(self.indexer).api_params.copy() l_indexer_api_parms['cache'] = cache l_indexer_api_parms[ 'language'] = self.lang or sickrage.app.config.indexer_default_language if self.dvdorder != 0: l_indexer_api_parms['dvdorder'] = True t = IndexerApi(self.indexer).indexer(**l_indexer_api_parms) sickrage.app.log.debug( str(self.indexer_id) + ": Loading all episodes from " + IndexerApi(self.indexer).name + "..") for season in t[self.indexer_id]: scanned_eps[season] = {} for episode in t[self.indexer_id][season]: # need some examples of wtf episode 0 means to decide if we want it or not if episode == 0: continue try: episode_obj = self.get_episode(season, episode) except EpisodeNotFoundException: object_session(self).add( TVEpisode( **{ 'showid': self.indexer_id, 'indexer': self.indexer, 'season': season, 'episode': episode, 'location': '' })) object_session(self).commit() episode_obj = self.get_episode(season, episode) sickrage.app.log.debug( "%s: Loading info from %s for episode S%02dE%02d" % (self.indexer_id, IndexerApi(self.indexer).name, season or 0, episode or 0)) try: episode_obj.populate_episode(season, episode, tvapi=t) except EpisodeNotFoundException: continue scanned_eps[season][episode] = True # Done updating save last update date self.last_update = datetime.date.today().toordinal() object_session(self).commit() return scanned_eps
def run(self, force=False): if self.amActive: return self.amActive = True # set thread name threading.currentThread().setName(self.name) update_timestamp = int(time.mktime(datetime.datetime.now().timetuple())) dbData = sickrage.app.cache_db.get('lastUpdate', 'theTVDB') if dbData: last_update = int(dbData['time']) else: last_update = update_timestamp dbData = sickrage.app.cache_db.insert({ '_t': 'lastUpdate', 'provider': 'theTVDB', 'time': 0 }) # get indexer updated show ids indexer_api = IndexerApi().indexer(**IndexerApi().api_params.copy()) updated_shows = set(s["id"] for s in indexer_api.updated(last_update) or {}) # start update process pi_list = [] for show in sickrage.app.showlist: if show.paused: sickrage.app.log.info('Show update skipped, show: {} is paused.'.format(show.name)) continue if show.status == 'Ended': if not sickrage.app.config.showupdate_stale: sickrage.app.log.info('Show update skipped, show: {} status is ended.'.format(show.name)) continue elif not (datetime.datetime.now() - datetime.datetime.fromordinal(show.last_update)).days >= 90: sickrage.app.log.info( 'Show update skipped, show: {} status is ended and recently updated.'.format(show.name)) continue try: if show.indexerid in updated_shows: pi_list.append(sickrage.app.show_queue.updateShow(show, indexer_update_only=True, force=False)) elif (datetime.datetime.now() - datetime.datetime.fromordinal(show.last_update)).days >= 7: pi_list.append(sickrage.app.show_queue.updateShow(show, force=False)) #else: # pi_list.append(sickrage.app.show_queue.refreshShow(show, False)) except (CantUpdateShowException, CantRefreshShowException) as e: sickrage.app.log.debug("Automatic update failed: {}".format(e)) ProgressIndicators.setIndicator('dailyShowUpdates', QueueProgressIndicator("Daily Show Updates", pi_list)) dbData['time'] = update_timestamp sickrage.app.cache_db.update(dbData) self.amActive = False
def _retrieve_show_image(self, image_type, show_obj, which=0): """ Gets an image URL from theTVDB.com and fanart.tv, downloads it and returns the data. image_type: type of image to retrieve (currently supported: fanart, poster, banner) show_obj: a TVShow object to use when searching for the image which: optional, a specific numbered poster to look for Returns: the binary image data if available, or else None """ image_data = None indexer_lang = show_obj.lang or sickrage.app.config.indexer_default_language if image_type not in ('fanart', 'poster', 'series', 'poster_thumb', 'series_thumb', 'fanart_thumb'): sickrage.app.log.warning("Invalid image type " + str(image_type) + ", couldn't find it in the " + IndexerApi(show_obj.indexer).name + " object") return # There's gotta be a better way of doing this but we don't wanna # change the language value elsewhere lINDEXER_API_PARMS = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if show_obj.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) is_image_thumb = '_thumb' in image_type image_types = { '{}'.format(image_type): { 'indexer': lambda: t.images(show_obj.indexer_id, key_type=image_type.replace('_thumb', ''))[which][('filename', 'thumbnail')[is_image_thumb]], 'fanart': lambda: self._retrieve_show_images_from_fanart(show_obj, image_type.replace('_thumb', ''), is_image_thumb) } } for fname in ['indexer', 'fanart']: try: image_url = image_types[image_type][fname]() if image_url: image_data = self.get_show_image(image_url) if image_data: break except (KeyError, IndexError, TypeError) as e: pass return image_data
def add_episodes_to_trakt_collection(self): trakt_data = [] sickrage.app.log.debug( "COLLECTION::SYNC::START - Look for Episodes to Add to Trakt Collection" ) for s in get_show_list(): for e in s.episodes: trakt_id = IndexerApi(s.indexer).trakt_id if not self._check_in_list(trakt_id, str(e.showid), e.season, e.episode, 'Collection'): sickrage.app.log.debug( "Adding Episode %s S%02dE%02d to collection" % (s.name, e.season, e.episode)) trakt_data.append((e.showid, s.indexer, s.name, s.startyear, e.season, e.episode)) if len(trakt_data): try: TraktAPI()["sync/collection"].add( self.trakt_bulk_data_generate(trakt_data)) self._get_show_collection() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error: %s" % e) sickrage.app.log.debug( "COLLECTION::ADD::FINISH - Look for Episodes to Add to Trakt Collection" )
def removeEpisodesFromTraktCollection(self): trakt_data = [] sickrage.app.log.debug( "COLLECTION::REMOVE::START - Look for Episodes to Remove From Trakt Collection" ) for s in sickrage.app.showlist: for e in sickrage.app.main_db.get_many('tv_episodes', s.indexerid): if e["location"]: continue trakt_id = IndexerApi(s.indexer).trakt_id if self._checkInList(trakt_id, str(e["showid"]), e["season"], e["episode"], 'Collection'): sickrage.app.log.debug( "Removing Episode %s S%02dE%02d from collection" % (s.name, e["season"], e["episode"])) trakt_data.append((e["showid"], s.indexer, s.name, s.startyear, e["season"], e["episode"])) if len(trakt_data): try: srTraktAPI()["sync/collection"].remove( self.trakt_bulk_data_generate(trakt_data)) self._getShowCollection() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error: %s" % e) sickrage.app.log.debug( "COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection" )
def add_episodes_to_trakt_watch_list(self): session = sickrage.app.main_db.session() trakt_data = [] sickrage.app.log.debug( "WATCHLIST::ADD::START - Look for Episodes to Add to Trakt Watchlist" ) for s in get_show_list(): for e in session.query(MainDB.TVEpisode).filter_by( showid=s.indexer_id).filter(~MainDB.TVEpisode.episode.in_( Quality.SNATCHED + Quality.SNATCHED_PROPER + [UNKNOWN] + [WANTED])): trakt_id = IndexerApi(s.indexer).trakt_id if self._check_in_list(trakt_id, str(e.showid), e.season, e.episode): sickrage.app.log.debug( "Adding Episode %s S%02dE%02d to watchlist" % (s.name, e.season, e.episode)) trakt_data.append((e.showid, s.indexer, s.name, s.startyear, e.season, e.episode)) if len(trakt_data): try: data = self.trakt_bulk_data_generate(trakt_data) TraktAPI()["sync/watchlist"].add(data) self._get_episode_watchlist() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error %s" % e) sickrage.app.log.debug( "WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist" )
def trakt_bulk_data_generate(data): """ Build the JSON structure to send back to Trakt """ show_list = [] shows = {} seasons = {} for indexerid, indexer, show_name, startyear, season, episode in data: if indexerid not in shows: shows[indexerid] = {'title': show_name, 'year': startyear, 'ids': {IndexerApi(indexer).trakt_id: indexerid}} if indexerid not in seasons: seasons[indexerid] = {} if season not in seasons[indexerid]: seasons[indexerid] = {season: []} if episode not in seasons[indexerid][season]: seasons[indexerid][season] += [{'number': episode}] for indexerid, seasonlist in seasons.items(): if 'seasons' not in shows[indexerid]: shows[indexerid]['seasons'] = [] for season, episodelist in seasonlist.items(): shows[indexerid]['seasons'] += [{'number': season, 'episodes': episodelist}] show_list.append(shows[indexerid]) return {'shows': show_list}
def remove_episodes_from_trakt_watch_list(self): trakt_data = [] sickrage.app.log.debug( "WATCHLIST::REMOVE::START - Look for Episodes to Remove from Trakt Watchlist" ) for s in get_show_list(): for e in s.episodes: trakt_id = IndexerApi(s.indexer).trakt_id if self._check_in_list(trakt_id, str(e.showid), e.season, e.episode): sickrage.app.log.debug( "Removing Episode %s S%02dE%02d from watchlist" % (s.name, e.season, e.episode)) trakt_data.append((e.showid, s.indexer, s.name, s.startyear, e.season, e.episode)) if len(trakt_data): try: data = self.trakt_bulk_data_generate(trakt_data) TraktAPI()["sync/watchlist"].remove(data) self._get_episode_watchlist() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error: %s" % e) sickrage.app.log.debug( "WATCHLIST::REMOVE::FINISH - Look for Episodes to Remove from Trakt Watchlist" )
def addEpisodesToTraktWatchList(self): trakt_data = [] sickrage.app.log.debug( "WATCHLIST::ADD::START - Look for Episodes to Add to Trakt Watchlist" ) for s in sickrage.app.showlist: for e in sickrage.app.main_db.get_many('tv_episodes', s.indexerid): if not e[ 'status'] in Quality.SNATCHED + Quality.SNATCHED_PROPER + [ UNKNOWN ] + [WANTED]: continue trakt_id = IndexerApi(s.indexer).trakt_id if self._checkInList(trakt_id, str(e["showid"]), e["season"], e["episode"]): sickrage.app.log.debug( "Adding Episode %s S%02dE%02d to watchlist" % (s.name, e["season"], e["episode"])) trakt_data.append((e["showid"], s.indexer, s.name, s.startyear, e["season"], e["episode"])) if len(trakt_data): try: data = self.trakt_bulk_data_generate(trakt_data) srTraktAPI()["sync/watchlist"].add(data) self._getEpisodeWatchlist() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error %s" % e) sickrage.app.log.debug( "WATCHLIST::ADD::FINISH - Look for Episodes to Add to Trakt Watchlist" )
def remove_episodes_from_trakt_collection(self): trakt_data = [] sickrage.app.log.debug( "COLLECTION::REMOVE::START - Look for Episodes to Remove From Trakt Collection" ) for s in get_show_list(): for e in s.episodes: if e.location: continue trakt_id = IndexerApi(s.indexer).trakt_id if self._check_in_list(trakt_id, str(e.showid), e.season, e.episode, 'Collection'): sickrage.app.log.debug( "Removing Episode %s S%02dE%02d from collection" % (s.name, e.season, e.episode)) trakt_data.append((e.showid, s.indexer, s.name, s.startyear, e.season, e.episode)) if len(trakt_data): try: TraktAPI()["sync/collection"].remove( self.trakt_bulk_data_generate(trakt_data)) self._get_show_collection() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error: %s" % e) sickrage.app.log.debug( "COLLECTION::REMOVE::FINISH - Look for Episodes to Remove From Trakt Collection" )
def add_show_to_trakt_library(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.find_show_match(show_obj.indexer, show_obj.indexer_id): # URL parameters data = { 'shows': [{ 'title': show_obj.name, 'year': show_obj.startyear, 'ids': { IndexerApi(show_obj.indexer).trakt_id: show_obj.indexer_id } }] } if len(data): sickrage.app.log.debug("Adding %s to tv library" % show_obj.name) try: TraktAPI()["sync/collection"].add(data) except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Aborting adding show %s to Trakt library. Error: %s" % (show_obj.name, repr(e))) return
def removeEpisodesFromTraktWatchList(self): trakt_data = [] sickrage.app.log.debug( "WATCHLIST::REMOVE::START - Look for Episodes to Remove from Trakt Watchlist" ) for s in sickrage.app.showlist: for e in sickrage.app.main_db.get_many('tv_episodes', s.indexerid): trakt_id = IndexerApi(s.indexer).trakt_id if self._checkInList(trakt_id, str(e["showid"]), e["season"], e["episode"]): sickrage.app.log.debug( "Removing Episode %s S%02dE%02d from watchlist" % (s.name, e["season"], e["episode"])) trakt_data.append((e["showid"], s.indexer, s.name, s.startyear, e["season"], e["episode"])) if len(trakt_data): try: data = self.trakt_bulk_data_generate(trakt_data) srTraktAPI()["sync/watchlist"].remove(data) self._getEpisodeWatchlist() except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Error: %s" % e) sickrage.app.log.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 = int(time.mktime(datetime.datetime.now().timetuple())) try: dbData = sickrage.app.cache_db.db.get('lastUpdate', 'theTVDB', with_doc=True)['doc'] last_update = int(dbData['time']) except RecordNotFound: last_update = update_timestamp dbData = sickrage.app.cache_db.db.insert({ '_t': 'lastUpdate', 'provider': 'theTVDB', 'time': 0 }) # get indexer updated show ids indexer_api = IndexerApi().indexer(**IndexerApi().api_params.copy()) updated_shows = set(s["id"] for s in indexer_api.updated(last_update) or {}) # start update process pi_list = [] for show in sickrage.app.showlist: if show.paused: sickrage.app.log.info('Show update skipped, show: {} is paused.'.format(show.name)) try: show.nextEpisode() stale = (datetime.datetime.now() - datetime.datetime.fromordinal(show.last_update)).days > 7 if show.indexerid in updated_shows or stale: pi_list.append(sickrage.app.show_queue.updateShow(show, False)) else: pi_list.append(sickrage.app.show_queue.refreshShow(show, False)) except (CantUpdateShowException, CantRefreshShowException) as e: sickrage.app.log.debug("Automatic update failed: {}".format(e.message)) ProgressIndicators.setIndicator('dailyShowUpdates', QueueProgressIndicator("Daily Show Updates", pi_list)) dbData['time'] = update_timestamp sickrage.app.cache_db.db.update(dbData) self.amActive = False
def validateShow(show, season=None, episode=None): indexer_lang = show.lang or sickrage.app.config.indexer_default_language try: lINDEXER_API_PARMS = IndexerApi(show.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if show.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(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 _retrieve_show_image(self, image_type, show_obj, which=0): """ Gets an image URL from theTVDB.com and fanart.tv, downloads it and returns the data. image_type: type of image to retrieve (currently supported: fanart, poster, banner) show_obj: a TVShow object to use when searching for the image which: optional, a specific numbered poster to look for Returns: the binary image data if available, or else None """ image_data = None indexer_lang = show_obj.lang or sickrage.app.config.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 = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if show_obj.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) except (indexer_error, IOError) as e: sickrage.app.log.warning("{}: Unable to look up show on ".format(show_obj.indexerid) + IndexerApi( show_obj.indexer).name + ", not downloading images: {}".format(e)) sickrage.app.log.debug("Indexer " + IndexerApi( show_obj.indexer).name + " maybe experiencing some problems. Try again later") return None if image_type not in ('fanart', 'poster', 'series', 'poster_thumb', 'series_thumb'): sickrage.app.log.warning( "Invalid image type " + str(image_type) + ", couldn't find it in the " + IndexerApi( show_obj.indexer).name + " object") return if image_type == 'poster_thumb': try: image_url = t.images(show_obj.indexerid, key_type='poster')[which]['thumbnail'] except (KeyError, IndexError): image_url = self._retrieve_show_images_from_fanart(show_obj, image_type, True) elif image_type == 'series_thumb': try: image_url = t.images(show_obj.indexerid, key_type='series')[which]['thumbnail'] except (KeyError, IndexError): image_url = self._retrieve_show_images_from_fanart(show_obj, image_type, True) else: try: image_url = t.images(show_obj.indexerid, key_type=image_type)[which]['filename'] except (KeyError, IndexError): image_url = self._retrieve_show_images_from_fanart(show_obj, image_type) if image_url: image_data = getShowImage(image_url) return image_data
def update_episodes(self): """ Sets episodes to wanted that are in trakt watchlist """ sickrage.app.log.debug( "SHOW_WATCHLIST::CHECK::START - Trakt Episode Watchlist") if not len(self.EpisodeWatchlist): sickrage.app.log.debug( "No episode found in your watchlist, aborting episode update") return managed_show = [] for key, show in self.EpisodeWatchlist.items(): # get traktID and indexerID values trakt_id, indexer_id = key try: # determine indexer = IndexerApi().indexersByTraktID[trakt_id] except KeyError: continue show_object = find_show(indexer_id) try: if show_object is None: if indexer_id not in managed_show: self.add_default_show(indexer, indexer_id, show.title, SKIPPED) managed_show.append(indexer_id) for season_number, season in show.seasons.items(): for episode_number, _ in season.episodes.items(): self.todoWanted.append( (int(indexer_id), int(season_number), int(episode_number))) else: if show_object.indexer == indexer: for season_number, season in show.seasons.items(): for episode_number, _ in season.episodes.items(): set_episode_to_wanted(show_object, int(season_number), int(episode_number)) except TypeError: sickrage.app.log.debug( "Could not parse the output from trakt for %s " % show.title) sickrage.app.log.debug( "SHOW_WATCHLIST::CHECK::FINISH - Trakt Episode Watchlist")
async def get(self, *args, **kwargs): indexer_id = self.get_argument('indexer_id') show_name = self.get_argument('showName') if re.search(r'tt\d+', indexer_id): l_indexer_api_parms = IndexerApi(1).api_params.copy() t = IndexerApi(1).indexer(**l_indexer_api_parms) indexer_id = t[indexer_id]['id'] if find_show(int(indexer_id), session=self.db_session): return location = None if sickrage.app.config.root_dirs: root_dirs = sickrage.app.config.root_dirs.split('|') location = root_dirs[int(root_dirs[0]) + 1] if not location: sickrage.app.log.warning( "There was an error creating the show, no root directory setting found" ) return self.write( _('No root directories setup, please go back and add one.')) show_dir = os.path.join(location, sanitize_file_name(show_name)) response = await TornadoHTTP().get( url_concat( self.get_url("/home/addShows/newShow"), { 'show_to_add': '1|{show_dir}|{indexer_id}|{show_name}'.format( **{ 'show_dir': show_dir, 'indexer_id': indexer_id, 'show_name': show_name }) })) return self.write(response.body)
def indexerImage(id=None, which=None): media_format = ('normal', 'thumb')[which in ('banner_thumb', 'poster_thumb', 'small')] image_type = which[0:6] if image_type not in ('fanart', 'poster', 'banner'): sickrage.app.log.error( "Invalid image type " + str(image_type) + ", couldn't find it in the " + IndexerApi( INDEXER_TVDB).name + " object") return try: lINDEXER_API_PARMS = IndexerApi(INDEXER_TVDB).api_params.copy() t = IndexerApi(INDEXER_TVDB).indexer(**lINDEXER_API_PARMS) image_name = str(id) + '.' + image_type + '.jpg' try: if media_format == "thumb": image_path = os.path.join(ImageCache()._thumbnails_dir(), image_name) if not os.path.exists(image_path): image_url = t.images(int(id), key_type=image_type)[0]['thumbnail'] sickrage.app.wsession.download(image_url, image_path) else: image_path = os.path.join(ImageCache()._cache_dir(), image_name) if not os.path.exists(image_path): image_url = t.images(int(id), key_type=image_type)[0]['filename'] sickrage.app.wsession.download(image_url, image_path) except (KeyError, IndexError): return if image_type == 'banner': return Banner(int(id), media_format).url elif image_type == 'fanart': return FanArt(int(id), media_format).url elif image_type == 'poster': return Poster(int(id), media_format).url except (indexer_error, IOError) as e: sickrage.app.log.warning("{}: Unable to look up show on ".format(id) + IndexerApi( INDEXER_TVDB).name + ", not downloading images: {}".format(e.message))
def map_indexers(indexer, indexer_id, name): session = sickrage.app.main_db.session() mapped = {} # init mapped indexers object for mindexer in IndexerApi().indexers: mapped[mindexer] = indexer_id if int(mindexer) == int(indexer) else 0 # for each mapped entry for dbData in session.query(MainDB.IndexerMapping).filter_by( indexer_id=indexer_id, indexer=indexer): # Check if its mapped with both tvdb and tvrage. if len([i for i in dbData if i is not None]) >= 4: sickrage.app.log.debug( "Found indexer mapping in cache for show: " + name) mapped[int(dbData.mindexer)] = int(dbData.mindexer_id) return mapped else: for mindexer in IndexerApi().indexers: if mindexer == indexer: mapped[mindexer] = indexer_id continue indexer_api_parms = IndexerApi(mindexer).api_params.copy() indexer_api_parms['custom_ui'] = ShowListUI t = IndexerApi(mindexer).indexer(**indexer_api_parms) mapped_show = t[name] if not mapped_show: continue if mapped_show and len(mapped_show) == 1: sickrage.app.log.debug("Mapping " + IndexerApi(indexer).name + "->" + IndexerApi(mindexer).name + " for show: " + name) mapped[mindexer] = int(mapped_show['id']) sickrage.app.log.debug( "Adding indexer mapping to DB for show: " + name) try: session.query(MainDB.IndexerMapping).filter_by( indexer_id=indexer_id, indexer=indexer, mindexer_id=int(mapped_show['id'])).one() except orm.exc.NoResultFound: session.add( MainDB.IndexerMapping( **{ 'indexer_id': indexer_id, 'indexer': indexer, 'mindexer_id': int(mapped_show['id']), 'mindexer': mindexer })) session.commit() return mapped
def get(self, *args, **kwargs): """ Display the new show page which collects a tvdb id, folder, and extra options and posts them to addNewShow """ show_to_add = self.get_argument('show_to_add', None) other_shows = self.get_arguments('other_shows') search_string = self.get_argument('search_string', None) indexer, show_dir, indexer_id, show_name = split_extra_show( show_to_add) use_provided_info = False if indexer_id and indexer and show_name: use_provided_info = True # use the given show_dir for the indexer search if available default_show_name = show_name or '' if not show_dir and search_string: default_show_name = search_string elif not show_name and show_dir: default_show_name = re.sub( r' \(\d{4}\)', '', os.path.basename(os.path.normpath(show_dir)).replace('.', ' ')) provided_indexer_id = int(indexer_id or 0) provided_indexer_name = show_name or '' provided_indexer = int(indexer or sickrage.app.config.indexer_default) return self.render("/home/new_show.mako", enable_anime_options=True, use_provided_info=use_provided_info, default_show_name=default_show_name, other_shows=other_shows, provided_show_dir=show_dir, provided_indexer_id=provided_indexer_id, provided_indexer_name=provided_indexer_name, provided_indexer=provided_indexer, indexers=IndexerApi().indexers, quality=sickrage.app.config.quality_default, whitelist=[], blacklist=[], groups=[], title=_('New Show'), header=_('New Show'), topmenu='home', controller='home', action="new_show")
def findShowMatch(self, indexer, indexerid): traktShow = None try: library = srTraktAPI()["sync/collection"].shows() or {} if not library: sickrage.app.log.debug("No shows found in your library, aborting library update") return traktShow = [x for __, x in library.items() if int(indexerid) == int(x.ids[IndexerApi(indexer).trakt_id])] except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service. Aborting library check. Error: %s" % repr(e)) return traktShow
async def get(self, *args, **kwargs): search_term = self.get_argument('search_term') indexer = self.get_argument('indexer') lang = self.get_argument('lang', None) if not lang or lang == 'null': lang = sickrage.app.config.indexer_default_language results = {} final_results = [] # Query Indexers for each search term and build the list of results for indexer in IndexerApi().indexers if not int(indexer) else [ int(indexer) ]: l_indexer_api_parms = IndexerApi(indexer).api_params.copy() l_indexer_api_parms['language'] = lang l_indexer_api_parms['custom_ui'] = AllShowsUI t = IndexerApi(indexer).indexer(**l_indexer_api_parms) sickrage.app.log.debug( "Searching for Show with term: %s on Indexer: %s" % (search_term, IndexerApi(indexer).name)) try: # search via series name result = await self.run_task(lambda: t[search_term]) if isinstance(result, dict): result = [result] results.setdefault(indexer, []).extend(result) except Exception: continue for i, shows in results.items(): final_results.extend([[ IndexerApi(i).name, i, IndexerApi(i).config["show_url"], int(show['id']), show['seriesname'], show['firstaired'], ('', 'disabled')[isinstance(find_show(int(show['id'])), TVShow)] ] for show in shows]) lang_id = IndexerApi().indexer().languages[lang] or 7 return self.write( json_encode({ 'results': final_results, 'langid': lang_id }))
def trakt_show_data_generate(self, data): showList = [] for indexer, indexer_id, title, year in data: show = { 'title': title, 'year': year, 'ids': { IndexerApi(indexer).trakt_id: indexer_id } } showList.append(show) post_data = {'shows': showList} return post_data
def get_show(self, name): show = None show_id = 0 fromCache = False if not all([name, sickrage.app.showlist]): return show, show_id try: # check cache for show cache = sickrage.app.name_cache.get(name) if cache: fromCache = True show_id = cache # try indexers if not show_id and self.tryIndexers: try: show_id1 = int(IndexerApi().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.app.showlist, int(show_id)) if show_id else None # add show to cache if show and not fromCache: sickrage.app.name_cache.put(name, show.indexerid) except Exception as e: sickrage.app.log.debug( "Error when attempting to find show: %s in SiCKRAGE. Error: %r " % (name, repr(e))) return show, show_id or 0
def update_library(self, ep_obj): """ Sends a request to trakt indicating that the given episode is part of our library. ep_obj: The TVEpisode object to add to trakt """ if sickrage.app.config.use_trakt: try: # URL parameters data = { 'shows': [{ 'title': ep_obj.show.name, 'year': ep_obj.show.startyear, 'ids': { IndexerApi(ep_obj.show.indexer).trakt_id: ep_obj.show.indexer_id }, }] } if sickrage.app.config.trakt_sync_watchlist: if sickrage.app.config.trakt_remove_serieslist: TraktAPI()["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.related_episodes: data['shows'][0]['seasons'][0]['episodes'].append( {'number': relEp_Obj.episode}) if sickrage.app.config.trakt_sync_watchlist: if sickrage.app.config.trakt_remove_watchlist: TraktAPI()["sync/watchlist"].remove(data) # update library TraktAPI()["sync/collection"].add(data) except Exception as e: sickrage.app.log.warning( "Could not connect to Trakt service: %s" % e)
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 or sickrage.app.config.indexer_default_language try: lINDEXER_API_PARMS = IndexerApi(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 = IndexerApi(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.app.log.error("Unable to connect to " + IndexerApi( 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.app.log.info( "Unable to find episode %dx%d on %s, has it been removed? Should I delete from db?" % ( curEpToWrite.season, curEpToWrite.episode, IndexerApi(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. for actor in t.actors(int(ep_obj.show.indexerid)): 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 _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 or sickrage.app.config.indexer_default_language lINDEXER_API_PARMS = IndexerApi(ep_obj.show.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if ep_obj.show.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True try: t = IndexerApi(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.app.log.error("Unable to connect to {} while creating meta files - skipping - {}".format( IndexerApi( 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.app.log.info( "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" % (curEpToWrite.season, curEpToWrite.episode, IndexerApi(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.app.log.debug("Not generating nfo because the ep has no title") return None sickrage.app.log.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 for actor in t.actors(int(ep_obj.show.indexerid)): 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 _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 or sickrage.app.config.indexer_default_language lINDEXER_API_PARMS = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if show_obj.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) tv_node = Element("tvshow") try: myShow = t[int(show_ID)] except indexer_shownotfound: sickrage.app.log.error("Unable to find show with id " + str(show_ID) + " on " + IndexerApi( show_obj.indexer).name + ", skipping it") raise except indexer_error: sickrage.app.log.error( "" + IndexerApi(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.app.log.info("Incomplete info for show with id " + str(show_ID) + " on " + IndexerApi( 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 = IndexerApi(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() for actor in t.actors(int(show_ID)): 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 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 or sickrage.app.config.indexer_default_language try: lINDEXER_API_PARMS = IndexerApi(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 = IndexerApi(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.app.log.error("Unable to connect to " + IndexerApi( ep_obj.show.indexer).name + " while creating meta files - skipping - {}".format(e)) return False rootNode = Element("details") # write an WDTV XML containing info for all matching episodes for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (indexer_episodenotfound, indexer_seasonnotfound): sickrage.app.log.info( "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" % (curEpToWrite.season, curEpToWrite.episode, IndexerApi(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.pretty_name() 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'] for actor in t.actors(int(ep_obj.show.indexerid)): 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
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.app.config.indexer_default_language # There's gotta be a better way of doing this but we don't wanna # change the language value elsewhere lINDEXER_API_PARMS = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if show_obj.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) tv_node = Element("Series") try: myShow = t[int(show_obj.indexerid)] except indexer_shownotfound: sickrage.app.log.error( "Unable to find show with id " + str(show_obj.indexerid) + " on " + IndexerApi( show_obj.indexer).name + ", skipping it") raise except indexer_error: sickrage.app.log.error( "" + IndexerApi(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.app.log.info( "Incomplete info for show with id " + str(show_obj.indexerid) + " on " + IndexerApi( 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, 'airstime', None): Airs_Time = SubElement(tv_node, "Airs_Time") Airs_Time.text = myShow['airstime'] if getattr(myShow, 'airsdayofweek', None): Airs_DayOfWeek = SubElement(tv_node, "Airs_DayOfWeek") Airs_DayOfWeek.text = myShow['airsdayofweek'] 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, 'imdbid', None): imdb_id = SubElement(tv_node, "IMDB_ID") imdb_id.text = myShow['imdbid'] imdb_id = SubElement(tv_node, "IMDB") imdb_id.text = myShow['imdbid'] imdb_id = SubElement(tv_node, "IMDbId") imdb_id.text = myShow['imdbid'] if getattr(myShow, 'zap2itid', None): Zap2ItId = SubElement(tv_node, "Zap2ItId") Zap2ItId.text = myShow['zap2itid'] 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'] Persons = SubElement(tv_node, "Persons") for actor in t.actors(int(show_obj.indexerid)): 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 _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 or sickrage.app.config.indexer_default_language try: lINDEXER_API_PARMS = IndexerApi(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 = IndexerApi(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.app.log.error("Unable to connect to " + IndexerApi( ep_obj.show.indexer).name + " while creating meta files - skipping - {}".format(e)) return False rootNode = Element("Item") # write an MediaBrowser XML containing info for all matching episodes for curEpToWrite in eps_to_write: try: myEp = myShow[curEpToWrite.season][curEpToWrite.episode] except (indexer_episodenotfound, indexer_seasonnotfound): sickrage.app.log.info( "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" % (curEpToWrite.season, curEpToWrite.episode, IndexerApi(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 for actor in t.actors(int(ep_obj.show.indexerid)): 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']['overview'] except Exception: Language.text = sickrage.app.config.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 EpisodeNumberEnd.text = str(curEpToWrite.episode) if curEpToWrite.name: if not EpisodeName.text: EpisodeName.text = curEpToWrite.name else: EpisodeName.text = ', '.join([EpisodeName.text, curEpToWrite.name]) if curEpToWrite.description: if not Overview.text: Overview.text = curEpToWrite.description else: Overview.text = '\r'.join([Overview.text, 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 _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.app.config.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 = IndexerApi(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 = IndexerApi(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.app.log.error( "Unable to connect to TVDB while creating meta files - skipping - {}".format(e)) 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.app.log.info( "Unable to find episode %dx%d on %s... has it been removed? Should I delete from db?" % (curEpToWrite.season, curEpToWrite.episode, IndexerApi(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'] 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 for actor in t.actors(int(ep_obj.show.indexerid)): 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 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.app.config.indexer_default_language lINDEXER_API_PARMS = IndexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS['language'] = indexer_lang if show_obj.dvdorder != 0: lINDEXER_API_PARMS['dvdorder'] = True t = IndexerApi(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.app.log.error( "Unable to find show with id " + str(show_obj.indexerid) + " on tvdb, skipping it") raise except indexer_error: sickrage.app.log.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.app.log.info( "Incomplete info for show with id " + str(show_obj.indexerid) + " on " + IndexerApi( 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'] cast = SubElement(tv_node, "cast") for actor in t.actors(int(show_obj.indexerid)): 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