0
votes

I'm new to javascript and have reccently been tinkering around with the discord API called discord.js. I would like to make a command in my bot that can purge all the messages in a channel, unless it includes a certian string or emoji, and it is written by a certian person. Does anyone know how I could go about doing this? I have taken a look at the .bulkDelete() method, but there is no way to tell it not to delete some messages that include a certian string.

EDIT: I have seen this post: Search a given discord channel for all messages that satisfies the condition and delete, but it does the opposite of what I want; that post is if there is a certian keyword in the message, it gets deleted.

1

1 Answers

2
votes

Let's work our way to a solution step by step.

  1. To gather a Collection of Messages from a channel, use the TextBasedChannel.fetchMessages() method.

  2. With Collection.filter(), you can return only the elements from a Collection that meet certain conditions.

  3. You can check if a message contains a string in a variety of ways, but perhaps the simplest is the combination of Message.content and String.includes().

  4. The sender of a message can be referenced via the Message.author property. To check the author against another user, you should compare their IDs, returned by User.id.

  5. In the filter method's predicate function, "unless" would translate to the logical NOT operator, !. We can place it before a set of conditions so that if they are met, the operator will return false. That way, messages that don't meet your specified constrains will be excluded from the returned Collection.

Tying this together so far...

channel.fetchMessages(...)
  .then(fetchedMessages => {
    const messagesToDelete = fetchedMessages.filter(msg => !(msg.author.id === 'someID' && msg.content.includes('keep')));
    ...
  })
  .catch(console.error);
  1. To bulk delete messages, you can use the TextChannel.bulkDelete() method, as you have discovered.
  2. After the correct messages have been deleted, you can add a response if you wish, employing TextBasedChannel.send().

Altogether...

// Depending on your use case...
// const channel = message.channel;
// const channel = client.channels.get('someID');

channel.fetchMessages({ limit: 100 })
//                      ^^^^^^^^^^
// You can only bulk delete up to 100 messages per call.
  .then(fetchedMessages => {
    const messagesToDelete = fetchedMessages.filter(msg => !(msg.author.id === 'someID' && msg.content.includes('keep')));

    return channel.bulkDelete(messagesToDelete, true);
//                                              ^^^^
//        The second parameter here represents whether or not to automatically skip messages
//               that are too old to delete (14 days old) due to API restrictions.
  })
  .then(deletedMessages => channel.send(`Deleted **${deletedMessages.size}** message${deletedMessages.size !== 1 ? 's' : ''}.`))
//                                                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//                                                                This template literal will add an 's' if the word 'message' should be plural.
  .catch(console.error);

To maintain better flow of your code, consider using async/await.