discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.4k stars 3.97k forks source link

Collector#end not firing off unless there's been another button pressed. #9922

Closed variable-formation closed 1 year ago

variable-formation commented 1 year ago

Which package is this bug report for?

discord.js

Issue description

Steps to reproduce:

  1. Start bot
  2. Press either the smash or pass button in Discord client
  3. interaction.content should update to "Game over!" and there should be something logged in the console that says "stopped"

Collection.stop() works perfectly fine provided there is pagination input. But if someone presses smash or pass without paginating then it does not fire off.

Code sample

module.exports = {
    data: new SlashCommandBuilder()
        .setName('smash')
        .setDescription('Would you smash this Gundam?'),
    async execute(interaction) {
        let currentPage = 0;

        let getSmashesSQL = `SELECT SMASHES FROM MOBILE_WEAPONS WHERE NAME = ?`;
        let getPassesSQL = `SELECT PASSES FROM MOBILE_WEAPONS WHERE NAME = ?`;
        let smashes;
        let passes;

        const num = randomNum(0, 4);
        const name = gundams[num].title;
        const nameLower = name.toLowerCase();
        const images = gundams[num].images;

        let embeds = [];
        for (image in images) {
            let embed = new EmbedBuilder()
                .setTitle(`Would you smash the ${name}?`)
                .setImage(images[image])

            embeds.push(embed)
        }

        const smash = new ButtonBuilder()
            .setCustomId(`${nameLower}-smash`)
            .setLabel('Smash')
            .setStyle(ButtonStyle.Success);

        const pass = new ButtonBuilder()
            .setCustomId(`${nameLower}-pass`)
            .setLabel('Pass')
            .setStyle(ButtonStyle.Danger);

        const back = new ButtonBuilder()
            .setCustomId("page-back")
            .setLabel("Previous Page")
            .setEmoji("◀️")
            .setStyle(ButtonStyle.Primary)
            .setDisabled(true);

        const forward = new ButtonBuilder()
            .setCustomId("page-forward")
            .setLabel("Next Page")
            .setEmoji("▶️")
            .setStyle(ButtonStyle.Primary)

        let voteActions;
        if (images.length > 1) {
            voteActions = new ActionRowBuilder()
                .addComponents(back, smash, pass, forward);
        } else {
            voteActions = new ActionRowBuilder()
                .addComponents(back.setDisabled(true), smash, pass, forward.setDisabled(true));
        }

        db.get(getSmashesSQL, [nameLower], (err, row) => {
            if (err) {
                return console.error(err.message);
            }
            smashes = row.SMASHES;
        });

        db.get(getPassesSQL, [nameLower], (err, row) => {
            if (err) {
                return console.error(err.message);
            }
            passes = row.PASSES;
        });

        await interaction.reply({
            content: ":eyes:",
            embeds: [embeds[0]],
            components: [voteActions],
            ephemeral: true,
            fetchReply: true
        }).then(sentInteraction => {
            const filter = (i) => ['page-back', 'page-forward', `${nameLower}-smash`, `${nameLower}-pass`].includes(i.customId) && i.user.id === interaction.user.id;
            const collector = sentInteraction.createMessageComponentCollector({
                filter: filter, 
                componentType: ComponentType.Button, 
                time: 60_000,
                idle: 60_000,
                dispose: true,
            });

            collector.on('collect', async (i) => {
                const resultsEmbed = new EmbedBuilder()
                    .setTitle(`Here's how other people voted on the ${name}!`)
                    .setImage(images[currentPage])

                if (i.customId === 'page-back' && currentPage === 1) {
                    currentPage--;

                    voteActions = new ActionRowBuilder()
                        .addComponents(back.setDisabled(true), smash, pass, forward.setDisabled(false));

                    await i.update({
                        content: ":eyes:",
                        embeds: [embeds[currentPage]],
                        components: [voteActions],
                    });
                } else if (i.customId === 'page-forward' && currentPage === (embeds.length - 2)) {
                    currentPage++;

                    voteActions = new ActionRowBuilder()
                        .addComponents(back.setDisabled(false), smash, pass, forward.setDisabled(true));

                    await i.update({
                        content: ":eyes:",
                        embeds: [embeds[currentPage]],
                        components: [voteActions],
                    });
                } else if (i.customId === 'page-back' || i.customId === 'page-forward' && currentPage >= 0 && currentPage < embeds.length - 1) {
                    if (i.customId === 'page-back') {
                        currentPage--;
                    } else if (i.customId === 'page-forward') {
                        currentPage++;
                    }

                    voteActions = new ActionRowBuilder()
                        .addComponents(back.setDisabled(false), smash, pass, forward.setDisabled(false));

                    await i.update({
                        content: ":eyes:",
                        embeds: [embeds[currentPage]],
                        components: [voteActions],
                    });
                };

                if (i.customId === `${nameLower}-smash`) {
                    updateSQL = `UPDATE MOBILE_WEAPONS SET SMASHES = SMASHES + 1 WHERE NAME = ?`;
                    db.run(updateSQL, [nameLower], function (err) {
                        if (err) {
                            return console.error(err.message);
                        }
                    });

                    await i.update({
                        content: "You voted smash!",
                        embeds: [resultsEmbed.addFields(
                            {
                                name: "🟢 Smashes",
                                value: `${smashes + 1}`,
                                inline: true,
                            },
                            {
                                name: "🔴 Passes",
                                value: `${passes}`,
                                inline: true,
                            },
                        )],
                        components: [],
                    });

                    collector.stop("smashed");
                } else if (i.customId === `${nameLower}-pass`) {
                    updateSQL = `UPDATE MOBILE_WEAPONS SET PASSES = PASSES + 1 WHERE NAME = ?`;
                    db.run(updateSQL, [nameLower], function (err) {
                        if (err) {
                            return console.error(err.message);
                        }
                    });

                    await i.update({
                        content: "You voted pass!",
                        embeds: [resultsEmbed.addFields(
                            {
                                name: "🟢 Smashes",
                                value: `${smashes}`,
                                inline: true,
                            },
                            {
                                name: "🔴 Passes",
                                value: `${passes + 1}`,
                                inline: true,
                            },
                        )],
                        components: [],
                    });

                    collector.stop("passed");
                }

                collector.on('end', () => interaction.editReply({ content: 'Game Over!', components: [] }) && console.log("stopped"));
            });
        });
    },
};

Versions

discord.js 14.13.0 Node.js v21.0.0 WSL 1.2.5.0 // Ubuntu 22.04.3 LTS

Issue priority

Low (slightly annoying)

Which partials do you have configured?

Not applicable

Which gateway intents are you subscribing to?

Guilds

I have tested this issue on a development release

No response

Jiralite commented 1 year ago

You nested your listener, so it will not register until something reaches it. This is not a bug.


Please don't dump your file and expect someone to comb through it to find your issue. You should provide a minimal reproducible code sample—whilst doing that, you may even find your issue.

mcfriend99 commented 3 months ago

@Jiralite I think you conclusion is invalid. If user is getting response, then the parent scope was fulfilled and the collector should be registered. The code look pretty valid and looks like Discord.JS collector is actually not working well. I took his sample out and unnested it. Same behavior.

didinele commented 3 months ago

Once again,

Please don't dump your file and expect someone to comb through it to find your issue. You should provide a minimal reproducible code sample—whilst doing that, you may even find your issue.

"A minimal reproducible code sample" means a one-file I can copy paste exactly as-provided (minus the token) and reproduce the issue.