def get_subtitles_dir(video_path): """Return the correct subtitles directory based on the user configuration. If the directory doesn't exist, it will be created :param video_path: the video path :type video_path: str :return: the subtitles directory :rtype: str """ if not app.SUBTITLES_DIR: return os.path.dirname(video_path) if os.path.isabs(app.SUBTITLES_DIR): return _decode(app.SUBTITLES_DIR) new_subtitles_path = os.path.join(os.path.dirname(video_path), app.SUBTITLES_DIR) if helpers.make_dir(new_subtitles_path): helpers.chmod_as_parent(new_subtitles_path) else: logger.warning(u'Unable to create subtitles folder %s', new_subtitles_path) return new_subtitles_path
def change_LOG_DIR(log_dir): """ Change logging directory for application and webserver. :param log_dir: Path to new logging directory :return: True on success, False on failure """ abs_log_dir = os.path.normpath(os.path.join(app.DATA_DIR, log_dir)) if os.path.normpath(app.LOG_DIR) != abs_log_dir: if not helpers.make_dir(abs_log_dir): return False app.ACTUAL_LOG_DIR = os.path.normpath(log_dir) app.LOG_DIR = abs_log_dir return True
def change_HTTPS_KEY(https_key): """ Replace HTTPS Key file path. :param https_key: path to the new key file :return: True on success, False on failure """ if https_key == '': app.HTTPS_KEY = '' return True if os.path.normpath(app.HTTPS_KEY) != os.path.normpath(https_key): if helpers.make_dir(os.path.dirname(os.path.abspath(https_key))): app.HTTPS_KEY = os.path.normpath(https_key) log.info(u'Changed https key path to {key_path}', {u'key_path': https_key}) else: return False return True
def change_HTTPS_CERT(https_cert): """ Replace HTTPS Certificate file path. :param https_cert: path to the new certificate file :return: True on success, False on failure """ if https_cert == '': app.HTTPS_CERT = '' return True if os.path.normpath(app.HTTPS_CERT) != os.path.normpath(https_cert): if helpers.make_dir(os.path.dirname(os.path.abspath(https_cert))): app.HTTPS_CERT = os.path.normpath(https_cert) log.info(u'Changed https cert path to {cert_path}', {u'cert_path': https_cert}) else: return False return True
def change_TV_DOWNLOAD_DIR(tv_download_dir): """ Change TV_DOWNLOAD directory (used by postprocessor) :param tv_download_dir: New tv download directory :return: True on success, False on failure """ if tv_download_dir == '': app.TV_DOWNLOAD_DIR = '' return True if os.path.normpath(app.TV_DOWNLOAD_DIR) != os.path.normpath(tv_download_dir): if helpers.make_dir(tv_download_dir): app.TV_DOWNLOAD_DIR = os.path.normpath(tv_download_dir) log.info(u'Changed TV download folder to {tv_download_dir}', {u'tv_download_dir': tv_download_dir}) else: return False return True
def change_TORRENT_DIR(torrent_dir): """ Change torrent directory :param torrent_dir: New torrent directory :return: True on success, False on failure """ if torrent_dir == '': app.TORRENT_DIR = '' return True if os.path.normpath(app.TORRENT_DIR) != os.path.normpath(torrent_dir): if helpers.make_dir(torrent_dir): app.TORRENT_DIR = os.path.normpath(torrent_dir) log.info(u'Changed torrent folder to {torrent_dir}', {u'torrent_dir': torrent_dir}) else: return False return True
def change_NZB_DIR(nzb_dir): """ Change NZB Folder :param nzb_dir: New NZB Folder location :return: True on success, False on failure """ if nzb_dir == '': app.NZB_DIR = '' return True if os.path.normpath(app.NZB_DIR) != os.path.normpath(nzb_dir): if helpers.make_dir(nzb_dir): app.NZB_DIR = os.path.normpath(nzb_dir) log.info(u'Changed NZB folder to {nzb_dir}', {'nzb_dir': nzb_dir}) else: return False return True
def addNewShow(self, whichSeries=None, indexer_lang=None, rootDir=None, defaultStatus=None, quality_preset=None, allowed_qualities=None, preferred_qualities=None, season_folders=None, subtitles=None, fullShowPath=None, other_shows=None, skipShow=None, providedIndexer=None, anime=None, scene=None, blacklist=None, whitelist=None, defaultStatusAfter=None): """ Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are provided then it forwards back to newShow, if not it goes to /home. """ provided_indexer = providedIndexer indexer_lang = app.INDEXER_DEFAULT_LANGUAGE if not indexer_lang else indexer_lang # grab our list of other dirs if given if not other_shows: other_shows = [] elif not isinstance(other_shows, list): other_shows = [other_shows] def finishAddShow(): # if there are no extra shows then go home if not other_shows: return json_redirect('/home/') # go to add the next show return json_redirect( '/addShows/newShow/', [('show_to_add' if not i else 'other_shows', cur_dir) for i, cur_dir in enumerate(other_shows)]) # if we're skipping then behave accordingly if skipShow: return finishAddShow() # sanity check on our inputs if (not rootDir and not fullShowPath) or not whichSeries: return 'Missing params, no Indexer ID or folder:{series!r} and {root!r}/{path!r}'.format( series=whichSeries, root=rootDir, path=fullShowPath) # figure out what show we're adding and where series_pieces = whichSeries.split('|') if (whichSeries and rootDir) or (whichSeries and fullShowPath and len(series_pieces) > 1): if len(series_pieces) < 6: logger.log( u'Unable to add show due to show selection. Not enough arguments: %s' % (repr(series_pieces)), logger.ERROR) ui.notifications.error( 'Unknown error. Unable to add show due to problem with show selection.' ) return json_redirect('/addShows/existingShows/') indexer = int(series_pieces[1]) indexer_id = int(series_pieces[3]) show_name = series_pieces[4] else: # if no indexer was provided use the default indexer set in General settings if not provided_indexer: provided_indexer = app.INDEXER_DEFAULT indexer = int(provided_indexer) indexer_id = int(whichSeries) show_name = os.path.basename(os.path.normpath(fullShowPath)) # use the whole path if it's given, or else append the show name to the root dir to get the full show path if fullShowPath: show_dir = os.path.normpath(fullShowPath) else: show_dir = os.path.join(rootDir, sanitize_filename(show_name)) # blanket policy - if the dir exists you should have used 'add existing show' numbnuts if os.path.isdir(show_dir) and not fullShowPath: ui.notifications.error( 'Unable to add show', 'Folder {path} exists already'.format(path=show_dir)) return json_redirect('/addShows/existingShows/') # don't create show dir if config says not to if app.ADD_SHOWS_WO_DIR: logger.log( u'Skipping initial creation of {path} due to config.ini setting' .format(path=show_dir)) else: dir_exists = helpers.make_dir(show_dir) if not dir_exists: logger.log( u'Unable to create the folder {path}, can\'t add the show'. format(path=show_dir), logger.ERROR) ui.notifications.error( 'Unable to add show', 'Unable to create the folder {path}, can\'t add the show'. format(path=show_dir)) # Don't redirect to default page because user wants to see the new show return json_redirect('/home/') else: helpers.chmod_as_parent(show_dir) # prepare the inputs for passing along scene = config.checkbox_to_value(scene) anime = config.checkbox_to_value(anime) season_folders = config.checkbox_to_value(season_folders) subtitles = config.checkbox_to_value(subtitles) if whitelist: whitelist = short_group_names(whitelist) if blacklist: blacklist = short_group_names(blacklist) if not allowed_qualities: allowed_qualities = [] if not preferred_qualities or try_int(quality_preset, None): preferred_qualities = [] if not isinstance(allowed_qualities, list): allowed_qualities = [allowed_qualities] if not isinstance(preferred_qualities, list): preferred_qualities = [preferred_qualities] new_quality = Quality.combine_qualities( [int(q) for q in allowed_qualities], [int(q) for q in preferred_qualities]) # add the show app.show_queue_scheduler.action.addShow(indexer, indexer_id, show_dir, int(defaultStatus), new_quality, season_folders, indexer_lang, subtitles, anime, scene, None, blacklist, whitelist, int(defaultStatusAfter)) ui.notifications.message( 'Show added', 'Adding the specified show into {path}'.format(path=show_dir)) return finishAddShow()
def addNewShow(self, whichSeries=None, indexer_lang=None, rootDir=None, defaultStatus=None, quality_preset=None, allowed_qualities=None, preferred_qualities=None, season_folders=None, subtitles=None, fullShowPath=None, other_shows=None, skipShow=None, providedIndexer=None, anime=None, scene=None, blacklist=None, whitelist=None, defaultStatusAfter=None): """ Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are provided then it forwards back to newShow, if not it goes to /home. """ provided_indexer = providedIndexer indexer_lang = app.INDEXER_DEFAULT_LANGUAGE if not indexer_lang else indexer_lang # grab our list of other dirs if given if not other_shows: other_shows = [] elif not isinstance(other_shows, list): other_shows = [other_shows] other_shows = decode_shows(other_shows) def finishAddShow(): # if there are no extra shows then go home if not other_shows: return json_response(redirect='/home/') # go to add the next show return json_response( redirect='/addShows/newShow/', params=[ ('show_to_add' if not i else 'other_shows', cur_dir) for i, cur_dir in enumerate(other_shows) ] ) # if we're skipping then behave accordingly if skipShow: return finishAddShow() # sanity check on our inputs if (not rootDir and not fullShowPath) or not whichSeries: error_msg = 'Missing params, no Indexer ID or folder: {series!r} and {root!r}/{path!r}'.format( series=whichSeries, root=rootDir, path=fullShowPath) log.error(error_msg) return json_response( result=False, message=error_msg, redirect='/home/' ) # figure out what show we're adding and where series_pieces = whichSeries.split('|') if (whichSeries and rootDir) or (whichSeries and fullShowPath and len(series_pieces) > 1): if len(series_pieces) < 6: log.error('Unable to add show due to show selection. Not enough arguments: {pieces!r}', {'pieces': series_pieces}) ui.notifications.error('Unknown error. Unable to add show due to problem with show selection.') return json_response( result=False, message='Unable to add show due to show selection. Not enough arguments: {0!r}'.format(series_pieces), redirect='/addShows/existingShows/' ) indexer = int(series_pieces[1]) indexer_id = int(series_pieces[3]) show_name = series_pieces[4] else: # if no indexer was provided use the default indexer set in General settings if not provided_indexer: provided_indexer = app.INDEXER_DEFAULT indexer = int(provided_indexer) indexer_id = int(whichSeries) show_name = os.path.basename(os.path.normpath(fullShowPath)) # use the whole path if it's given, or else append the show name to the root dir to get the full show path if fullShowPath: show_dir = os.path.normpath(fullShowPath) else: show_dir = os.path.join(rootDir, sanitize_filename(show_name)) # blanket policy - if the dir exists you should have used 'add existing show' numbnuts if os.path.isdir(show_dir) and not fullShowPath: ui.notifications.error('Unable to add show', 'Folder {path} exists already'.format(path=show_dir)) return json_response( result=False, message='Unable to add show: Folder {path} exists already'.format(path=show_dir), redirect='/addShows/existingShows/' ) # don't create show dir if config says not to if app.ADD_SHOWS_WO_DIR: log.info('Skipping initial creation of {path} due to config.ini setting', {'path': show_dir}) else: dir_exists = helpers.make_dir(show_dir) if not dir_exists: log.error("Unable to create the folder {path}, can't add the show", {'path': show_dir}) ui.notifications.error('Unable to add show', 'Unable to create the folder {path}, can\'t add the show'.format(path=show_dir)) # Don't redirect to default page because user wants to see the new show return json_response( result=False, message='Unable to add show: Unable to create the folder {path}'.format(path=show_dir), redirect='/home/' ) else: helpers.chmod_as_parent(show_dir) # prepare the inputs for passing along scene = config.checkbox_to_value(scene) anime = config.checkbox_to_value(anime) season_folders = config.checkbox_to_value(season_folders) subtitles = config.checkbox_to_value(subtitles) if whitelist: if not isinstance(whitelist, list): whitelist = [whitelist] whitelist = short_group_names(whitelist) if blacklist: if not isinstance(blacklist, list): blacklist = [blacklist] blacklist = short_group_names(blacklist) if not allowed_qualities: allowed_qualities = [] if not preferred_qualities or try_int(quality_preset, None): preferred_qualities = [] if not isinstance(allowed_qualities, list): allowed_qualities = [allowed_qualities] if not isinstance(preferred_qualities, list): preferred_qualities = [preferred_qualities] new_quality = Quality.combine_qualities([int(q) for q in allowed_qualities], [int(q) for q in preferred_qualities]) # add the show app.show_queue_scheduler.action.addShow(indexer, indexer_id, show_dir, int(defaultStatus), new_quality, season_folders, indexer_lang, subtitles, anime, scene, None, blacklist, whitelist, int(defaultStatusAfter)) ui.notifications.message('Show added', 'Adding the specified show into {path}'.format(path=show_dir)) return finishAddShow()
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 u"by Indexer Id: {0}".format(self.indexer_id))) # make sure the Indexer IDs are valid try: l_indexer_api_params = indexerApi(self.indexer).api_params.copy() if self.lang: l_indexer_api_params['language'] = self.lang logger.log(u"" + str(indexerApi(self.indexer).name) + ": " + repr(l_indexer_api_params)) indexer_api = indexerApi( self.indexer).indexer(**l_indexer_api_params) s = indexer_api[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 = os.path.join(self.root_dir, sanitize_filename(show_name)) dir_exists = make_dir(self.showDir) if not dir_exists: logger.log( u"Unable to create the folder {0}, can't add the show" .format(self.showDir)) return chmod_as_parent(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 {0} has no name on {1}, probably searched with the wrong language." .format(self.showDir, indexerApi(self.indexer).name), logger.ERROR) ui.notifications.error( 'Unable to add show', 'Show in {0} has no name on {1}, probably the wrong language. \ Delete .nfo and manually add the correct language.' .format(self.showDir, indexerApi(self.indexer).name)) self._finishEarly() return # if the show has no episodes/seasons if not s: logger.log(u"Show " + str(s['seriesname']) + u" is on " + str(indexerApi(self.indexer).name) + u" but contains no season/episode data.") ui.notifications.error( "Unable to add show", "Show {0} is on {1} but contains no season/episode data.". format(s['seriesname'], indexerApi(self.indexer).name)) self._finishEarly() return # Check if we can already find this show in our current showList. try: check_existing_shows(s, self.indexer) except IndexerShowAllreadyInLibrary as e: logger.log( u"Could not add the show %s, as it already is in your library." u" Error: %s" % (s['seriesname'], e.message), logger.WARNING) ui.notifications.error('Unable to add show', 'reason: {0}'.format(e.message)) self._finishEarly() # Clean up leftover if the newly created directory is empty. delete_empty_folders(self.showDir) return # TODO: Add more specific indexer exceptions, that should provide the user with some accurate feedback. except IndexerShowIncomplete as e: logger.log( u"%s Error while loading information from indexer %s. " u"Error: %s" % (self.indexer_id, indexerApi(self.indexer).name, e.message), logger.WARNING) ui.notifications.error( "Unable to add show", "Unable to look up the show in {0} on {1} using ID {2} " "Reason: {3}".format(self.showDir, indexerApi(self.indexer).name, self.indexer_id, e.message)) self._finishEarly() return except IndexerShowNotFoundInLanguage as e: logger.log( u'{id}: Data retrieved from {indexer} was incomplete. The indexer does not provide ' u'show information in the searched language {language}. Aborting: {error_msg}' .format(id=self.indexer_id, indexer=indexerApi(self.indexer).name, language=e.language, error_msg=e.message), logger.WARNING) ui.notifications.error( 'Error adding show!', 'Unable to add show {indexer_id} on {indexer} with this language: {language}' .format(indexer_id=self.indexer_id, indexer=indexerApi(self.indexer).name, language=e.language)) self._finishEarly() return except Exception as e: logger.log( u"%s Error while loading information from indexer %s. " u"Error: %r" % (self.indexer_id, indexerApi(self.indexer).name, e.message), logger.ERROR) ui.notifications.error( "Unable to add show", "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, indexerApi(self.indexer).name, self.indexer_id)) self._finishEarly() return try: newShow = Series(self.indexer, self.indexer_id, self.lang) newShow.load_from_indexer(indexer_api) self.show = newShow # set up initial values self.show.location = self.showDir self.show.subtitles = self.subtitles if self.subtitles is not None else app.SUBTITLES_DEFAULT self.show.quality = self.quality if self.quality else app.QUALITY_DEFAULT self.show.flatten_folders = self.flatten_folders if self.flatten_folders is not None \ else app.FLATTEN_FOLDERS_DEFAULT self.show.anime = self.anime if self.anime is not None else app.ANIME_DEFAULT self.show.scene = self.scene if self.scene is not None else app.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 previously aired episodes to the specified status: {status}" .format(status=statusStrings[self.default_status])) self.show.default_ep_status = self.default_status if self.show.anime: self.show.release_groups = BlackAndWhiteList( self.show.indexerid) if self.blacklist: self.show.release_groups.set_black_keywords(self.blacklist) if self.whitelist: self.show.release_groups.set_white_keywords(self.whitelist) # # be smartish about this # if self.show.genre and "talk show" in self.show.genre.lower(): # self.show.air_by_date = 1 # if self.show.genre and "documentary" in self.show.genre.lower(): # self.show.air_by_date = 0 # if self.show.classification and "sports" in self.show.classification.lower(): # self.show.sports = 1 except IndexerException as e: logger.log( u"Unable to add show due to an error with " + indexerApi(self.indexer).name + ": " + e.message, logger.ERROR) if self.show: ui.notifications.error("Unable to add " + str(self.show.name) + " due to an error with " + indexerApi(self.indexer).name + "") else: ui.notifications.error( "Unable to add show due to an error with " + 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: " + e.message, 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.load_imdb_info() except ImdbAPIError as e: logger.log(u"Something wrong on IMDb api: " + e.message, logger.INFO) except Exception as e: logger.log(u"Error loading IMDb info: " + e.message, logger.ERROR) try: self.show.save_to_db() except Exception as e: logger.log(u"Error saving the show to the database: " + e.message, logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) self._finishEarly() raise # add it to the show list app.showList.append(self.show) try: self.show.load_episodes_from_indexer(tvapi=indexer_api) except Exception as e: logger.log( u"Error with " + indexerApi(self.show.indexer).name + ", not creating episode list: " + e.message, logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) # update internal name cache name_cache.build_name_cache(self.show) try: self.show.load_episodes_from_dir() except Exception as e: logger.log(u"Error searching dir for episodes: " + e.message, 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" ) app.backlog_search_scheduler.action.search_backlog([self.show]) self.show.write_metadata() self.show.update_metadata() self.show.populate_cache() self.show.flush_episodes() if app.USE_TRAKT: # if there are specific episodes that need to be added by trakt app.trakt_checker_scheduler.action.manage_new_show(self.show) # add show to trakt.tv library if app.TRAKT_SYNC: app.trakt_checker_scheduler.action.add_show_trakt_library( self.show) if app.TRAKT_SYNC_WATCHLIST: logger.log(u"update watchlist") notifiers.trakt_notifier.update_watchlist(show_obj=self.show) # Load XEM data to DB for show scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer, force=True) # check if show has XEM mapping so we can determine if searches # should go by scene numbering or indexer numbering. if not self.scene and 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()
def run(self): ShowQueueItem.run(self) log.info('Starting to add show by {0}', ('show_dir: {0}'.format(self.show_dir) if self.show_dir else 'Indexer Id: {0}'.format(self.indexer_id))) # make sure the Indexer IDs are valid try: l_indexer_api_params = indexerApi(self.indexer).api_params.copy() if self.lang: l_indexer_api_params['language'] = self.lang log.info( '{indexer_name}: {indexer_params!r}', { 'indexer_name': indexerApi(self.indexer).name, 'indexer_params': l_indexer_api_params }) indexer_api = indexerApi( self.indexer).indexer(**l_indexer_api_params) s = indexer_api[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.show_dir and self.root_dir: show_name = get_showname_from_indexer(self.indexer, self.indexer_id, self.lang) if show_name: self.show_dir = os.path.join(self.root_dir, sanitize_filename(show_name)) dir_exists = make_dir(self.show_dir) if not dir_exists: log.info( "Unable to create the folder {0}, can't add the show", self.show_dir) return chmod_as_parent(self.show_dir) else: log.info("Unable to get a show {0}, can't add the show", self.show_dir) 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: log.error( 'Show in {path} has no name on {indexer}, probably searched with the wrong language.', { 'path': self.show_dir, 'indexer': indexerApi(self.indexer).name }) ui.notifications.error( 'Unable to add show', 'Show in {path} has no name on {indexer}, probably the wrong language.' ' Delete .nfo and manually add the correct language.'. format(path=self.show_dir, indexer=indexerApi(self.indexer).name)) self._finishEarly() return # Check if we can already find this show in our current showList. try: check_existing_shows(s, self.indexer) except IndexerShowAlreadyInLibrary as error: log.warning( 'Could not add the show {series}, as it already is in your library.' ' Error: {error}', { 'series': s['seriesname'], 'error': error }) ui.notifications.error('Unable to add show', 'reason: {0}'.format(error)) self._finishEarly() # Clean up leftover if the newly created directory is empty. delete_empty_folders(self.show_dir) return # TODO: Add more specific indexer exceptions, that should provide the user with some accurate feedback. except IndexerShowNotFound as error: log.warning( '{id}: Unable to look up the show in {path} using id {id} on {indexer}.' ' Delete metadata files from the folder and try adding it again.\n' 'With error: {error}', { 'id': self.indexer_id, 'path': self.show_dir, 'indexer': indexerApi(self.indexer).name, 'error': error }) ui.notifications.error( 'Unable to add show', 'Unable to look up the show in {path} using id {id} on {indexer}.' ' Delete metadata files from the folder and try adding it again.' .format(path=self.show_dir, id=self.indexer_id, indexer=indexerApi(self.indexer).name)) self._finishEarly() return except IndexerShowNotFoundInLanguage as error: log.warning( '{id}: Data retrieved from {indexer} was incomplete. The indexer does not provide' ' show information in the searched language {language}. Aborting: {error_msg}', { 'id': self.indexer_id, 'indexer': indexerApi(self.indexer).name, 'language': error.language, 'error_msg': error }) ui.notifications.error( 'Error adding show!', 'Unable to add show {indexer_id} on {indexer} with this language: {language}' .format(indexer_id=self.indexer_id, indexer=indexerApi(self.indexer).name, language=error.language)) self._finishEarly() return except Exception as error: log.error( '{id}: Error while loading information from indexer {indexer}. Error: {error!r}', { 'id': self.indexer_id, 'indexer': indexerApi(self.indexer).name, 'error': error }) ui.notifications.error( 'Unable to add show', 'Unable to look up the show in {path} on {indexer} using ID {id}.' .format(path=self.show_dir, indexer=indexerApi(self.indexer).name, id=self.indexer_id)) self._finishEarly() return try: newShow = Series(self.indexer, self.indexer_id, self.lang) newShow.load_from_indexer(indexer_api) self.show = newShow # set up initial values self.show.location = self.show_dir self.show.subtitles = self.subtitles if self.subtitles is not None else app.SUBTITLES_DEFAULT self.show.quality = self.quality if self.quality else app.QUALITY_DEFAULT self.show.season_folders = self.season_folders if self.season_folders is not None \ else app.SEASON_FOLDERS_DEFAULT self.show.anime = self.anime if self.anime is not None else app.ANIME_DEFAULT self.show.scene = self.scene if self.scene is not None else app.SCENE_DEFAULT self.show.paused = self.paused if self.paused is not None else False # set up default new/missing episode status log.info( 'Setting all previously aired episodes to the specified status: {status}', {'status': statusStrings[self.default_status]}) self.show.default_ep_status = self.default_status if self.show.anime: self.show.release_groups = BlackAndWhiteList(self.show) if self.blacklist: self.show.release_groups.set_black_keywords(self.blacklist) if self.whitelist: self.show.release_groups.set_white_keywords(self.whitelist) except IndexerException as error: log.error( 'Unable to add show due to an error with {indexer}: {error}', { 'indexer': indexerApi(self.indexer).name, 'error': error }) ui.notifications.error( 'Unable to add {series_name} due to an error with {indexer_name}' .format(series_name=self.show.name if self.show else 'show', indexer_name=indexerApi(self.indexer).name)) self._finishEarly() return except MultipleShowObjectsException: log.warning( 'The show in {show_dir} is already in your show list, skipping', {'show_dir': self.show_dir}) ui.notifications.error( 'Show skipped', 'The show in {show_dir} is already in your show list'.format( show_dir=self.show_dir)) self._finishEarly() return except Exception as error: log.error('Error trying to add show: {0}', error) log.debug(traceback.format_exc()) self._finishEarly() raise log.debug('Retrieving show info from IMDb') try: self.show.load_imdb_info() except ImdbAPIError as error: log.info('Something wrong on IMDb api: {0}', error) except RequestException as error: log.warning('Error loading IMDb info: {0}', error) try: log.debug('{id}: Saving new show to database', {'id': self.show.series_id}) self.show.save_to_db() except Exception as error: log.error('Error saving the show to the database: {0}', error) log.debug(traceback.format_exc()) self._finishEarly() raise # add it to the show list app.showList.append(self.show) try: self.show.load_episodes_from_indexer(tvapi=indexer_api) except Exception as error: log.error( 'Error with {indexer}, not creating episode list: {error}', { 'indexer': indexerApi(self.show.indexer).name, 'error': error }) log.debug(traceback.format_exc()) # update internal name cache name_cache.build_name_cache(self.show) try: self.show.load_episodes_from_dir() except Exception as error: log.error('Error searching dir for episodes: {0}', error) log.debug(traceback.format_exc()) # if they set default ep status to WANTED then run the backlog to search for episodes if self.show.default_ep_status == WANTED: log.info( 'Launching backlog for this show since its episodes are WANTED' ) wanted_segments = self.show.get_wanted_segments() for season, segment in viewitems(wanted_segments): cur_backlog_queue_item = BacklogQueueItem(self.show, segment) app.forced_search_queue_scheduler.action.add_item( cur_backlog_queue_item) log.info('Sending forced backlog for {show} season {season}' ' because some episodes were set to wanted'.format( show=self.show.name, season=season)) self.show.write_metadata() self.show.update_metadata() self.show.populate_cache() self.show.flush_episodes() if app.USE_TRAKT: # if there are specific episodes that need to be added by trakt app.trakt_checker_scheduler.action.manage_new_show(self.show) # add show to trakt.tv library if app.TRAKT_SYNC: app.trakt_checker_scheduler.action.add_show_trakt_library( self.show) if app.TRAKT_SYNC_WATCHLIST: log.info('update watchlist') notifiers.trakt_notifier.update_watchlist(show_obj=self.show) # Load XEM data to DB for show scene_numbering.xem_refresh(self.show, force=True) # check if show has XEM mapping so we can determine if searches # should go by scene numbering or indexer numbering. Warn the user. if not self.scene and scene_numbering.get_xem_numbering_for_show( self.show): log.warning( '{id}: while adding the show {title} we noticed thexem.de has an episode mapping available' '\nyou might want to consider enabling the scene option for this show.', { 'id': self.show.series_id, 'title': self.show.name }) ui.notifications.message( 'consider enabling scene for this show', 'for show {title} you might want to consider enabling the scene option' .format(title=self.show.name)) # After initial add, set to default_status_after. self.show.default_ep_status = self.default_status_after try: log.debug('{id}: Saving new show info to database', {'id': self.show.series_id}) self.show.save_to_db() except Exception as error: log.warning( '{id}: Error saving new show info to database: {error_msg}', { 'id': self.show.series_id, 'error_msg': error }) log.error(traceback.format_exc()) # Send ws update to client ws.Message('showAdded', self.show.to_json(detailed=False)).push() self.finish()