You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Discord机器人开发:Reaction事件如何获取对应消息

Discord.Net 反应事件获取目标消息对象解决方案

问题背景

开发Discord机器人时需要实现以下逻辑:用户对某条消息添加表情反应时,机器人自动将该消息转发至指定频道。实际开发中无法正确获取被添加反应的目标消息内容,尝试传入message、message.GetOrDownloadAsync、message.DownloadAsync、reaction.Message等取值,均无法得到正确消息对象,仅返回类似System.Func1[System.Threading.Tasks.Task1[Discord.IUserMessage]]的结果。
相关业务初始代码如下:

private async Task MainAsyns()
{
    _client.ReactionAdded += HandleReaction;
}
private async Task HandleReaction(Cacheable<IUserMessage, ulong> message, Cacheable<IMessageChannel, ulong> channel, SocketReaction reaction)
{
    var toOtherChanel = _client.GetChannel(_toOtherChanelId) as IMessageChannel;
    var msg = ???;
    if (!_client.GetUser(reaction.UserId).IsBot)
    {
            if (reaction.Emote.Name == "\uD83D\uDC4D")
            {
                await toOtherChanel.SendMessageAsync($"Message is {msg}");
            }
    }
}

错误原因

  • GetOrDownloadAsync、DownloadAsync都是异步方法,直接传入方法名不加await关键字等待执行结果,拿到的是方法本身的委托/Task对象,不是执行完成后的消息实例,才会打印出Func类型的字符串。
  • reaction.Message属性依赖本地缓存,反应事件触发时关联消息大概率未被加载到缓存,会返回null,不适合直接使用。

正确实现

???位置的正确写法为await message.GetOrDownloadAsync(),该方法会优先从本地缓存读取消息对象,缓存不存在时自动调用Discord API拉取完整消息数据。

优化后完整代码

private async Task MainAsync()
{
    _client.ReactionAdded += HandleReaction;
}
private async Task HandleReaction(Cacheable<IUserMessage, ulong> message, Cacheable<IMessageChannel, ulong> channel, SocketReaction reaction)
{
    var toOtherChanel = _client.GetChannel(_toOtherChanelId) as IMessageChannel;
    // 正确获取目标消息对象
    var msg = await message.GetOrDownloadAsync();
    // 优化用户获取逻辑,避免缓存为空触发空引用异常
    var reactionUser = await reaction.User.GetOrDownloadAsync();
    
    if (!reactionUser.IsBot && reaction.Emote.Name == "\uD83D\uDC4D")
    {
        // 通过msg.Content获取消息正文,直接插值msg对象默认调用ToString()不会返回正文内容
        await toOtherChanel.SendMessageAsync($"Message is {msg.Content}");
    }
}

注意事项

  • 所有返回Task类型的异步方法必须加await关键字等待执行完成,才能拿到预期的返回值
  • 事件参数里的Cacheable类型是Discord.Net专门设计的缓存兼容结构,优先使用GetOrDownloadAsync()方法获取实例,不要直接依赖缓存读取
  • 获取消息正文需要访问IUserMessage的Content属性,直接对消息对象做字符串插值默认会调用类型的ToString()方法,不会返回实际消息内容

内容的提问来源于stack exchange,提问作者retusu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:27:22