Search code examples
buttondiscord.jsrolesdiscord-buttons

Discord.JS, How to use one discord button to allow the purchase of various server roles


Sorry for the poorly worded title, I'll try to explain as best as I can. I am creating a role shop command using the new discord-buttons module, and came across a problem, to my understanding I would have to create a button for each individual role, in order for someone to buy it. After searching through documentation, I'm still a bit stumped. Here's some example code I put together to show what I'm trying to do:

let embedRed = new Discord.MessageEmbed()
                
        .setTitle('Red Role')
        .setColor('#c46413')
        .addField('**Price**', '10,000', true)
        .addField('**Color Hex:**', '#ffffff',true)

 let embedBlue = new Discord.MessageEmbed() 
                  
          .setTitle('Blue')
          .setColor('#c2a289')
          .addField('**Price**', '10,000', true)
          .addField('**Color Hex:**', '#ffffff',true)

  ///Buttons
let buttonBuyRed = new MessageButton()
.setStyle('green')
.setLabel('Buy Red Role')
.setID('role_buy1')


let buttonBuyBlue = new MessageButton()
.setStyle('green')
.setLabel('Buy Blue Role')
.setID('role_buy2')

//embeded messages being sent
 message.channel.send({ buttons: [buttonBuyRed], embed: embedRed});
    message.channel.send({ buttons: [buttonBuyRed], embed: embedBlue});


//What happens if buttons are pressed
client.on('clickButton', async (role_buy1) => {
  if (button.id === 'roley_buy1') {
    button.channel.send(`${button.clicker.user.tag} bought red role`);
db.push(message.author.id, `${message.guild.roles.cache.get('role id here')}`) //role being pushed to user's inventory
  }
});

client.on('clickButton', async (role_buy2) => {
  if (button.id === 'role_buy2') {
    button.channel.send(`${button.clicker.user.tag} bought blue role`);
db.push(message.author.id, `${message.guild.roles.cache.get('role id here')}`) //role being pushed to user's inventory
  }
});

Since I have about 25 different roles that I want users to be able to purchase, it's quite a hassle to create a button for each role, I am looking for a way to just use one single "buy_role" button that works for all available roles.

If I didn't explain something clearly, please let me know, any help is appreciated!


Solution

  • So i came to a conclusion, this code works, but if your guild has a lot of roles, it would throw an error "Invalid form body"

            const rolesInGuild = message.guild.roles.cache.array(); //creating array from collection of roles in a guild
            const buttons = []; // an empty array for our buttons
            for (const role of rolesInGuild) { // creating a loop inorder to create a button for every roles in rolesInGuild Array
                const button = new MessageButton()
                    .setStyle('red') // default: blurple
                    .setLabel(`${role.name}`) // default: NO_LABEL_PROVIDED
                    .setID(`${role.id}`);
                buttons.push(button); // button id is the same as role id so its unique!
            }
            console.log(rolesInGuild);
            console.log(buttons);
            await message.channel.send('test', { buttons: buttons }); // sending our buttons
    
            bot.on('clickButton', async(button) => {
                for (const btn of buttons) {
                    if (btn.custom_id == button.id) {
                        const role = button.guild.roles.cache.get(btn.custom_id);
                        const member = message.guild.members.cache.get(button.clicker.user.id);
                        member.roles.add(role);
                    }
                }
            });
    

    enter image description here

    you could add specific roles to the array rolesInGuild in this format [{ name: 'rolename', id: 'roleid' }] instead of every roles in the guild ( I wasn't sure what your goal was)