I am trying to create a discord bot using DSharpPlus library where if you react on a message with specific emoji, you will get a specific role. The concept is pretty straight forward but I fail to figure out one rather important concept. That is, how do I get the bot to listen for a reaction on an existing message all the time.
I tried to do it via commands and I got it to work, however the problem with this approach as I learned is that the bot only listens for reactions after I type a command and it only lasts a minute or so (based on configuration).
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);
}
}
}
How can I do this outside of a command where I can pass it a message Id and then it listens to that message for reactions all the time as oppose to a limited time?
The full answer to my question is to use DiscordClient.MessageReactionAdded += OnReactionAdded;
and to implement the method as such:
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);
}
}
}