Search code examples
javascriptnode.jsdiscorddiscord.jsbots

When purging messages by user and term, the wrong embed is sent


I've been working to create a Purge Command in JavaScript based off this Purge Command written in TypeScript for reconlx's DJS v13 command handler (I modified a few bits to make all the handlers and whatnot function in DJS v14), however, there are some bugs and a few things I'm losing my mind over.

Firstly, everytime the command is enacted, this little nuisance of a message appears with the success confirmation embeds, and I don't really know how to deal with it.

The little nuisance of a message I'm referring to

Secondly, when I purge specifically by user and term, the wrong embed is sent and my bot will purge as normal. According to the source code, it (referring to my bot) should be sending the cleanPurge embed, but it instead sends the userPurge embed. Purging specifically by user works as intended, just with the annoying "thinking" message as an unwanted bonus.

Thirdly, when purging by term, I can only purge if I enact the command right after a message with the specified term. Here's an example (if you don't understand my wording).

// It is okay to purge during these situations

// cat in a hat
// cat in a hat
// cat in a hat

// /purge [amount: 3] {term: cat}

// The command will purge only if it is enacted right after the message with the specific term, however...


// The command won't purge during these situations

// cat in a hat
// cat in a hat
// cat in a hat
// SHITPOST

// /purge [amount: 3] {term: cat}

// The message "SHITPOST" is in-between the last message with the term "cat" and when I enact my command, 
// therefore, for some reason, I can't purge any messages with my specified keyword before the message "SHITPOST".

// I can purge messages with the term "cat" AFTER the message "SHITPOST" until another message gets in the way.

// If you have no idea what I mean, a link to my bot's demo is below.

Purging without specifics DOESN'T bring up the "{Bot} is thinking..." message and works as intended.

If you're confused, here's a link to a demo of my bot's bugs

Any questions, please feel free to ask me, and sorry if my wording is shit.

Source code for purge.js

const { EmbedBuilder, ApplicationCommandOptionType, PermissionsBitField } = require("discord.js");
const { Command } = require("reconlx");
const ms = require("ms");

module.exports = new Command({
    name: "purge",
    description: "Deletes a specified number of messages",
    userPermissions: PermissionsBitField.Flags.ManageMessages,
    options: [
        {
            name: "amount",
            description: "Number of messages to purge",
            type: ApplicationCommandOptionType.Integer,
            min_value: 1,
            max_value: 100,
            required: true,
        },
        {
            name: "user",
            description: "Purge this member's messages",
            type: ApplicationCommandOptionType.User,
            required: false,
        },
        {
            name: "term",
            description: "Purge messages with this specific term",
            type: ApplicationCommandOptionType.String,
            required: false,
        },
        {
            name: "reason",
            description: "Reason for purging",
            type: ApplicationCommandOptionType.String,
            required: false,
        },
    ],

    run: async ({ interaction }) => {
        const amount = interaction.options.getInteger("amount");
        const user = interaction.options.getUser("user");
        const term = interaction.options.getString("term");
        const reason = interaction.options.getString("reason") || "Unspecified";
        const channel = interaction.channel
        const messages = await interaction.channel.messages.fetch({ 
            limit: amount + 1,
        });

        if (user) {
            const userMessages = messages.filter((m) => m.author.id === user.id);
            const purged = await interaction.channel.bulkDelete(userMessages, true);

            const userPurge = new EmbedBuilder()
                .setColor("#2F3136")
                .setTitle(`🧹  PURGED!`)
                .addFields(
                    {
                        name: `Cleared ${purged.size} message${
                            purged.size > 1 ? "s" : ""
                        }!`,
                        value: `Any messages from \`${user.tag}\` have been deleted from ${channel}!`
                    },
                    {
                        name: `User`,
                        value: `\`${user.tag}\``,
                        inline: true
                    },
                    {
                        name: `Term`,
                        value: `\`Unspecified\``,
                        inline: true
                    },
                    {
                        name: `Reason(s)`,
                        value: `\`${reason}\``,
                        inline: true
                    },
                )

            interaction.channel.send({ embeds: [userPurge] });
        } else if (term) {
            const filteredTerm = messages.filter((m) =>
                m.content.toLowerCase().includes(term)
            );
            const purged = await interaction.channel.bulkDelete(filteredTerm, true);

            const termPurge = new EmbedBuilder()
                .setColor("#2F3136")
                .setTitle(`🧹  PURGED!`)
                .addFields(
                    {
                        name: `Cleared ${purged.size} message${
                            purged.size > 1 ? "s" : ""
                        }!`,
                        value: `Any messages with the term ||\`${term}\`|| have been deleted from ${channel}!`
                    },
                    {
                        name: `User`,
                        value: `\`Unspecified\``,
                        inline: true
                    },
                    {
                        name: `Term`,
                        value: `||\`${term}\`||`,
                        inline: true
                    },
                    {
                        name: `Reason(s)`,
                        value: `\`${reason}\``,
                        inline: true
                    },
                )

            interaction.channel.send({ embeds: [termPurge] });
        } else if (term && user) {
            const memberMessages = messages.filter((m) => m.author.id === member.id && m.content.toLowerCase().includes(term));
            const purged = await interaction.channel.bulkDelete(memberMessages, true);

            const cleanPurge = new EmbedBuilder()
                .setColor("#2F3136")
                .setTitle(`🧹  PURGED!`)
                .addFields(
                    {
                        name: `Cleared ${purged.size} message${
                            purged.size > 1 ? "s" : ""
                        }!`,
                        value: `Any messages from \`${user.tag}\` with the term ||\`${term}\`|| have been deleted from ${channel}!`
                    },
                    {
                        name: `User`,
                        value: `\`${user.tag}\``,
                        inline: true
                    },
                    {
                        name: `Term`,
                        value: `||\`${term}\`||`,
                        inline: true
                    },
                    {
                        name: `Reason(s)`,
                        value: `\`${reason}\``,
                        inline: true
                    },
                )
                
            interaction.channel.send({ embeds: [cleanPurge] });
        } else {
            const purged = await interaction.channel.bulkDelete(messages, true);

            const purge = new EmbedBuilder()
                .setColor("#2F3136")
                .setTitle(`🧹  PURGED!`)
                .addFields(
                    {
                        name: `Cleared ${purged.size - 1} message${
                            purged.size > 1 ? "s" : ""
                        }!`,
                        value: `The specified number of messages have been deleted from ${channel}!`
                    },
                    {
                        name: `User`,
                        value: `\`Unspecified\``,
                        inline: true
                    },
                    {
                        name: `Term`,
                        value: `\`Unspecified\``,
                        inline: true
                    },
                    {
                        name: `Reason(s)`,
                        value: `\`Unspecified\``,
                        inline: true
                    },
                )
            interaction.channel.send({ embeds: [purge] });
        }
    },
});

