def test_is_rar_file(self): """ Test is_rar_file """ self.assertTrue(helpers.is_rar_file('lala.rar')) self.assertFalse(helpers.is_rar_file('lala.zip')) self.assertFalse(helpers.is_rar_file('lala.iso')) self.assertFalse(helpers.is_rar_file('lala.wmv')) self.assertFalse(helpers.is_rar_file('lala.avi')) self.assertFalse(helpers.is_rar_file('lala.mkv')) self.assertFalse(helpers.is_rar_file('lala.mp4'))
def unrar(path, rar_files, force, result): # pylint: disable=too-many-branches,too-many-statements """ Extracts RAR files :param path: Path to look for files in :param rar_files: Names of RAR files :param force: process currently processing items :param result: Previous results :return: List of unpacked file names """ unpacked_dirs = [] if sickbeard.UNPACK == 1 and rar_files: result.output += log_helper("Packed Releases detected: {0}".format(rar_files), logger.DEBUG) for archive in rar_files: failure = None rar_handle = None try: archive_path = ek(os.path.join, path, archive) if already_processed(path, archive, force, result): result.output += log_helper( "Archive file already post-processed, extraction skipped: {0}".format (archive_path), logger.DEBUG) continue if not helpers.is_rar_file(archive_path): continue result.output += log_helper("Checking if archive is valid and contains a video: {0}".format(archive_path), logger.DEBUG) rar_handle = RarFile(archive_path) if rar_handle.needs_password(): # TODO: Add support in settings for a list of passwords to try here with rar_handle.set_password(x) result.output += log_helper('Archive needs a password, skipping: {0}'.format(archive_path)) continue # rar_handle.testrar() # If there are no video files in the rar, don't extract it rar_media_files = filter(helpers.is_media_file, rar_handle.namelist()) if not rar_media_files: continue rar_release_name = archive.rpartition('.')[0] # Choose the directory we'll unpack to: if sickbeard.UNPACK_DIR and os.path.isdir(sickbeard.UNPACK_DIR): # verify the unpack dir exists unpack_base_dir = sickbeard.UNPACK_DIR else: unpack_base_dir = path if sickbeard.UNPACK_DIR: # Let user know if we can't unpack there result.output += log_helper('Unpack directory cannot be verified. Using {0}'.format(path), logger.DEBUG) # Fix up the list for checking if already processed rar_media_files = [os.path.join(unpack_base_dir, rar_release_name, rar_media_file) for rar_media_file in rar_media_files] skip_rar = False for rar_media_file in rar_media_files: check_path, check_file = os.path.split(rar_media_file) if already_processed(check_path, check_file, force, result): result.output += log_helper( "Archive file already post-processed, extraction skipped: {0}".format (rar_media_file), logger.DEBUG) skip_rar = True break if skip_rar: continue rar_extract_path = ek(os.path.join, unpack_base_dir, rar_release_name) result.output += log_helper("Unpacking archive: {0}".format(archive), logger.DEBUG) rar_handle.extractall(path=rar_extract_path) unpacked_dirs.append(rar_extract_path) except RarCRCError: failure = ('Archive Broken', 'Unpacking failed because of a CRC error') except RarWrongPassword: failure = ('Incorrect RAR Password', 'Unpacking failed because of an Incorrect Rar Password') except PasswordRequired: failure = ('Rar is password protected', 'Unpacking failed because it needs a password') except RarOpenError: failure = ('Rar Open Error, check the parent folder and destination file permissions.', 'Unpacking failed with a File Open Error (file permissions?)') except RarExecError: failure = ('Invalid Rar Archive Usage', 'Unpacking Failed with Invalid Rar Archive Usage. Is unrar installed and on the system PATH?') except BadRarFile: failure = ('Invalid Rar Archive', 'Unpacking Failed with an Invalid Rar Archive Error') except NeedFirstVolume: continue except (Exception, Error) as e: failure = (ex(e), 'Unpacking failed') finally: if rar_handle: del rar_handle if failure: result.output += log_helper('Failed to extract the archive {0}: {1}'.format(archive, failure[0]), logger.WARNING) result.missed_files.append('{0} : Unpacking failed: {1}'.format(archive, failure[1])) result.result = False continue return unpacked_dirs
def process_dir(process_path, release_name=None, process_method=None, force=False, is_priority=None, delete_on=False, failed=False, mode="auto"): """ Scans through the files in process_path and processes whatever media files it finds :param process_path: The folder name to look in :param release_name: The NZB/Torrent name which resulted in this folder being downloaded :param process_method: processing method, copy/move/symlink/link :param force: True to process previously processed files :param is_priority: whether to replace the file even if it exists at higher quality :param delete_on: delete files and folders after they are processed (always happens with move and auto combination) :param failed: Boolean for whether or not the download failed :param mode: Type of postprocessing auto or manual """ result = ProcessResult() # if they passed us a real dir then assume it's the one we want if ek(os.path.isdir, process_path): process_path = ek(os.path.realpath, process_path) result.output += log_helper("Processing in folder {0}".format(process_path), logger.DEBUG) # if the client and SickRage are not on the same machine translate the directory into a network directory elif all([sickbeard.TV_DOWNLOAD_DIR, ek(os.path.isdir, sickbeard.TV_DOWNLOAD_DIR), ek(os.path.normpath, process_path) == ek(os.path.normpath, sickbeard.TV_DOWNLOAD_DIR)]): process_path = ek(os.path.join, sickbeard.TV_DOWNLOAD_DIR, ek(os.path.abspath, process_path).split(os.path.sep)[-1]) result.output += log_helper("Trying to use folder: {0} ".format(process_path), logger.DEBUG) # if we didn't find a real dir then quit if not ek(os.path.isdir, process_path): result.output += log_helper("Unable to figure out what folder to process. " "If your downloader and SickRage aren't on the same PC " "make sure you fill out your TV download dir in the config.", logger.DEBUG) return result.output process_method = process_method or sickbeard.PROCESS_METHOD directories_from_rars = set() # If we have a release name (probably from nzbToMedia), and it is a rar/video, only process that file if release_name and (helpers.is_media_file(release_name) or helpers.is_rar_file(release_name)): result.output += log_helper("Processing {}".format(release_name), logger.INFO) generator_to_use = [(process_path, [], [release_name])] else: result.output += log_helper("Processing {}".format(process_path), logger.INFO) generator_to_use = ek(os.walk, process_path, followlinks=sickbeard.PROCESSOR_FOLLOW_SYMLINKS) for current_directory, directory_names, file_names in generator_to_use: result.result = True file_names = [f for f in file_names if not is_torrent_or_nzb_file(f)] rar_files = [x for x in file_names if helpers.is_rar_file(ek(os.path.join, current_directory, x))] if rar_files: extracted_directories = unrar(current_directory, rar_files, force, result) if extracted_directories: for extracted_directory in extracted_directories: if extracted_directory.split(current_directory)[-1] not in directory_names: result.output += log_helper( "Adding extracted directory to the list of directories to process: {0}".format(extracted_directory), logger.DEBUG ) directories_from_rars.add(extracted_directory) if not validate_dir(current_directory, release_name, failed, result): continue video_files = filter(helpers.is_media_file, file_names) if video_files: process_media(current_directory, video_files, release_name, process_method, force, is_priority, result) else: result.result = False # Delete all file not needed and avoid deleting files if Manual PostProcessing if not(process_method == "move" and result.result) or (mode == "manual" and not delete_on): continue # noinspection PyTypeChecker unwanted_files = filter(lambda x: x in video_files + rar_files, file_names) if unwanted_files: result.output += log_helper("Found unwanted files: {0}".format(unwanted_files), logger.DEBUG) delete_folder(ek(os.path.join, current_directory, '@eaDir'), False) delete_files(current_directory, unwanted_files, result) if delete_folder(current_directory, check_empty=not delete_on): result.output += log_helper("Deleted folder: {0}".format(current_directory), logger.DEBUG) # For processing extracted rars, only allow methods 'move' and 'copy'. # On different methods fall back to 'move'. method_fallback = ('move', process_method)[process_method in ('move', 'copy')] # auto post-processing deletes rar content by default if method is 'move', # sickbeard.DELRARCONTENTS allows to override even if method is NOT 'move' # manual post-processing will only delete when prompted by delete_on delete_rar_contents = any([sickbeard.DELRARCONTENTS and mode != 'manual', not sickbeard.DELRARCONTENTS and mode == 'auto' and method_fallback == 'move', mode == 'manual' and delete_on]) for directory_from_rar in directories_from_rars: process_dir( process_path=directory_from_rar, release_name=ek(os.path.basename, directory_from_rar), process_method=method_fallback, force=force, is_priority=is_priority, delete_on=delete_rar_contents, failed=failed, mode=mode ) # Delete rar file only if the extracted dir was successfully processed if mode == 'auto' and method_fallback == 'move' or mode == 'manual' and delete_on: this_rar = [rar_file for rar_file in rar_files if os.path.basename(directory_from_rar) == rar_file.rpartition('.')[0]] delete_files(current_directory, this_rar, result) # Deletes only if result.result == True result.output += log_helper(("Processing Failed", "Successfully processed")[result.aggresult], (logger.WARNING, logger.INFO)[result.aggresult]) if result.missed_files: result.output += log_helper("Some items were not processed.") for missed_file in result.missed_files: result.output += log_helper(missed_file) return result.output
def process_dir(process_path, release_name=None, process_method=None, force=False, is_priority=None, delete_on=False, failed=False, mode="auto"): """ Scans through the files in process_path and processes whatever media files it finds :param process_path: The folder name to look in :param release_name: The NZB/Torrent name which resulted in this folder being downloaded :param force: True to process previously processed files :param failed: Boolean for whether or not the download failed :param mode: Type of postprocessing auto or manual """ result = ProcessResult() # if they passed us a real dir then assume it's the one we want if ek(os.path.isdir, process_path): process_path = ek(os.path.realpath, process_path) result.output += log_helper( u"Processing folder {0}".format(process_path), logger.DEBUG) # if the client and SickRage are not on the same machine translate the directory into a network directory elif all([ sickbeard.TV_DOWNLOAD_DIR, ek(os.path.isdir, sickbeard.TV_DOWNLOAD_DIR), ek(os.path.normpath, process_path) == ek(os.path.normpath, sickbeard.TV_DOWNLOAD_DIR) ]): process_path = ek( os.path.join, sickbeard.TV_DOWNLOAD_DIR, ek(os.path.abspath, process_path).split(os.path.sep)[-1]) result.output += log_helper( u"Trying to use folder: {0} ".format(process_path), logger.DEBUG) # if we didn't find a real dir then quit if not ek(os.path.isdir, process_path): result.output += log_helper( u"Unable to figure out what folder to process. " u"If your downloader and SickRage aren't on the same PC " u"make sure you fill out your TV download dir in the config.", logger.DEBUG) return result.output process_method = process_method or sickbeard.PROCESS_METHOD directories_from_rars = [] for current_directory, directory_names, file_names in ek( os.walk, process_path): if not validate_dir(current_directory, release_name, failed, result): continue result.result = True file_names = [f for f in file_names if not is_torrent_or_nzb_file(f)] rar_files = [ x for x in file_names if helpers.is_rar_file(ek(os.path.join, current_directory, x)) ] if rar_files: extracted_directories = unrar(current_directory, rar_files, force, result) # Add the directories to the walk directories result.output += log_helper( u"Adding extracted directories to the list of directories to process: {0}" .format(extracted_directories), logger.DEBUG) directories_from_rars += extracted_directories video_files = filter(helpers.is_media_file, file_names) unwanted_files = [ x for x in file_names if x not in video_files and x != '.stfolder' ] if unwanted_files: result.output += log_helper( u"Found unwanted files: {0}".format(unwanted_files), logger.DEBUG) process_media(current_directory, video_files, release_name, process_method, force, is_priority, result) # Delete all file not needed and avoid deleting files if Manual PostProcessing if not (process_method == u"move" and result.result) or (mode == u"manual" and not delete_on): continue delete_folder(ek(os.path.join, current_directory, u'@eaDir')) delete_files(current_directory, unwanted_files, result) if all([ not sickbeard.NO_DELETE or mode == u"manual", process_method == u"move", ek(os.path.normpath, current_directory) != ek( os.path.normpath, sickbeard.TV_DOWNLOAD_DIR) ]): if delete_folder(current_directory, check_empty=True): result.output += log_helper( u"Deleted folder: {0}".format(current_directory), logger.DEBUG) for directory_from_rar in directories_from_rars: process_dir( process_path=directory_from_rar, release_name=ek(os.path.basename, directory_from_rar), process_method=('move', process_method)[process_method in ('move', 'copy')], force=force, is_priority=is_priority, delete_on=sickbeard.DELRARCONTENTS, failed=failed, mode=mode) if sickbeard.DELRARCONTENTS: delete_folder(directory_from_rar, False) result.output += log_helper( (u"Processing Failed", u"Successfully processed")[result.aggresult], (logger.WARNING, logger.INFO)[result.aggresult]) if result.missed_files: result.output += log_helper(u"Some items were not processed.") for missed_file in result.missed_files: result.output += log_helper(missed_file) return result.output
def process_dir(process_path, release_name=None, process_method=None, force=False, is_priority=None, delete_on=False, failed=False, mode="auto"): """ Scans through the files in process_path and processes whatever media files it finds :param process_path: The folder name to look in :param release_name: The NZB/Torrent name which resulted in this folder being downloaded :param force: True to process previously processed files :param failed: Boolean for whether or not the download failed :param mode: Type of postprocessing auto or manual """ result = ProcessResult() # if they passed us a real dir then assume it's the one we want if ek(os.path.isdir, process_path): process_path = ek(os.path.realpath, process_path) result.output += log_helper(u"Processing folder {0}".format(process_path), logger.DEBUG) # if the client and SickRage are not on the same machine translate the directory into a network directory elif all([sickbeard.TV_DOWNLOAD_DIR, ek(os.path.isdir, sickbeard.TV_DOWNLOAD_DIR), ek(os.path.normpath, process_path) == ek(os.path.normpath, sickbeard.TV_DOWNLOAD_DIR)]): process_path = ek(os.path.join, sickbeard.TV_DOWNLOAD_DIR, ek(os.path.abspath, process_path).split(os.path.sep)[-1]) result.output += log_helper(u"Trying to use folder: {0} ".format(process_path), logger.DEBUG) # if we didn't find a real dir then quit if not ek(os.path.isdir, process_path): result.output += log_helper(u"Unable to figure out what folder to process. " u"If your downloader and SickRage aren't on the same PC " u"make sure you fill out your TV download dir in the config.", logger.DEBUG) return result.output process_method = process_method or sickbeard.PROCESS_METHOD directories_from_rars = [] for current_directory, directory_names, file_names in ek(os.walk, process_path): if not validate_dir(current_directory, release_name, failed, result): continue result.result = True file_names = [f for f in file_names if not is_torrent_or_nzb_file(f)] rar_files = [x for x in file_names if helpers.is_rar_file(ek(os.path.join, current_directory, x))] if rar_files: extracted_directories = unrar(current_directory, rar_files, force, result) # Add the directories to the walk directories result.output += log_helper(u"Adding extracted directories to the list of directories to process: {0}".format(extracted_directories), logger.DEBUG) directories_from_rars += extracted_directories video_files = filter(helpers.is_media_file, file_names) unwanted_files = [x for x in file_names if x not in video_files] if unwanted_files: result.output += log_helper(u"Found unwanted files: {0}".format(unwanted_files), logger.DEBUG) process_media(current_directory, video_files, release_name, process_method, force, is_priority, result) # Delete all file not needed and avoid deleting files if Manual PostProcessing if not(process_method == u"move" and result.result) or (mode == u"manual" and not delete_on): continue delete_folder(ek(os.path.join, current_directory, u'@eaDir')) delete_files(current_directory, unwanted_files, result) if all([not sickbeard.NO_DELETE or mode == u"manual", process_method == u"move", ek(os.path.normpath, current_directory) != ek(os.path.normpath, sickbeard.TV_DOWNLOAD_DIR)]): if delete_folder(current_directory, check_empty=True): result.output += log_helper(u"Deleted folder: {0}".format(current_directory), logger.DEBUG) for directory_from_rar in directories_from_rars: process_dir( process_path=directory_from_rar, release_name=ek(os.path.basename, directory_from_rar), process_method=('move', process_method)[process_method in ('move', 'copy')], force=force, is_priority=is_priority, delete_on=sickbeard.DELRARCONTENTS, failed=failed, mode=mode ) if sickbeard.DELRARCONTENTS: delete_folder(directory_from_rar, False) result.output += log_helper((u"Processing Failed", u"Successfully processed")[result.aggresult], (logger.WARNING, logger.INFO)[result.aggresult]) if result.missed_files: result.output += log_helper(u"Some items were not processed.") for missed_file in result.missed_files: result.output += log_helper(missed_file) return result.output