diff --git a/gui/slick/views/config_postProcessing.mako b/gui/slick/views/config_postProcessing.mako index f18f267f08433ca8e7e0063c56a5adfb06162336..cb202f50dcabc8b674a29b9b7851f9e19c31f463 100644 --- a/gui/slick/views/config_postProcessing.mako +++ b/gui/slick/views/config_postProcessing.mako @@ -137,7 +137,17 @@ <input type="checkbox" name="move_associated_files" id="move_associated_files" ${('', 'checked="checked"')[bool(sickbeard.MOVE_ASSOCIATED_FILES)]}/> <label for="move_associated_files"> <span class="component-title">Move Associated Files</span> - <span class="component-desc">Move srr/srt/sfv/etc files with the episode when processed?</span> + <span class="component-desc">Move srr/sfv/etc files with the episode when processed?</span> + </label> + </div> + <div class="field-pair"> + <label class="nocheck"> + <span class="component-title">Allowed associated file extensions</span> + <input type="text" name="allowed_extensions" id="allowed_extensions" value="${sickbeard.ALLOWED_EXTENSIONS}" class="form-control input-sm input350" /> + </label> + <label class="nocheck"> + <span class="component-title"> </span> + <span class="component-desc">Comma seperated list of associated file extensions SickRage should move while Post Processing. Leaving it empty means all extensions will be allowed</span> </label> </div> <div class="field-pair"> diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index d4e7ab1ec8d40331b172f7b4512fe7a89ff17172..af912e0ea988391570c7c44195defd7bcb474168 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -280,6 +280,7 @@ NFO_RENAME = True TV_DOWNLOAD_DIR = None UNPACK = False SKIP_REMOVED_FILES = False +ALLOWED_EXTENSIONS = "nfo,srr,sfv" NZBS = False NZBS_UID = None @@ -578,7 +579,7 @@ def initialize(consoleLogging=True): KODI_UPDATE_LIBRARY, KODI_HOST, KODI_USERNAME, KODI_PASSWORD, BACKLOG_FREQUENCY, \ USE_TRAKT, TRAKT_USERNAME, TRAKT_ACCESS_TOKEN, TRAKT_REFRESH_TOKEN, TRAKT_REMOVE_WATCHLIST, TRAKT_SYNC_WATCHLIST, TRAKT_REMOVE_SHOW_FROM_SICKRAGE, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, TRAKT_USE_RECOMMENDED, TRAKT_SYNC, TRAKT_SYNC_REMOVE, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, TRAKT_TIMEOUT, TRAKT_BLACKLIST_NAME, \ USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_UPDATE_LIBRARY, USE_PLEX_CLIENT, PLEX_CLIENT_USERNAME, PLEX_CLIENT_PASSWORD, \ - PLEX_SERVER_HOST, PLEX_SERVER_TOKEN, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, MIN_BACKLOG_FREQUENCY, SKIP_REMOVED_FILES, \ + PLEX_SERVER_HOST, PLEX_SERVER_TOKEN, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, MIN_BACKLOG_FREQUENCY, SKIP_REMOVED_FILES, ALLOWED_EXTENSIONS, \ USE_EMBY, EMBY_HOST, EMBY_APIKEY, \ showUpdateScheduler, __INITIALIZED__, INDEXER_DEFAULT_LANGUAGE, EP_DEFAULT_DELETED_STATUS, LAUNCH_BROWSER, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, SORT_ARTICLE, showList, loadingShowList, \ NEWZNAB_DATA, NZBS, NZBS_UID, NZBS_HASH, INDEXER_DEFAULT, INDEXER_TIMEOUT, USENET_RETENTION, TORRENT_DIR, \ @@ -870,6 +871,8 @@ def initialize(consoleLogging=True): SKIP_REMOVED_FILES = bool(check_setting_int(CFG, 'General', 'skip_removed_files', 0)) + ALLOWED_EXTENSIONS = check_setting_str(CFG, 'General', 'allowed_extensions', ALLOWED_EXTENSIONS) + USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', 500) AUTOPOSTPROCESSER_FREQUENCY = check_setting_int(CFG, 'General', 'autopostprocesser_frequency', @@ -1695,6 +1698,7 @@ def save_config(): new_config['General']['check_propers_interval'] = CHECK_PROPERS_INTERVAL new_config['General']['allow_high_priority'] = int(ALLOW_HIGH_PRIORITY) new_config['General']['skip_removed_files'] = int(SKIP_REMOVED_FILES) + new_config['General']['allowed_extensions'] = ALLOWED_EXTENSIONS new_config['General']['quality_default'] = int(QUALITY_DEFAULT) new_config['General']['status_default'] = int(STATUS_DEFAULT) new_config['General']['status_default_after'] = int(STATUS_DEFAULT_AFTER) diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index c831b0d9439f418a3e1553c606ac8698ffed8fbe..6915af51e5c1a5a79f6a22297f832d905de5a7bd 100644 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -171,6 +171,8 @@ class PostProcessor(object): file_path_list = [] + extensions_to_delete = [] + if subfolders: base_name = ek(os.path.basename, globbable_file_path).rpartition('.')[0] else: @@ -207,6 +209,7 @@ class PostProcessor(object): # only add associated to list if associated_file_path == file_path: continue + # only list it if the only non-shared part is the extension or if it is a subtitle if subtitles_only and not associated_file_path[len(associated_file_path) - 3:] in common.subtitleExtensions: continue @@ -215,11 +218,22 @@ class PostProcessor(object): if re.search(r'(^.+\.(rar|r\d+)$)', associated_file_path): continue + # Add the extensions that the user doesn't allow to the 'extensions_to_delete' list + if sickbeard.MOVE_ASSOCIATED_FILES and sickbeard.ALLOWED_EXTENSIONS: + allowed_extensions = sickbeard.ALLOWED_EXTENSIONS.split(",") + if not associated_file_path[-3:] in allowed_extensions and not associated_file_path[-3:] in common.subtitleExtensions: + if ek(os.path.isfile, associated_file_path): + extensions_to_delete.append(associated_file_path) + if ek(os.path.isfile, associated_file_path): file_path_list.append(associated_file_path) if file_path_list: self._log(u"Found the following associated files for %s: %s" % (file_path, file_path_list), logger.DEBUG) + if extensions_to_delete: + # Rebuild the 'file_path_list' list only with the extensions the user allows + file_path_list = [associated_file for associated_file in file_path_list if associated_file not in extensions_to_delete] + self._delete(extensions_to_delete) else: self._log(u"No associated files for %s were found during this pass" % file_path, logger.DEBUG) @@ -236,8 +250,13 @@ class PostProcessor(object): if not file_path: return + # Check if file_path is a list, if not, make it one + if not isinstance(file_path, list): + file_list = [file_path] + else: + file_list = file_path + # figure out which files we want to delete - file_list = [file_path] if associated_files: file_list = file_list + self.list_associated_files(file_path, base_name_only=True, subfolders=True) @@ -940,6 +959,19 @@ class PostProcessor(object): self._log(u"File exists and new file is same size, marking it unsafe to replace") return False + # Check if the processed file season is already in our indexer. If not, the file is most probably mislabled/fake and will be skipped + # Only proceed if the file season is > 0 + if int(ep_obj.season) > 0: + myDB = db.DBConnection() + max_season = myDB.select( + "SELECT MAX(season) as maxseason FROM tv_episodes WHERE showid = ? and indexer = ?", + [show.indexerid, show.indexer]) + # If the file season (ep_obj.season) is bigger than the indexer season (max_season[0][0]), skip the file + if int(ep_obj.season) > int(max_season[0][0]): + self._log(u"File has season %s, while the indexer is on season %s. The file may be incorrectly labeled or fake, aborting." + % (str(ep_obj.season), str(max_season[0][0]))) + return False + # if the file is priority then we're going to replace it even if it exists else: self._log( diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 95aa2c9870adf7eb11d227c60b66a62b32990162..d70c1fa5f78caea5647b161db24cb08cdfb04a27 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -3946,7 +3946,7 @@ class ConfigPostProcessing(Config): no_delete=None, rename_episodes=None, airdate_episodes=None, file_timestamp_timezone=None, unpack=None, move_associated_files=None, sync_files=None, postpone_if_sync_files=None, postpone_if_no_subs=None, nfo_rename=None, - tv_download_dir=None, naming_custom_abd=None, naming_anime=None, + allowed_extensions=None, tv_download_dir=None, naming_custom_abd=None, naming_anime=None, create_missing_show_dirs=None, add_shows_wo_dir=None, naming_abd_pattern=None, naming_strip_year=None, use_failed_downloads=None, delete_failed=None, extra_scripts=None, @@ -3982,6 +3982,7 @@ class ConfigPostProcessing(Config): sickbeard.FILE_TIMESTAMP_TIMEZONE = file_timestamp_timezone sickbeard.MOVE_ASSOCIATED_FILES = config.checkbox_to_value(move_associated_files) sickbeard.SYNC_FILES = sync_files + sickbeard.ALLOWED_EXTENSIONS = allowed_extensions sickbeard.POSTPONE_IF_SYNC_FILES = config.checkbox_to_value(postpone_if_sync_files) sickbeard.POSTPONE_IF_NO_SUBS = config.checkbox_to_value(postpone_if_no_subs) sickbeard.NAMING_CUSTOM_ABD = config.checkbox_to_value(naming_custom_abd)