添加注释,增加redis支持,添加了聊天记录构建支持
This commit is contained in:
109
README.md
109
README.md
@@ -39,6 +39,42 @@ NEO 框架的设计遵循以下核心理念:
|
||||
* **异步核心**:基于 `asyncio` 和 `websockets` 的高性能异步核心。
|
||||
* **自动重连**:内置 WebSocket 断线重连机制。
|
||||
|
||||
## ⚡️ 性能优化
|
||||
|
||||
### Redis 缓存机制
|
||||
为了提升响应速度并减少对 OneBot API 的重复调用,框架核心集成了一套基于 Redis 的缓存系统。对于一些不频繁变更的数据(如群信息、好友列表等),首次查询后会将其缓存至 Redis,在缓存有效期内(默认为 1 小时),后续请求将直接从 Redis 读取,极大提升了性能。
|
||||
|
||||
#### 工作原理
|
||||
- **自动缓存**:框架会自动缓存特定 API 的调用结果。
|
||||
- **缓存键**:缓存键根据 API 名称和关键参数(如 `group_id`, `user_id`)生成,确保唯一性。
|
||||
- **过期时间**:默认缓存 1 小时,之后会自动失效,下次调用时将重新从 OneBot 实现端获取最新数据。
|
||||
|
||||
#### 受影响的 API
|
||||
以下核心 API 已默认启用缓存:
|
||||
- `get_group_info`
|
||||
- `get_group_member_info`
|
||||
- `get_friend_list`
|
||||
- `get_stranger_info`
|
||||
- `get_login_info`
|
||||
|
||||
#### 如何绕过缓存
|
||||
在某些场景下,你可能需要获取实时数据而非缓存数据。为此,所有受缓存影响的 API 方法都增加了一个 `no_cache: bool = False` 的可选参数。
|
||||
|
||||
当你需要强制从服务器获取最新信息时,只需在调用时传入 `no_cache=True` 即可。
|
||||
|
||||
**示例:**
|
||||
```python
|
||||
# 正常调用,会使用缓存
|
||||
group_info = await bot.get_group_info(group_id=12345)
|
||||
|
||||
# 强制获取最新信息,不使用缓存
|
||||
latest_group_info = await bot.get_group_info(group_id=12345, no_cache=True)
|
||||
```
|
||||
|
||||
### `__slots__` 内存优化
|
||||
框架内的所有数据模型(包括事件、消息段、API 返回对象等)均已启用 `__slots__ = True` 优化。这可以显著减少每个对象实例的内存占用,特别是在处理大量事件和数据时,能够有效降低机器人的整体内存消耗。
|
||||
|
||||
|
||||
## 📝 待办事项 (TODO)
|
||||
|
||||
### API 封装
|
||||
@@ -90,10 +126,11 @@ NEO 框架的设计遵循以下核心理念:
|
||||
- [ ] **系统控制**
|
||||
- `set_restart`
|
||||
- [ ] **扩展功能**
|
||||
- `send_forward_msg`: 发送合并转发消息
|
||||
- [x] `send_forward_msg`: 发送合并转发消息
|
||||
|
||||
### 其他改进
|
||||
- [x] **API 强类型封装**: 将 API 返回值从 `dict` 转换为数据模型对象。
|
||||
- [x] **Redis 支持**: 集成 Redis 连接池,便于插件复用连接。
|
||||
- [ ] **日志系统优化**: 引入更完善的日志记录机制,支持文件输出和日志级别控制。
|
||||
- [ ] **异常处理增强**: 增强插件执行过程中的异常捕获,防止单个插件崩溃影响整个 Bot。
|
||||
- [ ] **中间件支持**: 添加消息处理中间件,支持在指令执行前/后进行拦截和处理。
|
||||
@@ -104,7 +141,10 @@ NEO 框架的设计遵循以下核心理念:
|
||||
```
|
||||
NEO/
|
||||
├── plugins/ # 插件目录,新建插件文件即可自动加载(支持热重载)
|
||||
│ └── echo.py # 示例插件:实现 /echo 和 /赞我 指令
|
||||
│ ├── echo.py # 示例插件:实现 /echo 和 /赞我 指令
|
||||
│ ├── forward_test.py # 示例插件:演示合并转发消息的构建和发送
|
||||
│ ├── jrcd.py # 娱乐插件:提供 /jrcd 和 /bbcd 指令
|
||||
│ └── thpic.py # 图片插件:提供 /thpic 指令,发送随机东方图片
|
||||
├── core/ # 核心框架代码
|
||||
│ ├── api/ # API 模块抽象层 (MessageAPI, GroupAPI, FriendAPI, AccountAPI)
|
||||
│ │ ├── __init__.py
|
||||
@@ -117,6 +157,7 @@ NEO/
|
||||
│ ├── command_manager.py # 命令与事件分发器
|
||||
│ ├── config_loader.py # 配置加载器
|
||||
│ ├── plugin_manager.py # 插件加载与管理
|
||||
│ ├── redis_manager.py # Redis 连接管理器
|
||||
│ └── ws.py # WebSocket 客户端核心
|
||||
├── models/ # 数据模型
|
||||
│ ├── events/ # OneBot 事件定义 (Message, Notice, Request, Meta)
|
||||
@@ -378,6 +419,70 @@ async def dangerous_command(bot: Bot, event: MessageEvent, args: list[str]):
|
||||
5. **性能考虑**:避免在插件中执行耗时同步操作
|
||||
6. **资源清理**:必要时使用 `try...finally` 确保资源释放
|
||||
|
||||
### 🚀 高性能插件开发规范 (避坑指南)
|
||||
为了保证整个机器人框架的响应速度和稳定性,所有插件都必须遵循异步、非阻塞的开发原则。任何一个插件中的阻塞操作都可能导致整个机器人卡顿或无响应。
|
||||
|
||||
以下是必须遵守的核心规范:
|
||||
|
||||
#### 1. 禁止任何形式的同步网络请求
|
||||
- **错误示范**: 使用 `requests` 库发起网络请求。
|
||||
```python
|
||||
import requests
|
||||
# 错误!这会阻塞整个程序
|
||||
response = requests.get("https://api.example.com")
|
||||
```
|
||||
- **正确做法**: 必须使用异步 HTTP 客户端,如 `aiohttp` 或 `httpx`。
|
||||
```python
|
||||
import httpx
|
||||
# 正确,使用 async with 和 await
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get("https://api.example.com")
|
||||
```
|
||||
|
||||
#### 2. 禁止使用 `time.sleep()`
|
||||
- **错误示范**: 使用 `time.sleep()` 进行等待。
|
||||
```python
|
||||
import time
|
||||
# 错误!这会阻塞事件循环
|
||||
time.sleep(5)
|
||||
```
|
||||
- **正确做法**: 必须使用 `asyncio.sleep()`。
|
||||
```python
|
||||
import asyncio
|
||||
# 正确,这会将控制权交还给事件循环
|
||||
await asyncio.sleep(5)
|
||||
```
|
||||
|
||||
#### 3. 谨慎处理文件 I/O
|
||||
- 对于读写小型、本地文件,直接使用 `with open(...)` 通常是可接受的。
|
||||
- 但对于大型文件或网络文件系统(NFS)上的文件,同步 I/O 可能会导致明显的阻塞。
|
||||
- **推荐做法**: 对于可能耗时较长的文件操作,使用 `aiofiles` 库。
|
||||
```python
|
||||
import aiofiles
|
||||
async with aiofiles.open('large_file.dat', mode='rb') as f:
|
||||
contents = await f.read()
|
||||
```
|
||||
|
||||
#### 4. 将 CPU 密集型任务移出事件循环
|
||||
- 如果插件需要执行复杂的计算(例如,图像处理、视频转码、数据分析),这些任务会长时间占用 CPU,同样会阻塞事件循环。
|
||||
- **正确做法**: 使用 `loop.run_in_executor()` 将这类任务抛到独立的线程池或进程池中执行。
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
def cpu_bound_task(data):
|
||||
# 这是一个耗时的同步函数
|
||||
# ... 进行大量计算 ...
|
||||
return "计算结果"
|
||||
|
||||
# 在异步的事件处理器中调用
|
||||
loop = asyncio.get_running_loop()
|
||||
# `None` 表示使用默认的线程池
|
||||
result = await loop.run_in_executor(None, cpu_bound_task, "一些数据")
|
||||
await event.reply(result)
|
||||
```
|
||||
|
||||
遵循以上规范,可以确保您开发的插件不会成为整个机器人应用的性能瓶颈。
|
||||
|
||||
### 示例:完整插件模板
|
||||
```python
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user