快速入门

March 22, 2023 · View on GitHub

准备工作

配置mirai与mirai-api-http

你需要根据mirai的相关说明安装mirai(Mirai Console Loader, 或者其他你喜欢的方式,见用户手册),并安装mirai-api-http。确保以上软件可以正确运行并成功登陆Bot的账号。

cpp-mirai-client 依赖 mirai-api-http 的 http adapterwebsocket adapter 来正确工作,因此你的配置文件中应该至少有这样一条

## 启用 http 和 ws adapter
adapters:
    - http
    - ws

此外,你还可能需要根据需求来配置其他选项,详情可以见 mirai-api-http 对应的文档。其中与 cpp-mirai-client 相关的部分为verifyKey, http 监听地址以及 websocket 监听地址。

链接cpp-mirai-client

你需要用自己喜欢的方式编译cpp-mirai-client并确保你的项目链接到对应的库文件。如果不知道具体怎么做,可以使用 cppmirai-template 生成一个项目模板(TBD)

一个简易的复读机

我们将以一个简单的复读机Bot为例,介绍cpp-mirai-client的基本用法。完整的代码可见 examples/echo

头文件

为了使用 cpp-mirai-client 中的接口,你需要包含对应的头文件

#include <libmirai/mirai.hpp>

这将包含所有的 cpp-mirai-client 相关类与函数的声明。你也可以根据自己的需求仅包含部分头文件

#include <libmirai/Events/Events.hpp>	// include all event classes
#include <libmirai/Messages/PlainMessage.hpp>	// include declaration for PlainMessage class only
#include <libmirai/models.hpp>		// include everything but the client

连接mirai-api-http

为了与mirai-api-http通信,你需要一个 Mirai::MiraiClient 对象

Mirai::MiraiClient client;

在连接之前,你需要设置一些基本的选项,这些配置被保存在 Mirai::HttpWsAdaptorConfig 对象中

Mirai::HttpWsAdaptorConfig config;

// You can set them manually
config.HttpUrl = "http://localhost:8080";
config.WebsocketUrl = "ws://localhost:8080";
config.VerifyKey = "xxx";

using namespace Mirai;
config.BotQQ = 12345_qq;

using namespace std::chrono_literals;
config.ReadTimeout = 10s;
config.HeartbeatInterval = 1min;

// Or you can read them from file
config.FromJsonFile("/path/to/config.json");

为了指定与mirai-api-http通信的具体方式,我们需要设置合适的适配器(Adaptor)。目前我们需要使用的是 HttpWsAdaptor,在client中设置适配器的方式如下

client.SetAdaptor(MakeHttpWsAdaptor(std::move(config)));

其中,Mirai::MakeHttpWsAdaptor会创建一个适配器对象并返回。我们在参数中传入刚刚设置好的config

Mirai::MakeHttpWsAdaptor返回的类型为std::unique_ptr<Mirai::IAdaptor>,其中Mirai::IAdaptor为所有适配器的通用接口类。

现在开始连接mirai

try
{
	client.Connect();
}
catch(const std::exception& e)
{
	// do something...
}

如果你想关闭连接,只需要调用

client.Disconnect();

处理事件

显然,仅仅只连接mirai是不够的。我们希望能接收到QQ传来的消息并做出相应的处理。一般来说,除了好友和群聊发来的消息外,Bot还会收到消息撤回、群体禁言之类的信息,这些被统称为事件 Events 。 完整的事件列表可以参考 libmirai/Events/Events.hpp

在复读机Bot中,我们需要处理的是 Mirai::FriendMessageEvent,这代表来自好友发送的消息

client.On<Mirai::FriendMessageEvent>(
	[](Mirai::FriendMessageEvent event)
	{
		try
		{
			event.GetMiraiClient()
			.SendFriendMessage(
				event.GetSender().id, 
				event.GetMessage(),
				std::nullopt
			);
		}
		catch(std::exception& e)
		{
			// do something...
		}
	}
);

我们来一点点分析这段代码。首先为了注册响应事件的回调函数,我们需要调用 Mirai::MiraiClient::On<EventType>(callback) ,其中回调函数的格式为 std::function<void(EventType)>。为了简便,我们直接使用了lambda作为事件处理函数。

回调函数的核心语句只有一条:

event.GetMiraiClient()
.SendFriendMessage(
	event.GetSender().id, 
	event.GetMessage(),
	std::nullopt
);

它可以拆分为两个部分。首先,Mirai::FriendMessageEvent::GetMiraiClient() 负责返回一个 Mirai::MiraiClient 对象的引用,大部分事件(除了与网络连接相关的事件外)都拥有这个方法。我们需要这个对象来进行消息的回复以及其他可能的操作。

Mirai::FriendMessageEvent::GetMiraiClient() 返回的类型是 Mirai::MiraiClient&,而出于显而易见的原因 Mirai::MiraiClient 是non-copyable的。因此如果你想为了方便暂时储存该对象的话,你应该使用 auto& client = event.GetMiraiClient() 而非 auto client = event.GetMiraiClient()

当然,你也可以直接在lambda捕获里直接捕获 client 对象,但是要注意循环引用的问题。

为了复读,我们需要获得发送者的资料以及发送的具体消息,这些对象是通过 Mirai::FriendMessageEvent::GetSender()Mirai::FriendMessageEvent::GetMessage() 获取的。

大部分事件对象都定义了很多Get方法,你可以通过这些方法获取事件相关的信息。利用IDE的语法提示以及API文档可以快速获知每种事件所拥有的属性。

最后,我们通过 Mirai::MiraiClient::SendFriendMessage() 将复读的信息发送给对方。你也可以加入其他事件的处理函数,实现对群聊消息的复读或者对戳一戳消息的复读。