def validate_worker_config(self): valid = True frontend_messages = self.data_queues.get('frontend_messages') # Ensure that the enabled plugins are compatible with the PluginHandler version plugin_handler = PluginsHandler() if plugin_handler.get_incompatible_enabled_plugins(frontend_messages): valid = False if not self.links.within_enabled_link_limits(frontend_messages): valid = False # Check if plugin configuration has been modified. If it has, stop the workers. # What we want to avoid here is someone partially modifying the plugin configuration # and having the workers pickup a job mid configuration. if self.configuration_changed(): # Generate a frontend message and falsify validation frontend_messages.put({ 'id': 'pluginSettingsChangeWorkersStopped', 'type': 'warning', 'code': 'pluginSettingsChangeWorkersStopped', 'message': '', 'timeout': 0 }) valid = False # Ensure library config is within limits if not Library.within_library_count_limits(frontend_messages): valid = False return valid
def reload_plugin_from_disk(self): # Fetch list of installed plugins plugins = PluginsHandler() order = [{ "column": 'name', "dir": 'asc', }] plugin_results = plugins.get_plugin_list_filtered_and_sorted( order=order, start=0, length=None) # Build choice selection list from installed plugins for plugin in plugin_results: plugin_path = os.path.join(self.plugins_directory, plugin.get('plugin_id')) # Read plugin info.json info_file = os.path.join(plugin_path, 'info.json') with open(info_file) as json_file: plugin_info = json.load(json_file) # Insert plugin details to DB try: PluginsHandler.write_plugin_data_to_db(plugin_info, plugin_path) except Exception as e: print("Exception while saving plugin info to DB. - {}".format( str(e))) return install_plugin_requirements(plugin_path) print() print()
def create_new_plugins(self): plugin_details = inquirer.prompt(menus.get('create_plugin')) # Ensure results are not empty if not plugin_details.get('plugin_name') or not plugin_details.get('plugin_id'): print("ERROR! Invalid input.") return # TODO: Ensure plugin ID has only underscore and a-z, 0-9 # Create new plugin path new_plugin_path = os.path.join(self.plugins_directory, plugin_details.get('plugin_id')) if not os.path.exists(new_plugin_path): os.makedirs(new_plugin_path) # Touch main python file main_python_file = os.path.join(new_plugin_path, 'plugin.py') plugin_template = [ "#!/usr/bin/env python3", "# -*- coding: utf-8 -*-", "", "from unmanic.libs.unplugins.settings import PluginSettings", "", "", "class Settings(PluginSettings):", " settings = {}", "", "" ] if not os.path.exists(main_python_file): with open(main_python_file, 'a') as outfile: for plugin_template_line in plugin_template: outfile.write("{}\n".format(plugin_template_line)) common.touch(os.path.join(new_plugin_path, 'plugin.py')) # Create plugin info.json info_file = os.path.join(new_plugin_path, 'info.json') plugin_info = { "id": plugin_details.get('plugin_id'), "name": plugin_details.get('plugin_name'), "author": "", "version": "0.0.1", "tags": "", "description": "", "icon": "" } if not os.path.exists(info_file): with open(info_file, 'w') as outfile: json.dump(plugin_info, outfile, sort_keys=True, indent=4) # Insert plugin details to DB try: PluginsHandler.write_plugin_data_to_db(plugin_info, new_plugin_path) except Exception as e: print("Exception while saving plugin info to DB. - {}".format(str(e))) return print("Plugin created - '{}'".format((plugin_details.get('plugin_id'))))
def reload_plugin_repos_data(): """ Reloads all plugin repos data from the configured URL path :return: """ plugins = PluginsHandler() return plugins.update_plugin_repos()
def get_enabled_plugin_data_panels(): """ Returns a list of all enabled plugin data panels :return: """ plugin_handler = PluginsHandler() return plugin_handler.get_enabled_plugin_modules_by_type('frontend.panel')
def update_repos(self, *args, **kwargs): plugins = PluginsHandler() if plugins.update_plugin_repos(): # Return success self.write(json.dumps({"success": True})) else: # Return failure self.write(json.dumps({"success": False}))
def get_enabled_plugin_plugin_apis(): """ Returns a list of all enabled plugin APIs :return: """ plugin_handler = PluginsHandler() return plugin_handler.get_enabled_plugin_modules_by_type( 'frontend.plugin_api')
def list_installed_plugins(): plugins = PluginsHandler() order = { "column": 'position', "dir": 'desc', } plugin_results = plugins.get_plugin_list_filtered_and_sorted(order=order, start=0, length=None) print_table(plugin_results) print()
def update_plugins(plugin_table_ids): """ Removes/Uninstalls a list of plugins :param plugin_table_ids: :return: """ plugins_handler = PluginsHandler() return plugins_handler.update_plugins_by_db_table_id(plugin_table_ids)
def exec_data_panels_plugin_runner(data, plugin_id): """ Exec a frontend.panel plugin runner :param data: :param plugin_id: :return: """ plugin_handler = PluginsHandler() return plugin_handler.exec_plugin_runner(data, plugin_id, 'frontend.panel')
def __get_enabled_plugins(self): """ Returns a list of enabled plugins :return: """ from unmanic.libs.plugins import PluginsHandler plugin_handler = PluginsHandler() return plugin_handler.get_plugin_list_filtered_and_sorted( order=self.plugin_sort_order, enabled=True)
def get_enabled_plugin_flows_for_plugin_type(plugin_type, library_id): """ Fetch all enabled plugin flows for a plugin type :param plugin_type: :param library_id: :return: """ plugin_handler = PluginsHandler() return plugin_handler.get_enabled_plugin_flows_for_plugin_type( plugin_type, library_id)
def exec_plugin_api_plugin_runner(data, plugin_id): """ Exec a frontend.plugin_api plugin runner :param data: :param plugin_id: :return: """ plugin_handler = PluginsHandler() return plugin_handler.exec_plugin_runner(data, plugin_id, 'frontend.plugin_api')
def prepare_installable_plugins_list(): """ Return a list of plugins able to be installed. At the moment this does not employ any pagination. The lists are small enough that it can all be done frontend. However that may change in the future. :return: """ plugins = PluginsHandler() # Fetch a list of plugin data cached locally return plugins.get_installable_plugins_list()
def install_plugin_by_id(plugin_id, repo_id=None): """ Install a plugin given its Plugin ID :param plugin_id: :param repo_id: :return: """ # Fetch a list of plugin data cached locally plugins = PluginsHandler() return plugins.install_plugin_by_id(plugin_id, repo_id)
def save_enabled_plugin_flows_for_plugin_type(plugin_type, library_id, plugin_flow): """ Save a plugin flow given the plugin type and library ID :param plugin_type: :param library_id: :param plugin_flow: :return: """ plugins = PluginsHandler() return plugins.set_plugin_flow(plugin_type, library_id, plugin_flow)
def install_plugin_by_id(self, *args, **kwargs): plugin_id = self.get_argument('plugin_id') # Fetch a list of plugin data cached locally plugins = PluginsHandler() success = plugins.install_plugin_by_id(plugin_id) if success: # Return success self.write(json.dumps({"success": True})) else: # Return failure self.write(json.dumps({"success": False}))
def __init__(self, library_id: int): self.settings = config.Config() unmanic_logging = unlogger.UnmanicLogger.__call__() self.logger = unmanic_logging.get_logger(__class__.__name__) # Init plugins self.library_id = library_id self.plugin_handler = PluginsHandler() self.plugin_modules = self.plugin_handler.get_enabled_plugin_modules_by_type( 'library_management.file_test', library_id=library_id) # List of filed tasks self.failed_paths = []
def __get_plugin_info_and_settings(self, plugin_id): plugins = PluginsHandler() plugin_installed = True plugin_results = plugins.get_plugin_list_filtered_and_sorted( plugin_id=plugin_id) if not plugin_results: # This plugin is not installed plugin_installed = False # Try to fetch it from the repository plugin_list = plugins.get_installable_plugins_list() for plugin in plugin_list: if plugin.get('id') == plugin_id: # Create changelog text from remote changelog text file plugin['changelog'] = plugins.read_remote_changelog_file( plugin.get('changelog_url')) # Create list as the 'plugin_results' var above will also have returned a list if any results were found. plugin_results = [plugin] break # Iterate over plugins and append them to the plugin data plugin_data = {} for plugin_result in plugin_results: # Set params as required in template plugin_data = { 'id': plugin_result.get('id'), 'plugin_id': plugin_result.get('plugin_id'), 'icon': plugin_result.get('icon'), 'name': plugin_result.get('name'), 'description': plugin_result.get('description'), 'tags': plugin_result.get('tags'), 'author': plugin_result.get('author'), 'version': plugin_result.get('version'), 'changelog': plugin_result.get('changelog', ''), 'settings': [], } if plugin_installed: plugin_data['settings'] = self.__get_plugin_settings( plugin_result.get('plugin_id')) plugin_data['changelog'] = "".join( self.__get_plugin_changelog( plugin_result.get('plugin_id'))) plugin_data['description'] += "\n" + "".join( self.__get_plugin_long_description( plugin_result.get('plugin_id'))) break return plugin_data
def update_repo_list(self, *args, **kwargs): repos_list = self.get_argument('repos_list') if repos_list: repos_list = repos_list.splitlines() try: plugins = PluginsHandler() plugins.set_plugin_repos(repos_list) except Exception as e: tornado.log.app_log.exception( "Exception in updating repo list - {}".format(str(e)), exc_info=True) self.get_repo_list()
def system_configuration_is_valid(self): """ Check and ensure the system configuration is correct for running :return: """ valid = True plugin_handler = PluginsHandler() if plugin_handler.get_incompatible_enabled_plugins( self.data_queues.get('frontend_messages')): valid = False if not Library.within_library_count_limits( self.data_queues.get('frontend_messages')): valid = False return valid
def get_plugin_types_with_flows(): """ Returns a list of all available plugin types :return: """ return PluginsHandler.get_plugin_types_with_flows()
def test_installed_plugins(): """ Test all plugin runners for correct return data :return: """ plugin_executor = PluginExecutor() plugins = PluginsHandler() order = { "column": 'position', "dir": 'desc', } plugin_results = plugins.get_plugin_list_filtered_and_sorted(order=order, start=0, length=None) for plugin_result in plugin_results: # plugin_runners = plugin_executor.get_plugin_runners('worker.process_item') print("{1}Testing plugin: '{0}'{2}".format(plugin_result.get("name"), BColours.HEADER, BColours.ENDC)) plugin_id = plugin_result.get("plugin_id") # Test Plugin runners print(" {0}Testing runners{1}".format(BColours.SUBHEADER, BColours.ENDC)) plugin_types_in_plugin = plugin_executor.get_all_plugin_types_in_plugin(plugin_id) if not plugin_types_in_plugin: error = "No runners found in plugin" print(" - {1}FAILED: {0}{2}".format(error, BColours.FAIL, BColours.ENDC)) else: for plugin_type_in_plugin in plugin_types_in_plugin: errors = plugin_executor.test_plugin_runner(plugin_id, plugin_type_in_plugin) if errors: for error in errors: print(" - {1}FAILED: {0}{2}".format(error, BColours.FAIL, BColours.ENDC)) else: print(" - {}PASSED{}".format(BColours.OKGREEN, BColours.ENDC)) # Test Plugin settings print(" {0}Testing settings{1}".format(BColours.SUBHEADER, BColours.ENDC)) errors, plugin_settings = plugin_executor.test_plugin_settings(plugin_id) if errors: for error in errors: print(" - {1}FAILED: {0}{2}".format(error, BColours.FAIL, BColours.ENDC)) else: formatted_plugin_settings = json.dumps(plugin_settings, indent=1) formatted_plugin_settings = formatted_plugin_settings.replace('\n', '\n' + ' ') print(" - {1}Settings: {0}{2}".format(formatted_plugin_settings, BColours.RESULTS, BColours.ENDC)) print(" - {}PASSED{}".format(BColours.OKGREEN, BColours.ENDC)) print()
def check_if_plugin_is_installed(plugin_id): """ Returns true if the given plugin is installed :param plugin_id: :return: """ plugins_handler = PluginsHandler() plugin_installed = True plugin_results = plugins_handler.get_plugin_list_filtered_and_sorted( plugin_id=plugin_id) if not plugin_results: # This plugin is not installed plugin_installed = False return plugin_installed
def export(library_id): from unmanic.libs.plugins import PluginsHandler # Read the library library_config = Library(library_id) # Get list of enabled plugins with their settings enabled_plugins = [] for enabled_plugin in library_config.get_enabled_plugins( include_settings=True): enabled_plugins.append({ 'plugin_id': enabled_plugin.get('plugin_id'), 'has_config': enabled_plugin.get('has_config'), 'settings': enabled_plugin.get('settings'), }) # Create plugin flow plugin_flow = {} plugin_handler = PluginsHandler() for plugin_type in plugin_handler.get_plugin_types_with_flows(): plugin_flow[plugin_type] = [] flow = plugin_handler.get_enabled_plugin_flows_for_plugin_type( plugin_type, library_id) for f in flow: plugin_flow[plugin_type].append(f.get('plugin_id')) return { "plugins": { "enabled_plugins": enabled_plugins, "plugin_flow": plugin_flow, }, "library_config": { "name": library_config.get_name(), "path": library_config.get_path(), 'enable_remote_only': library_config.get_enable_remote_only(), 'enable_scanner': library_config.get_enable_scanner(), 'enable_inotify': library_config.get_enable_inotify(), 'tags': library_config.get_tags(), }, }
def get_installed_plugin_flow(self, *args, **kwargs): plugin_type = self.get_argument('plugin_type') plugin_handler = PluginsHandler() plugin_modules = plugin_handler.get_plugin_modules_by_type(plugin_type) # Only return the data that we need return_plugin_flow = [] for plugin_module in plugin_modules: return_plugin_flow.append({ "plugin_id": plugin_module.get("plugin_id"), "name": plugin_module.get("name"), }) self.write( json.dumps({ "success": True, "plugin_flow": return_plugin_flow }))
def __get_plugin_info_and_settings(self, plugin_id): plugins = PluginsHandler() plugin_installed = True plugin_results = plugins.get_plugin_list_filtered_and_sorted( plugin_id=plugin_id) if not plugin_results: # This plugin is not installed plugin_installed = False # Try to fetch it from the repository plugin_list = plugins.get_installable_plugins_list() for plugin in plugin_list: if plugin.get('id') == plugin_id: plugin_results = [plugin] break # Iterate over plugins and append them to the plugin data plugin_data = {} for plugin_result in plugin_results: # Set params as required in template plugin_data = { 'id': plugin_result.get('id'), 'plugin_id': plugin_result.get('plugin_id'), 'icon': plugin_result.get('icon'), 'name': plugin_result.get('name'), 'description': plugin_result.get('description'), 'tags': plugin_result.get('tags'), 'author': plugin_result.get('author'), 'version': plugin_result.get('version'), 'settings': [], } if plugin_installed: plugin_data['settings'] = self.__get_plugin_settings( plugin_result.get('plugin_id')) plugin_data['changelog'] = "".join( self.__get_plugin_changelog( plugin_result.get('plugin_id'))) break return plugin_data
def __get_enabled_plugins(self, plugin_type=None): """ Returns a list of enabled plugins :return: """ from unmanic.libs.plugins import PluginsHandler plugin_handler = PluginsHandler() order = [ { "model": PluginFlow, "column": 'position', "dir": 'asc', }, { "column": 'name', "dir": 'asc', }, ] return plugin_handler.get_plugin_list_filtered_and_sorted( order=order, enabled=True, plugin_type=plugin_type)
def prepare_plugin_repos_list(): """ Return a list of plugin repos available to download from :return: """ return_repos = [] plugins = PluginsHandler() # Fetch the data again from the database current_repos = plugins.get_plugin_repos() # Remove the default plugin repo from the list default_repo = plugins.get_default_repo() for repo in current_repos: if not repo.get("path").startswith(default_repo): return_repos.append(repo) # Append metadata from repo cache files for repo in return_repos: repo_path = repo.get('path') repo_id = plugins.get_plugin_repo_id(repo_path) repo_data = plugins.read_repo_data(repo_id) repo_metadata = repo_data.get('repo', {}) repo['id'] = repo_metadata.get('id') repo['icon'] = repo_metadata.get('icon') repo['name'] = repo_metadata.get('name') return return_repos
def __set_default_plugin_flow_priority(self, plugin_list): from unmanic.libs.unplugins import PluginExecutor plugin_executor = PluginExecutor() from unmanic.libs.plugins import PluginsHandler plugin_handler = PluginsHandler() # Fetch current items configured_plugin_ids = [] query = LibraryPluginFlow.select().where( LibraryPluginFlow.library_id == self.model.id) for flow_item in query: configured_plugin_ids.append(flow_item.plugin_id.plugin_id) for plugin in plugin_list: # Ignore already configured plugins if plugin.get('plugin_id') in configured_plugin_ids: continue plugin_info = plugin_handler.get_plugin_info( plugin.get('plugin_id')) plugin_priorities = plugin_info.get('priorities') if plugin_priorities: # Fetch the plugin info back from the DB plugin_info = Plugins.select().where( Plugins.plugin_id == plugin.get("plugin_id")).first() # Fetch all plugin types in this plugin plugin_types_in_plugin = plugin_executor.get_all_plugin_types_in_plugin( plugin.get("plugin_id")) # Loop over the plugin types in this plugin for plugin_type in plugin_types_in_plugin: # get the plugin runner function name for this runner plugin_type_meta = plugin_executor.get_plugin_type_meta( plugin_type) runner_string = plugin_type_meta.plugin_runner() if plugin_priorities.get(runner_string) and int( plugin_priorities.get(runner_string, 0)) > 0: # If the runner has a priority set and that value is greater than 0 (default that wont set anything), # Save the priority PluginsHandler.set_plugin_flow_position_for_single_plugin( plugin_info, plugin_type, self.model.id, plugin_priorities.get(runner_string))