33import net .dv8tion .jda .api .entities .*;
44import net .dv8tion .jda .api .events .interaction .command .SlashCommandInteractionEvent ;
55import net .dv8tion .jda .api .interactions .commands .OptionMapping ;
6+ import net .dv8tion .jda .api .requests .restaction .MessageAction ;
67import net .dv8tion .jda .api .requests .restaction .interactions .ReplyCallbackAction ;
78import net .javadiscord .javabot .Bot ;
8- import net .javadiscord .javabot .command .ResponseException ;
99import net .javadiscord .javabot .command .Responses ;
10- import net .javadiscord .javabot .command .moderation .ModerateUserCommand ;
10+ import net .javadiscord .javabot .command .moderation .ModerateCommand ;
11+ import net .javadiscord .javabot .data .config .guild .ModerationConfig ;
1112import net .javadiscord .javabot .util .TimeUtils ;
1213
1314import javax .annotation .Nullable ;
2122import java .util .List ;
2223
2324/**
24- * This command deletes messages from a channel.
25+ * Moderation command that deletes multiple messages from a single channel.
2526 */
26- public class PurgeCommand extends ModerateUserCommand {
27+ public class PurgeCommand extends ModerateCommand {
2728
28- @ Override
29- protected ReplyCallbackAction handleModerationActionCommand (SlashCommandInteractionEvent event , Member commandUser , Member target ) throws ResponseException {
30- Member member = event .getMember ();
31- if (member == null ) {
32- return Responses .warning (event , "This command can only be used in a guild." );
33- }
34- var config = Bot .config .get (event .getGuild ()).getModeration ();
29+ private final Path ARCHIVE_DIR = Path .of ("purgeArchives" );
3530
31+ @ Override
32+ protected ReplyCallbackAction handleModerationCommand (SlashCommandInteractionEvent event , Member commandUser ) {
33+ this .setAllowThreads (true );
3634 OptionMapping amountOption = event .getOption ("amount" );
3735 OptionMapping userOption = event .getOption ("user" );
38- OptionMapping archiveOption = event .getOption ("archive" );
36+ boolean archive = event .getOption ("archive" , true , OptionMapping :: getAsBoolean );
3937
38+ ModerationConfig config = Bot .config .get (event .getGuild ()).getModeration ();
4039 Long amount = (amountOption == null ) ? null : amountOption .getAsLong ();
4140 User user = (userOption == null ) ? null : userOption .getAsUser ();
42- boolean archive = archiveOption != null && archiveOption .getAsBoolean ();
4341 int maxAmount = config .getPurgeMaxMessageCount ();
44-
45- if (amount != null && (amount < 1 || amount > maxAmount )) {
46- return Responses .warning (event , "Invalid amount. If specified, should be between 1 and " + maxAmount + ", inclusive." );
42+ if (amount == null || amount < 1 || amount > maxAmount ) {
43+ return Responses .warning (event , "Invalid amount. Should be between 1 and " + maxAmount + ", inclusive." );
4744 }
48-
49- Bot .asyncPool .submit (() -> this .purge (amount , user , archive , event .getTextChannel (), config .getLogChannel ()));
45+ Bot .asyncPool .submit (() -> this .purge (amount , user , event .getUser (), archive , event .getTextChannel (), config .getLogChannel ()));
5046 StringBuilder sb = new StringBuilder ();
51- sb .append (amount != null ? ( amount > 1 ? "Up to " + amount + " messages " : "1 message " ) : "All messages " );
47+ sb .append (amount > 1 ? "Up to " + amount + " messages " : "1 message " );
5248 if (user != null ) {
5349 sb .append ("by the user " ).append (user .getAsTag ()).append (' ' );
5450 }
@@ -59,21 +55,24 @@ protected ReplyCallbackAction handleModerationActionCommand(SlashCommandInteract
5955 /**
6056 * Purges messages from a channel.
6157 *
62- * @param amount The number of messages to remove. If null, all messages
63- * will be removed.
64- * @param user The user whose messages to remove. If null, messages from any
65- * user are removed .
66- * @param archive Whether to create an archive file for the purge.
67- * @param channel The channel to remove messages from.
68- * @param logChannel The channel to write log messages to during the purge.
58+ * @param amount The number of messages to remove.
59+ * @param user The user whose messages to remove. If null, messages from any
60+ * user are removed.
61+ * @param initiatedBy The user which initiated the purge .
62+ * @param archive Whether to create an archive file for the purge.
63+ * @param channel The channel to remove messages from.
64+ * @param logChannel The channel to write log messages to during the purge.
6965 */
70- private void purge (@ Nullable Long amount , @ Nullable User user , boolean archive , TextChannel channel , TextChannel logChannel ) {
66+ private void purge (@ Nullable Long amount , @ Nullable User user , User initiatedBy , boolean archive , MessageChannel channel , TextChannel logChannel ) {
7167 MessageHistory history = channel .getHistory ();
72- PrintWriter archiveWriter = archive ? createArchiveWriter (channel , logChannel ) : null ;
68+ String timestamp = LocalDateTime .now ().format (DateTimeFormatter .ofPattern ("yyyy-MM-dd_HH-mm-ss" ));
69+ String file = String .format ("purge_%s_%s.txt" , channel .getName (), timestamp );
70+ PrintWriter archiveWriter = archive ? createArchiveWriter (channel , logChannel , file ) : null ;
7371 List <Message > messages ;
7472 OffsetDateTime startTime = OffsetDateTime .now ();
7573 long count = 0 ;
76- logChannel .sendMessage ("Starting purge of channel " + channel .getAsMention ()).queue ();
74+ logChannel .sendMessageFormat ("Starting purge of channel %s, initiated by %s" , channel .getAsMention (), initiatedBy .getAsMention ())
75+ .queue ();
7776 do {
7877 messages = history .retrievePast (amount == null ? 100 : (int ) Math .min (100 , amount )).complete ();
7978 if (!messages .isEmpty ()) {
@@ -90,12 +89,14 @@ private void purge(@Nullable Long amount, @Nullable User user, boolean archive,
9089 if (archiveWriter != null ) {
9190 archiveWriter .close ();
9291 }
93- logChannel .sendMessage (String .format (
92+ MessageAction action = logChannel .sendMessage (String .format (
9493 "Purge of channel %s has completed. %d messages have been removed, and the purge took %s." ,
9594 channel .getAsMention (),
9695 count ,
9796 new TimeUtils ().formatDurationToNow (startTime )
98- )).queue ();
97+ ));
98+ if (archive ) action .addFile (ARCHIVE_DIR .resolve (file ).toFile ());
99+ action .queue ();
99100 }
100101
101102 /**
@@ -128,16 +129,15 @@ private int removeMessages(List<Message> messages, @Nullable User user, @Nullabl
128129 *
129130 * @param channel The channel to create the writer for.
130131 * @param logChannel The log channel, where log messages can be sent.
132+ * @param file The archive's filename.
131133 * @return The print writer to use.
132134 */
133- private PrintWriter createArchiveWriter (TextChannel channel , TextChannel logChannel ) {
135+ private PrintWriter createArchiveWriter (MessageChannel channel , TextChannel logChannel , String file ) {
134136 try {
135- Path purgeArchivesDir = Path .of ("purgeArchives" );
136- if (Files .notExists (purgeArchivesDir )) Files .createDirectory (purgeArchivesDir );
137- String timestamp = LocalDateTime .now ().format (DateTimeFormatter .ofPattern ("yyyy-MM-dd_HH-mm-ss" ));
138- Path archiveFile = purgeArchivesDir .resolve ("purge_" + channel .getName () + "_" + timestamp + ".txt" );
137+ if (Files .notExists (ARCHIVE_DIR )) Files .createDirectory (ARCHIVE_DIR );
138+ Path archiveFile = ARCHIVE_DIR .resolve (file );
139139 var archiveWriter = new PrintWriter (Files .newBufferedWriter (archiveFile ), true );
140- logChannel .sendMessage ("Created archive of purge of channel " + channel .getAsMention () + " at " + archiveFile ).queue ();
140+ logChannel .sendMessageFormat ("Created archive of purge of channel %s at `%s`" , channel .getAsMention (), archiveFile ).queue ();
141141 archiveWriter .println ("Purge of channel " + channel .getName ());
142142 return archiveWriter ;
143143 } catch (IOException e ) {
0 commit comments