DSharpPlus - 对现有消息的 WaitForReaction

DSharpPlus - WaitForReaction on existing Messages

我正在尝试使用 DSharpPlus 库创建一个 discord 机器人,如果您对带有特定表情符号的消息做出反应,您将获得特定角色。这个概念非常简单,但我想不出一个相当重要的概念。也就是说,如何让机器人始终监听对现有消息的反应。

我尝试通过命令来完成它并且我让它工作了,但是据我所知,这种方法的问题是机器人只在我键入命令后监听反应并且它只持续一分钟左右(基于配置)。

public class RoleCommands : BaseCommandModule
{
    [Command("join")]
    public async Task Join(CommandContext ctx)
    {
        var joinEmbed = new DiscordEmbedBuilder
        {
            Title = "Reaction with thumbs up!",
            Color = DiscordColor.Green
        };

        var joinMessage = await ctx.Channel.SendMessageAsync(embed: joinEmbed).ConfigureAwait(false);

        var thumbsUpEmoji = DiscordEmoji.FromName(ctx.Client, ":+1:");
        var thumbsDownEmoji = DiscordEmoji.FromName(ctx.Client, ":-1:");

        await joinMessage.CreateReactionAsync(thumbsUpEmoji).ConfigureAwait(false);
        await joinMessage.CreateReactionAsync(thumbsDownEmoji).ConfigureAwait(false);

        var interactivity = ctx.Client.GetInteractivity();

        var reactionResult = await interactivity.WaitForReactionAsync(x =>
            x.Message == joinMessage
            && x.User == ctx.User
            && x.Emoji == thumbsUpEmoji);

        if (reactionResult.Result.Emoji == thumbsUpEmoji)
        {
            var role = ctx.Guild.GetRole(773965440913375282);
            await ctx.Member.GrantRoleAsync(role).ConfigureAwait(false);

            await joinMessage.DeleteAsync().ConfigureAwait(false);
        }
    }
}

我如何在命令之外执行此操作,我可以将消息 ID 传递给它,然后它会一直收听该消息以进行反应,而不是在有限的时间内?

将消息 ID 存储在某处,然后将 MessageReactionAdded 事件挂接到您的 DiscordClient 并在那里执行您的逻辑。

我的问题的完整答案是使用 DiscordClient.MessageReactionAdded += OnReactionAdded; 并按如下方式实现方法:

private async Task OnReactionAdded(DiscordClient sender, MessageReactionRemoveEventArgs e)
{
    var messageId = e.Message.Id;
    var guild = e.Message.Channel.Guild;
    var reactionName = e.Emoji.GetDiscordName();

    var reactionDetail = ReactionDetails.FirstOrDefault(x =>
        x.MessageId == messageId
        && x.GuildId == guild.Id
        && x.ReactionName == reactionName);

    if (reactionDetail != null)
    {
        var member = e.User as DiscordMember;
        if (member != null)
        {
            var role = guild.Roles.FirstOrDefault(x => x.Value.Id == reactionDetail.RoleId).Value;
            await member.GrantRoleAsync(role).ConfigureAwait(false);
        }
    }
}