Skip to content

2. 使用 SDK

SlimeNull edited this page Jun 8, 2023 · 4 revisions

在上一节中, 我们讲到, 要制作一个 QQ 机器人, 我们需要与 Go-CqHttp 进行通信. 然而, Go-CqHttp 的操作接口与上报数据如此多, 如果我们从 0 开始开发, 肯定会遇到诸多困难.

✔️ 使用

使用 EleCho.GoCqHttpSdk 是极其便捷的, 你只需要为你的项目添加 EleCho.GoCqHttpSdk 包引用即可. 剩下的, 就是享受 SDK 为你带来的舒适与便捷了.

🔗 建立通信

Go-CqHttp 支持四种通信, EleCho.GoCqHttpSdk 拥有对它们的完全支持:

  • 正向 HTTP (机器人程序向 Go-CqHttp 发送 HTTP 请求实现执行操作)
  • 反向 HTTP (Go-CqHttp 向机器人程序发送 HTTP 请求实现消息上报)
  • 正向 WebSocket (机器人程序通过 WebSocket 连接到 Go-CqHttp 进行双向通信, 执行操作或消息上报)
  • 反向 WebSocket (和正向 WebSocket 一样, 只不过是由 Go-CqHttp 连接到机器人程序)

建立一个 WebSocket 会话, 你可以使用下面的代码:

// 初始化一个 CqWsSession 用来与 Go-CqHttp 通信
CqWsSession session = new CqWsSession(new CqWsSessionOptions()
{
    BaseUri = new Uri("ws://127.0.0.1:6700"),  // WebSocket 地址
});

session.Start();                               // 开始连接 (你也可以使用它的异步版本)

因为 WebSocket 会话是双向的, 并且是长连接, 所以在实际使用中, 更推荐 WebSocket 会话

✋ 执行操作

要执行一个操作, 例如发送一条消息, 你需要一个 能够执行操作 的会话, 例如 HTTP 会话和 WebSocket. 然后只需要使用它的 ActionSender 来执行操作即可. 下面是一个简单的操作:

// 新建一个发送私聊消息的操作
CqSendPrivateMessageAction action = new CqSendPrivateMessageAction(114514, new CqMessage("这是一条文本消息"));

// 执行操作
CqActionResult? rst = await session.ActionSender.InvokeActionAsync(action);

其中, rst 是 Action 的响应结果, 虽然你得到的是一个 CqActionResult, 但是你可以将它强转为对应具体的结果类型. 例如这样:

// 从父类转换为子类
CqSendPrivateMessageActionResult? msgRst = (CqSendPrivateMessageActionResult?)rst;

不过, 注意, 之所以你可以这么转换, 是因为执行 "发送私聊消息" 这个操作的时候, 它返回的就是一个 "发送私聊消息操作结果", 它们是一一对应的, 如果你将它转换为 CqSendGroupMessageActionResult, 那肯定是会出问题的, 因为它不是那样的实例.

很明显, 上面的操作十分繁琐, 我们也不推荐这样使用, 你可以使用 IActionSession 的拓展方法来直接执行特定操作, 并得到特定结果:

// 通过拓展方法直接进行调用
CqSendPrivateMessageActionResult? rst = await session.SendPrivateMessageAsync(114514, new CqMessage("这是一条文本消息"));

拓展方法内部帮你完成了上述繁琐的过程, 并自动将结果转换为了你想要类型的结果.

📣 获取上报

对于反向 HTTP 会话和 WebSocket 会话, 你可以拿到来自 Go-CqHttp 的上报数据, 并进行处理. 下面是一个最基础的, 处理群聊消息的逻辑:

// 在上报管线中, 添加自己的中间件
session.PostPipeline.Use(async (context, next) =>
{
    // 判断上报是否是一个群消息上报
    if (context is CqGroupMessagePostContext groupMessagePostContext)
    {
        // 在这个消息所在的群中发送一条消息 "检测到这个群发送了一条消息"
        await session.SendGroupMessageAsync(groupMessagePostContext.GroupId, new CqMessage("检测到这个群发送了一条消息"));
    }
    
    // 这里你可以放任何你想要的逻辑
    
    await next.Invoke();    // 执行下一个中间件
});

上面的代码中, 我们需要手动判断它的上报类型, 十分繁琐, 我们也不推荐这么使用, 你可以使用 IPostSession 提供的拓展方法来直接对特定类型的上报执行操作:

// 直接添加一个仅处理群消息上报的中间件
session.UseGroupMessage(async (context, next) =>
{
    await session.SendGroupMessageAsync(context.GroupId, new CqMessage("检测到这个群发送了一条消息"));
    await next.Invoke();    // 执行下一个中间件
});

同理, 其他类型的上报, 也可以使用拓展方法来快速添加处理逻辑.

中间件可以理解为一堆处理数据中的逻辑中的一个, 它可以具备 "拦截" 的功能, 例如上面的代码中, 在最后一句总有一个 await next.Invoke(); 这个就是执行处理逻辑中下一个中间件的意思. 如果你不想这个数据继续被其他的中间件处理, 你可以不调用 next.Invoke.