DEV Community

Janeth Graziani
Janeth Graziani

Posted on

How to Program Discord Message Embeds with Buttons

Hey there Autocoder! If you are reading this tip of the week to level up your Discord bot development skills, I assume that you have already completed our first guide “How to build a free Discord bot with Node.js.” If you have not, I highly recommend you complete it first. It covers creating a Discord bot, linking accounts, creating slash commands, and so much more that we will build on top of.

What you'll learn

Today we will learn how to program buttons. We will add functionality to our Discord bot so that it replies to a prefix command like !addrole. It will post a message embed into the Discord channel where the command was invoked. The embed will contain buttons and upon selection, a role will be added to the user pressing the button.

Embed Example

Prerequisites

  • A Discord bot built on Autocode using this guide.
  • The ambition to level up your Discord Bot development!

Let’s get started!

Step 1: Mocking up Embed Messages with Buttons

First, let’s mock up the message our bot will send. Head on over to the embed builder. For this example, we'll set a simple embed message with a title, description, and two buttons.

In the Components section, select Button, give it a style, label and acustome_id This custom id is unique to your button and you will use it again to handle the request when a user presses one of the buttons. I have set my custom id as dev_button_id and techie_button_id for my buttons.

Embed Image

Once your embed message looks perfect toggle the view code button on the top right. This is the code that will execute when a user invokes a command.

View Code

To set it up, copy this code, and head on over to your dashboard.



const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});

await lib.discord.channels['@0.2.0'].messages.create({
  "channel_id": `${context.params.event.channel_id}`,
  "content": "",
  "tts": false,
  "components": [
    {
      "type": 1,
      "components": [
        {
          "style": 1,
          "label": `Developer`,
          "custom_id": `dev_button_id`,
          "disabled": false,
          "emoji": {
            "id": null,
            "name": `🧑`
          },
          "type": 2
        },
        {
          "style": 3,
          "label": `Techie`,
          "custom_id": `techie_button_id`,
          "disabled": false,
          "emoji": {
            "id": null,
            "name": `😎`
          },
          "type": 2
        }
      ]
    }
  ],
  "embeds": [
    {
      "type": "rich",
      "title": `Select Your Desired Role`,
      "description": `What best describes you`,
      "color": 0x00FFFF
    }
  ]
}); 


Enter fullscreen mode Exit fullscreen mode

Step Two: Creating an Endpoint to Handle a Prefix Command

Click the project you built when completing the first tutorial “How to build a free Discord bot with Node.js.”.

Select New Endpoint.

Set your trigger to Discord and your event as message.create.prefix. A prefix input will appear, which we'll set as !role or whatever you wish your prefix command to be.

Prefix

Hit the blue Okay to finish setting the trigger.

Replace the existing code with the code generated from the embed builder in step 1 and press the orange save button.

Code Example

Great! We've created an endpoint that will handle a request whenever a user types !role in any channel.

Notice that we included the lib node package on line one which allows us to make the request to await lib.Discord.channels['@0.2.0'].messages.create API. This API will post our message back to the channel that sent the prefix command because ${context.params.event.channel_id} is populated with the data coming in from Discord.

Now we can test the prefix command by heading over to Discord and posting a message with our prefix command like so: !role

Embed Example

Great work so far! But you’ll notice that nothing will happen when you select a button. That is because we haven’t created the endpoint that will handle our request when a message button is clicked! Let’s go do that next.

Step 3: Create an Endpoint to Handle Button Interactions

Head back to your project in Autocode and select a new endpoint. Set your trigger as Discord and your event as message.button.interaction. A custom_id input will appear. This is where you place the custom_id of one of your buttons. I will begin programming my developer button that has the dev_button_id.

Hit the blue Okay to finish setting the trigger.

Button Interaction Handler

Next, we need to add the code which will give our user the Developer role upon selecting the button. We will use the members.roles.update() method from the discord/guilds API.

Copy this block of code onto the message.button.interaction handler.



const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});

let result = await lib.discord.guilds['@0.1.0'].members.roles.update({
  role_id: ``, // required
  user_id: context.params.event.member.user.id, // required 
  guild_id: context.params.event.guild_id // required
});

