def _configure_filebot_handler(settings, handler=None): """Configures a handler using the given settings dictionary. If no handler is given a new handler is created. Invalid settings will be skipped *settings*: a dictionary in format {"setting": value, ...} *handler*: the handler you want to use, defaults to new Handler *returns*: a configured handler. """ if not handler: handler = pyfilebot.FilebotHandler() valid_handler_attributes = [ "format_string", "database", "output", "episode_order", "rename_action", "recursive", "language_code", "encoding", "on_conflict", "query_override", "non_strict", "mode" ] for attribute in valid_handler_attributes: if attribute in settings: try: handler.__setattr__(attribute, settings[attribute]) except ValueError: log.warning("{0} is not a valid value for {1}, " "skipping...".format(settings[attribute], attribute)) return handler
def do_revert(self, torrent_ids): """calls filebottool.revert() on files in a torrent. Will only allow one torrent at a time""" errors = {} if isinstance(torrent_ids, str): torrent_ids = [torrent_ids] for torrent_id in torrent_ids: self._mark_processing(torrent_id) targets = self._get_filebot_target(torrent_id) log.debug("reverting torrent {0} with targets {1}".format( torrent_id, targets)) self.torrent_manager[torrent_id].pause() handler = pyfilebot.FilebotHandler() try: # noinspection PyUnresolvedReferences filebot_results = yield threads.deferToThread( handler.revert, targets) except Exception, err: log.error("FILEBOT ERROR {0}".format(err)) errors[torrent_id] = (str(err), err.msg) self._finish_processing(torrent_id, error=err) continue # noinspection PyUnboundLocalVariable deluge_movements = self._translate_filebot_movements( torrent_id, filebot_results[1]) if not deluge_movements: self._finish_processing(torrent_id) continue conflicts = self._file_conflicts(torrent_id, deluge_movements, filebot_results[2]) if conflicts: log.warning( 'Rename unsafe for torrent {0}, conflicting files:{1}'. format(torrent_id, conflicts)) log.warning('Rolling back torrent {0}.'.format(torrent_id)) self._rollback(filebot_results, torrent_id) errors[torrent_id] = ("FileConflicts", "Rename is not safe on torrent {0}.\n" "The following files already exsist:\n" "{1}" "Rolling Back and recheking.".format( torrent_id, ''.join(' ' + f + '\n' for f in conflicts))) self._finish_processing(torrent_id, error="File Conflict") continue log.debug("Attempting to re-reoute torrent: {0}".format( deluge_movements)) self._redirect_torrent_paths(torrent_id, deluge_movements)
def do_revert(self, torrent_id): """calls filebottool.revert() on files in a torrent. Will only allow one torrent at a time""" targets = self._get_filebot_target(torrent_id) log.debug("reverting torrent {0} with targets {1}".format(torrent_id, targets)) original_torrent_state = self.torrent_manager[torrent_id].state self.torrent_manager[torrent_id].pause() handler = pyfilebot.FilebotHandler() try: # noinspection PyUnresolvedReferences filebot_results = yield threads.deferToThread(handler.revert, targets) except Exception, err: log.error("FILEBOT ERROR {0}".format(err)) defer.returnValue((False, err))
def do_rename(self, torrent_ids, handler_settings=None, handler=None): """executes a filebot run. Args: torrent_id: id of torrent to execute against handler_settings: an optional dictionary of settings build a filebot handler from handler: an optional FilebotHandler to use (overrides handler_settings) returns: tuple in format (success, errors_dictionary, messages). """ if not handler: if handler_settings: try: handler_name = handler_settings['handler_name'] except KeyError: handler_name = None handler = self._configure_filebot_handler(handler_settings, handler) else: handler = pyfilebot.FilebotHandler() handler_name = None errors = {} new_files = [] for torrent_id in torrent_ids: self._mark_processing(torrent_id, handler_name) if handler.rename_action is not None: link = "link" in handler.rename_action or handler.rename_action == 'copy' else: link = False target = self._get_filebot_target(torrent_id) log.debug("beginning filebot run on torrent {0}, with target {1}".format( torrent_id, target)) if not link: self.torrent_manager[torrent_id].pause() try: filebot_results = yield threads.deferToThread(handler.rename, target) except pyfilebot.FilebotRuntimeError as err: log.error("FILEBOT ERROR!", exc_info=True) errors[torrent_id] = (str(err.__class__.__name__), err.msg) filebot_results = ["", {}, {}] self._finish_processing(torrent_id, error=err) continue except pyfilebot.FilebotLicenseError as err: log.error("Error Renaming, Unlicensed FileBot!") errors[torrent_id] = (str(err.__class__.__name__), err.msg) filebot_results = ["", {}, {}] self._finish_processing(torrent_id, error=err) continue except Exception as e: log.error("Unexpected error from pyfilebot.", exc_info=True) errors[torrent_id] = (str(err.__class__.__name__), err.msg) filebot_results = ["", {}, {}] self._finish_processing(torrent_id, error=err) continue log.debug("recieved results from filebot: {0}".format( filebot_results)) if not link: deluge_movements = self._translate_filebot_movements(torrent_id, filebot_results[1]) else: deluge_movements = None new_files += filebot_results[1] conflicts = self._file_conflicts(torrent_id, deluge_movements, filebot_results[2]) if conflicts and handler.on_conflict == 'override': # for non-fb files for conflict in conflicts: os.remove(conflict) elif conflicts: log.warning("Raname is not safe on torrent {0}. " "Rolling Back and recheking".format(torrent_id)) self._rollback(filebot_results, torrent_id) errors[torrent_id] = ( "File Conflict", "Problem with moving torrent \"{0}\".\n" "The following files already exsist:\n{1}" "Rolling back to previous state and rechecking.".format( self.torrent_manager[torrent_id].get_status( ["name"])["name"], ''.join(' '+f+'\n' for f in conflicts))) self._finish_processing(torrent_id, error="File Conflict") continue if deluge_movements: log.debug("Attempting to re-reoute torrent: {0}".format( deluge_movements)) self._redirect_torrent_paths(torrent_id, deluge_movements) # download subs if handler_settings: if handler_settings['download_subs']: handler.output = None if link: deluge_movements = self._translate_filebot_movements(torrent_id, filebot_results[1]) mock = self._get_mockup_files_dictionary(torrent_id, deluge_movements) new_save = deluge_movements[0] if deluge_movements else None if not new_save: torrent = self.torrent_manager[torrent_id] new_save = torrent.get_status(["save_path"])["save_path"] target = [self._get_full_os_path(new_save, f['path']) for f in mock] try: subs = yield threads.deferToThread(handler.get_subtitles, target, language_code=handler_settings['subs_language']) if not subs: log.info("No subs found for torrent {0}".format(torrent_id)) else: log.info('Downloaded subs: {0}'.format(subs)) new_files += subs except pyfilebot.FilebotRuntimeError as err: log.error("FILEBOT ERROR while getting subs!", exc_info=True) errors[torrent_id] = (str(err), err.msg) if not deluge_movements: self._finish_processing(torrent_id) if errors: defer.returnValue((False, errors, new_files)) else: defer.returnValue((True, None, new_files))
def do_dry_run(self, torrent_id, handler_settings=None, handler=None): """ Executes a dry run on torrent_id using handler_settings Args: torrent_id: deluge ID of torrent handler_settings: dictionary containing the handler settings handler: optional handler object Returns: Tuple in format: ((success, errors_dict), (new_save_path, files_dictionary)) """ if not handler: if handler_settings: handler = self._configure_filebot_handler(handler_settings, handler) else: handler = pyfilebot.FilebotHandler() handler.rename_action = "test" target = self._get_filebot_target(torrent_id) log.debug("running filbot dry run for torrent: {0} with target {1}".format( torrent_id, target)) try: filebot_results = yield threads.deferToThread(handler.rename, target) except pyfilebot.FilebotRuntimeError as err: log.error("FILEBOT ERROR!", exc_info=True) defer.returnValue(((False, {torrent_id:('FilebotRuntimeError', err.msg)}), ('FILEBOTERROR', None))) except Exception as e: log.error("Unexpected error in pyfilebot: {0}".format(e), exc_info=True) defer.returnValue(((False, {torrent_id:(str(e.__class__.__name__), str(e))}), ('FILEBOTTOOLERROR', None))) # noinspection PyUnboundLocalVariable log.debug("recieved results from filebot: {0}".format(filebot_results)) deluge_movements = self._translate_filebot_movements(torrent_id, filebot_results[1]) if not deluge_movements: new_save_path = self.torrent_manager[torrent_id].get_status( ["save_path"])["save_path"] defer.returnValue(((True, None), (new_save_path, self.torrent_manager[ torrent_id].get_files()))) log.debug("REQUIRED DELUGE MOVEMENTS: {0}".format(deluge_movements)) new_save_path = deluge_movements[0] if not new_save_path: new_save_path = self.torrent_manager[torrent_id].get_status( ["save_path"])["save_path"] conflicts = self._file_conflicts(torrent_id, deluge_movements, filebot_results[2]) if conflicts: overwrite = handler.on_conflict == 'override' errors = {} errors[torrent_id] = ('File Conflict', 'The following files already exsist{0}:\n{1}'.format( ' and will be overwritten!' if overwrite else '', ''.join(' ' + f + '\n' for f in conflicts)) ) defer.returnValue(( (True if not conflicts else False, None if not conflicts else errors), (new_save_path, self._get_mockup_files_dictionary(torrent_id, deluge_movements))))