背景介绍
NoneBot2 是一款基于 Python 的异步机器人框架,可用于对接各类即时通讯软件、办公协同工具以及物联网设备,为开发者提供统一的业务逻辑编写范式。但其本体只提供了命令行(CLI)工具进行管理和配置,无形之中给框架提高了一些使用门槛,导致许多想上手体验的小白望而却步。
作品介绍
为了解决 NoneBot 框架上手门槛高,无直观界面管理,配置繁杂等痛点,作品采用 Dart/Flutter 开发了 NoneBot WebUI(https://webui.nbgui.top),利用了Dart/Flutter的高性能跨平台特性,为用户提供了一套完整的图形化解决方案,并且利用 Web 应用程序的跨平台特点,使得用户能够随时随地管理自己的 Bot 实例。从而大大提升用户的使用体验与管理的便利。
亮点
实例可视化管理: 从实例创建到管理, 从配置文件快捷编辑到插件开关,均实现了可视化,极大降低了操作难度。
全平台通用: 得益于 Dart/Flutter 强大的跨平台特性, NoneBot WebUI 原生支持 ARM/x86 等异构计算环境,并且能够通过网页端/移动端进行管理,而不再需要远程连接到服务器进行配置。
自启动: 对于 Linux 设备, NoneBot WebUI 提供了系统 systemd 级别的自启动服务,实现了无人值守的高可用运行环境。
简洁的交互设计: 遵循 Material Design 核心设计规范,针对移动端与桌面端进行了深度适配。通过响应式布局与直观的模块化 UI,将复杂的异步框架参数具象化,实现了“低认知成本、高操作反馈”的用户体验。
高扩展性: 前后端分离,后端对外可开放 HTTP/WebSocket API, 并提供相关文档,以便开发者进行适配。
前后端通信
利用 WebSocket "握一次手即可持续通信" 的特征, 规范前后端之间的 WebSocket 消息流定义和接口, 使前后端能够正确处理对方发送的数据并交互。
后端与 NoneBot 的交互
主要原理: 通过 dart:io 的 Process.start() 方法调用系统命令,达到间接操作 NoneBot CLI 的效果, 同时用 await 来防止线程阻塞。在输出方面则通过 process.stdout.listen 来监听命令输出,并进行传输。
创建 Bot 实例: 参考 NoneBot 官方文档的 “手动创建实例” 和使用 CLI 生成出来的文件结构, 利用 dart:io 写入文件和目录达到与 CLI 初始化同样的效果,确保实例结构的标准化与规范化。同时为每个实例分配一个 uuid 来确保唯一性。
安装/卸载插件: 对外部提供一个 Plugin.install(name, id) 方法,调用 CLI 进行插件的安装/卸载。
配置文件管理: 配置文件内部总是以 "KEY=VALUE" 的形式储存配置项, 于是对外提供一个 Env.load() 方法,以供前端解析并使用。
插件管理: 实例目录下会存在一个名为 "pyproject.toml" 的文件, 其中包含了已加载的插件模块名, 于是对外提供 Plugin.list(id) 方法,解析这个TOML文件并从中分离出插件的列表,如需禁用插件则在实例目录下将禁用的目标插件模块名写入到 ".disable_plugins" 并从 pyproject 中移除掉这个模块名。
前端
通过 self-host 程序托管前端页面,并提供鉴权 API.
登录页: 如果会话过期或首次登录,则输入密码后请求 self-host 的 /auth 接口,密码正确则会返回一个有效期为3天的 JWT Token,并储存到浏览器的会话中,下次登录时无需输入密码,实现持久化登录。
前端页面: 通过 WebSocket 与后端建立连接,并处理发送过来的数据,存入全局变量中以供使用。