diff --git a/src/main/java/cc/fascinated/bat/command/BatCommand.java b/src/main/java/cc/fascinated/bat/command/BatCommand.java index 4d762a3..2f50a2f 100644 --- a/src/main/java/cc/fascinated/bat/command/BatCommand.java +++ b/src/main/java/cc/fascinated/bat/command/BatCommand.java @@ -4,7 +4,9 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.internal.interactions.CommandDataImpl; @@ -25,40 +27,69 @@ public abstract class BatCommand implements BatCommandExecutor { /** * The description of the command */ - private String description; + private final String description; + + /** + * The command data for the slash command + */ + private final CommandDataImpl commandData; + + /** + * The required permissions for the command + */ + private final List requiredPermissions; + + /** + * The sub commands of the command + */ + private final Map subCommands = new HashMap<>(); /** * The category of the command */ private Category category; - /** - * The command data for the slash command - */ - private CommandDataImpl commandData; - - /** - * The sub commands of the command - */ - private Map subCommands = new HashMap<>(); - - public BatCommand(@NonNull String name) { + public BatCommand(@NonNull String name, @NonNull String description, boolean guildOnly, Permission... permissions) { this.name = name; + this.description = description; + this.requiredPermissions = List.of(permissions); // Default values - this.description = "No description provided."; this.category = Category.GENERAL; + + this.commandData = new CommandDataImpl(this.name, description) + .setGuildOnly(guildOnly); + } + + public BatCommand(@NonNull String name) { + this(name, "No description provided.", false); + } + + public BatCommand(@NonNull String name, @NonNull String description) { + this(name, description, false); } /** * Adds a sub command to the command * - * @param name The name of the sub command + * @param name The name of the sub command * @param subCommand The sub command */ - public BatCommand addSubCommand(@NonNull String name, @NonNull BatSubCommand subCommand) { + public void addSubCommand(@NonNull String name, @NonNull BatSubCommand subCommand) { this.subCommands.put(name.toLowerCase(), subCommand); - return this; + this.commandData.addSubcommands(subCommand.getCommandData()); + } + + /** + * Adds an option to the sub command + * + * @param optionType the type of the option + * @param name the name of the option + * @param description the description of the option + * @param required whether the option is required + */ + private void addOption(OptionType optionType, String name, String description, boolean required) { + this.commandData.addOption(optionType, name, description, required); } /** diff --git a/src/main/java/cc/fascinated/bat/command/BatCommandExecutor.java b/src/main/java/cc/fascinated/bat/command/BatCommandExecutor.java index 277b597..53dc8a5 100644 --- a/src/main/java/cc/fascinated/bat/command/BatCommandExecutor.java +++ b/src/main/java/cc/fascinated/bat/command/BatCommandExecutor.java @@ -11,18 +11,17 @@ import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; * @author Fascinated (fascinated7) */ public interface BatCommandExecutor { - /** * Executes the command using a slash command interaction. * - * @param guild the bat guild the command was executed in + * @param guild the bat guild the command was executed in (null if the command was executed in a DM) * @param user the bat user that executed the command * @param channel the channel the command was executed in * @param member the member that executed the command * @param interaction the slash command interaction */ default void execute( - @NonNull BatGuild guild, + BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, diff --git a/src/main/java/cc/fascinated/bat/command/BatSubCommand.java b/src/main/java/cc/fascinated/bat/command/BatSubCommand.java index 19d4848..793c086 100644 --- a/src/main/java/cc/fascinated/bat/command/BatSubCommand.java +++ b/src/main/java/cc/fascinated/bat/command/BatSubCommand.java @@ -1,10 +1,41 @@ package cc.fascinated.bat.command; -import lombok.AllArgsConstructor; import lombok.Getter; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; + +import java.util.List; /** * @author Fascinated (fascinated7) */ -@AllArgsConstructor @Getter -public class BatSubCommand implements BatCommandExecutor { } +@Getter +public class BatSubCommand implements BatCommandExecutor { + /** + * The command data for the slash command + */ + private final SubcommandData commandData; + + /** + * The required permissions for the command + */ + private final List requiredPermissions; + + public BatSubCommand(String name, String description, Permission... permissions) { + this.commandData = new SubcommandData(name, description); + this.requiredPermissions = List.of(permissions); + } + + /** + * Adds an option to the sub command + * + * @param optionType the type of the option + * @param name the name of the option + * @param description the description of the option + * @param required whether the option is required + */ + public void addOption(OptionType optionType, String name, String description, boolean required) { + this.commandData.addOption(optionType, name, description, required); + } +} diff --git a/src/main/java/cc/fascinated/bat/command/impl/PingCommand.java b/src/main/java/cc/fascinated/bat/command/impl/PingCommand.java index 37539c2..e6f5293 100644 --- a/src/main/java/cc/fascinated/bat/command/impl/PingCommand.java +++ b/src/main/java/cc/fascinated/bat/command/impl/PingCommand.java @@ -8,7 +8,6 @@ import lombok.NonNull; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; -import net.dv8tion.jda.internal.interactions.CommandDataImpl; import org.springframework.stereotype.Component; /** @@ -18,9 +17,7 @@ import org.springframework.stereotype.Component; public class PingCommand extends BatCommand { public PingCommand() { - super("ping"); - super.setDescription("Gets the ping of the bot"); - super.setCommandData(new CommandDataImpl(this.getName(), this.getDescription())); + super("ping", "Gets the ping of the bot"); } @Override diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java index e765c4a..c04853b 100644 --- a/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/AddSubCommand.java @@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,7 +25,9 @@ public class AddSubCommand extends BatSubCommand { private final GuildService guildService; @Autowired - public AddSubCommand(GuildService guildService) { + public AddSubCommand(@NonNull GuildService guildService) { + super("add", "Adds a role to the auto roles list"); + super.addOption(OptionType.ROLE, "role", "The role to add", true); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java index 61d71a8..c97309c 100644 --- a/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/AutoRoleCommand.java @@ -3,11 +3,6 @@ package cc.fascinated.bat.features.autorole.command; import cc.fascinated.bat.command.BatCommand; import lombok.NonNull; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; -import net.dv8tion.jda.internal.interactions.CommandDataImpl; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -17,26 +12,11 @@ import org.springframework.stereotype.Component; @Component("autoroles.command") public class AutoRoleCommand extends BatCommand { public AutoRoleCommand(@NonNull ApplicationContext context) { - super("autorole"); - super.setDescription("Set up the automatic role system for members on join"); + super("autorole", "Set up the automatic role system for members on join", true, Permission.MANAGE_SERVER); super.addSubCommand("list", context.getBean(ListSubCommand.class)); super.addSubCommand("add", context.getBean(AddSubCommand.class)); super.addSubCommand("remove", context.getBean(RemoveSubCommand.class)); super.addSubCommand("clear", context.getBean(ClearSubCommand.class)); - - super.setCommandData(new CommandDataImpl(this.getName(), this.getDescription()) - .setGuildOnly(true) - .addSubcommands(new SubcommandData("list", "Show the current automatic roles")) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - .addSubcommands(new SubcommandData("add", "Add an automatic role") - .addOptions(new OptionData(OptionType.ROLE, "role", "The role to add", true)) - ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - .addSubcommands(new SubcommandData("remove", "Remove an automatic role") - .addOptions(new OptionData(OptionType.ROLE, "role", "The role to remove", true)) - ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - .addSubcommands(new SubcommandData("clear", "Clears all automatic roles")) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - ); } } diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java index f1c3f3a..8b84ea7 100644 --- a/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/ClearSubCommand.java @@ -22,6 +22,7 @@ public class ClearSubCommand extends BatSubCommand { @Autowired public ClearSubCommand(GuildService guildService) { + super("clear", "Clears all auto roles"); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java index 8e0bcae..8705212 100644 --- a/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/ListSubCommand.java @@ -18,6 +18,10 @@ import org.springframework.stereotype.Component; @Component("autoroles:list.sub") public class ListSubCommand extends BatSubCommand { + public ListSubCommand() { + super("list", "Lists all auto roles"); + } + @Override public void execute(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull TextChannel channel, @NonNull Member member, @NonNull SlashCommandInteraction interaction) { AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); diff --git a/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java b/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java index 4b37e4b..972da0f 100644 --- a/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/autorole/command/RemoveSubCommand.java @@ -11,6 +11,7 @@ import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,6 +25,8 @@ public class RemoveSubCommand extends BatSubCommand { @Autowired public RemoveSubCommand(GuildService guildService) { + super("remove", "Removes a role from the auto roles list"); + super.addOption(OptionType.ROLE, "role", "The role to remove", true); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java b/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java index 0d70dd4..041050b 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/NumberOneScoreFeedListener.java @@ -1,9 +1,6 @@ package cc.fascinated.bat.features.scoresaber; -import cc.fascinated.bat.common.DateUtils; -import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.NumberUtils; -import cc.fascinated.bat.common.ScoreSaberUtils; import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.features.scoresaber.profile.GuildNumberOneScoreFeedProfile; import cc.fascinated.bat.model.BatGuild; @@ -14,7 +11,6 @@ import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.GuildService; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java b/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java index 2b51518..e20cb1d 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/UserScoreFeedListener.java @@ -1,9 +1,5 @@ package cc.fascinated.bat.features.scoresaber; -import cc.fascinated.bat.common.DateUtils; -import cc.fascinated.bat.common.EmbedUtils; -import cc.fascinated.bat.common.NumberUtils; -import cc.fascinated.bat.common.ScoreSaberUtils; import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.features.scoresaber.profile.GuildUserScoreFeedProfile; import cc.fascinated.bat.model.BatGuild; @@ -14,7 +10,6 @@ import cc.fascinated.bat.service.DiscordService; import cc.fascinated.bat.service.GuildService; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java index 558141e..ec2ace9 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ChannelSubCommand.java @@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,6 +27,8 @@ public class ChannelSubCommand extends BatSubCommand { @Autowired public ChannelSubCommand(GuildService guildService) { + super("channel", "Sets the feed channel"); + super.addOption(OptionType.CHANNEL, "channel", "The channel scores are sent in", false); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/NumberOneFeedCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/NumberOneFeedCommand.java index 999ccb2..b608723 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/NumberOneFeedCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/NumberOneFeedCommand.java @@ -3,11 +3,6 @@ package cc.fascinated.bat.features.scoresaber.command.numberone; import cc.fascinated.bat.command.BatCommand; import lombok.NonNull; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; -import net.dv8tion.jda.internal.interactions.CommandDataImpl; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -17,20 +12,10 @@ import org.springframework.stereotype.Component; @Component("scoresaber-number-one-feed") public class NumberOneFeedCommand extends BatCommand { public NumberOneFeedCommand(@NonNull ApplicationContext context) { - super("scoresaber-number-one-feed"); + super("scoresaber-number-one-feed", "Modifies the settings for the feed.", true, Permission.MANAGE_SERVER); super.setCategory(Category.BEAT_SABER); super.addSubCommand("channel", context.getBean(ChannelSubCommand.class)); super.addSubCommand("reset", context.getBean(ResetSubCommand.class)); - - super.setDescription("Modifies the settings for the feed."); - super.setCommandData(new CommandDataImpl(this.getName(), this.getDescription()) - .setGuildOnly(true) - .addSubcommands(new SubcommandData("channel", "Change the channel the score feed is sent in") - .addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel scores are sent in", false)) - ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - .addSubcommands(new SubcommandData("reset", "Resets the feed settings to default")) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - ); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ResetSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ResetSubCommand.java index 9721d31..a7796df 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ResetSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/numberone/ResetSubCommand.java @@ -22,6 +22,7 @@ public class ResetSubCommand extends BatSubCommand { @Autowired public ResetSubCommand(GuildService guildService) { + super("reset", "Resets the settings"); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java index 575ca6b..394279e 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/LinkSubCommand.java @@ -12,6 +12,7 @@ import lombok.NonNull; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,6 +27,8 @@ public class LinkSubCommand extends BatSubCommand { @Autowired public LinkSubCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull UserService userService) { + super("link", "Links your ScoreSaber profile"); + super.addOption(OptionType.STRING, "link", "Link your ScoreSaber profile", true); this.scoreSaberService = scoreSaberService; this.userService = userService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/MeSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/MeSubCommand.java index ccf7cf2..d613e70 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/MeSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/MeSubCommand.java @@ -20,6 +20,7 @@ public class MeSubCommand extends BatSubCommand { @Autowired public MeSubCommand(@NonNull ScoreSaberService scoreSaberService) { + super("me", "Gets your ScoreSaber profile"); this.scoreSaberService = scoreSaberService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java index 82f3085..830dcfa 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/ScoreSaberCommand.java @@ -14,11 +14,7 @@ import lombok.NonNull; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; -import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; -import net.dv8tion.jda.internal.interactions.CommandDataImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -34,24 +30,13 @@ public class ScoreSaberCommand extends BatCommand { @Autowired public ScoreSaberCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull ApplicationContext context) { - super("scoresaber"); + super("scoresaber", "General ScoreSaber commands"); super.setCategory(Category.BEAT_SABER); this.scoreSaberService = scoreSaberService; super.addSubCommand("link", context.getBean(LinkSubCommand.class)); super.addSubCommand("user", context.getBean(UserSubCommand.class)); super.addSubCommand("me", context.getBean(MeSubCommand.class)); - - super.setDescription("General ScoreSaber commands"); - super.setCommandData(new CommandDataImpl(this.getName(), this.getDescription()) - .addSubcommands(new SubcommandData("link", "Link your ScoreSaber profile") - .addOptions(new OptionData(OptionType.STRING, "link", "Link your ScoreSaber profile", true)) - ) - .addSubcommands(new SubcommandData("user", "View a user's ScoreSaber profile") - .addOptions(new OptionData(OptionType.USER, "user", "The user to view the ScoreSaber profile of", true)) - ) - .addSubcommands(new SubcommandData("me", "View your ScoreSaber profile")) - ); } @Override diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java index b648601..b52a648 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/scoresaber/UserSubCommand.java @@ -10,6 +10,7 @@ import lombok.NonNull; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,6 +25,8 @@ public class UserSubCommand extends BatSubCommand { @Autowired public UserSubCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull UserService userService) { + super("user", "Gets a ScoreSaber profile"); + super.addOption(OptionType.USER, "user", "The user to view the ScoreSaber profile of", true); this.scoreSaberService = scoreSaberService; this.userService = userService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java index 3025e87..0130e7b 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ChannelSubCommand.java @@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,6 +27,8 @@ public class ChannelSubCommand extends BatSubCommand { @Autowired public ChannelSubCommand(GuildService guildService) { + super("channel", "Sets the feed channel"); + super.addOption(OptionType.CHANNEL, "channel", "The channel scores are sent in", false); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ResetSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ResetSubCommand.java index 4eca46e..2dbb6c6 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ResetSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/ResetSubCommand.java @@ -22,6 +22,7 @@ public class ResetSubCommand extends BatSubCommand { @Autowired public ResetSubCommand(GuildService guildService) { + super("reset", "Resets the settings"); this.guildService = guildService; } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java index 6411bbd..ccfd2d6 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserFeedCommand.java @@ -3,11 +3,6 @@ package cc.fascinated.bat.features.scoresaber.command.userfeed; import cc.fascinated.bat.command.BatCommand; import lombok.NonNull; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; -import net.dv8tion.jda.internal.interactions.CommandDataImpl; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @@ -17,26 +12,11 @@ import org.springframework.stereotype.Component; @Component("scoresaber-user-feed.command") public class UserFeedCommand extends BatCommand { public UserFeedCommand(@NonNull ApplicationContext context) { - super("scoresaber-user-feed"); + super("scoresaber-user-feed", "Modifies the settings for the feed.", true, Permission.MANAGE_SERVER); super.setCategory(Category.BEAT_SABER); super.addSubCommand("user", context.getBean(UserSubCommand.class)); super.addSubCommand("channel", context.getBean(ChannelSubCommand.class)); super.addSubCommand("reset", context.getBean(ResetSubCommand.class)); - - super.setDescription("Modifies the settings for the feed."); - super.setCommandData(new CommandDataImpl(this.getName(), this.getDescription()) - .setGuildOnly(true) - .addSubcommands(new SubcommandData("user", "Edit the users in the score feed") - .addOptions(new OptionData(OptionType.USER, "user", "Add or remove a user from the score feed", false)) - ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - - .addSubcommands(new SubcommandData("channel", "Change the channel the score feed is sent in") - .addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel scores are sent in", false)) - ).setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - - .addSubcommands(new SubcommandData("reset", "Resets the feed settings to default")) - .setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.MANAGE_SERVER)) - ); } } diff --git a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java index 122af70..2e53a98 100644 --- a/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/scoresaber/command/userfeed/UserSubCommand.java @@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -27,6 +28,8 @@ public class UserSubCommand extends BatSubCommand { @Autowired public UserSubCommand(GuildService guildService, UserService userService) { + super("user", "Adds or removes a user from the feed"); + super.addOption(OptionType.USER, "user", "Add or remove a user from the score feed", false); this.guildService = guildService; this.userService = userService; } diff --git a/src/main/java/cc/fascinated/bat/service/CommandService.java b/src/main/java/cc/fascinated/bat/service/CommandService.java index 144fbc8..439ef44 100644 --- a/src/main/java/cc/fascinated/bat/service/CommandService.java +++ b/src/main/java/cc/fascinated/bat/service/CommandService.java @@ -1,6 +1,7 @@ package cc.fascinated.bat.service; import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.BatCommandExecutor; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.model.BatGuild; @@ -8,6 +9,7 @@ import cc.fascinated.bat.model.BatUser; import lombok.NonNull; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; @@ -16,7 +18,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -96,22 +100,54 @@ public class CommandService extends ListenerAdapter { return; } - BatGuild guild = guildService.getGuild(discordGuild.getId()); + boolean ranInGuild = event.isFromGuild(); + BatGuild guild = ranInGuild ? guildService.getGuild(discordGuild.getId()) : null; BatUser user = userService.getUser(event.getUser().getId()); + try { + BatCommandExecutor executor = null; + List requiredPermissions = new ArrayList<>(); + // No args provided, use the main command executor if (event.getInteraction().getSubcommandName() == null) { - command.execute(guild, user, event.getChannel().asTextChannel(), event.getMember(), event.getInteraction()); + executor = command; + requiredPermissions.addAll(command.getRequiredPermissions()); + } else { + // Subcommand provided, use the subcommand executor + for (Map.Entry subCommand : command.getSubCommands().entrySet()) { + if (subCommand.getKey().equalsIgnoreCase(event.getInteraction().getSubcommandName())) { + executor = subCommand.getValue(); + requiredPermissions.addAll(subCommand.getValue().getRequiredPermissions()); + requiredPermissions.addAll(command.getRequiredPermissions()); // not sure if we'd want this, but it's here for now + break; + } + } + } + + if (executor == null) { + event.replyEmbeds(EmbedUtils.errorEmbed() + .setDescription("Unable to find a command executor the command name ):") + .build()).queue(); return; } - // Subcommand provided, use the subcommand executor - for (Map.Entry subCommand : command.getSubCommands().entrySet()) { - if (subCommand.getKey().equalsIgnoreCase(event.getInteraction().getSubcommandName())) { - subCommand.getValue().execute(guild, user, event.getChannel().asTextChannel(), event.getMember(), event.getInteraction()); - break; + // Check if the user has the required permissions + if (ranInGuild) { + List missingPermissions = new ArrayList<>(); + for (Permission permission : requiredPermissions) { + if (!event.getMember().hasPermission(permission)) { + missingPermissions.add(permission); + } + } + if (!missingPermissions.isEmpty()) { + event.replyEmbeds(EmbedUtils.errorEmbed() + .setDescription("You are missing the following permissions to execute this command: " + missingPermissions) + .build()).queue(); + return; } } + + executor.execute(guild, user, event.getChannel().asTextChannel(), event.getMember(), event.getInteraction()); } catch (Exception ex) { log.error("An error occurred while executing command \"{}\"", commandName, ex);