Skip to content
This repository was archived by the owner on Dec 1, 2021. It is now read-only.

Commit 8b127bc

Browse files
committed
Added ban command and improvements to moderation service.
1 parent 87c7cad commit 8b127bc

File tree

5 files changed

+93
-13
lines changed

5 files changed

+93
-13
lines changed

src/main/java/net/javadiscord/javabot2/command/ResponseException.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,13 @@ public static Supplier<ResponseException> warning(String message) {
4545
public static Supplier<ResponseException> error(String message) {
4646
return () -> new ResponseException(Responses.deferredErrorBuilder().message(message));
4747
}
48+
49+
/**
50+
* Standard helper method to generate a supplier of a response exception
51+
* with a simple "invalid argument" warning message.
52+
* @return The exception supplier.
53+
*/
54+
public static Supplier<ResponseException> invalidArgument() {
55+
return () -> new ResponseException(Responses.deferredWarningBuilder().message("Invalid argument."));
56+
}
4857
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package net.javadiscord.javabot2.systems.moderation;
2+
3+
import net.javadiscord.javabot2.Bot;
4+
import net.javadiscord.javabot2.command.ResponseException;
5+
import net.javadiscord.javabot2.command.Responses;
6+
import net.javadiscord.javabot2.command.SlashCommandHandler;
7+
import org.javacord.api.entity.user.User;
8+
import org.javacord.api.interaction.SlashCommandInteraction;
9+
import org.javacord.api.interaction.callback.InteractionImmediateResponseBuilder;
10+
11+
/**
12+
* Command which is used to ban naughty users.
13+
*/
14+
public class BanCommand implements SlashCommandHandler {
15+
@Override
16+
public InteractionImmediateResponseBuilder handle(SlashCommandInteraction interaction) throws ResponseException {
17+
User user = interaction.getOptionUserValueByName("user")
18+
.orElseThrow(ResponseException.warning("User is required."));
19+
String reason = interaction.getOptionStringValueByName("reason")
20+
.orElseThrow(ResponseException.warning("Reason is required."));
21+
var channel = interaction.getChannel()
22+
.orElseThrow(ResponseException.warning("This command can only be performed in a channel."))
23+
.asServerTextChannel()
24+
.orElseThrow(ResponseException.warning("This command can only be performed in a server text channel."));
25+
var moderationService = new ModerationService(interaction.getApi(), Bot.mongoDb, Bot.config.get(channel.getServer()).getModeration());
26+
moderationService.ban(user, reason, interaction.getUser(), channel);
27+
return Responses.successBuilder(interaction)
28+
.title("User Banned")
29+
.messageFormat("User %s has been banned.", user.getMentionTag())
30+
.build();
31+
}
32+
}

src/main/java/net/javadiscord/javabot2/systems/moderation/ModerationService.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.mongodb.client.FindIterable;
55
import com.mongodb.client.MongoDatabase;
66
import com.mongodb.client.model.Filters;
7-
import net.javadiscord.javabot2.Bot;
87
import net.javadiscord.javabot2.config.guild.ModerationConfig;
98
import net.javadiscord.javabot2.systems.moderation.model.WarnSeverity;
109
import org.bson.Document;
@@ -17,6 +16,7 @@
1716
import java.time.Instant;
1817
import java.time.OffsetDateTime;
1918
import java.util.Map;
19+
import java.util.concurrent.CompletableFuture;
2020

2121
/**
2222
* This service provides methods for performing moderation actions, like banning
@@ -48,8 +48,9 @@ public ModerationService(DiscordApi api, MongoDatabase db, ModerationConfig conf
4848
* @param reason The reason for this warning.
4949
* @param warnedBy The user who issued the warning.
5050
* @param channel The channel in which the warning was issued.
51+
* @return A future that completes when all warn operations are complete.
5152
*/
52-
public void warn(User user, WarnSeverity severity, String reason, User warnedBy, ServerTextChannel channel) {
53+
public CompletableFuture<Void> warn(User user, WarnSeverity severity, String reason, User warnedBy, ServerTextChannel channel) {
5354
var warns = db.getCollection("warn");
5455
Instant now = Instant.now();
5556
warns.insertOne(new Document(Map.of(
@@ -64,13 +65,12 @@ public void warn(User user, WarnSeverity severity, String reason, User warnedBy,
6465
totalSeverity += WarnSeverity.getWeightOrDefault(warnDoc.getString("severity"));
6566
}
6667
var warnEmbed = buildWarnEmbed(user, severity, reason, warnedBy, now, totalSeverity);
67-
Bot.asyncPool.submit(() -> {
68-
user.openPrivateChannel().thenAcceptAsync(privateChannel -> privateChannel.sendMessage(warnEmbed));
69-
channel.sendMessage(warnEmbed);
70-
});
68+
var future = channel.sendMessage(warnEmbed)
69+
.thenComposeAsync(unused -> user.openPrivateChannel().thenAcceptAsync(privateChannel -> privateChannel.sendMessage(warnEmbed)));
7170
if (totalSeverity > config.getMaxWarnSeverity()) {
72-
ban(user, "Too many warnings.", warnedBy, channel);
71+
return future.thenComposeAsync(unused -> ban(user, "Too many warnings.", warnedBy, channel));
7372
}
73+
return future;
7474
}
7575

7676
/**
@@ -79,15 +79,19 @@ public void warn(User user, WarnSeverity severity, String reason, User warnedBy,
7979
* @param reason The reason for banning the user.
8080
* @param bannedBy The user who is responsible for banning this user.
8181
* @param channel The channel in which the ban was issued.
82+
* @return A future that completes once all ban operations are done.
8283
*/
83-
public void ban(User user, String reason, User bannedBy, ServerTextChannel channel) {
84+
public CompletableFuture<Void> ban(User user, String reason, User bannedBy, ServerTextChannel channel) {
8485
var banEmbed = buildBanEmbed(user, reason, bannedBy);
85-
Bot.asyncPool.submit(() -> {
86-
channel.sendMessage(banEmbed);
87-
user.openPrivateChannel()
86+
if (channel.getServer().canBanUser(bannedBy, user)) {
87+
return channel.getServer().banUser(user, BAN_DELETE_DAYS, reason)
88+
.thenComposeAsync(unused -> user.openPrivateChannel())
8889
.thenComposeAsync(privateChannel -> privateChannel.sendMessage(banEmbed))
89-
.thenRunAsync(() -> channel.getServer().banUser(user, BAN_DELETE_DAYS, reason));
90-
});
90+
.thenComposeAsync(unused -> channel.sendMessage(banEmbed))
91+
.thenApply(msg -> null);
92+
} else {
93+
return CompletableFuture.failedFuture(new PermissionException("You don't have permission to ban this user."));
94+
}
9195
}
9296

9397
private FindIterable<Document> findActiveWarns(User user) {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package net.javadiscord.javabot2.systems.moderation;
2+
3+
/**
4+
* An exception that's thrown when a user doesn't have permission to do something.
5+
*/
6+
public class PermissionException extends Exception {
7+
/**
8+
* Constructs a new exception with the specified detail message. The
9+
* cause is not initialized, and may subsequently be initialized by
10+
* a call to {@link #initCause}.
11+
*
12+
* @param message the detail message. The detail message is saved for
13+
* later retrieval by the {@link #getMessage()} method.
14+
*/
15+
public PermissionException(String message) {
16+
super(message);
17+
}
18+
}

src/main/resources/commands/moderation.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,20 @@
4242
description: The reason for this user's warning.
4343
type: STRING
4444
required: true
45+
46+
- name: ban
47+
description: Ban a user.
48+
handler: net.javadiscord.javabot2.systems.moderation.BanCommand
49+
enabledByDefault: false
50+
privileges:
51+
- type: ROLE
52+
id: moderation.staffRoleId
53+
options:
54+
- name: user
55+
description: The user to ban.
56+
type: USER
57+
required: true
58+
- name: reason
59+
description: The reason for banning this user.
60+
type: STRING
61+
required: true

0 commit comments

Comments
 (0)