Étienne
Étienne

Reputation: 13

How to delete all messages from a channel while accounting for the rate limit?

I'm currently programming a bot that will be able to purge a channel from all of his messages. While doing so, I encountered a few problems.

I started by using

IEnumerable<IMessage> messages = await channel.GetMessagesAsync(1000).FlattenAsync();



await ((ITextChannel)channel).DeleteMessagesAsync(messages);

It worked, but you can't deleted messages older than 2 weeks for some unknown reasons.

People told me than this doesn't happen if you delete each messages individualy using DeleteAsync(), so I did

IEnumerable<IMessage> messages;
do
{
    messages = await channel.GetMessagesAsync(100).FlattenAsync();
    foreach (IMessage item in messages)
    {
        item.DeleteAsync();
    }
} while (messages.Count() != 0);

Now when I use it, I get the "Rate limit triggered" error, which makes sense.

But now, I'm looking for a way to delete all of my messages, while staying under the rate limit.


How can I know that the next request (to deleted a message) will trigger the rate limit (so my bot can wait for the limit to leave)?

Is there a way to get the current "Bucket" using the wrapper/API?

Or is there an altogether better way to purge a channel?

Upvotes: 1

Views: 2757

Answers (1)

WQYeo
WQYeo

Reputation: 4056

Like someone in the comments mentioned; If you really wanted to delete all messages in a channel, 'copying' the channel and deleting the old one is a solution.

Like so:

var oldChannel = ((ITextChannel)channel);

// Assuming you have a variable 'guild' that is a IGuild
// (Which is your targeted guild)
await guild.CreateTextChannelAsync(oldChannel.Name, newChannel =>
{
    // Copies over all the properties of the channel to the new channel
    newChannel.CategoryId = oldChannel.CategoryId;
    newChannel.Topic = oldChannel.Topic;
    newChannel.Position = oldChannel.Position;
    newChannel.SlowModeInterval = oldChannel.SlowModeInterval;
    newChannel.IsNsfw = oldChannel.IsNsfw;
});


await oldChannel.DeleteAsync();

The downside is that the bot now needs permission to manage channel, rather than manage messages.



Though if you really wanted to only delete messages without using the former method, you can add a delay before you delete each message. Like so:

//...
foreach (IMessage item in messages)
{
    await item.DeleteAsync();

    // Waits half a second before deleting the next.
    await Task.Delay(500)
}
//...

Downside to this is that it would take some time to delete all the messages.

With some modifications, you can combine this with ((ITextChannel)channel).DeleteMessagesAsync(messages) first to purge the newer messages, before using this loop. This will cut down some time to delete all the messages.

Upvotes: 2

Related Questions