diff --git a/src/main/java/wtf/beatrice/hidekobot/listeners/SlashCommandListener.java b/src/main/java/wtf/beatrice/hidekobot/listeners/SlashCommandListener.java index beecaa9..101b146 100644 --- a/src/main/java/wtf/beatrice/hidekobot/listeners/SlashCommandListener.java +++ b/src/main/java/wtf/beatrice/hidekobot/listeners/SlashCommandListener.java @@ -6,6 +6,8 @@ import net.dv8tion.jda.api.entities.MessageHistory; import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.InteractionHook; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; import org.jetbrains.annotations.NotNull; import wtf.beatrice.hidekobot.utils.RandomUtil; @@ -49,22 +51,132 @@ public class SlashCommandListener extends ListenerAdapter return; } - int deleteCount = event.getOption("amount").getAsInt(); - if(deleteCount < 2 || deleteCount > 98) + int toDeleteAmount = event.getOption("amount").getAsInt(); // not null because the int arg is required + + if(toDeleteAmount <= 0) { - event.reply("Sorry! I can't delete that amount of messages!").queue(); - return; + event.reply("Sorry, I can't delete that amount of messages!").queue(); + } + else { + // answer by saying that the operation has begun. + InteractionHook replyInteraction = event.reply("Clearing...").complete(); + + // int to keep track of how many messages we deleted. + int deleted = 0; + + int limit = 95; //discord limits this method to range 2-100. we set it to 95 to be safe.. + + // increase the count by 1, because we technically aren't clearing the first ID ever + // which is actually the slash command's ID and not a message. + toDeleteAmount++; + + // count how many times we have to iterate this to delete the full messages. + int iterations = toDeleteAmount / limit; + + //if there are some messages left, but less than , we need one more iterations. + int remainder = toDeleteAmount % limit; + if(remainder != 0) iterations++; + + // set the starting point. + long messageId = event.getInteraction().getIdLong(); + + // boolean to see if we're trying to delete more messages than possible. + boolean outOfBounds = false; + + // do iterate. + for(int iteration = 0; iteration < iterations; iteration++) + { + if(outOfBounds) break; + + // set how many messages to delete for this iteration (usually unless there's a remainder) + int iterationSize = limit; + + // if we are at the last iteration... + if(iteration+1 == iterations) + { + // check if we have or fewer messages to delete + if(remainder != 0) iterationSize = remainder; + } + + if(iterationSize == 1) + { + // grab the message + Message toDelete = ((TextChannel)channel).retrieveMessageById(messageId).complete(); + //only delete one message + if(toDelete != null) toDelete.delete().queue(); + else outOfBounds = true; + // increase deleted counter by 1 + deleted++; + } else { + // get the last messages. + MessageHistory.MessageRetrieveAction action = channel.getHistoryBefore(messageId, iterationSize - 1); + // note: first one is the most recent, last one is the oldest message. + List messages = new ArrayList<>(); + // (we are skipping first iteration since it would return an error, given that the id is the slash command and not a message) + if(iteration!=0) messages.add(((TextChannel)channel).retrieveMessageById(messageId).complete()); + messages.addAll(action.complete().getRetrievedHistory()); + + // check if we only have one or zero messages left (trying to delete more than possible) + if(messages.size() <= 1) + { + outOfBounds = true; + } else { + // before deleting, we need to grab the message's id for next iteration. + action = channel.getHistoryBefore(messages.get(messages.size() - 1).getIdLong(), 1); + + List previousMessage = action.complete().getRetrievedHistory(); + + // if that message exists (we are not out of bounds)... store it + if(!previousMessage.isEmpty()) messageId = previousMessage.get(0).getIdLong(); + else outOfBounds = true; + } + + // queue messages for deletion + if(messages.size() == 1) + { + messages.get(0).delete().queue(); + } + else if(!messages.isEmpty()) + { + try { + ((TextChannel) channel).deleteMessages(messages).complete(); + /* alternatively, we could use purgeMessages, which is smarter... + however, it also tries to delete messages older than 2 weeks + which are restricted by discord, and thus has to use + a less efficient way that triggers rate-limiting very quickly. */ + } catch (Exception e) + { + replyInteraction.editOriginal("Sorry, it seems like there was an issue! " + e.getMessage()).queue(); + return; + } + } + + // increase deleted counter by + deleted += messages.size(); + } + } + + // log having deleted the messages. + if(deleted < 1) + { + replyInteraction.editOriginal("Couldn't clear any message!").queue(); + } else if(deleted == 1) + { + replyInteraction.editOriginal("Cleared 1 message!").queue(); + } else { + replyInteraction.editOriginal("Cleared " + deleted + " messages!").queue(); + } } - event.reply("Clearing...").queue(); - - MessageHistory.MessageRetrieveAction action = channel.getHistoryBefore(event.getInteraction().getIdLong(), deleteCount); - List messagesUnmodifiable = action.complete().getRetrievedHistory(); - List messages = new ArrayList<>(messagesUnmodifiable); + /*MessageHistory.MessageRetrieveAction action = channel.getHistoryBefore(event.getInteraction().getIdLong(), toDeleteAmount); + List messages = action.complete().getRetrievedHistory(); //more than 2 messages, less than 100 for this method ((TextChannel) channel).deleteMessages(messages).queue(); + // announce having cleared the messages. + replyInteraction.editOriginal("Cleared " + toDeleteAmount + " messages!").queue();*/ + } }