From bfb36a1aa51b235e7c2a76e1a51c5de121a17019 Mon Sep 17 00:00:00 2001 From: K2cr2O1 <2221577113@qq.com> Date: Fri, 2 Jan 2026 14:36:16 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9B=86=E6=88=90help=E4=BB=A5=E5=8F=8Ainit?= =?UTF-8?q?=E5=88=B0core=E5=86=85=EF=BC=8C=E4=BF=AE=E6=94=B9baseplugin?= =?UTF-8?q?=E4=B8=BAplugin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++--- base_plugins/help.py | 34 ------------------- core/command_manager.py | 28 +++++++++++++++ .../__init__.py => core/plugin_manager.py | 25 +++++++------- main.py | 11 +++--- {base_plugins => plugins}/echo.py | 0 6 files changed, 52 insertions(+), 54 deletions(-) delete mode 100644 base_plugins/help.py rename base_plugins/__init__.py => core/plugin_manager.py (65%) rename {base_plugins => plugins}/echo.py (100%) diff --git a/README.md b/README.md index 6a5ccb7..f74b384 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ NEO 框架的设计遵循以下核心理念: * **OneBot 11 标准支持**:完整支持 OneBot 11 的消息、通知、请求和元事件。 * **类型安全**:基于 `dataclasses` 的强类型事件模型,开发体验更佳。 * **插件系统**:轻量级的装饰器风格插件系统,支持指令 (`@matcher.command`) 和事件监听 (`@matcher.on_notice`, `@matcher.on_request`)。 -* **插件元数据与自动帮助**:插件可通过 `__plugin_meta__` 变量进行自我描述,框架会自动加载这些信息并生成 `/help` 指令,无需手动维护帮助列表。 +* **插件元数据与内置帮助**:插件可通过 `__plugin_meta__` 变量进行自我描述。框架核心内置了 `/help` 指令,可自动收集并展示所有插件的帮助信息,无需手动维护。 * **🔥 热重载支持**:内置文件监控,修改 `base_plugins` 下的代码自动重载,无需重启,极大提升调试效率。 * **异步核心**:基于 `asyncio` 和 `websockets` 的高性能异步核心。 * **自动重连**:内置 WebSocket 断线重连机制。 @@ -103,9 +103,8 @@ NEO 框架的设计遵循以下核心理念: ``` NEO/ -├── base_plugins/ # 基础插件目录,新建插件文件即可自动加载(支持热重载) -│ ├── echo.py # 示例插件:实现 /echo 和 /赞我 指令 -│ └── help.py # 帮助插件:自动生成所有插件的帮助信息 +├── plugins/ # 插件目录,新建插件文件即可自动加载(支持热重载) +│ └── echo.py # 示例插件:实现 /echo 和 /赞我 指令 ├── core/ # 核心框架代码 │ ├── api/ # API 模块抽象层 (MessageAPI, GroupAPI, FriendAPI, AccountAPI) │ │ ├── __init__.py @@ -117,6 +116,7 @@ NEO/ │ ├── bot.py # Bot API 封装,提供 send_group_msg 等方法 │ ├── command_manager.py # 命令与事件分发器 │ ├── config_loader.py # 配置加载器 +│ ├── plugin_manager.py # 插件加载与管理 │ └── ws.py # WebSocket 客户端核心 ├── models/ # 数据模型 │ ├── events/ # OneBot 事件定义 (Message, Notice, Request, Meta) diff --git a/base_plugins/help.py b/base_plugins/help.py deleted file mode 100644 index ac6014c..0000000 --- a/base_plugins/help.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -帮助插件 - -提供 /help 指令,用于展示所有已加载插件的帮助信息。 -""" -from core.command_manager import matcher -from models.events.message import MessageEvent - -__plugin_meta__ = { - "name": "帮助", - "description": "显示所有可用指令的帮助信息", - "usage": "/help", -} - -@matcher.command("help") -async def help_command(bot, event: MessageEvent): - """ - 处理 /help 指令,生成并发送帮助信息 - - :param bot: Bot 实例 - :param event: 消息事件对象 - """ - help_text = "--- 可用指令列表 ---\n" - - for plugin_name, meta in matcher.plugins.items(): - name = meta.get("name", "未命名插件") - description = meta.get("description", "暂无描述") - usage = meta.get("usage", "暂无用法说明") - - help_text += f"\n{name} ({plugin_name}):\n" - help_text += f" 功能: {description}\n" - help_text += f" 用法: {usage}\n" - - await bot.send(event, help_text.strip()) diff --git a/core/command_manager.py b/core/command_manager.py index 97300b0..e2bb131 100644 --- a/core/command_manager.py +++ b/core/command_manager.py @@ -29,6 +29,34 @@ class CommandManager: self.request_handlers: List[Dict] = [] # 存储请求处理器 self.plugins: Dict[str, Dict[str, Any]] = {} # 存储插件元数据 + # --- 内置 help 指令 --- + self.commands["help"] = self._help_command + self.plugins["core.help"] = { + "name": "帮助", + "description": "显示所有可用指令的帮助信息", + "usage": "/help", + } + + async def _help_command(self, bot, event): + """ + 内置的 /help 指令处理器 + + :param bot: Bot 实例 + :param event: 消息事件对象 + """ + help_text = "--- 可用指令列表 ---\n" + + for plugin_name, meta in self.plugins.items(): + name = meta.get("name", "未命名插件") + description = meta.get("description", "暂无描述") + usage = meta.get("usage", "暂无用法说明") + + help_text += f"\n{name}:\n" + help_text += f" 功能: {description}\n" + help_text += f" 用法: {usage}\n" + + await bot.send(event, help_text.strip()) + # --- 1. 消息指令装饰器 --- def command(self, name: str): """ diff --git a/base_plugins/__init__.py b/core/plugin_manager.py similarity index 65% rename from base_plugins/__init__.py rename to core/plugin_manager.py index 9e5ba36..df15828 100644 --- a/base_plugins/__init__.py +++ b/core/plugin_manager.py @@ -1,28 +1,32 @@ +""" +插件管理器模块 + +负责扫描、加载和管理 `base_plugins` 目录下的所有插件。 +""" import importlib import os import pkgutil import sys - from core.command_manager import matcher def load_all_plugins(): """ - 扫描并加载当前包下所有的插件(支持文件和文件夹) + 扫描并加载 `plugins` 目录下的所有插件。 - 该函数会遍历当前目录下的所有模块: - 1. 如果模块已加载,则执行 reload 操作(用于热重载) - 2. 如果模块未加载,则执行 import 操作 + 该函数会遍历 `plugins` 目录下的所有模块: + 1. 如果模块已加载,则执行 reload 操作(用于热重载)。 + 2. 如果模块未加载,则执行 import 操作。 - 加载过程中会打印详细的日志信息。 + 加载过程中会提取插件元数据 `__plugin_meta__` 并注册到 CommandManager。 """ - package_name = __package__ - package_path = [os.path.dirname(__file__)] + plugin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "plugins") + package_name = "plugins" print(f" 正在从 {package_name} 加载插件...") - for loader, module_name, is_pkg in pkgutil.iter_modules(package_path): + for loader, module_name, is_pkg in pkgutil.iter_modules([plugin_dir]): full_module_name = f"{package_name}.{module_name}" try: @@ -42,6 +46,3 @@ def load_all_plugins(): print(f" [{type_str}] 成功{action}: {module_name}") except Exception as e: print(f" {action if 'action' in locals() else '加载'}插件 {module_name} 失败: {e}") - - -load_all_plugins() diff --git a/main.py b/main.py index f96eec0..99e9a8d 100644 --- a/main.py +++ b/main.py @@ -10,8 +10,8 @@ import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler -import base_plugins # noqa: F401 别动这里是加载插件的 from core import WS +from core.plugin_manager import load_all_plugins class PluginReloadHandler(FileSystemEventHandler): @@ -59,7 +59,7 @@ class PluginReloadHandler(FileSystemEventHandler): try: # 重新扫描并加载插件 - base_plugins.load_all_plugins() + load_all_plugins() print("[HotReload] 插件重载完成") except Exception as e: print(f"[HotReload] 重载失败: {e}") @@ -73,9 +73,12 @@ async def main(): 2. 初始化 WebSocket 客户端 3. 建立连接并保持运行 """ + # 首次加载插件 + load_all_plugins() + # 启动文件监控 - # 监控 base_plugins 目录 - plugin_path = os.path.join(os.path.dirname(__file__), "base_plugins") + # 监控 plugins 目录 + plugin_path = os.path.join(os.path.dirname(__file__), "plugins") event_handler = PluginReloadHandler() observer = Observer() diff --git a/base_plugins/echo.py b/plugins/echo.py similarity index 100% rename from base_plugins/echo.py rename to plugins/echo.py