Files
NeoBot/README.md

522 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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*