def pickBestResult(results, show, quality_list=None): logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG) # build the black And white list bwl = None if show: if show.is_anime: bwl = BlackAndWhiteList(show.indexerid) else: logger.log("Could not create black and white list no show was given", logger.DEBUG) # find the best result for the current episode bestResult = None for cur_result in results: logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality]) if bwl: if not bwl.is_valid(cur_result): logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.MESSAGE) continue if quality_list and cur_result.quality not in quality_list: logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG) continue if show.rls_ignore_words and filter_release_name(cur_result.name, show.rls_ignore_words): logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words, logger.MESSAGE) continue if show.rls_require_words and not filter_release_name(cur_result.name, show.rls_require_words): logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words, logger.MESSAGE) continue if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size, cur_result.provider.name): logger.log(cur_result.name + u" has previously failed, rejecting it") continue if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN: bestResult = cur_result elif bestResult.quality == cur_result.quality: if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower(): bestResult = cur_result elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower(): bestResult = cur_result elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower(): logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)") bestResult = cur_result if bestResult: logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG) else: logger.log(u"No result picked.", logger.DEBUG) return bestResult
def makeSceneSearchString(show, ep_obj): myDB = db.DBConnection() numseasonsSQlResult = myDB.select( "SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0", [show.indexerid]) numseasons = int(numseasonsSQlResult[0][0]) # see if we should use dates instead of episodes if (show.air_by_date or show.sports) and ep_obj.airdate != datetime.date.fromordinal(1): epStrings = [str(ep_obj.airdate)] elif show.is_anime: epStrings = ["%02i" % int(ep_obj.scene_absolute_number if ep_obj.scene_absolute_number > 0 else ep_obj.scene_episode)] else: epStrings = ["S%02iE%02i" % (int(ep_obj.scene_season), int(ep_obj.scene_episode)), "%ix%02i" % (int(ep_obj.scene_season), int(ep_obj.scene_episode))] # for single-season shows just search for the show name -- if total ep count (exclude s0) is less than 11 # due to the amount of qualities and releases, it is easy to go over the 50 result limit on rss feeds otherwise if numseasons == 1 and not ep_obj.show.is_anime: epStrings = [''] bwl = BlackAndWhiteList(ep_obj.show.indexerid) showNames = set(makeSceneShowSearchStrings(show, ep_obj.scene_season)) toReturn = [] for curShow in showNames: for curEpString in epStrings: if len(bwl.whiteList) > 0: for keyword in bwl.whiteList: toReturn.append(keyword + '.' + curShow + '.' + curEpString) else: toReturn.append(curShow + '.' + curEpString) return toReturn
def isFinalResult(result): """ Checks if the given result is good enough quality that we can stop searching for other ones. If the result is the highest quality in both the any/best quality lists then this function returns True, if not then it's False """ logger.log( u"Checking if we should keep searching after we've found " + result.name, logger.DEBUG) show_obj = result.episodes[0].show bwl = None if show_obj.is_anime: bwl = BlackAndWhiteList(show_obj.indexerid) any_qualities, best_qualities = Quality.splitQuality(show_obj.quality) # if there is a redownload that's higher than this then we definitely need to keep looking if best_qualities and result.quality < max(best_qualities): return False # if it does not match the shows black and white list its no good elif bwl and not bwl.is_valid(result): return False # if there's no redownload that's higher (above) and this is the highest initial download then we're good elif any_qualities and result.quality in any_qualities: return True elif best_qualities and result.quality == max(best_qualities): # if this is the best redownload but we have a higher initial download then keep looking if any_qualities and result.quality < max(any_qualities): return False # if this is the best redownload and we don't have a higher initial download then we're done else: return True # if we got here than it's either not on the lists, they're empty, or it's lower than the highest required else: return False
def isFinalResult(result): """ Checks if the given result is good enough quality that we can stop searching for other ones. If the result is the highest quality in both the any/best quality lists then this function returns True, if not then it's False """ logger.log(u"Checking if we should keep searching after we've found " + result.name, logger.DEBUG) show_obj = result.episodes[0].show bwl = None if show_obj.is_anime: bwl = BlackAndWhiteList(show_obj.indexerid) any_qualities, best_qualities = Quality.splitQuality(show_obj.quality) # if there is a redownload that's higher than this then we definitely need to keep looking if best_qualities and result.quality < max(best_qualities): return False # if it does not match the shows black and white list its no good elif bwl and not bwl.is_valid(result): return False # if there's no redownload that's higher (above) and this is the highest initial download then we're good elif any_qualities and result.quality in any_qualities: return True elif best_qualities and result.quality == max(best_qualities): # if this is the best redownload but we have a higher initial download then keep looking if any_qualities and result.quality < max(any_qualities): return False # if this is the best redownload and we don't have a higher initial download then we're done else: return True # if we got here than it's either not on the lists, they're empty, or it's lower than the highest required else: return False
def pickBestResult(results, show, quality_list=None): results = results if isinstance(results, list) else [results] logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG) bwl = None bestResult = None # find the best result for the current episode for cur_result in results: if show and cur_result.show is not show: continue # filter out possible bad torrents from providers such as ezrss if isinstance(cur_result, sickbeard.classes.SearchResult): if cur_result.resultType == "torrent" and sickbeard.TORRENT_METHOD != "blackhole": if not cur_result.url.startswith('magnet'): cur_result.content = cur_result.provider.getURL(cur_result.url) if not cur_result.content: continue else: if not cur_result.url.startswith('magnet'): cur_result.content = cur_result.provider.getURL(cur_result.url) if not cur_result.content: continue # build the black And white list if cur_result.show.is_anime: if not bwl: bwl = BlackAndWhiteList(cur_result.show.indexerid) if not bwl.is_valid(cur_result): logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.INFO) continue logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality]) if quality_list and cur_result.quality not in quality_list: logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG) continue if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_ignore_words): logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words, logger.INFO) continue if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_require_words): logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words, logger.INFO) continue if not show_name_helpers.filterBadReleases(cur_result.name, parse=False): logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it", logger.INFO) continue if hasattr(cur_result, 'size'): if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size, cur_result.provider.name): logger.log(cur_result.name + u" has previously failed, rejecting it") continue if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN: bestResult = cur_result elif bestResult.quality == cur_result.quality: if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower(): bestResult = cur_result elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower(): bestResult = cur_result elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower(): logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)") bestResult = cur_result if bestResult: logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG) else: logger.log(u"No result picked.", logger.DEBUG) return bestResult
def run(self): ShowQueueItem.run(self) logger.log(u"Starting to add show {0}".format("by ShowDir: {0}".format(self.showDir) if self.showDir else "by Indexer Id: {0}".format(self.indexer_id))) # make sure the Indexer IDs are valid try: lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy() if self.lang: lINDEXER_API_PARMS['language'] = self.lang logger.log(u"" + str(sickbeard.indexerApi(self.indexer).name) + ": " + repr(lINDEXER_API_PARMS)) t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) s = t[self.indexer_id] # Let's try to create the show Dir if it's not provided. This way we force the show dir to build build using the # Indexers provided series name if not self.showDir and self.root_dir: show_name = get_showname_from_indexer(self.indexer, self.indexer_id, self.lang) if show_name: self.showDir = ek(os.path.join, self.root_dir, sanitize_filename(show_name)) dir_exists = makeDir(self.showDir) if not dir_exists: logger.log(u"Unable to create the folder {0}, can't add the show".format(self.showDir)) return chmodAsParent(self.showDir) else: logger.log(u"Unable to get a show {0}, can't add the show".format(self.showDir)) return # this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show if getattr(s, 'seriesname', None) is None: logger.log(u"Show in {} has no name on {}, probably searched with the wrong language.".format (self.showDir, sickbeard.indexerApi(self.indexer).name), logger.ERROR) ui.notifications.error("Unable to add show", "Show in " + self.showDir + " has no name on " + str(sickbeard.indexerApi( self.indexer).name) + ", probably the wrong language. Delete .nfo and add manually in the correct language.") self._finishEarly() return # if the show has no episodes/seasons if not s: logger.log(u"Show " + str(s['seriesname']) + " is on " + str( sickbeard.indexerApi(self.indexer).name) + " but contains no season/episode data.") ui.notifications.error("Unable to add show", "Show " + str(s['seriesname']) + " is on " + str(sickbeard.indexerApi( self.indexer).name) + " but contains no season/episode data.") self._finishEarly() return except Exception as e: logger.log(u"%s Error while loading information from indexer %s. Error: %r" % (self.indexer_id, sickbeard.indexerApi(self.indexer).name, ex(e)), logger.ERROR) # logger.log(u"Show name with ID %s doesn't exist on %s anymore. If you are using trakt, it will be removed from your TRAKT watchlist. If you are adding manually, try removing the nfo and adding again" % # (self.indexer_id, sickbeard.indexerApi(self.indexer).name), logger.WARNING) ui.notifications.error( "Unable to add show", "Unable to look up the show in %s on %s using ID %s, not using the NFO. Delete .nfo and try adding manually again." % (self.showDir, sickbeard.indexerApi(self.indexer).name, self.indexer_id) ) if sickbeard.USE_TRAKT: trakt_id = sickbeard.indexerApi(self.indexer).config['trakt_id'] trakt_api = TraktAPI(sickbeard.SSL_VERIFY, sickbeard.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') self._finishEarly() return try: newShow = TVShow(self.indexer, self.indexer_id, self.lang) newShow.loadFromIndexer() self.show = newShow # set up initial values self.show.location = self.showDir self.show.subtitles = self.subtitles if self.subtitles is not None else sickbeard.SUBTITLES_DEFAULT self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT self.show.flatten_folders = self.flatten_folders if self.flatten_folders is not None else sickbeard.FLATTEN_FOLDERS_DEFAULT self.show.anime = self.anime if self.anime is not None else sickbeard.ANIME_DEFAULT self.show.scene = self.scene if self.scene is not None else sickbeard.SCENE_DEFAULT self.show.paused = self.paused if self.paused is not None else False # set up default new/missing episode status logger.log(u"Setting all episodes to the specified default status: " + str(self.show.default_ep_status)) self.show.default_ep_status = self.default_status if self.show.anime: self.show.release_groups = BlackAndWhiteList(self.show.indexerid) if self.blacklist: self.show.release_groups.set_black_keywords(self.blacklist) if self.whitelist: self.show.release_groups.set_white_keywords(self.whitelist) # # be smartish about this # if self.show.genre and "talk show" in self.show.genre.lower(): # self.show.air_by_date = 1 # if self.show.genre and "documentary" in self.show.genre.lower(): # self.show.air_by_date = 0 # if self.show.classification and "sports" in self.show.classification.lower(): # self.show.sports = 1 except sickbeard.indexer_exception as e: logger.log( u"Unable to add show due to an error with " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.ERROR) if self.show: ui.notifications.error( "Unable to add " + str(self.show.name) + " due to an error with " + sickbeard.indexerApi( self.indexer).name + "") else: ui.notifications.error( "Unable to add show due to an error with " + sickbeard.indexerApi(self.indexer).name + "") self._finishEarly() return except MultipleShowObjectsException: logger.log(u"The show in " + self.showDir + " is already in your show list, skipping", logger.WARNING) ui.notifications.error('Show skipped', "The show in " + self.showDir + " is already in your show list") self._finishEarly() return except Exception as e: logger.log(u"Error trying to add show: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finishEarly() raise logger.log(u"Retrieving show info from IMDb", logger.DEBUG) try: self.show.loadIMDbInfo() except imdb_exceptions.IMDbError as e: logger.log(u" Something wrong on IMDb api: " + ex(e), logger.WARNING) except Exception as e: logger.log(u"Error loading IMDb info: " + ex(e), logger.ERROR) try: self.show.saveToDB() except Exception as e: logger.log(u"Error saving the show to the database: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finishEarly() raise # add it to the show list sickbeard.showList.append(self.show) try: self.show.loadEpisodesFromIndexer() except Exception as e: logger.log( u"Error with " + sickbeard.indexerApi(self.show.indexer).name + ", not creating episode list: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) # update internal name cache name_cache.buildNameCache(self.show) try: self.show.loadEpisodesFromDir() except Exception as e: logger.log(u"Error searching dir for episodes: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) # if they set default ep status to WANTED then run the backlog to search for episodes # FIXME: This needs to be a backlog queue item!!! if self.show.default_ep_status == WANTED: logger.log(u"Launching backlog for this show since its episodes are WANTED") sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) self.show.writeMetadata() self.show.updateMetadata() self.show.populateCache() self.show.flushEpisodes() if sickbeard.USE_TRAKT: # if there are specific episodes that need to be added by trakt sickbeard.traktCheckerScheduler.action.manageNewShow(self.show) # add show to trakt.tv library if sickbeard.TRAKT_SYNC: sickbeard.traktCheckerScheduler.action.addShowToTraktLibrary(self.show) if sickbeard.TRAKT_SYNC_WATCHLIST: logger.log(u"update watchlist") notifiers.trakt_notifier.update_watchlist(show_obj=self.show) # Load XEM data to DB for show sickbeard.scene_numbering.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 sickbeard.scene_numbering.get_xem_numbering_for_show(self.show.indexerid, self.show.indexer): self.show.scene = 1 # After initial add, set to default_status_after. self.show.default_ep_status = self.default_status_after self.finish()
class QueueItemAdd(ShowQueueItem): def __init__(self, indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, subtitles, anime, scene, paused, blacklist, whitelist, default_status_after, archive): self.indexer = indexer self.indexer_id = indexer_id self.showDir = showDir self.default_status = default_status self.quality = quality self.flatten_folders = flatten_folders self.lang = lang self.subtitles = subtitles self.anime = anime self.scene = scene self.paused = paused self.blacklist = blacklist self.whitelist = whitelist self.default_status_after = default_status_after self.archive = archive self.show = None # this will initialize self.show to None ShowQueueItem.__init__(self, ShowQueueActions.ADD, self.show) # Process add show in priority self.priority = generic_queue.QueuePriorities.HIGH def _getName(self): """ Returns the show name if there is a show object created, if not returns the dir that the show is being added to. """ if self.show == None: return self.showDir return self.show.name show_name = property(_getName) def _isLoading(self): """ Returns True if we've gotten far enough to have a show object, or False if we still only know the folder name. """ if self.show == None: return True return False isLoading = property(_isLoading) def run(self): ShowQueueItem.run(self) logger.log(u"Starting to add show " + self.showDir) # make sure the Indexer IDs are valid try: lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy() if self.lang: lINDEXER_API_PARMS['language'] = self.lang logger.log(u"" + str(sickbeard.indexerApi(self.indexer).name) + ": " + repr(lINDEXER_API_PARMS)) t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) s = t[self.indexer_id] # this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show if getattr(s, 'seriesname', None) is None: logger.log(u"Show in " + self.showDir + " has no name on " + str( sickbeard.indexerApi(self.indexer).name) + ", probably the wrong language used to search with.", logger.ERROR) ui.notifications.error("Unable to add show", "Show in " + self.showDir + " has no name on " + str(sickbeard.indexerApi( self.indexer).name) + ", probably the wrong language. Delete .nfo and add manually in the correct language.") self._finishEarly() return # if the show has no episodes/seasons if not s: logger.log(u"Show " + str(s['seriesname']) + " is on " + str( sickbeard.indexerApi(self.indexer).name) + " but contains no season/episode data.", logger.ERROR) ui.notifications.error("Unable to add show", "Show " + str(s['seriesname']) + " is on " + str(sickbeard.indexerApi( self.indexer).name) + " but contains no season/episode data.") self._finishEarly() return except Exception, e: logger.log(u"Error while loading information from indexer %s. Error: %r" % (self.indexer_id,sickbeard.indexerApi(self.indexer).name, ex(e)),logger.ERROR) #logger.log(u"Show name with ID %s doesn't exist on %s anymore. If you are using trakt, it will be removed from your TRAKT watchlist. If you are adding manually, try removing the nfo and adding again" % # (self.indexer_id,sickbeard.indexerApi(self.indexer).name) , logger.WARNING) ui.notifications.error("Unable to add show", "Unable to look up the show in " + self.showDir + " on " + str(sickbeard.indexerApi( self.indexer).name) + " using ID " + str( self.indexer_id) + ", not using the NFO. Delete .nfo and try adding manually again.") if sickbeard.USE_TRAKT: trakt_id = sickbeard.indexerApi(self.indexer).config['trakt_id'] trakt_api = TraktAPI(sickbeard.SSL_VERIFY, sickbeard.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') self._finishEarly() return try: newShow = TVShow(self.indexer, self.indexer_id, self.lang) newShow.loadFromIndexer() self.show = newShow # set up initial values self.show.location = self.showDir self.show.subtitles = self.subtitles if self.subtitles != None else sickbeard.SUBTITLES_DEFAULT self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT self.show.flatten_folders = self.flatten_folders if self.flatten_folders != None else sickbeard.FLATTEN_FOLDERS_DEFAULT self.show.anime = self.anime if self.anime != None else sickbeard.ANIME_DEFAULT self.show.scene = self.scene if self.scene != None else sickbeard.SCENE_DEFAULT self.show.archive_firstmatch = self.archive if self.archive != None else sickbeard.ARCHIVE_DEFAULT self.show.paused = self.paused if self.paused != None else False # set up default new/missing episode status logger.log(u"Setting all episodes to the specified default status: " + str(self.show.default_ep_status)) self.show.default_ep_status = self.default_status if self.show.anime: self.show.release_groups = BlackAndWhiteList(self.show.indexerid) if self.blacklist: self.show.release_groups.set_black_keywords(self.blacklist) if self.whitelist: self.show.release_groups.set_white_keywords(self.whitelist) # be smartish about this #if self.show.genre and "talk show" in self.show.genre.lower(): # self.show.air_by_date = 1 #if self.show.genre and "documentary" in self.show.genre.lower(): # self.show.air_by_date = 0 #if self.show.classification and "sports" in self.show.classification.lower(): # self.show.sports = 1 except sickbeard.indexer_exception, e: logger.log( u"Unable to add show due to an error with " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.ERROR) if self.show: ui.notifications.error( "Unable to add " + str(self.show.name) + " due to an error with " + sickbeard.indexerApi( self.indexer).name + "") else: ui.notifications.error( "Unable to add show due to an error with " + sickbeard.indexerApi(self.indexer).name + "") self._finishEarly() return
def run(self): # pylint: disable=too-many-branches, too-many-statements, too-many-return-statements super(QueueItemAdd, self).run() if self.showDir: try: assert isinstance(self.showDir, six.text_type) except AssertionError: logger.log(traceback.format_exc(), logger.WARNING) self._finish_early() return logger.log('Starting to add show {0}'.format( 'by ShowDir: {0}'.format(self.showDir) if self. showDir else 'by Indexer Id: {0}'.format(self.indexer_id))) # make sure the Indexer IDs are valid try: lINDEXER_API_PARMS = sickbeard.indexerApi( self.indexer).api_params.copy() lINDEXER_API_PARMS[ 'language'] = self.lang or sickbeard.INDEXER_DEFAULT_LANGUAGE logger.log('{0}: {1!r}'.format( sickbeard.indexerApi(self.indexer).name, lINDEXER_API_PARMS)) t = sickbeard.indexerApi( self.indexer).indexer(**lINDEXER_API_PARMS) s = t[self.indexer_id] # Let's try to create the show Dir if it's not provided. This way we force the show dir to build build using the # Indexers provided series name if self.root_dir and not self.showDir: show_name = get_showname_from_indexer(self.indexer, self.indexer_id, self.lang) if not show_name: logger.log( 'Unable to get a show {0}, can\'t add the show'.format( self.showDir)) self._finish_early() return self.showDir = ek(os.path.join, self.root_dir, sanitize_filename(show_name)) dir_exists = makeDir(self.showDir) if not dir_exists: logger.log( 'Unable to create the folder {0}, can\'t add the show'. format(self.showDir)) self._finish_early() return chmodAsParent(self.showDir) # this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show if getattr(s, 'seriesname', None) is None: error_string = 'Show in {0} has no name on {1}, probably searched with the wrong language. Delete .nfo and add manually in the correct language.'.format( self.showDir, sickbeard.indexerApi(self.indexer).name) logger.log(error_string, logger.WARNING) ui.notifications.error('Unable to add show', error_string) self._finish_early() return # if the show has no episodes/seasons if not s: error_string = 'Show {0} is on {1} but contains no season/episode data.'.format( s[b'seriesname'], sickbeard.indexerApi(self.indexer).name) logger.log(error_string) ui.notifications.error('Unable to add show', error_string) self._finish_early() return except Exception as error: error_string = 'Unable to look up the show in {0} on {1} using ID {2}, not using the NFO. Delete .nfo and try adding manually again.'.format( self.showDir, sickbeard.indexerApi(self.indexer).name, self.indexer_id) logger.log('{0}: {1}'.format(error_string, error), logger.ERROR) ui.notifications.error('Unable to add show', error_string) if sickbeard.USE_TRAKT: trakt_id = sickbeard.indexerApi( self.indexer).config[b'trakt_id'] trakt_api = TraktAPI(sickbeard.SSL_VERIFY, sickbeard.TRAKT_TIMEOUT) title = self.showDir.split('/')[-1] data = {'shows': [{'title': title, 'ids': {}}]} if trakt_id == 'tvdb_id': data[b'shows'][0][b'ids'][b'tvdb'] = self.indexer_id else: data[b'shows'][0][b'ids'][b'tvrage'] = self.indexer_id trakt_api.traktRequest('sync/watchlist/remove', data, method='POST') self._finish_early() return try: try: newShow = TVShow(self.indexer, self.indexer_id, self.lang) except MultipleShowObjectsException as error: # If we have the show in our list, but the location is wrong, lets fix it and refresh! existing_show = Show.find(sickbeard.showList, self.indexer_id) if existing_show and not ek(os.path.isdir, existing_show._location): # pylint: disable=protected-access newShow = existing_show else: raise error newShow.loadFromIndexer() self.show = newShow # set up initial values self.show.location = self.showDir self.show.subtitles = self.subtitles if self.subtitles is not None else sickbeard.SUBTITLES_DEFAULT self.show.subtitles_sr_metadata = self.subtitles_sr_metadata self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT self.show.season_folders = self.season_folders if self.season_folders is not None else sickbeard.SEASON_FOLDERS_DEFAULT self.show.anime = self.anime if self.anime is not None else sickbeard.ANIME_DEFAULT self.show.scene = self.scene if self.scene is not None else sickbeard.SCENE_DEFAULT self.show.paused = self.paused if self.paused is not None else False # set up default new/missing episode status logger.log( 'Setting all episodes to the specified default status: {0}'. format(self.show.default_ep_status)) self.show.default_ep_status = self.default_status if self.show.anime: self.show.release_groups = BlackAndWhiteList( self.show.indexerid) if self.blacklist: self.show.release_groups.set_black_keywords(self.blacklist) if self.whitelist: self.show.release_groups.set_white_keywords(self.whitelist) # # be 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 sickbeard.indexer_exception as error: error_string = 'Unable to add {0} due to an error with {1}'.format( self.show.name if self.show else 'show', sickbeard.indexerApi(self.indexer).name) logger.log('{0}: {1}'.format(error_string, error), logger.ERROR) ui.notifications.error('Unable to add show', error_string) self._finish_early() return except MultipleShowObjectsException: error_string = 'The show in {0} is already in your show list, skipping'.format( self.showDir) logger.log(error_string, logger.WARNING) ui.notifications.error('Show skipped', error_string) self._finish_early() return except Exception as error: logger.log('Error trying to add show: {0}'.format(error), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finish_early() raise logger.log('Retrieving show info from IMDb', logger.DEBUG) try: self.show.loadIMDbInfo() except imdb_exceptions.IMDbError as error: logger.log(' Something wrong on IMDb api: {0}'.format(error), logger.WARNING) except Exception as error: logger.log('Error loading IMDb info: {0}'.format(error), logger.ERROR) try: self.show.saveToDB() except Exception as error: logger.log( 'Error saving the show to the database: {0}'.format(error), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finish_early() raise # add it to the show list if not Show.find(sickbeard.showList, self.indexer_id): sickbeard.showList.append(self.show) try: self.show.loadEpisodesFromIndexer() except Exception as error: logger.log( 'Error with {0}, not creating episode list: {1}'.format( sickbeard.indexerApi(self.show.indexer).name, error), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) # update internal name cache name_cache.buildNameCache(self.show) try: self.show.loadEpisodesFromDir() except Exception as error: logger.log('Error searching dir for episodes: {0}'.format(error), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) # if they set default ep status to WANTED then run the backlog to search for episodes # FIXME: This needs to be a backlog queue item!!! if self.show.default_ep_status == WANTED: logger.log( 'Launching backlog for this show since its episodes are WANTED' ) sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) self.show.writeMetadata() self.show.updateMetadata() self.show.populateCache() self.show.flushEpisodes() if sickbeard.USE_TRAKT: # if there are specific episodes that need to be added by trakt sickbeard.traktCheckerScheduler.action.manageNewShow(self.show) # add show to trakt.tv library if sickbeard.TRAKT_SYNC: sickbeard.traktCheckerScheduler.action.addShowToTraktLibrary( self.show) if sickbeard.TRAKT_SYNC_WATCHLIST: logger.log('update watchlist') notifiers.trakt_notifier.update_watchlist(show_obj=self.show) # Load XEM data to DB for show sickbeard.scene_numbering.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 sickbeard.scene_numbering.get_xem_numbering_for_show( self.show.indexerid, self.show.indexer): self.show.scene = 1 # After initial add, set to default_status_after. self.show.default_ep_status = self.default_status_after super(QueueItemAdd, self).finish() self.finish()
def run(self): ShowQueueItem.run(self) logger.log('Starting to add show %s' % self.showDir) # make sure the Indexer IDs are valid try: lINDEXER_API_PARMS = sickbeard.indexerApi( self.indexer).api_params.copy() if self.lang: lINDEXER_API_PARMS['language'] = self.lang logger.log(u'' + str(sickbeard.indexerApi(self.indexer).name) + ': ' + repr(lINDEXER_API_PARMS)) t = sickbeard.indexerApi( self.indexer).indexer(**lINDEXER_API_PARMS) s = t[self.indexer_id, False] # this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show if getattr(s, 'seriesname', None) is None: logger.log( 'Show in %s has no name on %s, probably the wrong language used to search with.' % (self.showDir, sickbeard.indexerApi(self.indexer).name), logger.ERROR) ui.notifications.error( 'Unable to add show', 'Show in %s has no name on %s, probably the wrong language. Delete .nfo and add manually in the correct language.' % (self.showDir, sickbeard.indexerApi(self.indexer).name)) self._finishEarly() return except Exception as e: logger.log( 'Unable to find show ID:%s on Indexer: %s' % (self.indexer_id, sickbeard.indexerApi(self.indexer).name), logger.ERROR) ui.notifications.error( 'Unable to add show', 'Unable to look up the show in %s on %s using ID %s, not using the NFO. Delete .nfo and try adding manually again.' % (self.showDir, sickbeard.indexerApi( self.indexer).name, self.indexer_id)) self._finishEarly() return try: newShow = TVShow(self.indexer, self.indexer_id, self.lang) newShow.loadFromIndexer() self.show = newShow # set up initial values self.show.location = self.showDir self.show.subtitles = self.subtitles if None is not self.subtitles else sickbeard.SUBTITLES_DEFAULT self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT self.show.flatten_folders = self.flatten_folders if None is not self.flatten_folders else sickbeard.FLATTEN_FOLDERS_DEFAULT self.show.anime = self.anime if None is not self.anime else sickbeard.ANIME_DEFAULT self.show.scene = self.scene if None is not self.scene else sickbeard.SCENE_DEFAULT self.show.paused = self.paused if None is not self.paused else False self.show.tag = self.tag if None is not self.tag else 'Show List' 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 sickbeard.indexer_exception as e: logger.log( 'Unable to add show due to an error with %s: %s' % (sickbeard.indexerApi(self.indexer).name, ex(e)), logger.ERROR) if self.show: ui.notifications.error( 'Unable to add %s due to an error with %s' % (self.show.name, sickbeard.indexerApi(self.indexer).name)) else: ui.notifications.error( 'Unable to add show due to an error with %s' % sickbeard.indexerApi(self.indexer).name) self._finishEarly() return except exceptions.MultipleShowObjectsException: logger.log( 'The show in %s is already in your show list, skipping' % self.showDir, logger.ERROR) ui.notifications.error( 'Show skipped', 'The show in %s is already in your show list' % self.showDir) self._finishEarly() return except Exception as e: logger.log('Error trying to add show: %s' % ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finishEarly() raise self.show.load_imdb_info() try: self.show.saveToDB() except Exception as e: logger.log('Error saving the show to the database: %s' % ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finishEarly() raise # add it to the show list sickbeard.showList.append(self.show) try: self.show.loadEpisodesFromIndexer() except Exception as e: logger.log( 'Error with %s, not creating episode list: %s' % (sickbeard.indexerApi(self.show.indexer).name, ex(e)), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) try: self.show.loadEpisodesFromDir() except Exception as e: logger.log('Error searching directory for episodes: %s' % ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) # if they gave a custom status then change all the eps to it my_db = db.DBConnection() if self.default_status != SKIPPED: logger.log( 'Setting all episodes to the specified default status: %s' % sickbeard.common.statusStrings[self.default_status]) my_db.action( 'UPDATE tv_episodes SET status = ? WHERE status = ? AND showid = ? AND season != 0', [self.default_status, SKIPPED, self.show.indexerid]) # if they gave a number to start or number to end as wanted, then change those eps to it def get_wanted(db_obj, wanted_max, latest): actual = 0 if wanted_max: select_id = 'FROM [tv_episodes] t5 JOIN (SELECT t3.indexerid, t3.status, t3.season*1000000+t3.episode AS t3_se, t2.start_season FROM [tv_episodes] t3'\ + ' JOIN (SELECT t1.showid, M%s(t1.season) AS start_season' % ('IN', 'AX')[latest]\ + ', MAX(t1.airdate) AS airdate, t1.episode, t1.season*1000000+t1.episode AS se FROM [tv_episodes] t1'\ + ' WHERE %s=t1.showid' % self.show.indexerid\ + ' AND 0<t1.season AND t1.status NOT IN (%s)) AS t2' % UNAIRED\ + ' ON t2.showid=t3.showid AND 0<t3.season AND t2.se>=t3_se ORDER BY t3_se %sSC' % ('A', 'DE')[latest]\ + ' %s) as t4' % (' LIMIT %s' % wanted_max, '')[-1 == wanted_max]\ + ' ON t4.indexerid=t5.indexerid'\ + '%s' % ('', ' AND t4.start_season=t5.season')[-1 == wanted_max]\ + ' AND t4.status NOT IN (%s)' % ','.join([str(x) for x in sickbeard.common.Quality.DOWNLOADED + [WANTED]]) select = 'SELECT t5.indexerid as indexerid, t5.season as season, t5.episode as episode, t5.status as status ' + select_id update = 'UPDATE [tv_episodes] SET status=%s WHERE indexerid IN (SELECT t5.indexerid %s)' % ( WANTED, select_id) wanted_updates = db_obj.select(select) db_obj.action(update) result = db_obj.select( 'SELECT changes() as last FROM [tv_episodes]') for cur_result in result: actual = cur_result['last'] break action_log = 'didn\'t find any episodes that need to be set wanted' if actual: action_log = ('updated %s %s episodes > %s' % ( (((('%s of %s' % (actual, wanted_max)), ('%s of max %s limited' % (actual, wanted_max)))[10 == wanted_max]), ('max %s available' % actual))[-1 == wanted_max], ('first season', 'latest')[latest], ','.join( [('S%02dE%02d=%d' % (a['season'], a['episode'], a['status'])) for a in wanted_updates]))) logger.log('Get wanted ' + action_log) return actual items_wanted = get_wanted(my_db, self.default_wanted_begin, latest=False) items_wanted += get_wanted(my_db, self.default_wanted_latest, latest=True) msg = ' the specified show into ' + self.showDir # if started with WANTED eps then run the backlog if WANTED == self.default_status or items_wanted: logger.log( 'Launching backlog for this show since episodes are WANTED') sickbeard.backlogSearchScheduler.action.search_backlog( [self.show]) #@UndefinedVariable ui.notifications.message( 'Show added/search', 'Adding and searching for episodes of' + msg) else: ui.notifications.message('Show added', 'Adding' + msg) self.show.writeMetadata() self.show.updateMetadata() self.show.populateCache() self.show.flushEpisodes() # load ids self.show.ids # if sickbeard.USE_TRAKT: # # if there are specific episodes that need to be added by trakt # sickbeard.traktCheckerScheduler.action.manageNewShow(self.show) # # # add show to trakt.tv library # if sickbeard.TRAKT_SYNC: # sickbeard.traktCheckerScheduler.action.addShowToTraktLibrary(self.show) # Load XEM data to DB for show sickbeard.scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer, force=True) # check if show has XEM mapping and if user disabled scene numbering during add show, output availability to log if not self.scene and self.show.indexerid in sickbeard.scene_exceptions.xem_ids_list[ self.show.indexer]: logger.log( 'Alternative scene episode numbers were disabled during add show. Edit show to enable them for searching.' ) # update internal name cache name_cache.buildNameCache(self.show) self.finish()
def makeSceneSeasonSearchString(show, ep_obj, extraSearchType=None): myDB = db.DBConnection() if show.air_by_date or show.sports: numseasons = 0 # the search string for air by date shows is just seasonStrings = [str(ep_obj.airdate).split('-')[0]] elif show.is_anime: numseasons = 0 seasonEps = show.getAllEpisodes(ep_obj.season) # get show qualities anyQualities, bestQualities = common.Quality.splitQuality(show.quality) # compile a list of all the episode numbers we need in this 'season' seasonStrings = [] for episode in seasonEps: # get quality of the episode curCompositeStatus = episode.status curStatus, curQuality = common.Quality.splitCompositeStatus( curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) else: highestBestQuality = 0 # if we need a better one then add it to the list of episodes to fetch if (curStatus in (common.DOWNLOADED, common.SNATCHED) and curQuality < highestBestQuality ) or curStatus == common.WANTED: ab_number = episode.scene_absolute_number if ab_number > 0: seasonStrings.append("%d" % ab_number) else: numseasonsSQlResult = myDB.select( "SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0", [show.indexerid]) numseasons = int(numseasonsSQlResult[0][0]) seasonStrings = ["S%02d" % int(ep_obj.scene_season)] bwl = BlackAndWhiteList(show.indexerid) showNames = set(makeSceneShowSearchStrings(show, ep_obj.scene_season)) toReturn = [] # search each show name for curShow in showNames: # most providers all work the same way if not extraSearchType: # if there's only one season then we can just use the show name straight up if numseasons == 1: toReturn.append(curShow) # for providers that don't allow multiple searches in one request we only search for Sxx style stuff else: for cur_season in seasonStrings: if len(bwl.whiteList) > 0: for keyword in bwl.whiteList: toReturn.append(keyword + '.' + curShow + "." + cur_season) else: toReturn.append(curShow + "." + cur_season) return toReturn
def pickBestResult(results, show=None, quality_list=None): results = results if isinstance(results, list) else [results] logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG) bwl = None bestResult = None # find the best result for the current episode for cur_result in results: if show and cur_result.show is not show: continue # build the black And white list if not bwl and cur_result.show.is_anime: bwl = BlackAndWhiteList(cur_result.show.indexerid) if not bwl.is_valid(cur_result): logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.INFO) continue logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality]) if quality_list and cur_result.quality not in quality_list: logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG) continue if show.rls_ignore_words and filter_release_name(cur_result.name, cur_result.show.rls_ignore_words): logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words, logger.INFO) continue if show.rls_require_words and not filter_release_name(cur_result.name, cur_result.show.rls_require_words): logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words, logger.INFO) continue if not show_name_helpers.filterBadReleases(cur_result.name, parse=False): logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it", logger.INFO) continue if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size, cur_result.provider.name): logger.log(cur_result.name + u" has previously failed, rejecting it") continue if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN: bestResult = cur_result elif bestResult.quality == cur_result.quality: if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower(): bestResult = cur_result elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower(): bestResult = cur_result elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower(): logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)") bestResult = cur_result if bestResult: logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG) else: logger.log(u"No result picked.", logger.DEBUG) return bestResult
def pickBestResult(results, show, quality_list=None): results = results if isinstance(results, list) else [results] logger.log( u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG) bwl = None bestResult = None # find the best result for the current episode for cur_result in results: if show and cur_result.show is not show: continue # filter out possible bad torrents from providers such as ezrss if isinstance(cur_result, sickbeard.classes.SearchResult): if cur_result.resultType == "torrent" and sickbeard.TORRENT_METHOD != "blackhole": if not cur_result.url.startswith('magnet'): cur_result.content = cur_result.provider.getURL( cur_result.url) if not cur_result.content: continue else: if not cur_result.url.startswith('magnet'): cur_result.content = cur_result.provider.getURL(cur_result.url) if not cur_result.content: continue # build the black And white list if cur_result.show.is_anime: if not bwl: bwl = BlackAndWhiteList(cur_result.show.indexerid) if not bwl.is_valid(cur_result): logger.log( cur_result.name + " does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.INFO) continue logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality]) if quality_list and cur_result.quality not in quality_list: logger.log( cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG) continue if show.lang == "de" and not filter_release_name( cur_result.name, "german|videoman"): logger.log( u"Ignoring " + cur_result.name + " based on ignored words filter: show language 'de'", logger.INFO) continue if show.lang != "de" and filter_release_name(cur_result.name, "german|videoman"): logger.log( u"Ignoring " + cur_result.name + " based on ignored words filter: show language '%s'" % show.lang, logger.INFO) continue if show.rls_ignore_words and filter_release_name( cur_result.name, cur_result.show.rls_ignore_words): logger.log( u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words, logger.INFO) continue if show.rls_require_words and not filter_release_name( cur_result.name, cur_result.show.rls_require_words): logger.log( u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words, logger.INFO) continue if not show_name_helpers.filterBadReleases(cur_result.name, parse=False): logger.log( u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it", logger.INFO) continue if hasattr(cur_result, 'size'): if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed( cur_result.name, cur_result.size, cur_result.provider.name): logger.log(cur_result.name + u" has previously failed, rejecting it") continue if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN: bestResult = cur_result elif bestResult.quality == cur_result.quality: if "proper" in cur_result.name.lower( ) or "repack" in cur_result.name.lower(): bestResult = cur_result elif "internal" in bestResult.name.lower( ) and "internal" not in cur_result.name.lower(): bestResult = cur_result elif "xvid" in bestResult.name.lower( ) and "x264" in cur_result.name.lower(): logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)") bestResult = cur_result if bestResult: logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG) else: logger.log(u"No result picked.", logger.DEBUG) return bestResult
class QueueItemAdd(ShowQueueItem): def __init__(self, indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, subtitles, anime, scene, paused, blacklist, whitelist): self.indexer = indexer self.indexer_id = indexer_id self.showDir = showDir self.default_status = default_status self.quality = quality self.flatten_folders = flatten_folders self.lang = lang self.subtitles = subtitles self.anime = anime self.scene = scene self.paused = paused self.blacklist = blacklist self.whitelist = whitelist if sickbeard.TRAKT_USE_ROLLING_DOWNLOAD and sickbeard.USE_TRAKT: self.paused = sickbeard.TRAKT_ROLLING_ADD_PAUSED # Process add show in priority self.priority = generic_queue.QueuePriorities.HIGH self.show = None # this will initialize self.show to None ShowQueueItem.__init__(self, ShowQueueActions.ADD, self.show) def _getName(self): """ Returns the show name if there is a show object created, if not returns the dir that the show is being added to. """ if self.show == None: return self.showDir return self.show.name show_name = property(_getName) def _isLoading(self): """ Returns True if we've gotten far enough to have a show object, or False if we still only know the folder name. """ if self.show == None: return True return False isLoading = property(_isLoading) def run(self): ShowQueueItem.run(self) logger.log(u"Starting to add show " + self.showDir) # make sure the Indexer IDs are valid try: lINDEXER_API_PARMS = sickbeard.indexerApi( self.indexer).api_params.copy() if self.lang: lINDEXER_API_PARMS['language'] = self.lang logger.log(u"" + str(sickbeard.indexerApi(self.indexer).name) + ": " + repr(lINDEXER_API_PARMS)) t = sickbeard.indexerApi( self.indexer).indexer(**lINDEXER_API_PARMS) s = t[self.indexer_id] # this usually only happens if they have an NFO in their show dir which gave us a Indexer ID that has no proper english version of the show if getattr(s, 'seriesname', None) is None: logger.log( u"Show in " + self.showDir + " has no name on " + str(sickbeard.indexerApi(self.indexer).name) + ", probably the wrong language used to search with.", logger.ERROR) ui.notifications.error( "Unable to add show", "Show in " + self.showDir + " has no name on " + str(sickbeard.indexerApi(self.indexer).name) + ", probably the wrong language. Delete .nfo and add manually in the correct language." ) self._finishEarly() return # if the show has no episodes/seasons if not s: logger.log( u"Show " + str(s['seriesname']) + " is on " + str(sickbeard.indexerApi(self.indexer).name) + " but contains no season/episode data.", logger.ERROR) ui.notifications.error( "Unable to add show", "Show " + str(s['seriesname']) + " is on " + str(sickbeard.indexerApi(self.indexer).name) + " but contains no season/episode data.") self._finishEarly() return except Exception, e: logger.log( u"Unable to find show ID:" + str(self.indexer_id) + " on Indexer: " + str(sickbeard.indexerApi(self.indexer).name), logger.ERROR) ui.notifications.error( "Unable to add show", "Unable to look up the show in " + self.showDir + " on " + str(sickbeard.indexerApi(self.indexer).name) + " using ID " + str(self.indexer_id) + ", not using the NFO. Delete .nfo and try adding manually again." ) self._finishEarly() return try: newShow = TVShow(self.indexer, self.indexer_id, self.lang) newShow.loadFromIndexer() self.show = newShow # set up initial values self.show.location = self.showDir self.show.subtitles = self.subtitles if self.subtitles != None else sickbeard.SUBTITLES_DEFAULT self.show.quality = self.quality if self.quality else sickbeard.QUALITY_DEFAULT self.show.flatten_folders = self.flatten_folders if self.flatten_folders != None else sickbeard.FLATTEN_FOLDERS_DEFAULT self.show.anime = self.anime if self.anime != None else sickbeard.ANIME_DEFAULT self.show.scene = self.scene if self.scene != None else sickbeard.SCENE_DEFAULT self.show.paused = self.paused if self.paused != None else False # set up default new/missing episode status logger.log( u"Setting all episodes to the specified default status: " + str(self.show.default_ep_status)) self.show.default_ep_status = self.default_status if self.show.anime: self.show.release_groups = BlackAndWhiteList( self.show.indexerid) if self.blacklist: self.show.release_groups.set_black_keywords(self.blacklist) if self.whitelist: self.show.release_groups.set_white_keywords(self.whitelist) # be smartish about this if self.show.genre and "talk show" in self.show.genre.lower(): self.show.air_by_date = 1 if self.show.genre and "documentary" in self.show.genre.lower(): self.show.air_by_date = 0 if self.show.classification and "sports" in self.show.classification.lower( ): self.show.sports = 1 except sickbeard.indexer_exception, e: logger.log( u"Unable to add show due to an error with " + sickbeard.indexerApi(self.indexer).name + ": " + ex(e), logger.ERROR) if self.show: ui.notifications.error( "Unable to add " + str(self.show.name) + " due to an error with " + sickbeard.indexerApi(self.indexer).name + "") else: ui.notifications.error( "Unable to add show due to an error with " + sickbeard.indexerApi(self.indexer).name + "") self._finishEarly() return