diff --git a/pkg/api/http/controller/groups/plugins.py b/pkg/api/http/controller/groups/plugins.py new file mode 100644 index 00000000..22a3e944 --- /dev/null +++ b/pkg/api/http/controller/groups/plugins.py @@ -0,0 +1,31 @@ +from __future__ import annotations + + +import traceback + +import quart + +from .....core import app +from .. import group + + +@group.group_class('plugins', '/api/v1/plugins') +class PluginsRouterGroup(group.RouterGroup): + + async def initialize(self) -> None: + @self.route('', methods=['GET']) + async def _() -> str: + plugins = self.ap.plugin_mgr.plugins + + plugins_data = [plugin.model_dump() for plugin in plugins] + + return self.success(data={ + 'plugins': plugins_data + }) + + @self.route('/toggle//', methods=['PUT']) + async def _(author: str, plugin_name: str) -> str: + data = await quart.request.json + target_enabled = data.get('target_enabled') + await self.ap.plugin_mgr.update_plugin_status(plugin_name, target_enabled) + return self.success() diff --git a/pkg/api/http/controller/main.py b/pkg/api/http/controller/main.py index 13b1afcf..99eb28e2 100644 --- a/pkg/api/http/controller/main.py +++ b/pkg/api/http/controller/main.py @@ -6,7 +6,7 @@ import quart import quart_cors from ....core import app -from .groups import logs, system, settings +from .groups import logs, system, settings, plugins from . import group diff --git a/pkg/command/operators/plugin.py b/pkg/command/operators/plugin.py index b1cf6ee1..715c7726 100644 --- a/pkg/command/operators/plugin.py +++ b/pkg/command/operators/plugin.py @@ -163,24 +163,6 @@ class PluginDelOperator(operator.CommandOperator): yield entities.CommandReturn(error=errors.CommandError("插件删除失败: "+str(e))) -async def update_plugin_status(plugin_name: str, new_status: bool, ap: app.Application): - if ap.plugin_mgr.get_plugin_by_name(plugin_name) is not None: - for plugin in ap.plugin_mgr.plugins: - if plugin.plugin_name == plugin_name: - plugin.enabled = new_status - - for func in plugin.content_functions: - func.enable = new_status - - await ap.plugin_mgr.setting.dump_container_setting(ap.plugin_mgr.plugins) - - break - - return True - else: - return False - - @operator.operator_class( name="on", help="启用插件", @@ -200,7 +182,7 @@ class PluginEnableOperator(operator.CommandOperator): plugin_name = context.crt_params[0] try: - if await update_plugin_status(plugin_name, True, self.ap): + if await self.ap.plugin_mgr.update_plugin_status(plugin_name, True): yield entities.CommandReturn(text="已启用插件: {}".format(plugin_name)) else: yield entities.CommandReturn(error=errors.CommandError("插件状态修改失败: 未找到插件 {}".format(plugin_name))) @@ -228,7 +210,7 @@ class PluginDisableOperator(operator.CommandOperator): plugin_name = context.crt_params[0] try: - if await update_plugin_status(plugin_name, False, self.ap): + if await self.ap.plugin_mgr.update_plugin_status(plugin_name, False): yield entities.CommandReturn(text="已禁用插件: {}".format(plugin_name)) else: yield entities.CommandReturn(error=errors.CommandError("插件状态修改失败: 未找到插件 {}".format(plugin_name))) diff --git a/pkg/plugin/context.py b/pkg/plugin/context.py index f6cc1769..46ffb4ac 100644 --- a/pkg/plugin/context.py +++ b/pkg/plugin/context.py @@ -320,3 +320,31 @@ class RuntimeContainer(pydantic.BaseModel): for function in self.content_functions: function.enable = self.enabled + + def model_dump(self, *args, **kwargs): + return { + 'name': self.plugin_name, + 'description': self.plugin_description, + 'version': self.plugin_version, + 'author': self.plugin_author, + 'source': self.plugin_source, + 'main_file': self.main_file, + 'pkg_path': self.pkg_path, + 'enabled': self.enabled, + 'priority': self.priority, + 'event_handlers': { + event_name.__name__: handler.__name__ + for event_name, handler in self.event_handlers.items() + }, + 'content_functions': [ + { + 'name': function.name, + 'human_desc': function.human_desc, + 'description': function.description, + 'parameters': function.parameters, + 'enable': function.enable, + 'func': function.func.__name__, + } + for function in self.content_functions + ], + } diff --git a/pkg/plugin/loaders/classic.py b/pkg/plugin/loaders/classic.py index b5a733f8..b2553c1a 100644 --- a/pkg/plugin/loaders/classic.py +++ b/pkg/plugin/loaders/classic.py @@ -5,7 +5,7 @@ import pkgutil import importlib import traceback -from .. import loader, events, context, models, host +from .. import loader, events, context, models from ...core import entities as core_entities from ...provider.tools import entities as tools_entities from ...utils import funcschema diff --git a/pkg/plugin/manager.py b/pkg/plugin/manager.py index b1241eaf..bc8f7817 100644 --- a/pkg/plugin/manager.py +++ b/pkg/plugin/manager.py @@ -186,3 +186,20 @@ class PluginManager: ) return ctx + + async def update_plugin_status(self, plugin_name: str, new_status: bool): + if self.get_plugin_by_name(plugin_name) is not None: + for plugin in self.plugins: + if plugin.plugin_name == plugin_name: + plugin.enabled = new_status + + for func in plugin.content_functions: + func.enable = new_status + + await self.setting.dump_container_setting(self.plugins) + + break + + return True + else: + return False diff --git a/web/src/components/PluginCard.vue b/web/src/components/PluginCard.vue new file mode 100644 index 00000000..1eb052b2 --- /dev/null +++ b/web/src/components/PluginCard.vue @@ -0,0 +1,257 @@ + + + + + diff --git a/web/src/pages/Plugins.vue b/web/src/pages/Plugins.vue index 3ccb7a8e..984cefb7 100644 --- a/web/src/pages/Plugins.vue +++ b/web/src/pages/Plugins.vue @@ -1,13 +1,111 @@