#How to handle tons of Buttons

13 messages · Page 1 of 1 (latest)

gleaming fox
#

Hi. I wanted to ask your advice for my code.

I have a bot, in committee, that has a lot of buttons. I structure the bot's folder like this: src/events/{category}/{interaction-customId}, which means that I if I have 100 buttons, I will have 100 files to have as neat a structure as possible, making it easy to maintain.

The problem is that with my current eventHandler, I create as many 100 client.on(interactionCreate,...), exposing myself to lots of memory leaks, anceh because I have to put .setMaxListeners(0) to the discord.js emitter.

My question is, how do I handle all these events without doing 100 client.on? The short solution is with a switch(customId), but I don't think it is neat and professional, because a switch should not be used to call "only" the function and do nothing else.

PS: 100 is a number to exaggerate, but it gives the idea.

crisp sparrowBOT
#

• What's your exact discord.js npm list discord.js and node node -v version?
• Post the full error stack trace, not just the top part!
• Show your code!
• Explain what exactly your issue is.
• Not a discord.js issue? Check out #useful-servers.

gleaming fox
#

Event Handler

import fs from 'fs';
// String to import ascii-table
import ascii from 'ascii-table';
import { logger } from '../utils/logger.js';


export async function loadEvents(client) {
    const table = new ascii().setHeading('Event', 'Status');

    const folders = fs.readdirSync('./src/events');
    for (const folder of folders) {
        const files = fs.readdirSync(`./src/events/${folder}`).filter(file => file.endsWith('.js'));

        for (const file of files) {
            const event = await import(`../events/${folder}/${file}`).then(m => m.default).catch(err => {
                table.addRow(`${folder}/${file}`, 'Error');;
                return logger.error(err);
            });

            if(!event) continue;

            if (event.rest) {
                if(event.once) client.rest.once(event.name, (...args) => event.execute(...args, client));
                else client.rest.on(event.name, (...args) => event.execute(...args, client));
            } else {
                if(event.once) client.on(event.name, (...args) => event.execute(...args, client));
                else client.on(event.name, (...args) => event.execute(...args, client));
            }

            table.addRow(`${folder}/${file}`.replace('.js', ''), 'Done');
            continue;
        }
    }

    return console.log(table.toString());
}                  
#

Example Button

import { Events, EmbedBuilder } from "discord.js";
import { Ticket } from "../../classes/Ticket.js";

export default {
    name: Events.InteractionCreate,
    async execute(interaction) {
        if (!interaction.isButton()) return;
        if (interaction.customId !== "ticket-order") return;

        const config = interaction.client.config;
        const ticket = await new Ticket(interaction.client, interaction).createTicketOrder();

        if (!ticket) return interaction.reply({ content: "An error occurred while creating the ticket.", ephemeral: true });

        const embed = new EmbedBuilder()
            .setTitle("Ticket created!")
            .setDescription(`Your ticket has been created! You can access it by clicking [here](${ticket.url}).`)
            .setColor(config.embeds.colors.normal)
            .setFooter({ text: "Constant Creation", iconUrl: interaction.guild.iconURL() });

        await interaction.reply({ embeds: [embed], ephemeral: true });
    }
}
rancid mason
#

I just have the function in the command file and format the custom id in a specific way s.t. the handler knows which file to hand it off to

rancid mason
#

I assumed you have a command handler

gleaming fox
#

Yes, i have a command handler

#

but it's for slash commands

#

i'm speaking about buttons now

#

or interaction like context menus etc

grand elbow
#

you can have a similar handler for those

gleaming fox
#

yes was thinking about a button collection