522 lines
20 KiB
Markdown
522 lines
20 KiB
Markdown
# NEO Bot Framework
|
||
|
||
## 📖 概述
|
||
|
||
NEO 是一个基于 Python 的现代化 OneBot 11 协议机器人框架,专为需要高性能、可扩展性和开发效率的团队设计。该框架通过 WebSocket 与各种 OneBot 实现端(如 NapCatQQ、LLOneBot 等)通信,提供了一套完整的机器人开发解决方案。
|
||
|
||
### 设计理念
|
||
|
||
NEO 框架的设计遵循以下核心理念:
|
||
|
||
1. **开发者友好**:简洁的 API 设计、完整的类型提示和详细的文档,让开发者能够快速上手和高效开发
|
||
2. **架构清晰**:采用模块化设计,分离关注点,使代码易于维护和扩展
|
||
3. **高性能异步**:基于 `asyncio` 和 `websockets` 构建,支持高并发消息处理
|
||
4. **类型安全**:全面使用 Python 类型系统,提供编译时类型检查,减少运行时错误
|
||
5. **热重载支持**:支持插件热重载,开发过程中修改代码无需重启机器人
|
||
|
||
### 核心价值
|
||
|
||
- **快速原型开发**:通过简洁的装饰器语法快速定义指令和事件处理器
|
||
- **生产环境就绪**:内置断线重连、错误处理和性能监控机制
|
||
- **可扩展架构**:支持自定义插件、中间件和权限系统
|
||
- **现代化开发体验**:支持热重载、类型提示和完整的 API 文档
|
||
|
||
### 适用场景
|
||
|
||
- QQ 群机器人管理
|
||
- 自动化客服与问答系统
|
||
- 游戏社区管理
|
||
- 团队内部工具集成
|
||
- 教育与培训辅助
|
||
|
||
## ✨ 特性
|
||
|
||
* **OneBot 11 标准支持**:完整支持 OneBot 11 的消息、通知、请求和元事件。
|
||
* **类型安全**:基于 `dataclasses` 的强类型事件模型,开发体验更佳。
|
||
* **插件系统**:轻量级的装饰器风格插件系统,支持指令 (`@matcher.command`) 和事件监听 (`@matcher.on_notice`, `@matcher.on_request`)。
|
||
* **插件元数据与内置帮助**:插件可通过 `__plugin_meta__` 变量进行自我描述。框架核心内置了 `/help` 指令,可自动收集并展示所有插件的帮助信息,无需手动维护。
|
||
* **🔥 热重载支持**:内置文件监控,修改 `base_plugins` 下的代码自动重载,无需重启,极大提升调试效率。
|
||
* **异步核心**:基于 `asyncio` 和 `websockets` 的高性能异步核心。
|
||
* **自动重连**:内置 WebSocket 断线重连机制。
|
||
|
||
## 📝 待办事项 (TODO)
|
||
|
||
### API 封装
|
||
- [x] **消息相关**
|
||
- `delete_msg`: 撤回消息
|
||
- `get_msg`: 获取消息
|
||
- `get_forward_msg`: 获取合并转发消息
|
||
- `send_like`: 发送点赞
|
||
- [x] **群组管理**
|
||
- `set_group_kick`: 群组踢人
|
||
- `set_group_ban`: 群组单人禁言
|
||
- `set_group_anonymous_ban`: 群组匿名禁言
|
||
- `set_group_whole_ban`: 群组全员禁言
|
||
- `set_group_admin`: 群组设置管理员
|
||
- `set_group_anonymous`: 群组匿名
|
||
- `set_group_card`: 设置群名片(群备注)
|
||
- `set_group_name`: 设置群名
|
||
- `set_group_leave`: 退出群组
|
||
- `set_group_special_title`: 设置群组专属头衔
|
||
- [x] **群组信息**
|
||
- `get_group_info`: 获取群信息
|
||
- `get_group_list`: 获取群列表
|
||
- `get_group_member_info`: 获取群成员信息
|
||
- `get_group_member_list`: 获取群成员列表
|
||
- `get_group_honor_info`: 获取群荣誉信息
|
||
- [x] **用户相关**
|
||
- `get_login_info`: 获取登录号信息
|
||
- `get_stranger_info`: 获取陌生人信息
|
||
- `get_friend_list`: 获取好友列表
|
||
- [x] **请求处理**
|
||
- `set_friend_add_request`: 处理加好友请求
|
||
- `set_group_add_request`: 处理加群请求/邀请
|
||
- [x] **系统/其他**
|
||
- `get_version_info`: 获取版本信息
|
||
- `get_status`: 获取状态
|
||
- `can_send_image`: 检查是否可以发送图片
|
||
- `can_send_record`: 检查是否可以发送语音
|
||
- `clean_cache`: 清理缓存
|
||
|
||
### 待实现 API
|
||
- [ ] **Web 凭证类**
|
||
- `get_cookies`
|
||
- `get_csrf_token`
|
||
- `get_credentials`
|
||
- [ ] **文件/资源信息**
|
||
- `get_image`
|
||
- `get_record`
|
||
- `get_file`
|
||
- [ ] **系统控制**
|
||
- `set_restart`
|
||
- [ ] **扩展功能**
|
||
- `send_forward_msg`: 发送合并转发消息
|
||
|
||
### 其他改进
|
||
- [x] **API 强类型封装**: 将 API 返回值从 `dict` 转换为数据模型对象。
|
||
- [ ] **日志系统优化**: 引入更完善的日志记录机制,支持文件输出和日志级别控制。
|
||
- [ ] **异常处理增强**: 增强插件执行过程中的异常捕获,防止单个插件崩溃影响整个 Bot。
|
||
- [ ] **中间件支持**: 添加消息处理中间件,支持在指令执行前/后进行拦截和处理。
|
||
- [ ] **权限系统**: 实现基础的权限管理(如超级管理员、群管理员等)。
|
||
|
||
## 📂 项目结构
|
||
|
||
```
|
||
NEO/
|
||
├── plugins/ # 插件目录,新建插件文件即可自动加载(支持热重载)
|
||
│ └── echo.py # 示例插件:实现 /echo 和 /赞我 指令
|
||
├── core/ # 核心框架代码
|
||
│ ├── api/ # API 模块抽象层 (MessageAPI, GroupAPI, FriendAPI, AccountAPI)
|
||
│ │ ├── __init__.py
|
||
│ │ ├── account.py
|
||
│ │ ├── base.py
|
||
│ │ ├── friend.py
|
||
│ │ ├── group.py
|
||
│ │ └── message.py
|
||
│ ├── 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)
|
||
│ ├── message.py # 消息段定义 (MessageSegment)
|
||
│ └── sender.py # 发送者定义 (Sender)
|
||
├── config.toml # 配置文件
|
||
├── main.py # 启动入口(包含热重载监控)
|
||
└── requirements.txt # 项目依赖
|
||
```
|
||
|
||
## 🚀 快速开始
|
||
|
||
### 1. 环境准备
|
||
|
||
* Python 3.8+
|
||
* OneBot 11 实现端(推荐 [NapCatQQ](https://github.com/NapNeko/NapCatQQ) 或 LLOneBot)
|
||
|
||
### 2. 安装依赖
|
||
|
||
```bash
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### 3. 配置文件
|
||
|
||
修改根目录下的 `config.toml`,配置 WebSocket 连接信息:
|
||
|
||
```toml
|
||
[napcat_ws]
|
||
uri = "ws://127.0.0.1:30004" # OneBot 实现端的 WebSocket 地址
|
||
token = "your_token" # Access Token (如果有)
|
||
reconnect_interval = 5 # 断线重连间隔(秒)
|
||
|
||
[bot]
|
||
command = ["/"] # 指令前缀,支持多个,如 ["/", "#"]
|
||
```
|
||
|
||
### 4. 运行
|
||
|
||
```bash
|
||
python main.py
|
||
```
|
||
|
||
## 🛠️ 开发指南
|
||
|
||
### 🔥 热重载调试
|
||
|
||
项目集成了 `watchdog` 文件监控。在开发过程中,你只需要:
|
||
1. 保持 `main.py` 运行。
|
||
2. 修改或新建 `base_plugins` 目录下的 `.py` 插件文件。
|
||
3. 保存文件。
|
||
4. 控制台会自动提示 `[HotReload] 插件重载完成`,新的逻辑立即生效。
|
||
|
||
### 创建新插件
|
||
|
||
在 `base_plugins` 目录下创建一个新的 `.py` 文件(例如 `my_plugin.py`),框架会自动加载它。
|
||
|
||
### 示例代码
|
||
|
||
#### 1. 注册消息指令
|
||
|
||
使用 `@matcher.command("指令名")` 注册指令。
|
||
|
||
```python
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import MessageEvent
|
||
|
||
# 注册 /hello 指令
|
||
@matcher.command("hello")
|
||
async def handle_hello(bot: Bot, event: MessageEvent, args: list[str]):
|
||
# args 是去除指令后的参数列表
|
||
await event.reply("你好!这里是 NEO Bot。")
|
||
```
|
||
|
||
#### 2. 监听通知事件
|
||
|
||
使用 `@matcher.on_notice("通知类型")` 监听通知。
|
||
|
||
```python
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import GroupIncreaseNoticeEvent
|
||
|
||
# 监听群成员增加事件
|
||
@matcher.on_notice("group_increase")
|
||
async def welcome_new_member(bot: Bot, event: GroupIncreaseNoticeEvent):
|
||
await bot.send_group_msg(event.group_id, f"欢迎新成员 {event.user_id} 加入!")
|
||
```
|
||
|
||
#### 3. 监听请求事件
|
||
|
||
使用 `@matcher.on_request("请求类型")` 监听请求。
|
||
|
||
```python
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import FriendRequestEvent
|
||
|
||
# 自动同意好友请求
|
||
@matcher.on_request("friend")
|
||
async def auto_approve_friend(bot: Bot, event: FriendRequestEvent):
|
||
await bot.call_api("set_friend_add_request", {
|
||
"flag": event.flag,
|
||
"approve": True
|
||
})
|
||
```
|
||
|
||
#### 4. API 调用方式对比
|
||
|
||
框架提供两种 API 调用方式:**类型化 API**(推荐)和 **通用 API**(备用)。
|
||
|
||
##### 方式一:类型化 API(推荐)
|
||
对于已封装的 API,框架提供了类型化的方法,返回数据模型对象而非原始字典:
|
||
|
||
```python
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import MessageEvent
|
||
from models.objects import Group
|
||
|
||
@matcher.command("info")
|
||
async def get_group_info_typed(bot: Bot, event: MessageEvent, args: list[str]):
|
||
# 使用类型化 API,返回 Group 对象
|
||
group: Group = await bot.get_group_info(event.group_id)
|
||
await event.reply(f"群名:{group.group_name}\n成员数:{group.member_count}\n创建时间:{group.create_time}")
|
||
```
|
||
|
||
##### 方式二:通用 API(备用)
|
||
如果框架尚未封装某个 OneBot API,你可以使用 `bot.call_api` 直接调用。这是通用的备用调用方法。
|
||
|
||
```python
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import MessageEvent
|
||
|
||
@matcher.command("info_legacy")
|
||
async def get_group_info_legacy(bot: Bot, event: MessageEvent, args: list[str]):
|
||
# 直接调用 get_group_info API
|
||
# action: API 名称
|
||
# params: API 参数字典
|
||
resp = await bot.call_api("get_group_info", {
|
||
"group_id": event.group_id,
|
||
"no_cache": False
|
||
})
|
||
|
||
if resp.get("status") == "ok":
|
||
group_name = resp["data"]["group_name"]
|
||
await event.reply(f"当前群名:{group_name}")
|
||
```
|
||
|
||
**建议**:优先使用类型化 API,获得更好的类型安全和代码提示。仅在框架未封装特定 API 时使用通用 API。
|
||
|
||
## 📖 插件开发指南
|
||
|
||
### 插件基本结构
|
||
一个标准的插件文件应该包含以下部分:
|
||
1. **模块文档字符串**:描述插件功能
|
||
2. **导入必要的模块**:从 `core` 和 `models` 导入所需类
|
||
3. **使用装饰器注册事件处理器**:`@matcher.command()`, `@matcher.on_notice()`, `@matcher.on_request()`
|
||
4. **异步函数实现业务逻辑**:使用 `async def` 定义处理函数
|
||
|
||
### 插件元数据 (`__plugin_meta__`)
|
||
为了实现插件的自动发现和帮助信息的自动生成,框架引入了插件元数据机制。你需要在你的插件模块中定义一个名为 `__plugin_meta__` 的字典。
|
||
|
||
`load_all_plugins` 函数在加载插件时会自动读取这个变量,并将其注册到 `CommandManager` 中。`/help` 指令会遍历所有已注册的元数据,生成格式化的帮助信息。
|
||
|
||
一个标准的 `__plugin_meta__` 包含以下字段:
|
||
|
||
- `name` (str): 插件的友好名称,例如 "回声"。
|
||
- `description` (str): 对插件功能的简短描述。
|
||
- `usage` (str): 插件的使用方法,可以包含多个指令和它们的说明。
|
||
|
||
**示例:**
|
||
```python
|
||
# base_plugins/echo.py
|
||
|
||
__plugin_meta__ = {
|
||
"name": "回声与交互",
|
||
"description": "提供 echo 和 赞我 功能",
|
||
"usage": "/echo [内容] - 复读内容\n/赞我 - 让机器人给你点赞",
|
||
}
|
||
```
|
||
|
||
### 使用类型化 API
|
||
框架现已提供完整的类型化 API 封装,建议优先使用这些封装方法而非原始的 `call_api`:
|
||
|
||
| API 方法 | 返回类型 | 说明 |
|
||
|---------|---------|------|
|
||
| `bot.send_group_msg()` | `Message` | 发送群消息 |
|
||
| `bot.get_group_info()` | `Group` | 获取群信息 |
|
||
| `bot.get_group_member_info()` | `GroupMember` | 获取群成员信息 |
|
||
| `bot.get_friend_list()` | `List[Friend]` | 获取好友列表 |
|
||
| `bot.get_login_info()` | `LoginInfo` | 获取登录信息 |
|
||
| `bot.get_version_info()` | `VersionInfo` | 获取版本信息 |
|
||
|
||
#### 示例:使用类型化 API 重构群信息查询
|
||
```python
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import MessageEvent
|
||
from models.objects import Group
|
||
|
||
@matcher.command("group_info")
|
||
async def get_group_info_typed(bot: Bot, event: MessageEvent, args: list[str]):
|
||
# 使用类型化 API,返回 Group 对象而非字典
|
||
group: Group = await bot.get_group_info(event.group_id)
|
||
await event.reply(f"群名:{group.group_name}\n成员数:{group.member_count}\n创建时间:{group.create_time}")
|
||
```
|
||
|
||
### 事件处理模式
|
||
除了基本的消息指令,还可以处理多种事件类型:
|
||
|
||
#### 1. 通知事件处理
|
||
```python
|
||
from models import GroupCardChangeEvent
|
||
|
||
@matcher.on_notice("group_card")
|
||
async def handle_group_card_change(bot: Bot, event: GroupCardChangeEvent):
|
||
# event.card_new 是新名片,event.card_old 是旧名片
|
||
await bot.send_group_msg(event.group_id, f"成员 {event.user_id} 的名片从 '{event.card_old}' 改为 '{event.card_new}'")
|
||
```
|
||
|
||
#### 2. 请求事件处理
|
||
```python
|
||
from models import GroupRequestEvent
|
||
|
||
@matcher.on_request("group")
|
||
async def handle_group_request(bot: Bot, event: GroupRequestEvent):
|
||
# 根据请求类型处理
|
||
if event.sub_type == "add":
|
||
# 自动同意加群请求
|
||
await bot.set_group_add_request(event.flag, event.sub_type, approve=True)
|
||
await bot.send_group_msg(event.group_id, f"已同意用户 {event.user_id} 的加群请求")
|
||
```
|
||
|
||
### 错误处理
|
||
建议在插件中添加适当的错误处理,避免单个插件崩溃影响整个机器人:
|
||
|
||
```python
|
||
@matcher.command("dangerous")
|
||
async def dangerous_command(bot: Bot, event: MessageEvent, args: list[str]):
|
||
try:
|
||
# 可能失败的操作
|
||
result = await bot.call_api("some_api", {"param": "value"})
|
||
await event.reply(f"成功:{result}")
|
||
except Exception as e:
|
||
await event.reply(f"执行失败:{str(e)}")
|
||
# 记录日志
|
||
import logging
|
||
logging.error(f"插件执行错误:{e}", exc_info=True)
|
||
```
|
||
|
||
### 插件开发最佳实践
|
||
1. **单一职责**:每个插件专注于一个功能领域
|
||
2. **错误处理**:妥善处理可能发生的异常
|
||
3. **类型提示**:为函数参数和返回值添加类型提示
|
||
4. **文档完整**:为每个函数添加文档字符串
|
||
5. **性能考虑**:避免在插件中执行耗时同步操作
|
||
6. **资源清理**:必要时使用 `try...finally` 确保资源释放
|
||
|
||
### 示例:完整插件模板
|
||
```python
|
||
"""
|
||
天气查询插件
|
||
|
||
提供 /weather 指令,查询指定城市的天气信息。
|
||
"""
|
||
from core.command_manager import matcher
|
||
from core.bot import Bot
|
||
from models import MessageEvent
|
||
|
||
# 插件元数据,用于 help 指令
|
||
__plugin_meta__ = {
|
||
"name": "天气查询",
|
||
"description": "查询指定城市的天气信息",
|
||
"usage": "/weather [城市名称]",
|
||
}
|
||
|
||
@matcher.command("weather")
|
||
async def handle_weather(bot: Bot, event: MessageEvent, args: list[str]):
|
||
"""
|
||
查询天气信息
|
||
|
||
:param bot: Bot 实例
|
||
:param event: 消息事件对象
|
||
:param args: 指令参数列表(城市名称)
|
||
"""
|
||
if not args:
|
||
await event.reply("请输入城市名称,例如:/weather 北京")
|
||
return
|
||
|
||
city = " ".join(args)
|
||
try:
|
||
# 这里可以调用天气 API
|
||
weather_info = f"{city} 的天气:晴,25℃"
|
||
await event.reply(weather_info)
|
||
except Exception as e:
|
||
await event.reply(f"查询天气失败:{str(e)}")
|
||
|
||
# 可以注册多个事件处理器
|
||
@matcher.on_notice("group_increase")
|
||
async def welcome_new_member(bot: Bot, event):
|
||
await bot.send_group_msg(event.group_id, f"欢迎新成员 {event.user_id} 加入!")
|
||
```
|
||
|
||
## 📚 事件模型说明
|
||
|
||
项目采用了基于工厂模式的事件处理系统,所有事件定义在 `models/events/` 下:
|
||
|
||
* **MessageEvent**: 消息事件,包含 `PrivateMessageEvent` 和 `GroupMessageEvent`。支持 `await event.reply()` 快速回复。
|
||
* **NoticeEvent**: 通知事件,如 `FriendAddNoticeEvent`, `GroupRecallNoticeEvent` 等。
|
||
* **RequestEvent**: 请求事件,如 `FriendRequestEvent`, `GroupRequestEvent`。
|
||
* **MetaEvent**: 元事件,如心跳 `HeartbeatEvent`。
|
||
|
||
所有事件均继承自 `OneBotEvent`,并包含 `bot` 属性用于调用 API。
|
||
|
||
## 🏗️ 技术架构
|
||
|
||
NEO 框架采用分层架构设计,各层职责明确,便于维护和扩展:
|
||
|
||
### 架构层次
|
||
|
||
1. **通信层 (WebSocket Client)**
|
||
- 负责与 OneBot 实现端的 Web Socket连接
|
||
- 实现断线自动重连机制
|
||
- 处理原始消息的收发和协议解析
|
||
|
||
2. **API 抽象层 (API Mixins)**
|
||
- 提供类型安全的 API 封装
|
||
- 按功能领域划分:消息、群组、好友、账号
|
||
- 所有 API 返回强类型数据模型对象
|
||
|
||
3. **业务逻辑层 (Bot & Command Manager)**
|
||
- Bot 类组合所有 API 功能
|
||
- 指令和事件分发器
|
||
- 插件加载和管理
|
||
|
||
4. **插件层 (Plugins)**
|
||
- 支持热重载的插件系统
|
||
- 装饰器风格的注册方式
|
||
- 独立的业务逻辑模块
|
||
|
||
5. **数据模型层 (Models)**
|
||
- 基于 dataclasses 的事件模型
|
||
- API 响应数据模型
|
||
- 类型安全的序列化/反序列化
|
||
|
||
### 核心组件交互
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ 插件层 (Plugins) │
|
||
│ @matcher.command() │
|
||
│ @matcher.on_notice() │
|
||
└──────────────┬──────────────────────┘
|
||
│
|
||
┌──────────────▼──────────────────────┐
|
||
│ 业务逻辑层 (Command Manager) │
|
||
│ • 事件分发与路由 │
|
||
│ • 指令参数解析 │
|
||
└──────────────┬──────────────────────┘
|
||
│
|
||
┌──────────────▼──────────────────────┐
|
||
│ Bot 组合类 │
|
||
│ • 继承所有 API Mixin │
|
||
│ • 提供统一接口 │
|
||
└──────────────┬──────────────────────┘
|
||
│
|
||
┌──────────────▼──────────────────────┐
|
||
│ API 抽象层 (Mixin) │
|
||
│ • MessageAPI │
|
||
│ • GroupAPI │
|
||
│ • FriendAPI │
|
||
│ • AccountAPI │
|
||
└──────────────┬──────────────────────┘
|
||
│
|
||
┌──────────────▼──────────────────────┐
|
||
│ 通信层 (WebSocket) │
|
||
│ • 连接管理 │
|
||
│ • 消息编解码 │
|
||
│ • 断线重连 │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 设计模式应用
|
||
|
||
- **工厂模式**:事件对象的创建和管理
|
||
- **装饰器模式**:插件和指令的注册
|
||
- **组合模式**:Bot 类通过继承组合 API 功能
|
||
- **观察者模式**:事件监听和处理
|
||
- **策略模式**:不同的消息处理策略
|
||
|
||
### 性能特点
|
||
|
||
- **异步非阻塞**:全面基于 asyncio,支持高并发
|
||
- **内存高效**:事件和模型对象使用 dataclasses,内存占用小
|
||
- **快速响应**:插件热重载和事件分发机制确保快速响应
|
||
- **可扩展性**:模块化设计便于功能扩展和定制
|
||
|
||
---
|
||
*Internal Use Only - DOGSOHA ond baby2016 by Fairy-Oracle-Sanctuary*
|