await lib.discord.channels['@0.2.0'].messages.create({
  channel_id: context.params.event.channel_id,
  content: `The Developer role has been assigned to <@!${context.params.event.member.user.id}>!`
});
```

On **line 4** in between the backticks, you will input the id for the role you wish to grant when a user presses the button. 

And a quick way to find your role’s id is by typing the role in Discord then adding a backslash before the role like this \@role.  

![Role Id](https://janethl.public.files.stdlib.com/_stdlib/provider/JanethL/images/roleId.png)

Your code should look like this with your unique role id on line 4. Press the orange save button.

![Button Handler Code](https://janethl.public.files.stdlib.com/_stdlib/provider/JanethL/images/code2.png)

On **lines 3 - 7** we are making a request to **members.roles.update.** In the argument for `role_id`, we pass in the unique id of the role we want to assign when a user selects the button. We also identify the user we want to assign with `context.params.event.member.user.id.` 

On **lines 9 - 12** we then make a request to **message.create** to post a message confirming that the developer role was assigned. We post the message to the channel where the button was invoked by passing in `context.params.event.channel_id` into `channel_id.` For the `content` argument we pass in a string and we use backticks for this  since we are using a [template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) to retrieve the user id with `${context.params.event.channel_id}.` 

We use `context.params.event.member.user.id` and `context.params.event.channel_id` because all Discord endpoints on Autocode have a **context.params.event** property that holds all the data for the specific event. In this instance, the event is a button interaction. When that button is pressed, Discord sends a unique payload of data to your endpoint. A sample of that data can be seen when you press the `payload` button to the bottom right of Autocode. 

We use [dot notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors) to extract  the user id from this payload like this `context.params.event.member.user.id.`

![Sample Payload](https://janethl.public.files.stdlib.com/_stdlib/provider/JanethL/images/samplePayload.png)

Keep in mind that every endpoint receives a unique payload of data. The way you retrieved the user id for this endpoint is not the same as retrieving it when using other endpoints like message.create. You must check the sample payload or log your event to the console using `console.log(context.params.event).`

Great now that you’ve programmed your button, it’s time to test on Discord! 

Select the button and watch as your bot successfully gives you a role and confirm with a message.

![Developer Button](https://janethl.public.files.stdlib.com/_stdlib/provider/JanethL/images/DeveloperButton.png)

![Role Update](https://janethl.public.files.stdlib.com/_stdlib/provider/JanethL/images/roleUpdate.png)

Amazing! You have successfully programmed your first button on Autocode! You can now repeat the same steps to program the second button.

## Step 4: Repeating the Process to Program More Buttons

Create another endpoint for **message.button.interaction** and in the input for `custom_id`, type in the second button’s `custom_id`.

Replace the auto-generated code with the following.

```javascript

const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});

let result = await lib.discord.guilds['@0.1.0'].members.roles.update({
  role_id: ``, // required
  user_id: context.params.event.member.user.id, // required 
  guild_id: context.params.event.guild_id // required
});

await lib.discord.channels['@0.2.0'].messages.create({
  channel_id: context.params.event.channel_id,
  content: `The Techie role has been assigned to <@!${context.params.event.member.user.id}>!`
}); 



Enter fullscreen mode Exit fullscreen mode

Press the orange save button.

You are on a roll! Time to test if it all works as expected! Head back to your discord server and press the second button.

Second Button

You have learned to program buttons on Autocode! You should be very proud of yourself for leveling up your Discord bot development skills!

Additional Tips

The possibilities are infinite now that you know how to program buttons and have access to Discord’s APIs on Autocode. Take some time to explore each API and discover different actions you can invoke via Discord button interactions.

How to remove a role from a user after button is pressed

If you’d like to remove a role from a user once a button is pressed use members.roles.destory() method from the discord/guilds API.

How to disable buttons after a button is pressed

I want to disable the developer button after it has been clicked. Therefore I make a request to message.update inside my message.button.interaction endpoint for the specific button I want to disable. I set the disabled field inside components to true and paste the following code at the end of my previous code.



await lib.discord.channels['@0.2.2'].messages.update({
"channel_id": context.params.event.channel_id,
"message_id": context.params.event.message.id,
"content": "",
"tts": false,
"components": [
{
"type": 1,
"components": [
{
"style": 1,
"label": Developer,
"custom_id": dev_button_id,
"disabled": true,
"emoji": {
"id": null,
"name": 👨
},
"type": 2
},
{
"style": 3,
"label": Techie,
"custom_id": techie_button_id,
"disabled": false,
"emoji": {
"id": null,
"name": 😎
},
"type": 2
}
]
}
],
"embeds": [
{
"type": "rich",
"title": Select Your Desired Role,
"description": What best describes you,
"color": 0x00FFFF
}
]
});

Enter fullscreen mode Exit fullscreen mode




Thank You!

Thank you for building with us! If you have additional questions regarding creating prefix commands, message embeds, updating roles, or anything else, don’t hesitate to ask us on our Discord Developer server.

Top comments (0)