* fix(discord): 修复 WebSocket 连接检测并增强跨平台文件处理 修复 Discord WebSocket 连接检测逻辑,使用正确的属性检查连接状态 为跨平台消息处理添加文件类型支持,并增加详细的调试日志 优化附件处理逻辑,确保所有文件类型都能正确识别和转发 * feat(跨平台): 优化消息处理并添加纯文本提取功能 添加 extract_text_only 函数过滤非文本标记 修改翻译逻辑仅处理纯文本内容 完善附件处理和消息内容拼接 修复仅包含表情时的消息处理问题 * refactor(discord-cross): 使用模块专用日志记录器替换全局日志记录器 将各模块中的全局日志记录器替换为模块专用日志记录器,以提供更清晰的日志来源标识 同时在适配器中添加会话状态检查和重连机制,提升消息发送的可靠性 * feat(翻译): 改进翻译功能,同时显示原文和译文 修改翻译功能,不再替换原文而是同时显示原文和翻译内容,方便用户对照 更新 DeepSeek API 配置为官方地址和模型 优化 Discord 适配器的重连逻辑,直接关闭 WebSocket 触发重连 修复 Discord 频道 ID 转换逻辑,简化处理流程 * feat(cross-platform): 添加跨平台功能支持及配置优化 - 新增跨平台配置模型和全局配置支持 - 优化 Discord 适配器的连接管理和错误处理 - 添加 watchdog 和 discord.py 依赖 - 创建 DeepSeek API 配置文档 - 移除重复的同步帮助图片代码 - 改进跨平台插件配置加载逻辑 * fix(jrcd): 修正群组ID检查条件 删除不再使用的示例插件文件 * feat: 改进配置加载逻辑并更新项目配置 当配置文件不存在时自动生成示例配置 添加pyproject.toml作为项目构建配置 更新.gitignore忽略更多文件类型 删除不再使用的反向WebSocket示例文件 * docs: 更新架构文档和项目结构说明 添加反向WebSocket连接模式说明 补充核心管理器文档 更新项目结构文件 在文档首页添加特色功能说明 * fix(discord): 修复WebSocket连接检查并添加错误日志 refactor(config): 更新配置文件的网络和认证信息 feat(cross-platform): 为跨平台消息处理添加异常捕获和日志
9.0 KiB
9.0 KiB
架构设计
NEO Bot 是一个现代化的、高性能的异步 QQ 机器人框架。本文介绍其核心架构和设计理念。
1. 性能优化体系
Python 3.14 JIT(Just-In-Time 编译)
原理:Python 3.14 内置 JIT 编译器,运行时将高频调用的代码编译成机器码。
适用场景:
- 插件业务逻辑(循环、函数调用密集)
- 消息处理流程
启用方法:
python -X jit main.py
预期性能提升:2-5 倍(取决于代码热点)。
Mypyc 编译(AOT - Ahead-Of-Time)
原理:将类型注解的 Python 代码编译为 C 扩展,生成平台相关的二进制文件。
编译范围:
core/ws.py- WebSocket 通信core/managers/- 各种管理器core/api/- API 封装models/- 数据模型
启用方法:
python setup_mypyc.py build_ext --inplace
预期性能提升:3-10 倍(核心模块)。
注意:编译产物平台相关,必须在目标环境编译。
异步 IO 模型
Linux:uvloop(libev 绑定,比 asyncio 快 2-4 倍)
Windows:IOCP(Windows 原生高性能 IO)
2. 连接架构
WebSocket 连接模式
NEO Bot 支持两种 WebSocket 连接模式,可根据需求在 config.toml 中配置:
1. 正向 WebSocket 连接 (默认)
Bot 主动连接 OneBot 实现(如 NapCatQQ)。
流程:
Bot 启动 → 连接到 NapCatQQ (ws://127.0.0.1:3001)
↓
监听消息事件
↓
分发到处理器
↓
调用 API 回复
2. 反向 WebSocket 连接
OneBot 客户端主动连接 Bot 提供的 WebSocket 服务。
流程:
Bot 启动反向 WS 服务 (监听 0.0.0.0:3002)
↓
NapCatQQ 主动连接到 Bot
↓
监听消息事件
↓
分发到处理器
↓
调用 API 回复
3. 资源管理架构
单例管理器
所有全局资源通过单例管理器统一管理,避免重复创建和资源泄漏。
Playwright 页面池
预初始化页面,无需每次都启动浏览器,大幅降低延迟。
HTTP 连接复用
全局 aiohttp.ClientSession 支持 Keep-Alive,减少连接建立开销。
4. 技术栈全景
NEO Bot 的“骨架”是由一堆现代 Python 库和技术堆起来的。下面这张清单能让你一眼看清整个项目的技术选型。
编程语言与运行时
- Python 3.14: 镀铬酸钾创项目的时候用的 Python 3.14 3.14兼容JIT,那就这样吧
- JIT (Just-In-Time): 启动时加
-X jit参数,运行时把热点代码编译成机器码 - Mypyc (AOT): 核心模块(
core/ws.py,core/managers/*.py)编译成C扩展,机器码运行
异步与网络
- asyncio: Python 原生异步框架,所有 IO 操作都是非阻塞的
- uvloop (Linux): 替代 asyncio 默认事件循环,性能更高
- IOCP (Windows): Windows 上的高性能 IO 完成端口
- aiohttp: 异步 HTTP 客户端/服务器,用于 API 请求和 WebSocket 通信
- websockets: 纯粹的 WebSocket 客户端/服务器库
- Playwright: 浏览器自动化工具,负责截图、页面渲染
数据与存储
- Redis: 内存数据库,用于缓存帮助图片、会话状态等
- orjson: Rust 编写的 JSON 序列化库,比标准
json快很多 - Pydantic: 数据验证与设置管理,配置文件、API 请求/响应都靠它
工具与工具链
- Loguru: 结构化日志记录,输出漂亮且支持文件轮转
- Watchdog: 文件系统监控,实现插件热重载
- Jinja2: 模板引擎,渲染 HTML 页面然后转为图片
- Pillow: 图像处理库,负责图片格式转换、尺寸调整
- BeautifulSoup4: HTML 解析,B站、抖音等链接解析插件在用
- httpx: 异步 HTTP 客户端,某些插件用它发请求
测试与开发
- Pytest: 测试框架,写单元测试、集成测试
- Docker: 容器化,沙箱执行用户代码时可能用到
- cryptography: 加密解密,处理一些安全相关的操作
架构模式
- Singleton (单例): 全局唯一实例,所有管理器都是单例
- Connection Pool (连接池): Redis 连接、HTTP 会话都复用
- Plugin System (插件系统): 动态导入、装饰器注册,一个
.py文件就是一个插件
5. Python 动态语言特性运用
Python 是一门“动态”语言,这意味着你可以在运行时做很多静态语言做不到的事情。NEO Bot 大量利用了这些特性,让框架变得灵活、易扩展。
装饰器 (Decorator)
- 何用: 给函数“贴上标签”,告诉框架这个函数是干什么的
- 何处:
@matcher.command("echo")– 注册一个消息指令@matcher.on_message()– 注册一个通用消息处理器@matcher.on_notice()– 注册一个通知事件处理器
- 何原理: 装饰器本质上是一个高阶函数,它接收被装饰的函数,然后把它“注册”到某个管理器里
动态导入 (Dynamic Import)
- 何用: 不需要在代码开头写死
import,运行时根据情况加载模块 - 何处:
PluginManager.load_all_plugins()用importlib.import_module()扫描plugins/目录,找到.py文件就导入 - 何原理: Python 的模块系统是完全动态的,
import语句实际上调用了__import__()函数
自省 (Introspection)
- 何用: 让代码能“看到”自己的结构,比如函数属于哪个模块、有哪些参数
- 何处:
inspect.getmodule(func)– 获取函数所在的模块名,用于记录插件来源func.__name__,func.__module__– 获取函数名和模块名
- 何原理: Python 把几乎所有元信息都存在对象的
__dict__里,你可以随时翻看
鸭子类型 (Duck Typing)
- 何用: “如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。”——不检查类型,只检查行为
- 何处:
- 事件处理器不要求事件对象必须是某个类,只要它有
post_type、user_id等属性就行 - 插件不需要继承某个基类,只要它有
__plugin_meta__字典就行
- 事件处理器不要求事件对象必须是某个类,只要它有
- 何原理: Python 的变量没有类型,类型是对象自己的事。只要对象有你需要的方法或属性,你就可以调用它
反射 (Reflection)
- 何用: 在运行时检查、修改对象的结构
- 何处:
getattr(module, "__plugin_meta__")– 获取插件的元数据字典hasattr(event, "raw_message")– 检查事件对象是否有某个属性setattr()– 动态设置属性(虽然用得少)
- 何原理: Python 的对象本质上就是字典(
__dict__),getattr/setattr就是对这个字典的操作
元编程 (Metaprogramming)
- 何用: 在代码运行时改变代码的行为
- 何处:
Singleton基类重写__new__方法,控制实例创建,确保全局只有一个实例- 装饰器在函数定义时修改函数,给它添加额外逻辑
- 何原理: Python 的类也是对象(类型对象),你可以通过修改类来影响它所有实例的行为
上下文管理器 (Context Manager)
- 何用: 安全地获取和释放资源,比如文件、网络连接、浏览器页面
- 何处:
async with browser_manager.get_page() as page:– 从页面池获取一个页面,用完后自动放回async with aiohttp.ClientSession() as session:– 发起 HTTP 请求后自动关闭会话
- 何原理:
__enter__/__exit__(同步)或__aenter__/__aexit__(异步)协议
描述符 (Descriptor)
- 何用: 控制属性访问的逻辑,比如把方法伪装成属性
- 何处:
@property– 把方法变成只读属性,比如PluginManager.command_manager@property.setter– 给属性设置值时的自定义逻辑
- 何原理: 描述符是一个实现了
__get__、__set__或__delete__方法的类
猴子补丁 (Monkey Patching)
- 何用: 在运行时修改模块、类或对象,通常用于测试或修复第三方库
- 何处: 测试中可能会用
unittest.mock.patch临时替换某个函数,模拟它的行为 - 何原理: Python 的模块和类都是可变的,你可以直接给它们赋值新属性
eval/exec
- 何用: 执行字符串形式的 Python 代码
- 何处:
code_py.py插件中,用户发送的代码片段会被exec()执行,实现代码沙箱功能 - 何原理: Python 解释器本身就是一个运行时环境,
eval()用于表达式,exec()用于语句
类型提示 (Type Hints)
- 何用: 虽然 Python 是动态类型,但类型提示能让代码更清晰,工具(如 Mypy)也能做静态检查
- 何处: 几乎所有函数和方法的参数、返回值都加了类型提示,这让 Mypyc 编译成为可能
- 何原理: 类型提示只是注解,运行时通常被忽略(除非你用
typing模块做检查)