一套开源的,基于C++编写的基于 Onebot11
的高性能、扩展性强、模块化的QQ机器人框架
基于 Onebot11
协议(正向WS连接)
觉得 C++
太难?学习成本太高?本框架没有要求插件必须使用 C++
编写。
本框架开放插件引擎注册,除了可以加载 C++
的原生插件以外,你还可以编写任意语言的插件引擎,做到跨语言加载任意语言的插件。
我们已经编写并提供了 Python插件引擎,可加载Python插件。
未来我们还计划提供 Node.js
引擎,支持Node.js插件。
以上这只是插件引擎的示例,插件引擎只是一个模块,本质上就是一个原生插件,因此插件引擎并不需要官方编写实现。
只要你愿意,你可以编写支持任意你喜欢的语言对应的插件引擎,来加载对应语言的插件。
框架内置了强大的 事件系统(EventBus)
和 远程函数导出/导入(Service)
系统,可提供跨语言的事件发布和函数调用。
即使是不同语言编写的插件,依旧能够实现相互交互。例如C++插件可以和Python插件直接进行交互。
相比于常见的机器人框架,只能使用单一语言编写,我们的框架提供了跨语言的能力,可在一个框架上加载多种语言插件。
本框架是模块化的,只有核心部分 KobeBryant.exe
是必需的,其余模块(例如其它插件引擎)都是可选的,你可以只用核心部分运行原生插件,也可以加载其它插件引擎运行各种类型的插件(例如Python插件)
编写模块是开放的,插件加载高度开放,正如前面所讲的,你可以编写任意你想要的插件引擎一样,你可以编写任意你需要的模块。
使用 C++
编写,真正实现无锁多线程运行,带来最好的、最真实的性能。
相同条件下,运行速度是目前常用的一些Python机器人框架的近百倍,实现真正的高性能,即使非常大的数据量也能高效解析,吞吐自如。
我们注重真实性能优化,必要时使用无锁线程池进行管理,无论是I/O密集型还是CPU密集型环境下,都能真正实现并发处理,而非打着异步噱头。
事实上,例如常用的Python里面,
async
和await
创建异步是协程实现的,依旧是单线程,只能在I/O密集型环境下减少等待时间,从而避免I/O等待(例如网络请求等待)造成的阻塞,提高CPU利用率,但是并不会提高性能。
但是,在机器人运行过程中,除了网络数据包请求等待这种I/O密集型任务,还会有大量时间花在解析数据包内容这种CPU密集型环境上。
然而,在上述这种情况下,也就是CPU密集型环境,使用异步操作不仅不会带来性能的提升,还会带来性能的下降,因为处理依旧是单线程,而创建异步需要额外开销。
系统和架构 | 支持情况 | 是否计划支持 | 支持的版本 |
---|---|---|---|
Windows-x64 | ✅ | ✅ | >= v0.1.0 |
Windows-arm64 | ❌ | ✅ | - |
Linux-x64 | ❌ | ✅ | - |
Linux-arm64 | ❌ | ✅ | - |
macOS-x64 | ❌ | ❌ | - |
macOS-arm64 | ❌ | ❌ | - |
注意:
我们没有计划支持32位系统,也不要开支持32位系统的Issue。
暂时没有计划支持macOS,如需支持,可自行 Fork 并 PR 。
- 从 GitHub Release 下载你对应系统的最新版,解压后,将
KobeBryant.exe
放入一个文件夹中(最好是空文件夹)。 - 双击
KobeBryant.exe
运行机器人,第一次运行会自动生成相应的文件。 - 打开生成的
config/config.json
配置你的机器人(具体配置项后续介绍)。 - 向
plugins
文件夹内放入需要运行的插件(插件格式后续介绍)。 - 重启机器人。
注意:
你不能更改可执行文件的名字,可执行文件的名字只能是KobeBryant.exe
如果你无法运行KobeBryant.exe
或者运行后闪退,请更新 VC运行库
- 你可以在控制台上面使用命令
plugins list
列出当前加载的插件 - 你可以在控制台上面使用命令
plugins load/unload/reload <PluginName>
来进行热加载、热卸载和热重载插件。
注意:热加载不会有任何问题,但是热卸载和热重载能否成功,取决于插件开发者是否支持
- 你可以在控制台上面使用命令
stop
安全关闭KobeBryant
默认配置文件如下,请自行修改
// config.json
{
"ws_url": "ws://127.0.0.1:3001", // WS连接的url(请使用Onebot11的正向WS连接)
"token": "", // WS连接的Token
"language": "zh_CN", // 插件语言(默认只附带了zh_CN.lang)
"logger": { // 日志系统
"colorLog": true, // 启用彩色输出(一般不需要禁用,除非你的系统不支持)
"level": 4, // 输出等级(0为静默,1只输出严重错误,2输出错误以上等级信息,3输出警告以上信息,4输出正常信息,5输出中包含debug信息)
"logFile": true, // 日志是否保存到文件
"logFilePath": "./logs/latest.log" // 日志文件路径
}
}
如果你愿意自己构建项目,或者向 KobeBryant
贡献代码,您可以按照以下说明自行构建项目
- 克隆仓库到本地,并使用你熟悉的 IDE (VS / VSCode / CLion等)打开项目目录,对 Cmake 项目进行编译生成。
- 正常构建该项目即可。
KobeBryant本体只能加载原生插件
KobeBryant在读取到非原生插件(manifest.json
里面的"type"
字段不是"native"
时),会寻找已注册的插件引擎,并交由对应的插件引擎加载
插件引擎本质上也是一个原生插件,你可以编写插件引擎来加载其它插件。
每一个插件应该是一个文件夹,里面包含了插件运行需要的内容,和一个插件清单 manifest.json
KobeBryant在运行时会读取每一个插件(文件夹)里面的 manifest.json
,如果 manifest.json
里面的内容是合法的,则会视该文件夹为插件,并加载插件。
原生插件会由KobeBryant直接加载,非原生插件会交给对应的引擎进行加载(如果有的话)。
由于引擎本身也是原生插件,在不指定插件依赖的情况下,原生插件总是最先加载。
此处以原生插件为例,其余插件也是类似结构,只是入口文件类型可能不一样
├── ...
├── KobeBryant.exe
└── plugins
└── PluginName(插件所在文件夹)
├── PluginEntry.dll(插件入口文件)
├── manifest.json
└── ...(可选)
KobeBryant在加载插件时,是先读取插件文件夹里面的 manifest.json
你应该确保你的 manifest.json
正确填写
// manifest.json
{
"name": "PluginName", // 必需:插件名,必须和文件夹名称一致
"entry": "PluginEntry.dll", // 必需:插件入口文件
"version": "v1.0.0", // 可选:(默认是"v0.0.0")插件的版本
"description": "Manba out!", // 可选:插件描述
"type": "native", // 可选:(默认是"native")原生插件请填写"native",其它类型由插件引擎注册
"preload": [ // 可选:需要预加载的DLL,格式如下
"MyPreload_1.dll",
"MyPreload_2.dll"
],
"passive": false, // 可选:如果插件不被其它插件依赖,是否跳过加载(一般纯前置插件才填写true)
"dependence": [ // 可选:插件依赖项(硬依赖),格式如下
{
"name": "MyDependence_1", // 依赖插件的名字(每项依赖必填此字段)
"min_version": "v1.0.0", // 依赖插件的最低版本(没有最低版本要求可不填)
"max_version": "v1.8.0" // 依赖插件的最高版本(没有最高版本要求可不填)
},
{
"name": "MyDependence_2"
}
],
"optional_dependence": [] // 可选:插件依赖项(可选依赖),格式同 `"dependence"`,此处不再展开
}
KobeBryant基于
C++23
编写,请确保你的开发环境和编译器支持C++23
正如名字所描述的一样,原生插件也就是KobeBryant所原生支持的插件类型,通常由 C++
编写
本处提供由 C++
编写的原生插件的示例。
当然,原生插件的本质是能被KobeBryant直接加载的插件,因此你也可以使用
C
、Go
、Rust
等语言编写,但是由于KobeBryant直接提供的是C++
的接口,因此你需要自己处理API的转化问题。
- 选择你最喜欢的IDE,例如
Visual Studio
、Clion
、Visual Studio Code
等等,并安装Cmake - 安装
Visual Studio
并选择安装使用C++的桌面开发
工具包 - 克隆我们提供的 插件模板,以及子模块
SDK
到你的开发目录下,并打开项目 - 开始编写你的插件
- 编译、测试、发布插件
// Main.cpp
#include "api/EventBus.hpp"
#include "api/PacketSender.hpp"
#include "api/event/MessageEvent.hpp"
// 此处写插件加载时执行的操作
void onEnable() {
// 运行插件
EventBus::subscribe<MessageEvent>([&](const MessageEvent& ev) {
if (ev.mType == MessageType::Group && ev.mSubType == MessageSubType::Normal) {
if (ev.mRawMessage.find("man") != std::string::npos) {
auto& sender = PacketSender::getInstance();
sender.sendGroupMessage(
*ev.mGroup,
Message().at(ev.mSender).text(" Man! \nWhat can I say? \nMamba out!")
);
}
}
});
}
// 此处写插件卸载载时执行的操作
void onDisable() {
// 卸载插件需要释放全部资源
// 注册的监听器、命令、Service可以不显式清理,会自动销毁
// 使用KobeBryant内置的Schedule创建的定时任务可以不显式清理,会自动销毁
}
本项目采用 LGPL-3.0 许可证发行 - 阅读 LICENSE 文件获取更多信息。
- 开发者不对您负责,开发者没有义务为你编写代码、为你使用造成的任何后果负责
- 本框架全部代码采用
LGPL 3.0
开源协议。 - 您可以使用任何开源许可证编写基于
KobeBryant
运行的插件或者引擎,甚至不发布您的源代码。 - 如果你修改了
KobeBryant
的源代码,或者基于KobeBryant
框架编写了一个新的框架,你必须开源它。 - 如果你想要分发,转载本框架,你必须得到我们的授权!
欢迎参与贡献!
- 你可以通过 反馈问题 帮助我们进行改进
- 如果你有能力帮助我们贡献代码,你也可以 Fork 本仓库,并 提交 Pull Requests
这个项目之所以存在,离不开本项目所有的贡献者。