Discord.js collector collects button interaction 2 times when I run the same command twice?

Viewed 201

I am currently working on a /inventory command, the way it works is that the user does /inventory and I saved that user.id with the page they are on { user.id: page } and based on that generate the page. The way you move from page to page is with buttons and collectors, but my problem is that when the same user does /inventory twice so that there is 2 inventory embeds both with the exact same buttons whenever the user presses one button, the code checks if I am the user who did the /inventory commands (so true) and what customId the button has (both embeds have the same button customId). Due to this both inv embeds are updated and I get an error "Interaction has already been acknowledged."

Is there anyway to differentiate which button has been pressed to update the corresponding embed correctly?

Since there is no actual bug with the code I am not posting the code here, if you need the code just ask. I just want to know what I should do to avoid this.

2 Answers

I encountered a similar issue right now. You should create your collector on a message instead of a channel. You can use fetchReply: true on your reply() method to fetch a message and then use it to call createMessageComponentCollector() method from it.
I know this question is 4 months old, but maybe it'll help someone anyway.

The best way to do this is to create your collector on the message you want to send.

// For example:
const MSG = await message.channel.send({embeds: [yourEmbed]});

const collector = await MSG.createMessageComponentCollector({ filter, idle: 20000 });

Another way to solve this is to create a random ID for your buttons. Like this:

  const randomID = Math.floor(100000 + Math.random() * 900000);

  const button = new MessageButton()
  .setCustomId(`button${randomID}`)
  .setLabel('Just a button')
  .setStyle('PRIMARY')

There is still a small possibility of getting the same ID on two interactions, but it's really low. You can also create longer IDs to lower the chances even further.

And lastly, another way would be to prevent the user from using the command again while your inventory command is active. This would be achievable by creating a Map and when the user triggers the command you add user's ID and the command's name. After the collector ends or the command is stopped you can clear the Map.

Related