diff --git a/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java b/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java index def64eb..3cf42ec 100644 --- a/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java +++ b/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java @@ -113,6 +113,7 @@ public class HidekoBot ProfileImageCommandCompleter avatarCommandCompleter = new ProfileImageCommandCompleter(avatarCommand); slashCommandListener.registerCommand(avatarCommand); slashCommandCompletionListener.registerCommandCompleter(avatarCommandCompleter); + slashCommandListener.registerCommand(new BanCommand()); BannerCommand bannerCommand = new BannerCommand(); ProfileImageCommandCompleter bannerCommandCompleter = new ProfileImageCommandCompleter(bannerCommand); slashCommandListener.registerCommand(bannerCommand); @@ -124,10 +125,12 @@ public class HidekoBot slashCommandListener.registerCommand(new DieCommand()); slashCommandListener.registerCommand(new HelpCommand()); slashCommandListener.registerCommand(new InviteCommand()); + slashCommandListener.registerCommand(new KickCommand()); slashCommandListener.registerCommand(new LoveCalculatorCommand()); slashCommandListener.registerCommand(new MagicBallCommand()); slashCommandListener.registerCommand(new PingCommand()); slashCommandListener.registerCommand(new SayCommand()); + slashCommandListener.registerCommand(new TimeoutCommand()); slashCommandListener.registerCommand(new TriviaCommand()); slashCommandListener.registerCommand(new UrbanDictionaryCommand()); Cache.setSlashCommandListener(slashCommandListener); diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/base/UserPunishment.java b/src/main/java/wtf/beatrice/hidekobot/commands/base/UserPunishment.java index f143a3e..d0491f4 100644 --- a/src/main/java/wtf/beatrice/hidekobot/commands/base/UserPunishment.java +++ b/src/main/java/wtf/beatrice/hidekobot/commands/base/UserPunishment.java @@ -7,8 +7,11 @@ import net.dv8tion.jda.api.entities.Mentions; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.requests.restaction.AuditableRestAction; +import org.apache.commons.lang3.ArrayUtils; import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.HidekoBot; import wtf.beatrice.hidekobot.objects.MessageResponse; @@ -16,6 +19,9 @@ import wtf.beatrice.hidekobot.util.FormatUtil; import java.time.Duration; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -25,6 +31,63 @@ public class UserPunishment private final static Duration maxTimeoutDuration = Duration.of(28, ChronoUnit.DAYS); private final static Duration minTimeoutDuration = Duration.of(30, ChronoUnit.SECONDS); + public static void handle(SlashCommandInteractionEvent event, PunishmentType punishmentType) + { + // this might take a sec + event.deferReply().queue(); + + User targetUser = null; + + OptionMapping targetUserArg = event.getOption("target"); + if(targetUserArg != null) + { + targetUser = targetUserArg.getAsUser(); + } + + List mentions = null; + if(targetUser != null) mentions = new ArrayList<>(Collections.singletonList(targetUser)); + + String reason = null; + OptionMapping reasonArg = event.getOption("reason"); + if(reasonArg != null) + { + reason = reasonArg.getAsString(); + } + + String timeDiff = null; + OptionMapping timeDiffArg = event.getOption("duration"); + if(timeDiffArg != null) + { + timeDiff = timeDiffArg.getAsString(); + } + + // todo: the following code is not great, because we are making an array and then + // we are also recreating the string later in code. this is useless and a bit hacked on, + // but works for now. this happened because the function was NOT written with slash commands + // in mind, but with message commands, that send every word as a separate argument. + // we should probably rework the it so that it works better in both scenarios. + String[] reasonSplit = null; + // generate the arguments array by splitting the string + if(reason != null) reasonSplit = reason.split("\\s+"); + //prepend timediff at index 0 + if(timeDiff != null) reasonSplit = ArrayUtils.insert(0, reasonSplit, timeDiff); + // in message-commands, the first arg would contain the user mention. since we have no one mentioned here, + // because it's in its own argument, we just prepend an empty string. note that this makes relying on the + // first argument BAD, because it is no longer ensured that it contains the user mention. + if(timeDiff != null) reasonSplit = ArrayUtils.insert(0, reasonSplit, ""); + + MessageResponse response = getResponse(event.getUser(), + punishmentType, + event.getChannel(), + mentions, + reasonSplit); + + if(response.embed() != null) + event.getHook().editOriginalEmbeds(response.embed()).queue(); + else if(response.content() != null) + event.getHook().editOriginal(response.content()).queue(); + } + public static void handle(MessageReceivedEvent event, String[] args, PunishmentType punishmentType) { Mentions msgMentions = event.getMessage().getMentions(); @@ -57,7 +120,7 @@ public class UserPunishment return new MessageResponse("Sorry! I can't " + punishmentTypeName + " people in DMs.", null); } - if(mentions.isEmpty()) + if(mentions == null || mentions.isEmpty()) { // todo nicer looking with emojis return new MessageResponse("You have to tell me who to " + punishmentTypeName + "!", null); @@ -80,7 +143,7 @@ public class UserPunishment // some commands require an additional parameter before the reason, so in that case, we should start at 2. int startingPoint = punishmentType == PunishmentType.TIMEOUT ? 2 : 1; - if(args.length > startingPoint) + if(args != null && args.length > startingPoint) { for(int i = startingPoint; i < args.length; i++) { @@ -110,8 +173,11 @@ public class UserPunishment case BAN -> punishmentAction = guild.ban(mentioned, 0, TimeUnit.SECONDS); case KICK -> punishmentAction = guild.kick(mentioned); case TIMEOUT -> { - String durationStr = args[1]; - duration = FormatUtil.parseDuration(durationStr); + if(args != null) + { + String durationStr = args[1]; + duration = FormatUtil.parseDuration(durationStr); + } boolean isDurationValid = true; @@ -137,7 +203,8 @@ public class UserPunishment null); } - if(!reason.isEmpty() && !reasonBuilder.isEmpty()) punishmentAction.reason(reason); + if(!reason.isEmpty() && !reasonBuilder.isEmpty()) + punishmentAction.reason("[" + author.getAsTag() + "] " + reason); try { punishmentAction.complete(); diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/message/KickCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/message/KickCommand.java index ae9ff7a..ba478d8 100644 --- a/src/main/java/wtf/beatrice/hidekobot/commands/message/KickCommand.java +++ b/src/main/java/wtf/beatrice/hidekobot/commands/message/KickCommand.java @@ -50,7 +50,7 @@ public class KickCommand implements MessageCommand @NotNull @Override public String getDescription() { - return "Kick the mentioned user."; + return "Kick the mentioned user from the guild."; } @Nullable diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/slash/BanCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/slash/BanCommand.java new file mode 100644 index 0000000..4b61d42 --- /dev/null +++ b/src/main/java/wtf/beatrice/hidekobot/commands/slash/BanCommand.java @@ -0,0 +1,36 @@ +package wtf.beatrice.hidekobot.commands.slash; + +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import org.jetbrains.annotations.NotNull; +import wtf.beatrice.hidekobot.commands.base.UserPunishment; +import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl; + +public class BanCommand extends SlashCommandImpl +{ + @Override + public CommandData getSlashCommandData() + { + + return Commands.slash("ban", "Ban someone from the guild.") + .addOption(OptionType.MENTIONABLE, "target", + "The member user to ban.", + true, + false) + .addOption(OptionType.STRING, "reason", + "The reason for the punishment.", + false, + false) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.BAN_MEMBERS)); + } + + @Override + public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) + { + UserPunishment.handle(event, UserPunishment.PunishmentType.BAN); + } +} diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/slash/KickCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/slash/KickCommand.java new file mode 100644 index 0000000..76b4470 --- /dev/null +++ b/src/main/java/wtf/beatrice/hidekobot/commands/slash/KickCommand.java @@ -0,0 +1,46 @@ +package wtf.beatrice.hidekobot.commands.slash; + +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.IMentionable; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import org.jetbrains.annotations.NotNull; +import wtf.beatrice.hidekobot.commands.base.Say; +import wtf.beatrice.hidekobot.commands.base.UserPunishment; +import wtf.beatrice.hidekobot.objects.MessageResponse; +import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class KickCommand extends SlashCommandImpl +{ + @Override + public CommandData getSlashCommandData() + { + + return Commands.slash("kick", "Kick someone from the guild.") + .addOption(OptionType.MENTIONABLE, "target", + "The member user to kick.", + true, + false) + .addOption(OptionType.STRING, "reason", + "The reason for the punishment.", + false, + false) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.KICK_MEMBERS)); + } + + @Override + public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) + { + UserPunishment.handle(event, UserPunishment.PunishmentType.KICK); + } +} diff --git a/src/main/java/wtf/beatrice/hidekobot/commands/slash/TimeoutCommand.java b/src/main/java/wtf/beatrice/hidekobot/commands/slash/TimeoutCommand.java new file mode 100644 index 0000000..1277c3b --- /dev/null +++ b/src/main/java/wtf/beatrice/hidekobot/commands/slash/TimeoutCommand.java @@ -0,0 +1,40 @@ +package wtf.beatrice.hidekobot.commands.slash; + +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.Commands; +import org.jetbrains.annotations.NotNull; +import wtf.beatrice.hidekobot.commands.base.UserPunishment; +import wtf.beatrice.hidekobot.objects.commands.SlashCommandImpl; + +public class TimeoutCommand extends SlashCommandImpl +{ + @Override + public CommandData getSlashCommandData() + { + + return Commands.slash("timeout", "Timeout someone in the guild.") + .addOption(OptionType.MENTIONABLE, "target", + "The member user to time out.", + true, + false) + .addOption(OptionType.STRING, "duration", + "The duration of the timeout.", + true, + false) + .addOption(OptionType.STRING, "reason", + "The reason for the punishment.", + false, + false) + .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MODERATE_MEMBERS)); + } + + @Override + public void runSlashCommand(@NotNull SlashCommandInteractionEvent event) + { + UserPunishment.handle(event, UserPunishment.PunishmentType.TIMEOUT); + } +}