Skip to content

5. 学习处理上报

SlimeNull edited this page Jun 8, 2023 · 4 revisions

上报数据也就是所谓的 "事件", 所有继承了 EleCho.GoCqHttpSdk.ICqPostSession 接口的类都将处理上报数据, 该接口规定必须要有一个名为 PostPipelineCqPostPipeline 成员

🛒 接收上报

要接收上报数据, 你需要一个能够接收上报的会话, 例如反向 HTTP 会话 CqRHttpSession 或正向 WebSocket 会话 CqWsSession.

最基础的方法, 也就是从 session 拿到上报管线, 然后在管线中添加一个中间件.

// 在上报管线中, 添加自己的中间件
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();    // 执行下一个中间件
});

🔩 使用插件

除了手动往上报管线中添加中间件, 你还可以用 EleCho.GoCqHttpSdk 提供的插件, 它本质还是一个中间件, 但是插件中, 它分离了所有类型的上报. 如果要处理某种类型的上报, 只需要 override 对应的方法即可.

class MyPostPlugin : CqPostPlugin
{
    public override async Task OnGroupMessageAsync(CqGroupMessagePostContext context)
    {
        if (context.Session is not ICqActionSession actionSession)   // 判断是否能够发送 Action
            return;
        
        string text = context.Message.GetText();
        if (text.StartsWith("TTS:", StringComparison.OrdinalIgnoreCase))
        {
            await actionSession.SendGroupMessageAsync(context.GroupId, new CqTtsMsg(text[4..]));
        }
        else if (text.StartsWith("ToFace:"))
        {
            if (CqFaceMsg.FromName(text[7..]) is CqFaceMsg face)
            
            await actionSession.SendGroupMessageAsync(context.GroupId, face);
        }
    }

    public override async Task OnGroupMessageRecalledAsync(CqGroupMessageRecalledPostContext context)
    {
        if (context.Session is not ICqActionSession actionSession)   // 判断是否能够发送 Action
            return;

        var msg = (await actionSession.GetMessageAsync(context.MessageId));

        await actionSession.SendGroupMessageAsync(context.GroupId, new CqMessage("让我康康你撤回了什么: ", msg.Message));
    }
}

当然, 如果你不希望每次都判断上下文的会话是否是 ICqActionSession, 也可以通过插件的构造函数, 直接从外部传入一个 ICqActionSession.

要在一个会话中使用插件, 调用 UsePlugin 即可.

session.UsePlugin(new MyPostPlugin());