Skip to content

Commit 616a0e8

Browse files
committed
Reduced code duplication
* moved temporary data computation into util
1 parent 18347fa commit 616a0e8

3 files changed

Lines changed: 58 additions & 86 deletions

File tree

application/src/main/java/org/togetherjava/tjbot/commands/moderation/BanCommand.java

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.togetherjava.tjbot.config.Config;
2424

2525
import java.time.Instant;
26-
import java.time.temporal.ChronoUnit;
2726
import java.util.List;
2827
import java.util.Objects;
2928
import java.util.Optional;
@@ -46,9 +45,8 @@ public final class BanCommand extends SlashCommandAdapter {
4645
private static final String REASON_OPTION = "reason";
4746
private static final String COMMAND_NAME = "ban";
4847
private static final String ACTION_VERB = "ban";
49-
private static final String PERMANENT_DURATION = "permanent";
50-
private static final List<String> DURATIONS = List.of(PERMANENT_DURATION, "1 hour", "3 hours",
51-
"1 day", "2 days", "3 days", "7 days", "30 days");
48+
private static final List<String> DURATIONS = List.of(ModerationUtils.PERMANENT_DURATION,
49+
"1 hour", "3 hours", "1 day", "2 days", "3 days", "7 days", "30 days");
5250
private final Predicate<String> hasRequiredRole;
5351
private final ModerationActionsStore actionsStore;
5452

@@ -88,10 +86,10 @@ private static RestAction<InteractionHook> handleAlreadyBanned(@NotNull Guild.Ba
8886
}
8987

9088
private static RestAction<Boolean> sendDm(@NotNull ISnowflake target,
91-
@Nullable TemporaryBanData temporaryBanData, @NotNull String reason,
89+
@Nullable ModerationUtils.TemporaryData temporaryData, @NotNull String reason,
9290
@NotNull Guild guild, @NotNull GenericEvent event) {
9391
String durationMessage =
94-
temporaryBanData == null ? "permanently" : "for " + temporaryBanData.duration;
92+
temporaryData == null ? "permanently" : "for " + temporaryData.duration();
9593
String dmMessage =
9694
"""
9795
Hey there, sorry to tell you but unfortunately you have been banned %s from the server %s.
@@ -108,12 +106,10 @@ private static RestAction<Boolean> sendDm(@NotNull ISnowflake target,
108106
}
109107

110108
private static @NotNull MessageEmbed sendFeedback(boolean hasSentDm, @NotNull User target,
111-
@NotNull Member author, @Nullable TemporaryBanData temporaryBanData,
109+
@NotNull Member author, @Nullable ModerationUtils.TemporaryData temporaryData,
112110
@NotNull String reason) {
113-
@SuppressWarnings("java:S1192") // this is not the name of the option but the user-friendly
114-
// display text
115111
String durationText = "The ban duration is: "
116-
+ (temporaryBanData == null ? "permanent" : temporaryBanData.duration);
112+
+ (temporaryData == null ? "permanent" : temporaryData.duration());
117113
String dmNoticeText = "";
118114
if (!hasSentDm) {
119115
dmNoticeText = "\n(Unable to send them a DM.)";
@@ -145,48 +141,28 @@ private static Optional<RestAction<InteractionHook>> handleNotAlreadyBannedRespo
145141
.setEphemeral(true));
146142
}
147143

148-
private static @NotNull Optional<TemporaryBanData> computeTemporaryBanData(
149-
@NotNull String durationText) {
150-
if (PERMANENT_DURATION.equals(durationText)) {
151-
return Optional.empty();
152-
}
153-
154-
// 1 minute, 1 day, 2 days, ...
155-
String[] data = durationText.split(" ", 2);
156-
int duration = Integer.parseInt(data[0]);
157-
ChronoUnit unit = switch (data[1]) {
158-
case "minute", "minutes" -> ChronoUnit.MINUTES;
159-
case "hour", "hours" -> ChronoUnit.HOURS;
160-
case "day", "days" -> ChronoUnit.DAYS;
161-
default -> throw new IllegalArgumentException(
162-
"Unsupported ban duration: " + durationText);
163-
};
164-
165-
return Optional.of(new TemporaryBanData(Instant.now().plus(duration, unit), durationText));
166-
}
167-
168144
@SuppressWarnings("MethodWithTooManyParameters")
169145
private RestAction<InteractionHook> banUserFlow(@NotNull User target, @NotNull Member author,
170-
@Nullable TemporaryBanData temporaryBanData, @NotNull String reason,
146+
@Nullable ModerationUtils.TemporaryData temporaryData, @NotNull String reason,
171147
int deleteHistoryDays, @NotNull Guild guild, @NotNull SlashCommandEvent event) {
172-
return sendDm(target, temporaryBanData, reason, guild, event)
173-
.flatMap(hasSentDm -> banUser(target, author, temporaryBanData, reason,
174-
deleteHistoryDays, guild).map(banResult -> hasSentDm))
175-
.map(hasSentDm -> sendFeedback(hasSentDm, target, author, temporaryBanData, reason))
148+
return sendDm(target, temporaryData, reason, guild, event)
149+
.flatMap(hasSentDm -> banUser(target, author, temporaryData, reason, deleteHistoryDays,
150+
guild).map(banResult -> hasSentDm))
151+
.map(hasSentDm -> sendFeedback(hasSentDm, target, author, temporaryData, reason))
176152
.flatMap(event::replyEmbeds);
177153
}
178154

179155
private AuditableRestAction<Void> banUser(@NotNull User target, @NotNull Member author,
180-
@Nullable TemporaryBanData temporaryBanData, @NotNull String reason,
156+
@Nullable ModerationUtils.TemporaryData temporaryData, @NotNull String reason,
181157
int deleteHistoryDays, @NotNull Guild guild) {
182158
String durationMessage =
183-
temporaryBanData == null ? "permanently" : "for " + temporaryBanData.duration;
159+
temporaryData == null ? "permanently" : "for " + temporaryData.duration();
184160
logger.info(
185161
"'{}' ({}) banned the user '{}' ({}) {} from guild '{}' and deleted their message history of the last {} days, for reason '{}'.",
186162
author.getUser().getAsTag(), author.getId(), target.getAsTag(), target.getId(),
187163
durationMessage, guild.getName(), deleteHistoryDays, reason);
188164

189-
Instant expiresAt = temporaryBanData == null ? null : temporaryBanData.unbanTime;
165+
Instant expiresAt = temporaryData == null ? null : temporaryData.expiresAt();
190166
actionsStore.addAction(guild.getIdLong(), author.getIdLong(), target.getIdLong(),
191167
ModerationAction.BAN, expiresAt, reason);
192168

@@ -230,7 +206,8 @@ public void onSlashCommand(@NotNull SlashCommandEvent event) {
230206

231207
Guild guild = Objects.requireNonNull(event.getGuild());
232208
Member bot = guild.getSelfMember();
233-
Optional<TemporaryBanData> temporaryBanData = computeTemporaryBanData(duration);
209+
Optional<ModerationUtils.TemporaryData> temporaryData =
210+
ModerationUtils.computeTemporaryData(duration);
234211

235212
if (!handleChecks(bot, author, targetOption.getAsMember(), reason, guild, event)) {
236213
return;
@@ -247,12 +224,8 @@ public void onSlashCommand(@NotNull SlashCommandEvent event) {
247224

248225
return handleNotAlreadyBannedResponse(
249226
Objects.requireNonNull(alreadyBanned.getFailure()), event, guild, target)
250-
.orElseGet(() -> banUserFlow(target, author, temporaryBanData.orElse(null),
227+
.orElseGet(() -> banUserFlow(target, author, temporaryData.orElse(null),
251228
reason, deleteHistoryDays, guild, event));
252229
}).queue();
253230
}
254-
255-
256-
private record TemporaryBanData(@NotNull Instant unbanTime, @NotNull String duration) {
257-
}
258231
}

application/src/main/java/org/togetherjava/tjbot/commands/moderation/ModerationUtils.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
import java.awt.*;
1414
import java.time.Instant;
15+
import java.time.temporal.ChronoUnit;
16+
import java.time.temporal.TemporalUnit;
1517
import java.util.Optional;
1618
import java.util.function.Predicate;
1719
import java.util.regex.Pattern;
@@ -28,7 +30,10 @@ public enum ModerationUtils {
2830
* {@link Guild#ban(User, int, String)}.
2931
*/
3032
private static final int REASON_MAX_LENGTH = 512;
33+
// FIXME Javadoc
34+
static final String PERMANENT_DURATION = "permanent";
3135
static final Color AMBIENT_COLOR = Color.decode("#895FE8");
36+
// FIXME Javadoc
3237
public static final Predicate<String> isMuteRole =
3338
Pattern.compile(Config.getInstance().getMutedRolePattern()).asMatchPredicate();
3439

@@ -326,4 +331,25 @@ static boolean handleHasAuthorRole(@NotNull String actionVerb,
326331
return guild.getRoles().stream().filter(role -> isMuteRole.test(role.getName())).findAny();
327332
}
328333

334+
static @NotNull Optional<TemporaryData> computeTemporaryData(@NotNull String durationText) {
335+
if (PERMANENT_DURATION.equals(durationText)) {
336+
return Optional.empty();
337+
}
338+
339+
// 1 minute, 1 day, 2 days, ...
340+
String[] data = durationText.split(" ", 2);
341+
int duration = Integer.parseInt(data[0]);
342+
ChronoUnit unit = switch (data[1]) {
343+
case "minute", "minutes" -> ChronoUnit.MINUTES;
344+
case "hour", "hours" -> ChronoUnit.HOURS;
345+
case "day", "days" -> ChronoUnit.DAYS;
346+
default -> throw new IllegalArgumentException(
347+
"Unsupported mute duration: " + durationText);
348+
};
349+
350+
return Optional.of(new TemporaryData(Instant.now().plus(duration, unit), durationText));
351+
}
352+
353+
record TemporaryData(@NotNull Instant expiresAt, @NotNull String duration) {
354+
}
329355
}

application/src/main/java/org/togetherjava/tjbot/commands/moderation/MuteCommand.java

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import org.togetherjava.tjbot.config.Config;
1919

2020
import java.time.Instant;
21-
import java.time.temporal.ChronoUnit;
2221
import java.util.List;
2322
import java.util.Objects;
2423
import java.util.Optional;
@@ -39,9 +38,8 @@ public final class MuteCommand extends SlashCommandAdapter {
3938
private static final String REASON_OPTION = "reason";
4039
private static final String COMMAND_NAME = "mute";
4140
private static final String ACTION_VERB = "mute";
42-
private static final String PERMANENT_DURATION = "permanent";
4341
private static final List<String> DURATIONS = List.of("10 minutes", "30 minutes", "1 hour",
44-
"3 hours", "1 day", "3 days", "7 days", PERMANENT_DURATION);
42+
"3 hours", "1 day", "3 days", "7 days", ModerationUtils.PERMANENT_DURATION);
4543
private final Predicate<String> hasRequiredRole;
4644
private final ModerationActionsStore actionsStore;
4745

@@ -72,10 +70,10 @@ private static void handleAlreadyMutedTarget(@NotNull Interaction event) {
7270
}
7371

7472
private static RestAction<Boolean> sendDm(@NotNull ISnowflake target,
75-
@Nullable TemporaryMuteData temporaryMuteData, @NotNull String reason,
73+
@Nullable ModerationUtils.TemporaryData temporaryData, @NotNull String reason,
7674
@NotNull Guild guild, @NotNull GenericEvent event) {
7775
String durationMessage =
78-
temporaryMuteData == null ? "permanently" : "for " + temporaryMuteData.duration;
76+
temporaryData == null ? "permanently" : "for " + temporaryData.duration();
7977
String dmMessage =
8078
"""
8179
Hey there, sorry to tell you but unfortunately you have been muted %s in the server %s.
@@ -92,12 +90,10 @@ private static RestAction<Boolean> sendDm(@NotNull ISnowflake target,
9290
}
9391

9492
private static @NotNull MessageEmbed sendFeedback(boolean hasSentDm, @NotNull Member target,
95-
@NotNull Member author, @Nullable TemporaryMuteData temporaryMuteData,
93+
@NotNull Member author, @Nullable ModerationUtils.TemporaryData temporaryData,
9694
@NotNull String reason) {
97-
@SuppressWarnings("java:S1192") // this is not the name of the option but the user-friendly
98-
// display text
9995
String durationText = "The mute duration is: "
100-
+ (temporaryMuteData == null ? "permanent" : temporaryMuteData.duration);
96+
+ (temporaryData == null ? "permanent" : temporaryData.duration());
10197
String dmNoticeText = "";
10298
if (!hasSentDm) {
10399
dmNoticeText = "\n(Unable to send them a DM.)";
@@ -106,37 +102,16 @@ private static RestAction<Boolean> sendDm(@NotNull ISnowflake target,
106102
target.getUser(), durationText + dmNoticeText, reason);
107103
}
108104

109-
// FIXME Code duplication with BanCommand, get rid of it
110-
private static @NotNull Optional<TemporaryMuteData> computeTemporaryMuteData(
111-
@NotNull String durationText) {
112-
if (PERMANENT_DURATION.equals(durationText)) {
113-
return Optional.empty();
114-
}
115-
116-
// 1 minute, 1 day, 2 days, ...
117-
String[] data = durationText.split(" ", 2);
118-
int duration = Integer.parseInt(data[0]);
119-
ChronoUnit unit = switch (data[1]) {
120-
case "minute", "minutes" -> ChronoUnit.MINUTES;
121-
case "hour", "hours" -> ChronoUnit.HOURS;
122-
case "day", "days" -> ChronoUnit.DAYS;
123-
default -> throw new IllegalArgumentException(
124-
"Unsupported mute duration: " + durationText);
125-
};
126-
127-
return Optional.of(new TemporaryMuteData(Instant.now().plus(duration, unit), durationText));
128-
}
129-
130105
private AuditableRestAction<Void> muteUser(@NotNull Member target, @NotNull Member author,
131-
@Nullable TemporaryMuteData temporaryMuteData, @NotNull String reason,
106+
@Nullable ModerationUtils.TemporaryData temporaryData, @NotNull String reason,
132107
@NotNull Guild guild) {
133108
String durationMessage =
134-
temporaryMuteData == null ? "permanently" : "for " + temporaryMuteData.duration;
109+
temporaryData == null ? "permanently" : "for " + temporaryData.duration();
135110
logger.info("'{}' ({}) muted the user '{}' ({}) {} in guild '{}' for reason '{}'.",
136111
author.getUser().getAsTag(), author.getId(), target.getUser().getAsTag(),
137112
target.getId(), durationMessage, guild.getName(), reason);
138113

139-
Instant expiresAt = temporaryMuteData == null ? null : temporaryMuteData.unmuteTime;
114+
Instant expiresAt = temporaryData == null ? null : temporaryData.expiresAt();
140115
actionsStore.addAction(guild.getIdLong(), author.getIdLong(), target.getIdLong(),
141116
ModerationAction.MUTE, expiresAt, reason);
142117

@@ -145,12 +120,12 @@ private AuditableRestAction<Void> muteUser(@NotNull Member target, @NotNull Memb
145120
}
146121

147122
private void muteUserFlow(@NotNull Member target, @NotNull Member author,
148-
@Nullable TemporaryMuteData temporaryMuteData, @NotNull String reason,
123+
@Nullable ModerationUtils.TemporaryData temporaryData, @NotNull String reason,
149124
@NotNull Guild guild, @NotNull SlashCommandEvent event) {
150-
sendDm(target, temporaryMuteData, reason, guild, event)
151-
.flatMap(hasSentDm -> muteUser(target, author, temporaryMuteData, reason, guild)
125+
sendDm(target, temporaryData, reason, guild, event)
126+
.flatMap(hasSentDm -> muteUser(target, author, temporaryData, reason, guild)
152127
.map(banResult -> hasSentDm))
153-
.map(hasSentDm -> sendFeedback(hasSentDm, target, author, temporaryMuteData, reason))
128+
.map(hasSentDm -> sendFeedback(hasSentDm, target, author, temporaryData, reason))
154129
.flatMap(event::replyEmbeds)
155130
.queue();
156131
}
@@ -188,16 +163,14 @@ public void onSlashCommand(@NotNull SlashCommandEvent event) {
188163

189164
Guild guild = Objects.requireNonNull(event.getGuild());
190165
Member bot = guild.getSelfMember();
191-
Optional<TemporaryMuteData> temporaryMuteData = computeTemporaryMuteData(duration);
166+
Optional<ModerationUtils.TemporaryData> temporaryData =
167+
ModerationUtils.computeTemporaryData(duration);
192168

193169
if (!handleChecks(bot, author, target, reason, guild, event)) {
194170
return;
195171
}
196172

197-
muteUserFlow(Objects.requireNonNull(target), author, temporaryMuteData.orElse(null), reason,
173+
muteUserFlow(Objects.requireNonNull(target), author, temporaryData.orElse(null), reason,
198174
guild, event);
199175
}
200-
201-
private record TemporaryMuteData(@NotNull Instant unmuteTime, @NotNull String duration) {
202-
}
203176
}

0 commit comments

Comments
 (0)