Solution

  • Your video is still processing, so I couldn't watch it, but:

    In the "cat"/"cat"/"cat"/"shitpost" situation, you'd need amount=4, because you're only fetching N + 1 messages. If you need want your bot to purge N last matching messages even if there are more in between (e.g. in a "a"/"b"/"a"/"b"/"a"/"b" situation where you want to purge all "b"s), you'd need to fetch more messages until you've purged enough. Another "good enough" option might be to fetch e.g. amount * 2 messages and hope it's enough.

    In any case, you could start by de-quadriplicating your message filtering and embed building:

    {
      run: async ({ interaction }) => {
        const { options, channel } = interaction;
        const amount = options.getInteger("amount");
        const user = options.getUser("user");
        const term = options.getString("term");
        const reason = options.getString("reason") || "Unspecified";
        const lastNMessages = await channel.messages.fetch({
          limit: amount + 1,
        });
        const filteredMessages = lastNMessages.filter((message) => {
          if (user && message.author.id !== user.id) {
            return false;
          }
          if (term && !message.content.toLowerCase().includes(term)) {
            return false;
          }
          return true;
        });
        const purged = await channel.bulkDelete(filteredMessages, true);
        const title = `Cleared ${purged.size} message${purged.size > 1 ? "s" : ""}!`;
        const message = [
          `${purged.size} messages`,
          user ? ` from \`${user.tag}\`` : "",
          term ? ` containing \`${term}\`` : "",
          ` have been deleted from ${channel}!`,
        ].join("");
    
        const userPurge = new EmbedBuilder()
          .setColor("#2F3136")
          .setTitle(`🧹  PURGED!`)
          .addFields(
            {
              name: title,
              value: message,
            },
            {
              name: `User`,
              value: user ? `\`${user.tag}\`` : "Unspecified",
              inline: true,
            },
            {
              name: `Term`,
              value: term ? `||\`${term}\`||` : `\`Unspecified\``,
              inline: true,
            },
            {
              name: `Reason(s)`,
              value: `\`${reason}\``,
              inline: true,
            },
          );
        await channel.send({ embeds: [userPurge] });
      },
    }