From cb7bf446e3b9e55b3428ab8859de2b3d6c6238b2 Mon Sep 17 00:00:00 2001 From: lanvent Date: Mon, 13 Mar 2023 01:50:37 +0800 Subject: [PATCH] plugin: godcmd support manage plugins --- plugins/godcmd/godcmd.py | 56 ++++++++++++++++++++++++++ plugins/plugin_manager.py | 82 +++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 20 deletions(-) diff --git a/plugins/godcmd/godcmd.py b/plugins/godcmd/godcmd.py index 3dd8760..2f57d32 100644 --- a/plugins/godcmd/godcmd.py +++ b/plugins/godcmd/godcmd.py @@ -48,6 +48,24 @@ ADMIN_COMMANDS = { "alias": ["resetall", "重置所有会话"], "desc": "重置所有会话", }, + "scanp": { + "alias": ["scanp", "扫描插件"], + "desc": "扫描插件目录是否有新插件", + }, + "plist": { + "alias": ["plist", "插件"], + "desc": "打印当前插件列表", + }, + "enablep": { + "alias": ["enablep", "启用插件"], + "args": ["插件名"], + "desc": "启用指定插件", + }, + "disablep": { + "alias": ["disablep", "禁用插件"], + "args": ["插件名"], + "desc": "禁用指定插件", + }, "debug": { "alias": ["debug", "调试模式", "DEBUG"], "desc": "开启机器调试日志", @@ -163,6 +181,44 @@ class Godcmd(Plugin): elif cmd == "debug": logger.setLevel('DEBUG') ok, result = True, "DEBUG模式已开启" + elif cmd == "plist": + plugins = PluginManager().list_plugins() + ok = True + result = "插件列表:\n" + for name,plugincls in plugins.items(): + result += f"{name}_v{plugincls.version} - " + if plugincls.enabled: + result += "已启用\n" + else: + result += "未启用\n" + elif cmd == "scanp": + new_plugins = PluginManager().scan_plugins() + ok, result = True, "插件扫描完成" + if len(new_plugins) >0 : + PluginManager().activate_plugins() + result += "\n发现新插件:\n" + result += "\n".join([f"{p.name}_v{p.version}" for p in new_plugins]) + else : + result +=", 未发现新插件" + elif cmd == "enablep": + if len(args) != 1: + ok, result = False, "请提供插件名" + else: + ok = PluginManager().enable_plugin(args[0]) + if ok: + result = "插件已启用" + else: + result = "插件不存在" + elif cmd == "disablep": + if len(args) != 1: + ok, result = False, "请提供插件名" + else: + ok = PluginManager().disable_plugin(args[0]) + if ok: + result = "插件已禁用" + else: + result = "插件不存在" + logger.debug("[Godcmd] admin command: %s by %s" % (cmd, user)) else: ok, result = False, "需要管理员权限才能执行该指令" diff --git a/plugins/plugin_manager.py b/plugins/plugin_manager.py index dc8e892..630041a 100644 --- a/plugins/plugin_manager.py +++ b/plugins/plugin_manager.py @@ -15,6 +15,7 @@ class PluginManager: self.plugins = {} self.listening_plugins = {} self.instances = {} + self.pconf = {} def register(self, name: str, desc: str, version: str, author: str): def wrapper(plugincls): @@ -28,12 +29,27 @@ class PluginManager: return plugincls return wrapper - def save_config(self, pconf): + def save_config(self): with open("plugins/plugins.json", "w", encoding="utf-8") as f: - json.dump(pconf, f, indent=4, ensure_ascii=False) + json.dump(self.pconf, f, indent=4, ensure_ascii=False) def load_config(self): logger.info("Loading plugins config...") + + modified = False + if os.path.exists("plugins/plugins.json"): + with open("plugins/plugins.json", "r", encoding="utf-8") as f: + pconf = json.load(f) + else: + modified = True + pconf = {"plugins": []} + self.pconf = pconf + if modified: + self.save_config() + return pconf + + def scan_plugins(self): + logger.info("Scaning plugins ...") plugins_dir = "plugins" for plugin_name in os.listdir(plugins_dir): plugin_path = os.path.join(plugins_dir, plugin_name) @@ -44,31 +60,20 @@ class PluginManager: # 导入插件 import_path = "{}.{}.{}".format(plugins_dir, plugin_name, plugin_name) main_module = importlib.import_module(import_path) - + pconf = self.pconf + new_plugins = [] modified = False - if os.path.exists("plugins/plugins.json"): - with open("plugins/plugins.json", "r", encoding="utf-8") as f: - pconf = json.load(f) - else: - modified = True - pconf = {"plugins": []} for name, plugincls in self.plugins.items(): if name not in [plugin["name"] for plugin in pconf["plugins"]]: + new_plugins.append(plugincls) modified = True logger.info("Plugin %s not found in pconfig, adding to pconfig..." % name) pconf["plugins"].append({"name": name, "enabled": True}) if modified: - self.save_config(pconf) - return pconf - - def load_plugins(self): - pconf = self.load_config() - logger.debug("plugins.json config={}".format(pconf)) - for plugin in pconf["plugins"]: - name = plugin["name"] - enabled = plugin["enabled"] - self.plugins[name].enabled = enabled + self.save_config() + return new_plugins + def activate_plugins(self): for name, plugincls in self.plugins.items(): if plugincls.enabled: if name not in self.instances: @@ -79,11 +84,48 @@ class PluginManager: self.listening_plugins[event] = [] self.listening_plugins[event].append(name) + def load_plugins(self): + self.load_config() + self.scan_plugins() + pconf = self.pconf + logger.debug("plugins.json config={}".format(pconf)) + for plugin in pconf["plugins"]: + name = plugin["name"] + enabled = plugin["enabled"] + self.plugins[name].enabled = enabled + self.activate_plugins() + def emit_event(self, e_context: EventContext, *args, **kwargs): if e_context.event in self.listening_plugins: for name in self.listening_plugins[e_context.event]: - if e_context.action == EventAction.CONTINUE: + if self.plugins[name].enabled and e_context.action == EventAction.CONTINUE: logger.debug("Plugin %s triggered by event %s" % (name,e_context.event)) instance = self.instances[name] instance.handlers[e_context.event](e_context, *args, **kwargs) return e_context + + def enable_plugin(self,name): + if name not in self.plugins: + return False + if not self.plugins[name].enabled : + self.plugins[name].enabled = True + idx = next(i for i in range(len(self.pconf['plugins'])) if self.pconf["plugins"][i]['name'] == name) + self.pconf["plugins"][idx]["enabled"] = True + self.save_config() + self.activate_plugins() + return True + return True + + def disable_plugin(self,name): + if name not in self.plugins: + return False + if self.plugins[name].enabled : + self.plugins[name].enabled = False + idx = next(i for i in range(len(self.pconf['plugins'])) if self.pconf["plugins"][i]['name'] == name) + self.pconf["plugins"][idx]["enabled"] = False + self.save_config() + return True + return True + + def list_plugins(self): + return self.plugins \ No newline at end of file