#Updating embed field value on buttonpress

1 messages · Page 1 of 1 (latest)

glossy coral
#

There's a few key concepts I think I'm not understanding. Mainly Context, MessageProperties, and wild-card matching. (I'm generally unfamiliar with working with libraries, and lengthy browsing of the interaction framework documentation alongside this forum channel has only gotten me so far.)

Firstly, I don't know if await (Context.Interaction as IComponentInteraction).UpdateAsync(x => ...) is the correct way to go about it. I'm interpreting this as updating the MessageProperties of the message containing the Interaction Component (button in this case) that was used.

Secondly, I have no idea how to access and update the embed field values "Yes" and "No" in the UpdateAsync(). Do I need to make a new EmbedBuilder in the UpdateAsync and do x.Embed = newEmbedBuilder.Build() somehow? This does not make sense to me.

Lastly, it occurred to me when looking for an answer that the button's CustomId might need to be unique per instance of the command so as to not affect other instances of the command's embed field values. However, I don't really grasp how to do that. Setting CustomId to include MessageID $"yes:{(Context.Interaction as IComponentInteraction).Message}" was an idea, but then I don't know how to later fetch that in the ComponentInteraction without causing TypeReader errors.

[ComponentInteraction("yes:*")]
public async Task YesButton(SocketMessage message)

All help and advice appreciated. Is there somewhere there's more comprehensive information on these things where I can look?

#

My "poll" command

[SlashCommand("poll", "Create a poll")]
        public async Task Poll(string question)
        {
            var yesButton = new ButtonBuilder()
            {
                Label = "Yes",
                // Thumbs-up emoji
                //Emote = new Emoji(@"\uD83D\uDC4D"),
                CustomId = $"yes",
                Style = ButtonStyle.Success
            };

            var noButton = new ButtonBuilder()
            {
                Label = "No",
                // Thumbs-down emoji
                //Emote = new Emoji(@"\uD83D\uDC4E"),
                CustomId = $"no",
                Style = ButtonStyle.Danger
            };

            var embed = new EmbedBuilder()
            {
                Title = question,
                Color = Color.Blue
            };

            embed.AddField("Yes", 0, inline: true)
                .AddField("No", 0, inline: true);

            var component = new ComponentBuilder();
            component.WithButton(yesButton);
            component.WithButton(noButton);

            await RespondAsync(embed: embed.Build(), components: component.Build());
        }

The Component Interactions

[ComponentInteraction("yes")]
        public async Task YesButton()
        {
            await (Context.Interaction as IComponentInteraction).UpdateAsync(x =>
            {
                // Increase embed "yes" field value by one
            });

            await RespondAsync("\"Yes\" value updated.", ephemeral: true);
        }

        [ComponentInteraction("no")]
        public async Task NoButton(/*SocketMessageComponent component*/)
        {
            await (Context.Interaction as IComponentInteraction).UpdateAsync(x =>
            {
                // Increase embed "no" field value by one
            });

            await RespondAsync("\"No\" value updated.", ephemeral: true);
        }
peak cypress
#

your code looks good as is, however since UpdateAsync is a responce you need to use FollowupAsync instead of RespondAsync to let the user know you updated the message. Also, You could reduce the issues you might expierance by making a helper method to generate your embeds, then using the response from it in your UpdateAsync call as well as wherever you originally send it. I don't see why you would want to put a message in a component in that situation but if you do I would highly recommend using it's id.

glossy coral
# peak cypress your code looks good as is, however since `UpdateAsync` is a responce you need t...

Aha, gotcha. I'll make sure to use FollowupAsync.

I'm not quite sure what I should be picturing when you mention a helper method for generating embeds. Previously, I was sort of hoping for something like UpdateAsync(x => { x.Embed.Field[0].Value += 1) }. Are you saying that the solution is, in fact, to create a new EmbedBuilder and replace the old embed? I still need to figure out how to access the current field value in order to know what to set it to...

I thought (Context.Interaction as IComponentInteraction).Message was the message ID 🤔 If not, how do you get the ID? Is it (Context.Interaction as IComponentInteraction).Id that gives the message id?

peak cypress
#

.Message.Id gets the message id, and I meant you could make a method like

GetEmbedForPoll(int pollId, bool yesno)
{
  var poll = Service.GetPoll(pollId);
  return new EmbedBuilder()
    .WithTitle(poll.Title)
    .AddFeild("Allowed or Whatever", yesno ? "yes" : "no")
    ...
    .Build();
}
glossy coral
#

Right. Hm, I think I'm somewhat getting the idea of the helper method and the structure you're suggesting. I really appreciate your help. I assume Service in this case is a class written by the bot developer instead of something pre-existing in the Discord.NET library.

peak cypress
#

it is, yes

glossy coral
peak cypress
#

Probably a pole class you define yourself

#

I would just call it Poll

glossy coral
#

Oh right, okay! So, it's not unusual to create classes dedicated to just one command?

peak cypress
#

Nope, you need to store data so its a good idea to put it in a structure that can hold it

#

Unless your a touple fanatic IG

glossy coral
#

Okay, thanks! I'm definitely going to start building my poll class then and see how I go. Thanks again for the help!