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

4.5k Views Asked by At

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!

2

There are 2 best solutions below

7
AnanthDev On BEST ANSWER

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)

0
Sxpherr On

you have ${message.guild...}, that’s the wrong if you have an error, so try this:

client.on('clickButton', async (button) => {
  if (button.id === 'roley_buy1') {
    button.channel.send(`${button.clicker.user.tag} bought red role`);
    db.push(message.author.id, `${button.guild.roles.cache.get('role id here')}`)
    //role being pushed to user's inventory
    button.clicker.roles.add('your role id');
    // or you can find the role using
    const role = button.guild.roles.cache.find(role => role.name == 'rolename');
    button.clicker.roles.add(role);
  }
});```