Skip to content

Commit 683de21

Browse files
authored
Slash commands for moderation (#306)
* WIP slash commands for moderation * Run commands on own thread Implement list for blacklist * Clear black list * Adding to the blacklist * Remove blacklisted word * Finish blacklist command * Adding and listing vc autoroles * Add vcautorole command to slash support * Lint * Move dehoist command to slash support * Convert slowmode command * Convert warn command * Lint code * Convert warnings command * convert announce command * Implemeht slash method in all new mod commands
1 parent 33bd681 commit 683de21

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1381
-206
lines changed

bot/src/main/java/me/duncte123/skybot/CommandManager.java

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import me.duncte123.skybot.commands.utils.EnlargeCommand;
5858
import me.duncte123.skybot.commands.utils.RoleInfoCommand;
5959
import me.duncte123.skybot.commands.weeb.*;
60+
import me.duncte123.skybot.entities.jda.DunctebotGuild;
6061
import me.duncte123.skybot.objects.SlashSupport;
6162
import me.duncte123.skybot.objects.command.*;
6263
import me.duncte123.skybot.objects.pairs.LongLongPair;
@@ -745,29 +746,48 @@ public List<SlashCommandData> getAllSlashCommands() {
745746
}
746747

747748
public void executeSlashCommand(SlashCommandInteractionEvent event) {
748-
final String fullCommandName = event.getFullCommandName();
749+
this.commandThread.submit(() -> {
750+
try {
751+
MDC.put("command.invoke", event.getFullCommandName());
752+
MDC.put("user.tag", event.getUser().getAsTag());
753+
MDC.put("user.name", event.getUser().getEffectiveName());
754+
MDC.put("user.id", event.getUser().getId());
755+
MDC.put("guild", event.isFromGuild() ? event.getGuild().toString() : "(not in guild)");
756+
setJDAContext(event.getJDA());
749757

750-
if (fullCommandName.startsWith("music")) {
751-
final String musicName = fullCommandName.replace("music", "").trim();
752-
final MusicCommand command = (MusicCommand) this.getCommand(musicName);
758+
final var guild = new DunctebotGuild(event.getGuild(), variables);
753759

754-
if (command != null) {
755-
command.handleEvent(event, variables);
756-
}
760+
final String fullCommandName = event.getFullCommandName();
757761

758-
return;
759-
}
762+
if (fullCommandName.startsWith("music")) {
763+
final String musicName = fullCommandName.replace("music", "").trim();
764+
final MusicCommand command = (MusicCommand) this.getCommand(musicName);
760765

761-
try {
762-
final SlashSupport command = (SlashSupport) this.getCommand(event.getName());
766+
if (command != null) {
767+
command.handleEvent(event, guild, variables);
768+
}
769+
770+
return;
771+
}
763772

764-
if (command != null) {
765-
command.executeEventWithChecks(event, variables);
773+
final SlashSupport command = (SlashSupport) this.getCommand(event.getName());
774+
775+
if (command != null) {
776+
command.executeEventWithChecks(event, guild, variables);
777+
}
766778
}
767-
}
768-
catch (Exception e) {
769-
e.printStackTrace();
770-
}
779+
catch (Exception e) {
780+
event.reply(
781+
"Failed to run command: %s\nPlease join [my discord server](https://duncte.bot/discord) if this happens a lot.".formatted(
782+
e.getMessage()
783+
)
784+
).queue();
785+
LOGGER.error(
786+
"Error in '%s'".formatted(event.getCommandString()),
787+
e
788+
);
789+
}
790+
});
771791
}
772792

773793
private static long calcTimeRemaining(long startTime) {

bot/src/main/java/me/duncte123/skybot/commands/guild/mod/AnnounceCommand.java

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@
2020

2121
import me.duncte123.botcommons.messaging.EmbedUtils;
2222
import me.duncte123.botcommons.messaging.MessageConfig;
23-
import me.duncte123.skybot.extensions.StringKt;
23+
import me.duncte123.skybot.Variables;
24+
import me.duncte123.skybot.entities.jda.DunctebotGuild;
2425
import me.duncte123.skybot.objects.command.CommandCategory;
2526
import me.duncte123.skybot.objects.command.CommandContext;
2627
import me.duncte123.skybot.objects.command.Flag;
2728
import net.dv8tion.jda.api.EmbedBuilder;
2829
import net.dv8tion.jda.api.Permission;
29-
import net.dv8tion.jda.api.entities.Message;
30-
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
30+
import net.dv8tion.jda.api.entities.channel.ChannelType;
31+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
32+
import net.dv8tion.jda.api.interactions.commands.OptionType;
33+
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
34+
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
35+
import org.jetbrains.annotations.NotNull;
3136

3237
import javax.annotation.Nonnull;
33-
import java.util.List;
3438

35-
import static me.duncte123.botcommons.messaging.MessageUtils.*;
39+
import static me.duncte123.botcommons.messaging.MessageUtils.sendMsg;
3640

3741
public class AnnounceCommand extends ModBaseCommand {
3842

@@ -59,66 +63,110 @@ public AnnounceCommand() {
5963
}
6064

6165
@Override
62-
public void execute(@Nonnull CommandContext ctx) {
63-
final List<GuildMessageChannel> mentioned = ctx.getMessage().getMentions().getChannels(GuildMessageChannel.class);
66+
protected void configureSlashSupport(@NotNull SlashCommandData baseData) {
67+
baseData.addOptions(
68+
new OptionData(
69+
OptionType.CHANNEL,
70+
"channel",
71+
"Channel to send the message to",
72+
true
73+
),
74+
new OptionData(
75+
OptionType.STRING,
76+
"message",
77+
"The message to send",
78+
true
79+
),
80+
new OptionData(
81+
OptionType.ATTACHMENT,
82+
"image",
83+
"An image to send in the embed",
84+
false
85+
),
86+
new OptionData(
87+
OptionType.BOOLEAN,
88+
"embed",
89+
"Use an embed instead of plain text (defaults to true)",
90+
false
91+
),
92+
new OptionData(
93+
OptionType.BOOLEAN,
94+
"thumbnail",
95+
"Set the image as a thumbnail instead of a large image",
96+
false
97+
)
98+
);
99+
}
64100

65-
if (mentioned.isEmpty()) {
66-
sendMsg(ctx, "You did not specify a channel, usage: " + this.getUsageInstructions(ctx));
101+
@Override
102+
public void handleEvent(@NotNull SlashCommandInteractionEvent event, @NotNull DunctebotGuild guild, @NotNull Variables variables) {
103+
final var channel = event.getOption("channel").getAsChannel();
67104

105+
if (channel.getType() != ChannelType.TEXT) {
106+
event.reply("That channel is not a text channel!").queue();
68107
return;
69108
}
70109

71-
final GuildMessageChannel targetChannel = mentioned.get(0);
110+
final var txtChan = channel.asGuildMessageChannel();
72111

73-
if (!targetChannel.canTalk()) {
74-
sendErrorWithMessage(ctx.getMessage(), "I can not talk in " + targetChannel.getAsMention());
112+
if (!txtChan.canTalk()) {
113+
event.reply("I can't talk in that channel").queue();
75114
return;
76115
}
77116

78-
final var flags = ctx.getParsedFlags(this);
79-
final List<String> text = flags.get("undefined");
117+
final var message = event.getOption("message").getAsString();
80118

81-
if (text.isEmpty()) {
82-
this.sendUsageInstructions(ctx);
83-
return;
84-
}
119+
final var useEmbedOption = event.getOption("embed");
120+
final var useEmbed = useEmbedOption == null || useEmbedOption.getAsBoolean();
85121

86-
final String msg = StringKt.stripFlags(
87-
ctx.getArgsRaw()
88-
.replace(targetChannel.getAsMention(), ""),
89-
this
90-
);
122+
if (!useEmbed) {
123+
event.reply("Sending message.....").queue();
91124

92-
if (flags.containsKey("noembed")) {
93125
sendMsg(
94126
new MessageConfig.Builder()
95-
.setChannel(targetChannel)
96-
.setMessage(msg)
127+
.setChannel(txtChan)
128+
.setMessage(message)
129+
.setSuccessAction((msg) -> {
130+
event.getHook()
131+
.editOriginal("Message sent: " + msg.getJumpUrl())
132+
.queue();
133+
})
97134
);
98-
sendSuccess(ctx.getMessage());
99-
100135
return;
101136
}
102137

138+
final EmbedBuilder embed = EmbedUtils.getDefaultEmbed()
139+
.setDescription(message)
140+
.setFooter(null, "");
103141

104-
final EmbedBuilder embed = EmbedUtils.getDefaultEmbed().setDescription(msg).setFooter(null, "");
105-
final List<Message.Attachment> attachments = ctx.getMessage().getAttachments();
142+
final var attachmentOption = event.getOption("image");
143+
final var useThumbOption = event.getOption("thumbnail");
106144

107-
if (!attachments.isEmpty()) {
108-
attachments.stream().filter(Message.Attachment::isImage).findFirst().ifPresent((attachment) -> {
109-
if (flags.containsKey("thumbnail")) {
110-
embed.setThumbnail(attachment.getUrl());
111-
} else {
112-
embed.setImage(attachment.getUrl());
113-
}
114-
});
145+
// TODO: download the attachment??
146+
if (attachmentOption != null) {
147+
if (useThumbOption != null && useThumbOption.getAsBoolean()) {
148+
embed.setThumbnail(attachmentOption.getAsAttachment().getUrl());
149+
} else {
150+
embed.setImage(attachmentOption.getAsAttachment().getUrl());
151+
}
115152
}
116153

154+
event.reply("Sending message.....").queue();
155+
117156
sendMsg(new MessageConfig.Builder()
118-
.setChannel(targetChannel)
157+
.setChannel(txtChan)
119158
.addEmbed(embed)
159+
.setSuccessAction((msg) -> {
160+
event.getHook()
161+
.editOriginal("Message sent: " + msg.getJumpUrl())
162+
.queue();
163+
})
120164
.build());
121165

122-
sendSuccess(ctx.getMessage());
166+
}
167+
168+
@Override
169+
public void execute(@Nonnull CommandContext ctx) {
170+
sendMsg(ctx, "Guess what! Even this is a slash command now!");
123171
}
124172
}

bot/src/main/java/me/duncte123/skybot/commands/guild/mod/AutoBanBypassCommand.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818

1919
package me.duncte123.skybot.commands.guild.mod;
2020

21+
import me.duncte123.skybot.Variables;
2122
import me.duncte123.skybot.database.AbstractDatabase;
23+
import me.duncte123.skybot.entities.jda.DunctebotGuild;
2224
import me.duncte123.skybot.objects.command.CommandContext;
25+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
26+
import net.dv8tion.jda.api.interactions.commands.OptionType;
27+
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
28+
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
2329
import net.dv8tion.jda.api.utils.MiscUtil;
2430
import org.jetbrains.annotations.NotNull;
2531

@@ -33,6 +39,49 @@ public AutoBanBypassCommand() {
3339
this.usage = "<user id>";
3440
}
3541

42+
@Override
43+
protected void configureSlashSupport(@NotNull SlashCommandData baseData) {
44+
baseData.addOptions(
45+
new OptionData(
46+
OptionType.USER,
47+
"user_id",
48+
"The id of the user that you want to create the bypass for.",
49+
true
50+
)
51+
);
52+
}
53+
54+
@Override
55+
public void handleEvent(@NotNull SlashCommandInteractionEvent event, @NotNull DunctebotGuild guild, @NotNull Variables variables) {
56+
final var checkId = event.getOption("user_id").getAsLong();
57+
58+
final var database = variables.getDatabase();
59+
final var guildId = event.getGuild().getIdLong();
60+
61+
event.deferReply().queue();
62+
63+
database.getBanBypass(guildId, checkId).thenAccept((byPass) -> {
64+
if (byPass == null) {
65+
database.createBanBypass(guildId, checkId);
66+
event.getHook()
67+
.editOriginal("Single use bypass created, please note that this bypass will expire after a week if unused." +
68+
"\nPlease keep in mind that this has not unbanned any user, meaning that you will have to unban the user yourself if they are banned")
69+
.queue();
70+
return;
71+
}
72+
73+
event.getHook()
74+
.editOriginal("A bypass already exists for this user")
75+
.queue();
76+
}).exceptionally((thr) -> {
77+
event.getHook()
78+
.editOriginal("Something went wrong: " + thr.getMessage())
79+
.queue();
80+
81+
return null;
82+
});
83+
}
84+
3685
@Override
3786
public void execute(@NotNull CommandContext ctx) {
3887
final long checkId;

bot/src/main/java/me/duncte123/skybot/commands/guild/mod/BanCommand.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,23 @@
1818

1919
package me.duncte123.skybot.commands.guild.mod;
2020

21+
import me.duncte123.skybot.Variables;
22+
import me.duncte123.skybot.entities.jda.DunctebotGuild;
2123
import me.duncte123.skybot.objects.command.CommandContext;
2224
import me.duncte123.skybot.objects.command.Flag;
2325
import net.dv8tion.jda.api.Permission;
2426
import net.dv8tion.jda.api.entities.Member;
2527
import net.dv8tion.jda.api.entities.User;
28+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
29+
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
30+
import net.dv8tion.jda.api.interactions.commands.OptionType;
31+
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
32+
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
33+
import org.jetbrains.annotations.NotNull;
2634

2735
import javax.annotation.Nonnull;
2836
import java.util.List;
37+
import java.util.Optional;
2938
import java.util.concurrent.TimeUnit;
3039

3140
import static me.duncte123.botcommons.messaging.MessageUtils.sendMsg;
@@ -60,6 +69,59 @@ public BanCommand() {
6069
};
6170
}
6271

72+
@Override
73+
protected void configureSlashSupport(@NotNull SlashCommandData baseData) {
74+
baseData.addOptions(
75+
new OptionData(
76+
OptionType.USER,
77+
"user",
78+
"The user that you want to ban.",
79+
true
80+
),
81+
new OptionData(
82+
OptionType.STRING,
83+
"reason",
84+
"The reason for this ban",
85+
false
86+
),
87+
new OptionData(
88+
OptionType.BOOLEAN,
89+
"nodel",
90+
"Prevents the deletion of any messages",
91+
false
92+
)
93+
);
94+
}
95+
96+
@Override
97+
public void handleEvent(@NotNull SlashCommandInteractionEvent event, @NotNull DunctebotGuild guild, @NotNull Variables variables) {
98+
final var toBanMember = event.getOption("user").getAsMember();
99+
final var moderator = event.getMember();
100+
101+
if (!canInteract(moderator, toBanMember, "ban", event.getChannel())) {
102+
return;
103+
}
104+
105+
final var reason = Optional.ofNullable(event.getOption("reason"))
106+
.map(OptionMapping::getAsString)
107+
.orElse("No reason given");
108+
final var nodel = Optional.ofNullable(event.getOption("nodel"))
109+
.map(OptionMapping::getAsBoolean)
110+
.orElse(false);
111+
112+
final int delDays = nodel ? 0 : 1;
113+
final var modUser = moderator.getUser();
114+
115+
guild.ban(toBanMember, delDays, TimeUnit.DAYS)
116+
.reason(String.format("%#s: %s", modUser, reason))
117+
.queue(
118+
(m) -> {
119+
modLog(modUser, toBanMember.getUser(), "banned", reason, null, guild);
120+
event.reply("User has been banned").queue();
121+
}
122+
);
123+
}
124+
63125
@Override
64126
public void execute(@Nonnull CommandContext ctx) {
65127
final List<String> args = ctx.getArgs();

0 commit comments

Comments
 (0)