Files
NeoBot/docs/core-concepts/architecture.md
K2cr2O1 caf5b06097 refactor(managers): 重构单例管理器实现并优化代码结构
feat(ws_pool): 新增 WebSocket 连接池实现

perf(json): 使用 orjson 替代标准 json 库提升性能

style: 清理未使用的导入和冗余代码

docs: 更新架构文档和开发规范

test: 添加 WebSocket 连接池测试用例

fix(plugins): 修复自动审批插件 API 调用参数格式
2026-01-22 16:23:03 +08:00

8.6 KiB
Raw Blame History

骨架

Neobot是面向内部开发者的我会开源但是写的很烂。。。

1. 动力核心

Python 3.14 + JIT

镀铬酸钾创项目的时候用的 Python 3.14 3.14兼容JIT那就这样吧

  • 何原理: 运行时把热点代码编译成机器码Just-In-Time
  • 何用途: 密集CPU运算能提升一些尤其是插件里的循环和函数调用
  • 怎么开: 启动时加 -X jit 参数

Mypyc 编译 (AOT)

光 JIT 还不够。。核心模块(core/ws.py, core/managers/*.py我编译成了C扩展

  • 何原理: 因为这个项目有很多类型提示然后我就编译成C库了。。。
  • 何用途: WS和manager下边的模块都是机器码运行或许会快一些。。。

异步 IO 模型

  • Linux: uvloop
  • Windows:IOCP
    • : winloop 死了,会和面具打架。。。

2. 连接模式

正向 WebSocket 模式

这是一种简单直接的模式

  • 主动出击 (Client): Bot 是个客户端
    • 好处: 你电脑能上网就行实际上是因为没公网ip哈。。。
graph LR
    subgraph Local [你的电脑/服务器]
        Bot[NEO Bot]
        Browser[Playwright 页面池]
    end
    
    subgraph Remote [外部]
        NapCat[NapCatQQ]
    end

    Bot -- "WebSocket (主动连接)" --> NapCat
    Bot -- "内部调用" --> Browser

3. 资源管理

单例管理器

所有东西(指令、权限、浏览器、图片)都是全局独一份的。

  • 随叫随到: 在哪都能直接 import
  • 绝对权威: 全局就一份数据

资源池化

别几把开多个实例。。。

  • Browser Pool: 浏览器页面提前开好,用完洗干净放回去
  • Connection Pool: Redis 和 HTTP 请求都用连接池

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_typeuser_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 模块做检查)