MessageComponentCollector within a MessageComponentCollector

I have an embed with a SelectMenuBuilder attached. If an invalid selection is made, I want to reply to the interactor (user) with an ephemeral message that contains a ButtonBuilder to join a waitlist.
2 Replies
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
nullopt
nullopt2y ago
Code:
// create select menu
const select = new ActionRowBuilder<SelectMenuBuilder>().addComponents(
new SelectMenuBuilder()
.setCustomId(Date.now.toString())
.setPlaceholder("Claim a role")
.addOptions(...);

...

// create component selector
const collector = this.message.createMessageComponentCollector({ componentType: ComponentType.StringSelect });

collector.on("collect", async (interaction: SelectMenuInteraction) => {
// validate option
if (!isValid(interaction.values[0], interaction.user.id)) {
const waitListButton = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`${message.id}-${user.id}`)
.setLabel("Join waitlist")
.setStyle(ButtonStyle.Success)
);

const waitlistMessage = await interaction.reply({ content: "join waitlist...", ephemeral: true, components: [waitListButton] });

const waitlistCollector = waitlistMessage.createMessageComponentCollector({
componentType: ComponentType.Button,
time: 30_000,
});

waitlistCollector.on("collect", async (interaction: ButtonInteraction) => {
console.log(`<@${interaction.user.id}> joined the waitlist`);
await interaction.reply({ content: "Thank you for joining the waitlist", ephemeral: true });
});

return;
}

// handle valid selection
...

await interaction.deferUpdate();
});
// create select menu
const select = new ActionRowBuilder<SelectMenuBuilder>().addComponents(
new SelectMenuBuilder()
.setCustomId(Date.now.toString())
.setPlaceholder("Claim a role")
.addOptions(...);

...

// create component selector
const collector = this.message.createMessageComponentCollector({ componentType: ComponentType.StringSelect });

collector.on("collect", async (interaction: SelectMenuInteraction) => {
// validate option
if (!isValid(interaction.values[0], interaction.user.id)) {
const waitListButton = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`${message.id}-${user.id}`)
.setLabel("Join waitlist")
.setStyle(ButtonStyle.Success)
);

const waitlistMessage = await interaction.reply({ content: "join waitlist...", ephemeral: true, components: [waitListButton] });

const waitlistCollector = waitlistMessage.createMessageComponentCollector({
componentType: ComponentType.Button,
time: 30_000,
});

waitlistCollector.on("collect", async (interaction: ButtonInteraction) => {
console.log(`<@${interaction.user.id}> joined the waitlist`);
await interaction.reply({ content: "Thank you for joining the waitlist", ephemeral: true });
});

return;
}

// handle valid selection
...

await interaction.deferUpdate();
});
The waitlist collector fails and the console.log is never called - I expect due to the original interaction already being resolved/returned Just wonder if this sort of usecase is valid/possible, and if so, how? :) Closed - Resolved by changing usecase.