Compare commits

...

3 Commits

Author SHA1 Message Date
47b4796695 fix subcomamnds not having options 2024-07-04 08:51:27 -04:00
4fdd00453a rework command system 2024-07-04 08:47:32 -04:00
e19334a9ef dont require sentry 2024-07-04 07:20:31 -04:00
95 changed files with 603 additions and 560 deletions

22
pom.xml

@ -107,11 +107,13 @@
<groupId>io.mongock</groupId> <groupId>io.mongock</groupId>
<artifactId>mongock-springboot-v3</artifactId> <artifactId>mongock-springboot-v3</artifactId>
<version>5.2.4</version> <version>5.2.4</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.mongock</groupId> <groupId>io.mongock</groupId>
<artifactId>mongodb-springdata-v4-driver</artifactId> <artifactId>mongodb-springdata-v4-driver</artifactId>
<version>5.2.4</version> <version>5.2.4</version>
<scope>compile</scope>
</dependency> </dependency>
<!-- Redis for caching --> <!-- Redis for caching -->
@ -138,49 +140,41 @@
<version>1.18.32</version> <version>1.18.32</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Dependencies -->
<!-- <dependency>-->
<!-- <groupId>net.dv8tion</groupId>-->
<!-- <artifactId>JDA</artifactId>-->
<!-- <version>5.0.0-beta.24</version>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>io.github.freya022</groupId> <groupId>io.github.freya022</groupId>
<artifactId>JDA</artifactId> <artifactId>JDA</artifactId>
<version>2ed819ad15</version> <version>2ed819ad15</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.10.1</version> <version>2.10.1</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents.client5</groupId> <groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId> <artifactId>httpclient5</artifactId>
<version>5.3.1</version> <version>5.3.1</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.jodah</groupId> <groupId>net.jodah</groupId>
<artifactId>expiringmap</artifactId> <artifactId>expiringmap</artifactId>
<version>0.5.11</version> <version>0.5.11</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>se.michaelthelin.spotify</groupId> <groupId>se.michaelthelin.spotify</groupId>
<artifactId>spotify-web-api-java</artifactId> <artifactId>spotify-web-api-java</artifactId>
<version>8.4.0</version> <version>8.4.0</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>uk.co.conoregan</groupId> <groupId>uk.co.conoregan</groupId>
<artifactId>themoviedbapi</artifactId> <artifactId>themoviedbapi</artifactId>
<version>2.1.1</version> <version>2.1.1</version>
</dependency> <scope>compile</scope>
<!-- Test Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

@ -20,7 +20,7 @@ import java.nio.file.StandardCopyOption;
import java.util.Objects; import java.util.Objects;
@EnableScheduling @EnableScheduling
@SpringBootApplication(scanBasePackages = "cc.fascinated.bat") @SpringBootApplication
@EnableMongock @EnableMongock
@Log4j2(topic = "Bat") @Log4j2(topic = "Bat")
public class BatApplication { public class BatApplication {

@ -1,103 +1,123 @@
package cc.fascinated.bat.command; package cc.fascinated.bat.command;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.IntegrationType; import net.dv8tion.jda.api.interactions.IntegrationType;
import net.dv8tion.jda.api.interactions.InteractionContextType; import net.dv8tion.jda.api.interactions.InteractionContextType;
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.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 net.dv8tion.jda.internal.interactions.CommandDataImpl;
import java.util.HashMap; import java.util.*;
import java.util.List;
import java.util.Map;
/** /**
* @author Fascinated (fascinated7) * @author Braydon
*/ */
@Getter @Getter
@Setter public abstract class BatCommand {
public abstract class BatCommand implements BatCommandExecutor {
/** /**
* The information about the command * The info of this command.
*/ */
private final CommandInfo commandInfo; @NonNull private final InternalCommandInfo info;
/** /**
* The command data for the slash command * The feature this command belongs to.
*/ */
private final CommandDataImpl commandData; @Setter private Feature feature;
/** /**
* The sub commands of the command * The snowflake of this command, set when
* this command is registered with Discord.
*/ */
private final Map<String, BatSubCommand> subCommands = new HashMap<>(); @Setter private long snowflake;
/** /**
* The category of the command * The sub commands of this command, if any.
*/ */
private Category category; private final Map<String, BatCommand> subCommands = Collections.synchronizedMap(new HashMap<>());
/** /**
* The feature that the command belongs to * The internal data for this command.
*/ */
private Feature feature; @Setter(AccessLevel.PRIVATE) private CommandDataImpl commandData;
/** /**
* Whether the command can only be used by the bot owner * The internal subcommand data for this command.
*/ */
private boolean botOwnerOnly; @Setter(AccessLevel.PRIVATE) private SubcommandData subcommandData;
/**
* The command snowflake from Discord
*/
private long commandSnowflake;
public BatCommand() { public BatCommand() {
this.commandInfo = getClass().getAnnotation(CommandInfo.class); if (!getClass().isAnnotationPresent(CommandInfo.class)) {
this.category = this.commandInfo.category(); throw new IllegalStateException("Missing @CommandInfo annotation in " + getClass().getSimpleName());
this.botOwnerOnly = this.commandInfo.botOwnerOnly(); }
info = new InternalCommandInfo(getClass().getAnnotation(CommandInfo.class));
List<IntegrationType> integrationTypes = this.commandInfo.userInstall() ? List.of(IntegrationType.GUILD_INSTALL, IntegrationType.USER_INSTALL) : List<IntegrationType> integrationTypes = new ArrayList<>(Collections.singletonList(IntegrationType.GUILD_INSTALL));
List.of(IntegrationType.GUILD_INSTALL); if (info.isUserInstall()) {
this.commandData = new CommandDataImpl(this.commandInfo.name(), this.commandInfo.description()) integrationTypes.add(IntegrationType.USER_INSTALL);
.setGuildOnly(this.commandInfo.guildOnly()) }
commandData = new CommandDataImpl(info.getName(), info.getDescription())
.setContexts(InteractionContextType.ALL) .setContexts(InteractionContextType.ALL)
.setIntegrationTypes(integrationTypes); .setIntegrationTypes(integrationTypes)
.setGuildOnly(info.isGuildOnly());
} }
/** /**
* Adds a sub command to the command * Fired when this command is executed.
* *
* @param subCommand The sub command * @param guild the guild the command was executed in, if any
* @param user the user who executed the command
* @param channel the channel the command was executed in
* @param member the member who executed the command, null if not a guild
* @param event the event that invoked this command
*/ */
public void addSubCommand(@NonNull BatSubCommand subCommand) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { }
this.subCommands.put(subCommand.getCommandInfo().name().toLowerCase(), subCommand);
this.commandData.addSubcommands(subCommand.getCommandData()); /**
* Register the given sub commands.
*
* @param commands the commands to register
*/
protected final void addSubCommands(@NonNull BatCommand... commands) {
for (BatCommand command : commands) {
// Copy info from the parent command
if (command.getInfo().getCategory() != info.getCategory()) {
command.getInfo().setCategory(info.getCategory());
}
if (command.getInfo().getPermissions().length == 0) {
command.getInfo().setPermissions(info.getPermissions());
}
if (command.getInfo().isGuildOnly() != info.isGuildOnly()) {
command.getInfo().setGuildOnly(info.isGuildOnly());
}
if (command.getInfo().isBotOwnerOnly() != info.isBotOwnerOnly()) {
command.getInfo().setBotOwnerOnly(info.isBotOwnerOnly());
}
command.setSubcommandData(new SubcommandData(command.getInfo().getName(), command.getInfo().getDescription()));
for (OptionData option : command.getCommandData().getOptions()) {
command.getSubcommandData().addOptions(option);
}
commandData.addSubcommands(command.getSubcommandData());
subCommands.put(command.getInfo().getName(), command);
}
} }
/** /**
* Adds an option to the sub command * Add the given options
* to this command.
* *
* @param optionType the type of the option * @param options the options to add
* @param name the name of the option
* @param description the description of the option
* @param required whether the option is required
*/ */
protected void addOption(OptionType optionType, String name, String description, boolean required) { protected final void addOptions(OptionData... options) {
this.commandData.addOption(optionType, name, description, required); commandData.addOptions(options);
} }
}
/**
* Gets all the options for the command
*
* @param interaction The slash command interaction
* @return The option strings
*/
public List<String> getOptions(SlashCommandInteraction interaction) {
return interaction.getOptions().stream().map(OptionMapping::getName).toList();
}
}

@ -1,31 +0,0 @@
package cc.fascinated.bat.command;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
/**
* @author Fascinated (fascinated7)
*/
public interface BatCommandExecutor {
/**
* Executes the command using a slash command event.
*
* @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 event the slash command event
*/
default void execute(
BatGuild guild,
@NonNull BatUser user,
@NonNull MessageChannel channel,
Member member,
@NonNull SlashCommandInteraction event
) {
}
}

@ -1,45 +0,0 @@
package cc.fascinated.bat.command;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
/**
* @author Fascinated (fascinated7)
*/
@Getter
@Setter
public class BatSubCommand implements BatCommandExecutor {
/**
* The information about the sub command
*/
private final CommandInfo commandInfo;
/**
* The command data for the slash command
*/
private final SubcommandData commandData;
/**
* The commands snowflake from Discord
*/
private long commandSnowflake;
public BatSubCommand() {
this.commandInfo = getClass().getAnnotation(CommandInfo.class);
this.commandData = new SubcommandData(this.commandInfo.name(), this.commandInfo.description());
}
/**
* 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);
}
}

@ -2,43 +2,35 @@ package cc.fascinated.bat.command;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.emoji.Emoji;
import java.util.Arrays;
import java.util.List;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
public enum Category { public enum Category {
GENERAL(Emoji.fromUnicode("U+2699"), "General", false), GENERAL(Emoji.fromUnicode("U+2699"), "General"),
FUN(Emoji.fromFormatted("U+1F973"), "Fun", false), FUN(Emoji.fromFormatted("U+1F973"), "Fun"),
SERVER(Emoji.fromFormatted("U+1F5A5"), "Server", false), SERVER(Emoji.fromFormatted("U+1F5A5"), "Server"),
MODERATION(Emoji.fromFormatted("U+1F6E0"), "Moderation", false), MODERATION(Emoji.fromFormatted("U+1F6E0"), "Moderation"),
UTILITY(Emoji.fromFormatted("U+1F6E0"), "Utility", false), UTILITY(Emoji.fromFormatted("U+1F6E0"), "Utility"),
MUSIC(Emoji.fromFormatted("U+1F3B5"), "Music", false), MUSIC(Emoji.fromFormatted("U+1F3B5"), "Music"),
MOVIES_TV(Emoji.fromFormatted("U+1F3A5"), "Movies & TV", false), MOVIES_TV(Emoji.fromFormatted("U+1F3A5"), "Movies & TV"),
MESSAGES(Emoji.fromFormatted("U+1F4A3"), "Messages", false), MESSAGES(Emoji.fromFormatted("U+1F4A3"), "Messages"),
LOGS(Emoji.fromFormatted("U+1F4D1"), "Logs", false), LOGS(Emoji.fromFormatted("U+1F4D1"), "Logs"),
BEAT_SABER(Emoji.fromFormatted("U+1FA84"), "Beat Saber", false), BEAT_SABER(Emoji.fromFormatted("U+1FA84"), "Beat Saber");
BOT_ADMIN(null, null, true);
/** /**
* The emoji for the category * The emoji for the category
*/ */
private final Emoji emoji; @NonNull private final Emoji emoji;
/** /**
* The name of the category * The name of the category
*/ */
private final String name; @NonNull private final String name;
/**
* If the category is hidden
*/
private final boolean hidden;
/** /**
* Gets a category by its name * Gets a category by its name
@ -54,13 +46,4 @@ public enum Category {
} }
return null; return null;
} }
/**
* Gets all the visible categories
*
* @return the visible categories
*/
public static List<Category> getCategories() {
return Arrays.stream(Category.values()).filter(category -> !category.isHidden()).toList();
}
} }

@ -8,6 +8,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* Annotated at the top of a class to define
* the default values for a {@link BatCommand}.
*
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

@ -0,0 +1,60 @@
package cc.fascinated.bat.command;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import net.dv8tion.jda.api.Permission;
/**
* The internal command info of a {@link BatCommand}.
*
* @author Braydon
*/
@Setter(AccessLevel.PROTECTED) @Getter
public class InternalCommandInfo {
/**
* The name of the command.
*/
@NonNull private final String name;
/**
* The description of the command.
*/
@NonNull private final String description;
/**
* The category of the command.
*/
@NonNull private Category category;
/**
* The permissions required to run this command, if any.
*/
private Permission[] permissions;
/**
* Whether this command can only be ran within a guild.
*/
private boolean guildOnly;
/**
* Whether this command can be user installed.
*/
private final boolean userInstall;
/**
* Whether the command can only be ran by the bot owner.
*/
private boolean botOwnerOnly;
protected InternalCommandInfo(@NonNull CommandInfo annotation) {
name = annotation.name();
description = annotation.description();
category = annotation.category();
permissions = annotation.requiredPermissions();
guildOnly = annotation.guildOnly();
userInstall = annotation.userInstall();
botOwnerOnly = annotation.botOwnerOnly();
}
}

@ -37,11 +37,10 @@ public abstract class Feature {
* @param command The command to register * @param command The command to register
*/ */
public void registerCommand(@NonNull CommandService commandService, @NonNull BatCommand command) { public void registerCommand(@NonNull CommandService commandService, @NonNull BatCommand command) {
// If the command using the default category then set the category to the feature's category
if (command.getCategory() == Category.GENERAL) {
command.setCategory(this.category);
}
command.setFeature(this); command.setFeature(this);
for (BatCommand subCommand : command.getSubCommands().values()) {
subCommand.setFeature(this);
}
commandService.registerCommand(command); commandService.registerCommand(command);
} }
} }

@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -21,9 +22,18 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "afk", description = "Sets your AFK status") @CommandInfo(name = "afk", description = "Sets your AFK status")
public class AfkCommand extends BatCommand { public class AfkCommand extends BatCommand {
public AfkCommand() { public AfkCommand() {
super.addOption(OptionType.STRING, "reason", "The reason for being AFK", false); super.addOptions(new OptionData(OptionType.STRING, "reason", "The reason for being AFK", false));
} }
/**
* Fired when this command is executed.
*
* @param guild the guild the command was executed in, if any
* @param user the user who executed the command
* @param channel the channel the command was executed in
* @param member the member who executed the command, null if not a guild
* @param event the event that invoked this command
*/
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
AfkProfile profile = guild.getProfile(AfkProfile.class); AfkProfile profile = guild.getProfile(AfkProfile.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.features.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.RoleUtils; import cc.fascinated.bat.common.RoleUtils;
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:add.sub") @Component("autoroles:add.sub")
@CommandInfo(name = "add", description = "Adds a role to the auto roles list") @CommandInfo(name = "add", description = "Adds a role to the auto roles list")
public class AddSubCommand extends BatSubCommand { public class AddSubCommand extends BatCommand {
@Autowired @Autowired
public AddSubCommand() { public AddSubCommand() {
super.addOption(OptionType.ROLE, "role", "The role to add", true); super.addOptions(new OptionData(OptionType.ROLE, "role", "The role to add", true));
} }
@Override @Override

@ -14,9 +14,11 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "autorole", description = "Set up the automatic role system for members on join", requiredPermissions = Permission.MANAGE_SERVER) @CommandInfo(name = "autorole", description = "Set up the automatic role system for members on join", requiredPermissions = Permission.MANAGE_SERVER)
public class AutoRoleCommand extends BatCommand { public class AutoRoleCommand extends BatCommand {
public AutoRoleCommand(@NonNull ApplicationContext context) { public AutoRoleCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(ListSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(AddSubCommand.class)); context.getBean(ListSubCommand.class),
super.addSubCommand(context.getBean(RemoveSubCommand.class)); context.getBean(AddSubCommand.class),
super.addSubCommand(context.getBean(ClearSubCommand.class)); context.getBean(RemoveSubCommand.class),
context.getBean(ClearSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.features.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:clear.sub") @Component("autoroles:clear.sub")
@CommandInfo(name = "clear", description = "Clears all auto roles") @CommandInfo(name = "clear", description = "Clears all auto roles")
public class ClearSubCommand extends BatSubCommand { public class ClearSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.features.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:list.sub") @Component("autoroles:list.sub")
@CommandInfo(name = "list", description = "Lists all auto roles") @CommandInfo(name = "list", description = "Lists all auto roles")
public class ListSubCommand extends BatSubCommand { public class ListSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class); AutoRoleProfile profile = guild.getProfile(AutoRoleProfile.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.autorole.command; package cc.fascinated.bat.features.autorole.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile; import cc.fascinated.bat.features.autorole.profile.AutoRoleProfile;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -21,10 +22,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("autoroles:remove.sub") @Component("autoroles:remove.sub")
@CommandInfo(name = "remove", description = "Removes a role from the auto roles list") @CommandInfo(name = "remove", description = "Removes a role from the auto roles list")
public class RemoveSubCommand extends BatSubCommand { public class RemoveSubCommand extends BatCommand {
@Autowired @Autowired
public RemoveSubCommand() { public RemoveSubCommand() {
super.addOption(OptionType.ROLE, "role", "The role to remove", true); super.addOptions(new OptionData(OptionType.ROLE, "role", "The role to remove", true));
} }
@Override @Override

@ -1,7 +1,6 @@
package cc.fascinated.bat.features.base.commands.botadmin.premium; package cc.fascinated.bat.features.base.commands.botadmin.premium;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import lombok.NonNull; import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -12,11 +11,13 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@Component @Component
@CommandInfo(name = "premiumadmin", description = "Set a guild as premium", botOwnerOnly = true, category = Category.BOT_ADMIN) @CommandInfo(name = "premiumadmin", description = "Set a guild as premium", botOwnerOnly = true)
public class PremiumAdminCommand extends BatCommand { public class PremiumAdminCommand extends BatCommand {
@Autowired @Autowired
public PremiumAdminCommand(@NonNull ApplicationContext context) { public PremiumAdminCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(SetSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(RemoveSubCommand.class)); context.getBean(SetSubCommand.class),
context.getBean(RemoveSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.botadmin.premium; package cc.fascinated.bat.features.base.commands.botadmin.premium;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -20,13 +21,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "remove", description = "Remove premium from a guild") @CommandInfo(name = "remove", description = "Remove premium from a guild")
public class RemoveSubCommand extends BatSubCommand { public class RemoveSubCommand extends BatCommand {
private final GuildService guildService; private final GuildService guildService;
@Autowired @Autowired
public RemoveSubCommand(GuildService guildService) { public RemoveSubCommand(GuildService guildService) {
this.guildService = guildService; this.guildService = guildService;
super.addOption(OptionType.STRING, "guild", "The guild id to set as premium", true); super.addOptions(new OptionData(OptionType.STRING, "guild", "The guild id to set as premium", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.botadmin.premium; package cc.fascinated.bat.features.base.commands.botadmin.premium;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -20,14 +21,16 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "set", description = "Adds premium to a guild") @CommandInfo(name = "set", description = "Adds premium to a guild")
public class SetSubCommand extends BatSubCommand { public class SetSubCommand extends BatCommand {
private final GuildService guildService; private final GuildService guildService;
@Autowired @Autowired
public SetSubCommand(@NonNull GuildService guildService) { public SetSubCommand(@NonNull GuildService guildService) {
this.guildService = guildService; this.guildService = guildService;
super.addOption(OptionType.STRING, "guild", "The guild id to set as premium", true); super.addOptions(
super.addOption(OptionType.BOOLEAN, "infinite", "Whether the premium length should be infinite", true); new OptionData(OptionType.STRING, "guild", "The guild id to set as premium", true),
new OptionData(OptionType.BOOLEAN, "infinite", "Whether the premium length should be infinite", true)
);
} }
@Override @Override

@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -24,7 +25,7 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "lookupuser", description = "Lookup a user", userInstall = true) @CommandInfo(name = "lookupuser", description = "Lookup a user", userInstall = true)
public class LookupUserCommand extends BatCommand { public class LookupUserCommand extends BatCommand {
public LookupUserCommand() { public LookupUserCommand() {
super.addOption(OptionType.STRING, "id", "The id of the user", true); super.addOptions(new OptionData(OptionType.STRING, "id", "The id of the user", true));
} }
@Override @Override

@ -11,6 +11,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -43,7 +44,7 @@ public class EightBallCommand extends BatCommand {
}; };
public EightBallCommand() { public EightBallCommand() {
super.addOption(OptionType.STRING, "question", "The question you want to ask the 8ball", true); super.addOptions(new OptionData(OptionType.STRING, "question", "The question you want to ask the 8ball", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.features.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "cat", description = "Get a random cat image") @CommandInfo(name = "cat", description = "Get a random cat image")
public class CatSubCommand extends BatSubCommand { public class CatSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
CatImageToken[] responseEntity = WebRequest.getAsEntity("https://api.thecatapi.com/v1/images/search", CatImageToken[].class); CatImageToken[] responseEntity = WebRequest.getAsEntity("https://api.thecatapi.com/v1/images/search", CatImageToken[].class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.features.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "dog", description = "Get a random dog image") @CommandInfo(name = "dog", description = "Get a random dog image")
public class DogSubCommand extends BatSubCommand { public class DogSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
RandomImage responseEntity = WebRequest.getAsEntity("https://dog.ceo/api/breeds/image/random", RandomImage.class); RandomImage responseEntity = WebRequest.getAsEntity("https://dog.ceo/api/breeds/image/random", RandomImage.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.features.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "duck", description = "Get a random duck image") @CommandInfo(name = "duck", description = "Get a random duck image")
public class DuckSubCommand extends BatSubCommand { public class DuckSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
RandomDuck responseEntity = WebRequest.getAsEntity("https://random-d.uk/api/v2/random", RandomDuck.class); RandomDuck responseEntity = WebRequest.getAsEntity("https://random-d.uk/api/v2/random", RandomDuck.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.fun.image; package cc.fascinated.bat.features.base.commands.fun.image;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest; import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "fox", description = "Get a random fox image") @CommandInfo(name = "fox", description = "Get a random fox image")
public class FoxSubCommand extends BatSubCommand { public class FoxSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
RandomFoxToken responseEntity = WebRequest.getAsEntity("https://randomfox.ca/floof/", RandomFoxToken.class); RandomFoxToken responseEntity = WebRequest.getAsEntity("https://randomfox.ca/floof/", RandomFoxToken.class);

@ -16,9 +16,11 @@ import org.springframework.stereotype.Component;
public class ImageCommand extends BatCommand { public class ImageCommand extends BatCommand {
@Autowired @Autowired
public ImageCommand(@NonNull ApplicationContext context) { public ImageCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(CatSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(DogSubCommand.class)); context.getBean(CatSubCommand.class),
super.addSubCommand(context.getBean(FoxSubCommand.class)); context.getBean(DogSubCommand.class),
super.addSubCommand(context.getBean(DuckSubCommand.class)); context.getBean(FoxSubCommand.class),
context.getBean(DuckSubCommand.class)
);
} }
} }

@ -2,7 +2,6 @@ package cc.fascinated.bat.features.base.commands.general;
import cc.fascinated.bat.Consts; import cc.fascinated.bat.Consts;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -17,7 +16,6 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent; import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.Button;
@ -29,7 +27,6 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
@ -62,44 +59,45 @@ public class HelpCommand extends BatCommand implements EventListener {
event.reply("Invalid category selected.").queue(); event.reply("Invalid category selected.").queue();
return; return;
} }
event.reply("hello this doesnt work yet").queue();
StringBuilder commands = new StringBuilder(); // StringBuilder commands = new StringBuilder();
List<BatCommand> categoryCommands = commandService.getCommandsByCategory(category, true); // List<BatCommand> categoryCommands = commandService.getCommandsByCategory(category, true);
if (categoryCommands.isEmpty()) { // if (categoryCommands.isEmpty()) {
commands = new StringBuilder("No commands available in this category."); // commands = new StringBuilder("No commands available in this category.");
} else { // } else {
for (BatCommand command : categoryCommands) { // for (BatCommand command : categoryCommands) {
if (!command.getSubCommands().isEmpty()) { // if (!command.getSubCommands().isEmpty()) {
for (Map.Entry<String, BatSubCommand> entry : command.getSubCommands().entrySet()) { // for (Map.Entry<String, BatSubCommand> entry : command.getSubCommands().entrySet()) {
BatSubCommand subCommand = entry.getValue(); // BatSubCommand subCommand = entry.getValue();
SubcommandData commandData = subCommand.getCommandData(); // SubcommandData commandData = subCommand.getCommandData();
commands.append("</%s %s:%s> - %s\n".formatted( // commands.append("</%s %s:%s> - %s\n".formatted(
command.getCommandInfo().name(), // command.getCommandInfo().name(),
commandData.getName(), // commandData.getName(),
subCommand.getCommandSnowflake(), // subCommand.getCommandSnowflake(),
commandData.getDescription() // commandData.getDescription()
)); // ));
} // }
continue; // continue;
} // }
commands.append("</%s:%s> - %s\n".formatted( // commands.append("</%s:%s> - %s\n".formatted(
command.getCommandInfo().name(), // command.getCommandInfo().name(),
command.getCommandSnowflake(), // command.getCommandSnowflake(),
command.getCommandInfo().description() // command.getCommandInfo().description()
)); // ));
} // }
} // }
//
int subCommands = categoryCommands.stream().mapToInt(command -> command.getSubCommands().size()).sum(); // int subCommands = categoryCommands.stream().mapToInt(command -> command.getSubCommands().size()).sum();
event.editMessageEmbeds(EmbedUtils.genericEmbed() // event.editMessageEmbeds(EmbedUtils.genericEmbed()
.setAuthor("%s Category".formatted(category.getName())) // .setAuthor("%s Category".formatted(category.getName()))
.setDescription("%s command%s (with %s sub-command%s)\n\n**Commands:**\n%s".formatted( // .setDescription("%s command%s (with %s sub-command%s)\n\n**Commands:**\n%s".formatted(
categoryCommands.size(), // categoryCommands.size(),
categoryCommands.size() == 1 ? "" : "s", // categoryCommands.size() == 1 ? "" : "s",
subCommands, // subCommands,
subCommands == 1 ? "" : "s", // subCommands == 1 ? "" : "s",
commands.toString() // commands.toString()
)).build()).queue(); // )).build()).queue();
} }
/** /**
@ -109,8 +107,8 @@ public class HelpCommand extends BatCommand implements EventListener {
*/ */
private MessageEmbed createHomeEmbed() { private MessageEmbed createHomeEmbed() {
StringBuilder categories = new StringBuilder(); StringBuilder categories = new StringBuilder();
for (Category category : Category.getCategories()) { for (Category category : Category.values()) {
long commandCount = commandService.getCommandsByCategory(category, true).size(); long commandCount = commandService.getCommandsByCategory(category).size();
categories.append("➜ %s - **%s Command%s**\n".formatted( categories.append("➜ %s - **%s Command%s**\n".formatted(
category.getName(), category.getName(),
commandCount, commandCount,
@ -140,9 +138,9 @@ public class HelpCommand extends BatCommand implements EventListener {
private LayoutComponent[] createHomeActions() { private LayoutComponent[] createHomeActions() {
List<SelectOption> options = new ArrayList<>(); List<SelectOption> options = new ArrayList<>();
options.add(SelectOption.of("Home", "home").withEmoji(Emoji.fromUnicode("U+1F3E0"))); options.add(SelectOption.of("Home", "home").withEmoji(Emoji.fromUnicode("U+1F3E0")));
options.addAll(Category.getCategories().stream().map(category -> for (Category category : Category.values()) {
SelectOption.of(category.getName(), category.getName()).withEmoji(category.getEmoji())) options.add(SelectOption.of(category.getName(), category.getName()).withEmoji(category.getEmoji()));
.toList()); }
return new LayoutComponent[]{ return new LayoutComponent[]{
ActionRow.of( ActionRow.of(

@ -15,7 +15,9 @@ import org.springframework.stereotype.Component;
public class AvatarCommand extends BatCommand { public class AvatarCommand extends BatCommand {
@Autowired @Autowired
public AvatarCommand(@NonNull ApplicationContext context) { public AvatarCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(GuildSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(UserSubCommand.class)); context.getBean(GuildSubCommand.class),
context.getBean(UserSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.general.avatar; package cc.fascinated.bat.features.base.commands.general.avatar;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("avatar:guild.sub") @Component("avatar:guild.sub")
@CommandInfo(name = "guild", description = "View the avatar of the guild") @CommandInfo(name = "guild", description = "View the avatar of the guild")
public class GuildSubCommand extends BatSubCommand { public class GuildSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
ImageProxy icon = guild.getDiscordGuild().getIcon(); ImageProxy icon = guild.getDiscordGuild().getIcon();

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.general.avatar; package cc.fascinated.bat.features.base.commands.general.avatar;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -19,9 +20,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("avatar:user.sub") @Component("avatar:user.sub")
@CommandInfo(name = "user", description = "View the avatar of a user", guildOnly = false) @CommandInfo(name = "user", description = "View the avatar of a user", guildOnly = false)
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
public UserSubCommand() { public UserSubCommand() {
super.addOption(OptionType.USER, "user", "The user to view the avatar of", true); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the avatar of", true));
} }
@Override @Override

@ -15,7 +15,9 @@ import org.springframework.stereotype.Component;
public class BannerCommand extends BatCommand { public class BannerCommand extends BatCommand {
@Autowired @Autowired
public BannerCommand(@NonNull ApplicationContext context) { public BannerCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(GuildSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(UserSubCommand.class)); context.getBean(GuildSubCommand.class),
context.getBean(UserSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.general.banner; package cc.fascinated.bat.features.base.commands.general.banner;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("banner:guild.sub") @Component("banner:guild.sub")
@CommandInfo(name = "guild", description = "View the banner of the guild") @CommandInfo(name = "guild", description = "View the banner of the guild")
public class GuildSubCommand extends BatSubCommand { public class GuildSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
ImageProxy banner = guild.getDiscordGuild().getBanner(); ImageProxy banner = guild.getDiscordGuild().getBanner();

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.general.banner; package cc.fascinated.bat.features.base.commands.general.banner;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.utils.ImageProxy; import net.dv8tion.jda.api.utils.ImageProxy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -20,9 +21,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("banner:user.sub") @Component("banner:user.sub")
@CommandInfo(name = "user", description = "View the banner of a user", guildOnly = false) @CommandInfo(name = "user", description = "View the banner of a user", guildOnly = false)
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
public UserSubCommand() { public UserSubCommand() {
super.addOption(OptionType.USER, "user", "The user to view the banner of", true); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the banner of", true));
} }
@Override @Override

@ -16,8 +16,10 @@ import org.springframework.stereotype.Component;
public class ChannelCommand extends BatCommand { public class ChannelCommand extends BatCommand {
@Autowired @Autowired
public ChannelCommand(@NonNull ApplicationContext context) { public ChannelCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(ViewTopicSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(SetTopicSubCommand.class)); context.getBean(ViewTopicSubCommand.class),
super.addSubCommand(context.getBean(RemoveTopicSubCommand.class)); context.getBean(SetTopicSubCommand.class),
context.getBean(RemoveTopicSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.features.base.commands.server.channel;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -20,9 +21,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "removetopic", description = "Remove the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL) @CommandInfo(name = "removetopic", description = "Remove the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL)
public class RemoveTopicSubCommand extends BatSubCommand { public class RemoveTopicSubCommand extends BatCommand {
public RemoveTopicSubCommand() { public RemoveTopicSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel to remove the topic of", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel to remove the topic of", false));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.features.base.commands.server.channel;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -13,22 +13,27 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Objects;
/** /**
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component @Component
@CommandInfo(name = "settopic", description = "Set the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL) @CommandInfo(name = "settopic", description = "Set the topic of a channel", requiredPermissions = Permission.MANAGE_CHANNEL)
public class SetTopicSubCommand extends BatSubCommand { public class SetTopicSubCommand extends BatCommand {
public SetTopicSubCommand() { public SetTopicSubCommand() {
super.addOption(OptionType.STRING, "topic", "The topic to set", true); super.addOptions(
super.addOption(OptionType.CHANNEL, "channel", "The channel to set the topic of", false); new OptionData(OptionType.STRING, "topic", "The topic to set", true),
new OptionData(OptionType.CHANNEL, "channel", "The channel to set the topic of", false)
);
} }
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
Channel target = event.getOption("channel") == null ? channel : event.getOption("channel").getAsChannel(); Channel target = event.getOption("channel") == null ? channel : Objects.requireNonNull(event.getOption("channel")).getAsChannel();
if (!(target instanceof TextChannel textChannel)) { if (!(target instanceof TextChannel textChannel)) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("<#%s> is not a text channel!".formatted(target.getId())) .setDescription("<#%s> is not a text channel!".formatted(target.getId()))
@ -37,7 +42,7 @@ public class SetTopicSubCommand extends BatSubCommand {
return; return;
} }
String topic = event.getOption("topic").getAsString(); String topic = Objects.requireNonNull(event.getOption("topic")).getAsString();
if (topic.length() > 1024) { if (topic.length() > 1024) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("The topic must be 1024 characters or less!") .setDescription("The topic must be 1024 characters or less!")

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.server.channel; package cc.fascinated.bat.features.base.commands.server.channel;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -19,9 +20,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "viewtopic", description = "View the topic of a channel") @CommandInfo(name = "viewtopic", description = "View the topic of a channel")
public class ViewTopicSubCommand extends BatSubCommand { public class ViewTopicSubCommand extends BatCommand {
public ViewTopicSubCommand() { public ViewTopicSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel to view the topic of", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel to view the topic of", false));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.features.base.commands.server.feature;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("feature:disable.sub") @Component("feature:disable.sub")
@CommandInfo(name = "disable", description = "Disables a feature") @CommandInfo(name = "disable", description = "Disables a feature")
public class DisableSubCommand extends BatSubCommand { public class DisableSubCommand extends BatCommand {
@Autowired @Autowired
public DisableSubCommand() { public DisableSubCommand() {
super.addOption(OptionType.STRING, "feature", "The feature to disable", true); super.addOptions(new OptionData(OptionType.STRING, "feature", "The feature to disable", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.features.base.commands.server.feature;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("feature:enable.sub") @Component("feature:enable.sub")
@CommandInfo(name = "enable", description = "Enables a feature") @CommandInfo(name = "enable", description = "Enables a feature")
public class EnableSubCommand extends BatSubCommand { public class EnableSubCommand extends BatCommand {
@Autowired @Autowired
public EnableSubCommand() { public EnableSubCommand() {
super.addOption(OptionType.STRING, "feature", "The feature to enable", true); super.addOptions(new OptionData(OptionType.STRING, "feature", "The feature to enable", true));
} }
@Override @Override

@ -17,8 +17,10 @@ import org.springframework.stereotype.Component;
public class FeatureCommand extends BatCommand { public class FeatureCommand extends BatCommand {
@Autowired @Autowired
public FeatureCommand(@NonNull ApplicationContext context) { public FeatureCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(EnableSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(DisableSubCommand.class)); context.getBean(EnableSubCommand.class),
super.addSubCommand(context.getBean(ListSubCommand.class)); context.getBean(DisableSubCommand.class),
context.getBean(ListSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.base.commands.server.feature; package cc.fascinated.bat.features.base.commands.server.feature;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("feature:list.sub") @Component("feature:list.sub")
@CommandInfo(name = "list", description = "Lists the features and their states") @CommandInfo(name = "list", description = "Lists the features and their states")
public class ListSubCommand extends BatSubCommand { public class ListSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
StringBuilder featureStates = new StringBuilder(); StringBuilder featureStates = new StringBuilder();

@ -15,11 +15,13 @@ import org.springframework.stereotype.Component;
public class BirthdayCommand extends BatCommand { public class BirthdayCommand extends BatCommand {
@Autowired @Autowired
public BirthdayCommand(@NonNull ApplicationContext context) { public BirthdayCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(SetSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(RemoveSubCommand.class)); context.getBean(SetSubCommand.class),
super.addSubCommand(context.getBean(ChannelSubCommand.class)); context.getBean(RemoveSubCommand.class),
super.addSubCommand(context.getBean(MessageSubCommand.class)); context.getBean(ChannelSubCommand.class),
super.addSubCommand(context.getBean(ViewSubCommand.class)); context.getBean(MessageSubCommand.class),
super.addSubCommand(context.getBean(PrivateSubCommand.class)); context.getBean(ViewSubCommand.class),
context.getBean(PrivateSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.features.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.TextChannelUtils; import cc.fascinated.bat.common.TextChannelUtils;
@ -16,6 +16,7 @@ import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -24,10 +25,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:channel.sub") @Component("birthday:channel.sub")
@CommandInfo(name = "channel", description = "Sets the birthday notification channel", requiredPermissions = Permission.MANAGE_SERVER) @CommandInfo(name = "channel", description = "Sets the birthday notification channel", requiredPermissions = Permission.MANAGE_SERVER)
public class ChannelSubCommand extends BatSubCommand { public class ChannelSubCommand extends BatCommand {
@Autowired @Autowired
public ChannelSubCommand() { public ChannelSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel birthdays will be sent in", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel birthdays will be sent in", false));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.features.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.features.birthday.profile.BirthdayProfile;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:message.sub") @Component("birthday:message.sub")
@CommandInfo(name = "message", description = "Changes the message that is sent when it is a user's birthday", requiredPermissions = Permission.MANAGE_SERVER) @CommandInfo(name = "message", description = "Changes the message that is sent when it is a user's birthday", requiredPermissions = Permission.MANAGE_SERVER)
public class MessageSubCommand extends BatSubCommand { public class MessageSubCommand extends BatCommand {
@Autowired @Autowired
public MessageSubCommand() { public MessageSubCommand() {
super.addOption(OptionType.STRING, "message", "The message that is sent. (Placeholders: {user}, {age})", true); super.addOptions(new OptionData(OptionType.STRING, "message", "The message that is sent. (Placeholders: {user}, {age})", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.features.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.features.birthday.UserBirthday;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:private.sub") @Component("birthday:private.sub")
@CommandInfo(name = "private", description = "Changes whether your birthday is private or not") @CommandInfo(name = "private", description = "Changes whether your birthday is private or not")
public class PrivateSubCommand extends BatSubCommand { public class PrivateSubCommand extends BatCommand {
@Autowired @Autowired
public PrivateSubCommand() { public PrivateSubCommand() {
super.addOption(OptionType.BOOLEAN, "enabled", "Whether your birthday is private or not", true); super.addOptions(new OptionData(OptionType.BOOLEAN, "enabled", "Whether your birthday is private or not", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.features.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.profile.BirthdayProfile; import cc.fascinated.bat.features.birthday.profile.BirthdayProfile;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:remove.sub") @Component("birthday:remove.sub")
@CommandInfo(name = "remove", description = "Remove your birthday from this guild") @CommandInfo(name = "remove", description = "Remove your birthday from this guild")
public class RemoveSubCommand extends BatSubCommand { public class RemoveSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
BirthdayProfile profile = guild.getBirthdayProfile(); BirthdayProfile profile = guild.getBirthdayProfile();

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.features.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.features.birthday.UserBirthday;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -26,12 +27,12 @@ import java.util.Date;
*/ */
@Component("birthday:add.sub") @Component("birthday:add.sub")
@CommandInfo(name = "set", description = "Add your birthday to this guild") @CommandInfo(name = "set", description = "Add your birthday to this guild")
public class SetSubCommand extends BatSubCommand { public class SetSubCommand extends BatCommand {
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy"); private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy");
@Autowired @Autowired
public SetSubCommand() { public SetSubCommand() {
super.addOption(OptionType.STRING, "birthday", "Your birthday (format: DAY/MONTH/YEAR - 01/05/2004)", true); super.addOptions(new OptionData(OptionType.STRING, "birthday", "Your birthday (format: DAY/MONTH/YEAR - 01/05/2004)", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.birthday.command; package cc.fascinated.bat.features.birthday.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.birthday.UserBirthday; import cc.fascinated.bat.features.birthday.UserBirthday;
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -23,13 +24,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component("birthday:view.sub") @Component("birthday:view.sub")
@CommandInfo(name = "view", description = "Add your birthday to this guild") @CommandInfo(name = "view", description = "Add your birthday to this guild")
public class ViewSubCommand extends BatSubCommand { public class ViewSubCommand extends BatCommand {
private final UserService userService; private final UserService userService;
@Autowired @Autowired
public ViewSubCommand(@NonNull UserService userService) { public ViewSubCommand(@NonNull UserService userService) {
this.userService = userService; this.userService = userService;
super.addOption(OptionType.USER, "user", "The user to view the birthday of", false); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the birthday of", false));
} }
@Override @Override

@ -15,6 +15,6 @@ import org.springframework.stereotype.Component;
public class DragCommand extends BatCommand { public class DragCommand extends BatCommand {
@Autowired @Autowired
public DragCommand(@NonNull ApplicationContext context) { public DragCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(RequestSubCommand.class)); super.addSubCommands(context.getBean(RequestSubCommand.class));
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.drag.command; package cc.fascinated.bat.features.drag.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.TimerUtils; import cc.fascinated.bat.common.TimerUtils;
@ -16,6 +16,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -30,7 +31,7 @@ import java.util.Set;
*/ */
@Component @Component
@CommandInfo(name = "request", description = "Request to be moved to a voice channel") @CommandInfo(name = "request", description = "Request to be moved to a voice channel")
public class RequestSubCommand extends BatSubCommand implements EventListener { public class RequestSubCommand extends BatCommand implements EventListener {
/** /**
* A list of join requests * A list of join requests
*/ */
@ -40,7 +41,7 @@ public class RequestSubCommand extends BatSubCommand implements EventListener {
private final long checkInterval = Duration.ofSeconds(10).toMillis(); private final long checkInterval = Duration.ofSeconds(10).toMillis();
public RequestSubCommand() { public RequestSubCommand() {
super.addOption(OptionType.USER, "user", "The user you want to join", true); super.addOptions(new OptionData(OptionType.USER, "user", "The user you want to join", true));
TimerUtils.scheduleRepeating(() -> { TimerUtils.scheduleRepeating(() -> {
Set<DragRequest> toRemove = new HashSet<>(); Set<DragRequest> toRemove = new HashSet<>();

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.logging.command; package cc.fascinated.bat.features.logging.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -30,7 +30,7 @@ import java.util.List;
*/ */
@Component("logs:list.sub") @Component("logs:list.sub")
@CommandInfo(name = "list", description = "See all the log types and their channels") @CommandInfo(name = "list", description = "See all the log types and their channels")
public class ListSubCommand extends BatSubCommand implements EventListener { public class ListSubCommand extends BatCommand implements EventListener {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
List<Button> buttons = new ArrayList<>(); List<Button> buttons = new ArrayList<>();

@ -16,8 +16,10 @@ import org.springframework.stereotype.Component;
public class LogsCommand extends BatCommand { public class LogsCommand extends BatCommand {
@Autowired @Autowired
public LogsCommand(@NonNull ApplicationContext context) { public LogsCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(SetSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(RemoveSubCommand.class)); context.getBean(SetSubCommand.class),
super.addSubCommand(context.getBean(ListSubCommand.class)); context.getBean(RemoveSubCommand.class),
context.getBean(ListSubCommand.class)
);
} }
} }

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.logging.command; package cc.fascinated.bat.features.logging.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -16,6 +16,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
@ -25,9 +26,9 @@ import java.util.List;
*/ */
@Component("logs:remove.sub") @Component("logs:remove.sub")
@CommandInfo(name = "remove", description = "Remove the channel for a log type") @CommandInfo(name = "remove", description = "Remove the channel for a log type")
public class RemoveSubCommand extends BatSubCommand { public class RemoveSubCommand extends BatCommand {
public RemoveSubCommand() { public RemoveSubCommand() {
super.addOption(OptionType.STRING, "type", "The type of log to remove", true); super.addOptions(new OptionData(OptionType.STRING, "type", "The type of log to remove", true));
} }
@Override @Override

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.logging.command; package cc.fascinated.bat.features.logging.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -17,6 +17,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
@ -26,10 +27,12 @@ import java.util.List;
*/ */
@Component("logs:set.sub") @Component("logs:set.sub")
@CommandInfo(name = "set", description = "Set the channel for a log type") @CommandInfo(name = "set", description = "Set the channel for a log type")
public class SetSubCommand extends BatSubCommand { public class SetSubCommand extends BatCommand {
public SetSubCommand() { public SetSubCommand() {
super.addOption(OptionType.STRING, "type", "The type of log to set", true); super.addOptions(
super.addOption(OptionType.CHANNEL, "channel", "The channel to set the log to", true); new OptionData(OptionType.STRING, "type", "The type of log to set", true),
new OptionData(OptionType.CHANNEL, "channel", "The channel to set the log to", true)
);
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.messagesnipe.command; package cc.fascinated.bat.features.messagesnipe.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.messagesnipe.MessageSnipeFeature; import cc.fascinated.bat.features.messagesnipe.MessageSnipeFeature;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("messagesnipe:clear.sub") @Component("messagesnipe:clear.sub")
@CommandInfo(name = "clear", description = "Clears the known sniped messages for this guild", requiredPermissions = Permission.MESSAGE_MANAGE) @CommandInfo(name = "clear", description = "Clears the known sniped messages for this guild", requiredPermissions = Permission.MESSAGE_MANAGE)
public class ClearSubCommand extends BatSubCommand { public class ClearSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
boolean cleared = MessageSnipeFeature.clearSnipedMessages(guild); boolean cleared = MessageSnipeFeature.clearSnipedMessages(guild);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.messagesnipe.command; package cc.fascinated.bat.features.messagesnipe.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -21,7 +21,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "deleted", description = "Snipe the last deleted message in this channel") @CommandInfo(name = "deleted", description = "Snipe the last deleted message in this channel")
public class DeletedSubCommand extends BatSubCommand { public class DeletedSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
SnipedMessage message = MessageSnipeFeature.getDeletedMessage(guild, channel.getId()); SnipedMessage message = MessageSnipeFeature.getDeletedMessage(guild, channel.getId());

@ -13,7 +13,9 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "snipe", description = "Snipe messages") @CommandInfo(name = "snipe", description = "Snipe messages")
public class MessageSnipeCommand extends BatCommand { public class MessageSnipeCommand extends BatCommand {
public MessageSnipeCommand(@NonNull ApplicationContext context) { public MessageSnipeCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(DeletedSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(ClearSubCommand.class)); context.getBean(DeletedSubCommand.class),
context.getBean(ClearSubCommand.class)
);
} }
} }

@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
@ -28,7 +29,7 @@ public class PurgeCommand extends BatCommand {
private final long MESSAGE_DELETE_DELAY = TimeUnit.SECONDS.toMillis(10); private final long MESSAGE_DELETE_DELAY = TimeUnit.SECONDS.toMillis(10);
public PurgeCommand() { public PurgeCommand() {
super.addOption(OptionType.INTEGER, "amount", "The amount of messages to remove", true); super.addOptions(new OptionData(OptionType.INTEGER, "amount", "The amount of messages to remove", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.namehistory.command; package cc.fascinated.bat.features.namehistory.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.namehistory.TrackedName; import cc.fascinated.bat.features.namehistory.TrackedName;
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,13 +23,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component("namehistory:guild.sub") @Component("namehistory:guild.sub")
@CommandInfo(name = "guild", description = "View the guild nickname history of a user") @CommandInfo(name = "guild", description = "View the guild nickname history of a user")
public class GuildSubCommand extends BatSubCommand { public class GuildSubCommand extends BatCommand {
private final UserService userService; private final UserService userService;
@Autowired @Autowired
public GuildSubCommand(@NonNull UserService userService) { public GuildSubCommand(@NonNull UserService userService) {
this.userService = userService; this.userService = userService;
super.addOption(OptionType.USER, "user", "The user to view the name history of", false); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the name history of", false));
} }
@Override @Override

@ -15,7 +15,9 @@ import org.springframework.stereotype.Component;
public class NameHistoryCommand extends BatCommand { public class NameHistoryCommand extends BatCommand {
@Autowired @Autowired
public NameHistoryCommand(@NonNull ApplicationContext context) { public NameHistoryCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(UserSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(GuildSubCommand.class)); context.getBean(UserSubCommand.class),
context.getBean(GuildSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.namehistory.command; package cc.fascinated.bat.features.namehistory.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.namehistory.TrackedName; import cc.fascinated.bat.features.namehistory.TrackedName;
@ -14,6 +14,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,13 +23,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component("namehistory:user.sub") @Component("namehistory:user.sub")
@CommandInfo(name = "user", description = "View the global name history of a user", guildOnly = false) @CommandInfo(name = "user", description = "View the global name history of a user", guildOnly = false)
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
private final UserService userService; private final UserService userService;
@Autowired @Autowired
public UserSubCommand(@NonNull UserService userService) { public UserSubCommand(@NonNull UserService userService) {
this.userService = userService; this.userService = userService;
super.addOption(OptionType.USER, "user", "The user to view the name history of", false); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the name history of", false));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.reminder.command; package cc.fascinated.bat.features.reminder.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.reminder.ReminderProfile; import cc.fascinated.bat.features.reminder.ReminderProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("reminder:clear.sub") @Component("reminder:clear.sub")
@CommandInfo(name = "clear", description = "Clear all your active reminders.") @CommandInfo(name = "clear", description = "Clear all your active reminders.")
public class ClearSubCommand extends BatSubCommand { public class ClearSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
ReminderProfile profile = guild.getReminderProfile(); ReminderProfile profile = guild.getReminderProfile();

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.reminder.command; package cc.fascinated.bat.features.reminder.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("reminder:list.sub") @Component("reminder:list.sub")
@CommandInfo(name = "list", description = "View your active reminders.") @CommandInfo(name = "list", description = "View your active reminders.")
public class ListSubCommand extends BatSubCommand { public class ListSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
ReminderProfile profile = guild.getReminderProfile(); ReminderProfile profile = guild.getReminderProfile();

@ -15,8 +15,10 @@ import org.springframework.stereotype.Component;
public class ReminderCommand extends BatCommand { public class ReminderCommand extends BatCommand {
@Autowired @Autowired
public ReminderCommand(@NonNull ApplicationContext context) { public ReminderCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(SetSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(ListSubCommand.class)); context.getBean(SetSubCommand.class),
super.addSubCommand(context.getBean(ClearSubCommand.class)); context.getBean(ListSubCommand.class),
context.getBean(ClearSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.reminder.command; package cc.fascinated.bat.features.reminder.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.TimeUtils; import cc.fascinated.bat.common.TimeUtils;
@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Date; import java.util.Date;
@ -25,10 +26,12 @@ import java.util.concurrent.TimeUnit;
*/ */
@Component("reminder:set.sub") @Component("reminder:set.sub")
@CommandInfo(name = "set", description = "Set a reminder.") @CommandInfo(name = "set", description = "Set a reminder.")
public class SetSubCommand extends BatSubCommand { public class SetSubCommand extends BatCommand {
public SetSubCommand() { public SetSubCommand() {
super.addOption(OptionType.STRING, "reminder", "The reminder to set.", true); super.addOptions(
super.addOption(OptionType.STRING, "time", "After how long should the reminder be sent. (eg: 5m)", true); new OptionData(OptionType.STRING, "reminder", "The reminder to set.", true),
new OptionData(OptionType.STRING, "time", "After how long should the reminder be sent. (eg: 5m)", true)
);
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.numberone; package cc.fascinated.bat.features.scoresaber.command.numberone;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.TextChannelUtils; import cc.fascinated.bat.common.TextChannelUtils;
@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -23,10 +24,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber-number-one-feed:channel.sub") @Component("scoresaber-number-one-feed:channel.sub")
@CommandInfo(name = "channel", description = "Sets the feed channel") @CommandInfo(name = "channel", description = "Sets the feed channel")
public class ChannelSubCommand extends BatSubCommand { public class ChannelSubCommand extends BatCommand {
@Autowired @Autowired
public ChannelSubCommand() { public ChannelSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel scores are sent in", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel scores are sent in", false));
} }
@Override @Override

@ -14,7 +14,9 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "scoresaber-number-one-feed", description = "Modifies the settings for the feed.", requiredPermissions = Permission.MANAGE_SERVER) @CommandInfo(name = "scoresaber-number-one-feed", description = "Modifies the settings for the feed.", requiredPermissions = Permission.MANAGE_SERVER)
public class NumberOneFeedCommand extends BatCommand { public class NumberOneFeedCommand extends BatCommand {
public NumberOneFeedCommand(@NonNull ApplicationContext context) { public NumberOneFeedCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(ChannelSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(ResetSubCommand.class)); context.getBean(ChannelSubCommand.class),
context.getBean(ResetSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.numberone; package cc.fascinated.bat.features.scoresaber.command.numberone;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile; import cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber-number-one-feed:reset.sub") @Component("scoresaber-number-one-feed:reset.sub")
@CommandInfo(name = "reset", description = "Resets the settings") @CommandInfo(name = "reset", description = "Resets the settings")
public class ResetSubCommand extends BatSubCommand { public class ResetSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
NumberOneScoreFeedProfile profile = guild.getProfile(NumberOneScoreFeedProfile.class); NumberOneScoreFeedProfile profile = guild.getProfile(NumberOneScoreFeedProfile.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.scoresaber; package cc.fascinated.bat.features.scoresaber.command.scoresaber;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -21,12 +22,12 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber:link.sub") @Component("scoresaber:link.sub")
@CommandInfo(name = "link", description = "Links your ScoreSaber profile") @CommandInfo(name = "link", description = "Links your ScoreSaber profile")
public class LinkSubCommand extends BatSubCommand { public class LinkSubCommand extends BatCommand {
private final ScoreSaberService scoreSaberService; private final ScoreSaberService scoreSaberService;
@Autowired @Autowired
public LinkSubCommand(@NonNull ScoreSaberService scoreSaberService) { public LinkSubCommand(@NonNull ScoreSaberService scoreSaberService) {
super.addOption(OptionType.STRING, "link", "Link your ScoreSaber profile", true); super.addOptions(new OptionData(OptionType.STRING, "link", "Link your ScoreSaber profile", true));
this.scoreSaberService = scoreSaberService; this.scoreSaberService = scoreSaberService;
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.scoresaber; package cc.fascinated.bat.features.scoresaber.command.scoresaber;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber:me.sub") @Component("scoresaber:me.sub")
@CommandInfo(name = "me", description = "Gets your ScoreSaber profile") @CommandInfo(name = "me", description = "Gets your ScoreSaber profile")
public class MeSubCommand extends BatSubCommand { public class MeSubCommand extends BatCommand {
private final ScoreSaberService scoreSaberService; private final ScoreSaberService scoreSaberService;
@Autowired @Autowired

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.scoresaber; package cc.fascinated.bat.features.scoresaber.command.scoresaber;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile; import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber:reset.sub") @Component("scoresaber:reset.sub")
@CommandInfo(name = "reset", description = "Reset your settings") @CommandInfo(name = "reset", description = "Reset your settings")
public class ResetSubCommand extends BatSubCommand { public class ResetSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
ScoreSaberProfile profile = user.getScoreSaberProfile(); ScoreSaberProfile profile = user.getScoreSaberProfile();

@ -35,10 +35,12 @@ public class ScoreSaberCommand extends BatCommand {
public ScoreSaberCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull ApplicationContext context) { public ScoreSaberCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull ApplicationContext context) {
this.scoreSaberService = scoreSaberService; this.scoreSaberService = scoreSaberService;
super.addSubCommand(context.getBean(LinkSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(UserSubCommand.class)); context.getBean(LinkSubCommand.class),
super.addSubCommand(context.getBean(MeSubCommand.class)); context.getBean(UserSubCommand.class),
super.addSubCommand(context.getBean(ResetSubCommand.class)); context.getBean(MeSubCommand.class),
context.getBean(ResetSubCommand.class)
);
} }
/** /**

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.scoresaber; package cc.fascinated.bat.features.scoresaber.command.scoresaber;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -21,13 +22,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber:user.sub") @Component("scoresaber:user.sub")
@CommandInfo(name = "user", description = "Gets a ScoreSaber profile") @CommandInfo(name = "user", description = "Gets a ScoreSaber profile")
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
private final ScoreSaberService scoreSaberService; private final ScoreSaberService scoreSaberService;
private final UserService userService; private final UserService userService;
@Autowired @Autowired
public UserSubCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull UserService userService) { public UserSubCommand(@NonNull ScoreSaberService scoreSaberService, @NonNull UserService userService) {
super.addOption(OptionType.USER, "user", "The user to view the ScoreSaber profile of", true); super.addOptions(new OptionData(OptionType.USER, "user", "The user to view the ScoreSaber profile of", true));
this.scoreSaberService = scoreSaberService; this.scoreSaberService = scoreSaberService;
this.userService = userService; this.userService = userService;
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.userfeed; package cc.fascinated.bat.features.scoresaber.command.userfeed;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.TextChannelUtils; import cc.fascinated.bat.common.TextChannelUtils;
@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -23,10 +24,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber-user-feed:channel.sub") @Component("scoresaber-user-feed:channel.sub")
@CommandInfo(name = "channel", description = "Sets the feed channel") @CommandInfo(name = "channel", description = "Sets the feed channel")
public class ChannelSubCommand extends BatSubCommand { public class ChannelSubCommand extends BatCommand {
@Autowired @Autowired
public ChannelSubCommand() { public ChannelSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel scores are sent in", false); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel scores are sent in", false));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.userfeed; package cc.fascinated.bat.features.scoresaber.command.userfeed;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile; import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber-user-feed:reset.sub") @Component("scoresaber-user-feed:reset.sub")
@CommandInfo(name = "reset", description = "Resets the settings") @CommandInfo(name = "reset", description = "Resets the settings")
public class ResetSubCommand extends BatSubCommand { public class ResetSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
UserScoreFeedProfile profile = guild.getProfile(UserScoreFeedProfile.class); UserScoreFeedProfile profile = guild.getProfile(UserScoreFeedProfile.class);

@ -14,8 +14,10 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "scoresaber-user-feed", description = "Modifies the settings for the feed.", requiredPermissions = Permission.MANAGE_CHANNEL) @CommandInfo(name = "scoresaber-user-feed", description = "Modifies the settings for the feed.", requiredPermissions = Permission.MANAGE_CHANNEL)
public class UserFeedCommand extends BatCommand { public class UserFeedCommand extends BatCommand {
public UserFeedCommand(@NonNull ApplicationContext context) { public UserFeedCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(UserSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(ChannelSubCommand.class)); context.getBean(UserSubCommand.class),
super.addSubCommand(context.getBean(ResetSubCommand.class)); context.getBean(ChannelSubCommand.class),
context.getBean(ResetSubCommand.class
));
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber.command.userfeed; package cc.fascinated.bat.features.scoresaber.command.userfeed;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile; import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile;
@ -16,6 +16,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -24,13 +25,13 @@ import org.springframework.stereotype.Component;
*/ */
@Component("scoresaber-user-feed:user.sub") @Component("scoresaber-user-feed:user.sub")
@CommandInfo(name = "user", description = "Adds or removes a user from the feed") @CommandInfo(name = "user", description = "Adds or removes a user from the feed")
public class UserSubCommand extends BatSubCommand { public class UserSubCommand extends BatCommand {
private final GuildService guildService; private final GuildService guildService;
private final UserService userService; private final UserService userService;
@Autowired @Autowired
public UserSubCommand(GuildService guildService, UserService userService) { public UserSubCommand(GuildService guildService, UserService userService) {
super.addOption(OptionType.USER, "user", "Add or remove a user from the score feed", false); super.addOptions(new OptionData(OptionType.USER, "user", "Add or remove a user from the score feed", false));
this.guildService = guildService; this.guildService = guildService;
this.userService = userService; this.userService = userService;
} }

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.exception.BatException; import cc.fascinated.bat.exception.BatException;
@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit;
@Component @Component
@Log4j2(topic = "Spotify Current Command") @Log4j2(topic = "Spotify Current Command")
@CommandInfo(name = "current", description = "Gets the currently playing Spotify track") @CommandInfo(name = "current", description = "Gets the currently playing Spotify track")
public class CurrentSubCommand extends BatSubCommand implements EventListener { public class CurrentSubCommand extends BatCommand implements EventListener {
private final SpotifyService spotifyService; private final SpotifyService spotifyService;
@Autowired @Autowired

@ -2,7 +2,7 @@ package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Consts; import cc.fascinated.bat.Consts;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "link", description = "Link your Spotify account") @CommandInfo(name = "link", description = "Link your Spotify account")
public class LinkSubCommand extends BatSubCommand implements EventListener { public class LinkSubCommand extends BatCommand implements EventListener {
private final SpotifyService spotifyService; private final SpotifyService spotifyService;
@Autowired @Autowired

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.SpotifyFeature;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "pause", description = "Pause the current Spotify track") @CommandInfo(name = "pause", description = "Pause the current Spotify track")
public class PauseSubCommand extends BatSubCommand { public class PauseSubCommand extends BatCommand {
private final SpotifyService spotifyService; private final SpotifyService spotifyService;
@Autowired @Autowired

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.SpotifyFeature;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "resume", description = "Resume the current Spotify track") @CommandInfo(name = "resume", description = "Resume the current Spotify track")
public class ResumeSubCommand extends BatSubCommand { public class ResumeSubCommand extends BatCommand {
private final SpotifyService spotifyService; private final SpotifyService spotifyService;
@Autowired @Autowired

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.SpotifyFeature;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -20,7 +20,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "skip", description = "Skip the current Spotify track") @CommandInfo(name = "skip", description = "Skip the current Spotify track")
public class SkipSubCommand extends BatSubCommand { public class SkipSubCommand extends BatCommand {
private static final Logger log = LoggerFactory.getLogger(SkipSubCommand.class); private static final Logger log = LoggerFactory.getLogger(SkipSubCommand.class);
private final SpotifyService spotifyService; private final SpotifyService spotifyService;

@ -16,11 +16,13 @@ import org.springframework.stereotype.Component;
public class SpotifyCommand extends BatCommand { public class SpotifyCommand extends BatCommand {
@Autowired @Autowired
public SpotifyCommand(@NonNull ApplicationContext context) { public SpotifyCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(LinkSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(UnlinkSubCommand.class)); context.getBean(LinkSubCommand.class),
super.addSubCommand(context.getBean(PauseSubCommand.class)); context.getBean(UnlinkSubCommand.class),
super.addSubCommand(context.getBean(ResumeSubCommand.class)); context.getBean(PauseSubCommand.class),
super.addSubCommand(context.getBean(CurrentSubCommand.class)); context.getBean(ResumeSubCommand.class),
super.addSubCommand(context.getBean(SkipSubCommand.class)); context.getBean(CurrentSubCommand.class),
context.getBean(SkipSubCommand.class)
);
} }
} }

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
@ -21,7 +21,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@CommandInfo(name = "unlink", description = "Unlink your Spotify account") @CommandInfo(name = "unlink", description = "Unlink your Spotify account")
public class UnlinkSubCommand extends BatSubCommand implements EventListener { public class UnlinkSubCommand extends BatCommand implements EventListener {
@Override @SneakyThrows @Override @SneakyThrows
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
SpotifyProfile profile = user.getProfile(SpotifyProfile.class); SpotifyProfile profile = user.getProfile(SpotifyProfile.class);

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.tmdb.command; package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
@ -18,6 +18,7 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -27,7 +28,7 @@ import java.util.Map;
@Component @Component
@CommandInfo(name = "movie", description = "Get information about a movie") @CommandInfo(name = "movie", description = "Get information about a movie")
public class MovieSubCommand extends BatSubCommand implements EventListener { public class MovieSubCommand extends BatCommand implements EventListener {
private final TMDBService tmdbService; private final TMDBService tmdbService;
private final Map<String, Map<String, String>> userCommands; // Map to store user commands and their parameters private final Map<String, Map<String, String>> userCommands; // Map to store user commands and their parameters
@ -37,11 +38,12 @@ public class MovieSubCommand extends BatSubCommand implements EventListener {
this.tmdbService = tmdbService; this.tmdbService = tmdbService;
this.userCommands = new HashMap<>(); this.userCommands = new HashMap<>();
super.addOption(OptionType.STRING, "title", "The title of the movie", true); super.addOptions(
super.addOption(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false); new OptionData(OptionType.STRING, "title", "The title of the movie", true),
super.addOption(OptionType.STRING, "primary_release_year", "Filter the results so that only the primary release dates have this value", false); new OptionData(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false),
super.addOption(OptionType.STRING, "region", "An ISO 3166-1 code (US) to lookup movies from a specific region", false); new OptionData(OptionType.STRING, "primary_release_year", "Filter the results so that only the primary release dates have this value", false),
super.addOption(OptionType.STRING, "year", "Filter the results release dates to matches that include this value", false); new OptionData(OptionType.STRING, "region", "An ISO 3166-1 code (US) to lookup movies from a specific region", false)
);
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.tmdb.command; package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
@ -18,6 +18,7 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -27,7 +28,7 @@ import java.util.Map;
@Component @Component
@CommandInfo(name = "series", description = "Get information about a series") @CommandInfo(name = "series", description = "Get information about a series")
public class SeriesSubCommand extends BatSubCommand implements EventListener { public class SeriesSubCommand extends BatCommand implements EventListener {
private final TMDBService tmdbService; private final TMDBService tmdbService;
private final Map<String, Map<String, String>> userCommands; // Map to store user commands and their parameters private final Map<String, Map<String, String>> userCommands; // Map to store user commands and their parameters
@ -37,10 +38,12 @@ public class SeriesSubCommand extends BatSubCommand implements EventListener {
this.tmdbService = tmdbService; this.tmdbService = tmdbService;
this.userCommands = new HashMap<>(); this.userCommands = new HashMap<>();
super.addOption(OptionType.STRING, "title", "The title of the series", true); addOptions(
super.addOption(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false); new OptionData(OptionType.STRING, "title", "The title of the series", true),
super.addOption(OptionType.INTEGER, "first_air_year", "Filter the results so that only the first air year has this value", false); new OptionData(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false),
super.addOption(OptionType.INTEGER, "year", "Filter the results release dates to matches that include this value", false); new OptionData(OptionType.INTEGER, "first_air_year", "Filter the results so that only the first air year has this value", false),
new OptionData(OptionType.INTEGER, "year", "Filter the results release dates to matches that include this value", false)
);
} }
@Override @Override

@ -1,6 +1,7 @@
package cc.fascinated.bat.features.tmdb.command; package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import lombok.NonNull; import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -11,11 +12,13 @@ import org.springframework.stereotype.Component;
* @author Nick (okNick) * @author Nick (okNick)
*/ */
@Component @Component
@CommandInfo(name = "tmdb", description = "Get information about movies and TV shows", guildOnly = false, userInstall = true) @CommandInfo(name = "tmdb", description = "Get information about movies and TV shows", guildOnly = false, userInstall = true, category = Category.MOVIES_TV)
public class TMDBCommand extends BatCommand { public class TMDBCommand extends BatCommand {
@Autowired @Autowired
public TMDBCommand(@NonNull ApplicationContext context) { public TMDBCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(MovieSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(SeriesSubCommand.class)); context.getBean(MovieSubCommand.class),
context.getBean(SeriesSubCommand.class)
);
} }
} }

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.welcomer.command; package cc.fascinated.bat.features.welcomer.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.welcomer.WelcomerProfile; import cc.fascinated.bat.features.welcomer.WelcomerProfile;
@ -13,6 +13,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -20,9 +21,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("welcomer:channel.sub") @Component("welcomer:channel.sub")
@CommandInfo(name = "channel", description = "Set the welcomer channel") @CommandInfo(name = "channel", description = "Set the welcomer channel")
public class ChannelSubCommand extends BatSubCommand { public class ChannelSubCommand extends BatCommand {
public ChannelSubCommand() { public ChannelSubCommand() {
super.addOption(OptionType.CHANNEL, "channel", "The channel to send the welcomer messages to", true); super.addOptions(new OptionData(OptionType.CHANNEL, "channel", "The channel to send the welcomer messages to", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.welcomer.command; package cc.fascinated.bat.features.welcomer.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.welcomer.WelcomerPlaceholders; import cc.fascinated.bat.features.welcomer.WelcomerPlaceholders;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("welcomer:current.sub") @Component("welcomer:current.sub")
@CommandInfo(name = "current", description = "View the current welcomer configuration") @CommandInfo(name = "current", description = "View the current welcomer configuration")
public class CurrentSubCommand extends BatSubCommand { public class CurrentSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
WelcomerProfile profile = guild.getWelcomerProfile(); WelcomerProfile profile = guild.getWelcomerProfile();

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.welcomer.command; package cc.fascinated.bat.features.welcomer.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -22,12 +23,14 @@ import org.springframework.stereotype.Component;
*/ */
@Component("welcomer:embed.sub") @Component("welcomer:embed.sub")
@CommandInfo(name = "embed", description = "Set the welcomer embed (this will remove the welcomer plain message if set)") @CommandInfo(name = "embed", description = "Set the welcomer embed (this will remove the welcomer plain message if set)")
public class EmbedSubCommand extends BatSubCommand { public class EmbedSubCommand extends BatCommand {
public EmbedSubCommand() { public EmbedSubCommand() {
super.addOption(OptionType.BOOLEAN, "ping-before-send", "Should we ping the user before sending the message?", true); super.addOptions(
super.addOption(OptionType.STRING, "description", "The description of the embed", true); new OptionData(OptionType.BOOLEAN, "ping-before-send", "Should we ping the user before sending the message?", true),
super.addOption(OptionType.STRING, "color", "The color of the embed", true); new OptionData(OptionType.STRING, "description", "The description of the embed", true),
super.addOption(OptionType.STRING, "title", "The title of the embed (only set if you want a title)", false); new OptionData(OptionType.STRING, "color", "The color of the embed", true),
new OptionData(OptionType.STRING, "title", "The title of the embed (only set if you want a title)", false)
);
} }
@Override @Override

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.welcomer.command; package cc.fascinated.bat.features.welcomer.command;
import cc.fascinated.bat.Emojis; import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedDescriptionBuilder; import cc.fascinated.bat.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -22,9 +23,9 @@ import org.springframework.stereotype.Component;
*/ */
@Component("welcomer:message.sub") @Component("welcomer:message.sub")
@CommandInfo(name = "message", description = "Set the welcomer message (this will remove the welcomer embed if set)") @CommandInfo(name = "message", description = "Set the welcomer message (this will remove the welcomer embed if set)")
public class MessageSubCommand extends BatSubCommand { public class MessageSubCommand extends BatCommand {
public MessageSubCommand() { public MessageSubCommand() {
super.addOption(OptionType.STRING, "message", "The message to send", true); super.addOptions(new OptionData(OptionType.STRING, "message", "The message to send", true));
} }
@Override @Override

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.welcomer.command; package cc.fascinated.bat.features.welcomer.command;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.welcomer.WelcomerProfile; import cc.fascinated.bat.features.welcomer.WelcomerProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component("welcomer:reset.sub") @Component("welcomer:reset.sub")
@CommandInfo(name = "reset", description = "Clear the welcomer configuration") @CommandInfo(name = "reset", description = "Clear the welcomer configuration")
public class ResetSubCommand extends BatSubCommand { public class ResetSubCommand extends BatCommand {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
WelcomerProfile profile = guild.getWelcomerProfile(); WelcomerProfile profile = guild.getWelcomerProfile();

@ -16,10 +16,12 @@ import org.springframework.stereotype.Component;
public class WelcomerCommand extends BatCommand { public class WelcomerCommand extends BatCommand {
@Autowired @Autowired
public WelcomerCommand(@NonNull ApplicationContext context) { public WelcomerCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(MessageSubCommand.class)); super.addSubCommands(
super.addSubCommand(context.getBean(EmbedSubCommand.class)); context.getBean(MessageSubCommand.class),
super.addSubCommand(context.getBean(CurrentSubCommand.class)); context.getBean(EmbedSubCommand.class),
super.addSubCommand(context.getBean(ChannelSubCommand.class)); context.getBean(CurrentSubCommand.class),
super.addSubCommand(context.getBean(ResetSubCommand.class)); context.getBean(ChannelSubCommand.class),
context.getBean(ResetSubCommand.class)
);
} }
} }

@ -1,7 +1,8 @@
package cc.fascinated.bat.service; package cc.fascinated.bat.service;
import cc.fascinated.bat.Consts; import cc.fascinated.bat.Consts;
import cc.fascinated.bat.command.*; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.config.Config; import cc.fascinated.bat.config.Config;
import cc.fascinated.bat.features.base.profile.FeatureProfile; import cc.fascinated.bat.features.base.profile.FeatureProfile;
@ -21,7 +22,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
@ -59,11 +64,11 @@ public class CommandService extends ListenerAdapter {
* @param command The command to register * @param command The command to register
*/ */
public void registerCommand(@NonNull BatCommand command) { public void registerCommand(@NonNull BatCommand command) {
String commandName = command.getCommandInfo().name().toLowerCase(); String commandName = command.getInfo().getName().toLowerCase();
if (commands.get(commandName) != null) { if (commands.get(commandName) != null) {
return; return;
} }
log.info("Registered command \"{}\"", command.getCommandInfo().name()); log.info("Registered command \"{}\"", command.getInfo().getName());
commands.put(commandName, command); commands.put(commandName, command);
} }
@ -90,8 +95,7 @@ public class CommandService extends ListenerAdapter {
// Unregister all commands that Discord has but we don't // Unregister all commands that Discord has but we don't
jda.retrieveCommands().complete().forEach(command -> { jda.retrieveCommands().complete().forEach(command -> {
if (commands.containsKey(command.getName()) if (commands.containsKey(command.getName())
&& (commands.get(command.getName()).getCommandInfo().category().isHidden() || commands.get(command.getName()).getInfo().isBotOwnerOnly()) {
|| commands.get(command.getName()).getCommandInfo().botOwnerOnly())) {
jda.deleteCommandById(command.getId()).complete(); // Unregister the command on Discord jda.deleteCommandById(command.getId()).complete(); // Unregister the command on Discord
log.info("Unregistered hidden command \"{}\" from Discord", command.getName()); log.info("Unregistered hidden command \"{}\" from Discord", command.getName());
return; return;
@ -106,19 +110,19 @@ public class CommandService extends ListenerAdapter {
// Register all commands // Register all commands
List<Command> discordCommands = jda.updateCommands().addCommands(commands.values().stream() List<Command> discordCommands = jda.updateCommands().addCommands(commands.values().stream()
.filter(command -> !command.getCategory().isHidden() || !command.isBotOwnerOnly()) .filter(command -> !command.getInfo().isBotOwnerOnly())
.map(BatCommand::getCommandData).toList()).complete(); .map(BatCommand::getCommandData).toList()).complete();
for (Command discordCommand : discordCommands) { for (Command discordCommand : discordCommands) {
commands.get(discordCommand.getName()).setCommandSnowflake(discordCommand.getIdLong()); commands.get(discordCommand.getName()).setSnowflake(discordCommand.getIdLong());
if (!discordCommand.getSubcommands().isEmpty()) { if (!discordCommand.getSubcommands().isEmpty()) {
for (Command.Subcommand subCommand : discordCommand.getSubcommands()) { for (Command.Subcommand subCommand : discordCommand.getSubcommands()) {
commands.get(discordCommand.getName()).getSubCommands().get(subCommand.getName()).setCommandSnowflake(subCommand.getIdLong()); commands.get(discordCommand.getName()).getSubCommands().get(subCommand.getName()).setSnowflake(subCommand.getIdLong());
} }
} }
} }
if (adminGuild != null) { if (adminGuild != null) {
adminGuild.updateCommands().addCommands(commands.values().stream() adminGuild.updateCommands().addCommands(commands.values().stream()
.filter(command -> command.getCategory().isHidden() || command.isBotOwnerOnly()) .filter(command -> command.getInfo().isBotOwnerOnly())
.map(BatCommand::getCommandData).toList()).complete(); .map(BatCommand::getCommandData).toList()).complete();
} else { } else {
log.error("Unable to find the admin guild to register hidden commands"); log.error("Unable to find the admin guild to register hidden commands");
@ -132,111 +136,79 @@ public class CommandService extends ListenerAdapter {
* @param category The category * @param category The category
* @return The commands * @return The commands
*/ */
public List<BatCommand> getCommandsByCategory(Category category, boolean hideHiddenCategories) { public List<BatCommand> getCommandsByCategory(Category category) {
return commands.values().stream().filter(command -> command.getCategory() == category && (hideHiddenCategories && !category.isHidden())).toList(); return commands.values().stream().filter(command -> command.getInfo().getCategory() == category).toList();
} }
@Override @Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) { public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
long before = System.currentTimeMillis();
Guild discordGuild = event.getGuild();
if (event.getUser().isBot()) { if (event.getUser().isBot()) {
return; return;
} }
long before = System.currentTimeMillis();
String commandName = event.getName(); BatCommand command = commands.get(event.getName());
BatCommand command = commands.get(commandName);
if (command == null) { if (command == null) {
return; return;
} }
boolean ranInsideGuild = discordGuild != null; String subcommandName = event.getSubcommandName();
BatGuild guild = ranInsideGuild ? guildService.getGuild(discordGuild.getId()) : null; if (subcommandName != null) { // Use the sub command if given
command = command.getSubCommands().get(subcommandName);
}
BatUser user = userService.getUser(event.getUser().getId()); BatUser user = userService.getUser(event.getUser().getId());
BatGuild guild = event.getGuild() == null ? null : guildService.getGuild(event.getGuild().getId());
if (command.getCommandInfo().botOwnerOnly() && !user.getId().equalsIgnoreCase(Consts.BOT_OWNER)) { // Only the bot owner can run this command
if (command.getInfo().isBotOwnerOnly() && !user.getId().equalsIgnoreCase(Consts.BOT_OWNER)) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You do not have permission to execute this command") .setDescription("You do not have permission to execute this command")
.build()).setEphemeral(true).queue(); .build()).setEphemeral(true).queue();
return; return;
} }
try { // Check if the command is guild only and if it was not ran inside a guild
BatCommandExecutor executor = null; if (command.getInfo().isGuildOnly() && guild == null) {
CommandInfo commandInfo = command.getCommandInfo(); event.replyEmbeds(EmbedUtils.errorEmbed()
List<Permission> requiredPermissions = new ArrayList<>(); .setDescription("This command can only be executed in a guild")
.build()).setEphemeral(true).queue();
return;
}
// No args provided, use the main command executor // Check if the feature is disabled in the guild
if (event.getInteraction().getSubcommandName() == null) { if (guild != null) {
executor = command; FeatureProfile featureProfile = guild.getFeatureProfile();
requiredPermissions.addAll(Arrays.asList(command.getCommandInfo().requiredPermissions())); if (featureProfile.isFeatureDisabled(command.getFeature())) {
} else {
// Subcommand provided, use the subcommand executor
for (Map.Entry<String, BatSubCommand> subCommand : command.getSubCommands().entrySet()) {
if (subCommand.getKey().equalsIgnoreCase(event.getInteraction().getSubcommandName())) {
executor = subCommand.getValue();
requiredPermissions.addAll(Arrays.asList(subCommand.getValue().getCommandInfo().requiredPermissions()));
requiredPermissions.addAll(Arrays.asList(command.getCommandInfo().requiredPermissions())); // not sure if we'd want this, but it's here for now
commandInfo = subCommand.getValue().getCommandInfo();
break;
}
}
}
// Check if the executor is null
if (executor == null) {
event.replyEmbeds(EmbedUtils.errorEmbed() event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("Unable to find a command executor the command name ):") .setDescription("The feature `%s` is disabled in this guild".formatted(command.getFeature().getName()))
.build()).queue();
return;
}
// Check if the user has the required permissions
if (ranInsideGuild && event.getMember() != null) {
List<Permission> missingPermissions = new ArrayList<>();
for (Permission permission : requiredPermissions) {
if (!event.getMember().hasPermission(permission)) {
missingPermissions.add(permission);
}
}
if (!missingPermissions.isEmpty()) {
StringBuilder missing = new StringBuilder();
for (Permission permission : missingPermissions) {
missing.append("`").append(permission.getName()).append("`").append(", ");
}
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You are missing the following permissions to execute this command:\n" +
missing.substring(0, missing.length() - 2))
.build())
.setEphemeral(true)
.queue();
return;
}
}
// Check if the command is guild only and if it was not ran inside a guild
if (commandInfo.guildOnly() && guild == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("This command can only be executed in a guild")
.build()).setEphemeral(true).queue(); .build()).setEphemeral(true).queue();
return; return;
} }
}
// Check if the feature is disabled in the guild // Check if the user has the required permissions
if (guild != null) { if (guild != null && event.getMember() != null) {
FeatureProfile featureProfile = guild.getFeatureProfile(); List<Permission> missingPermissions = new ArrayList<>();
if (featureProfile.isFeatureDisabled(command.getFeature())) { for (Permission permission : command.getInfo().getPermissions()) {
event.replyEmbeds(EmbedUtils.errorEmbed() if (!event.getMember().hasPermission(permission)) {
.setDescription("The feature `%s` is disabled in this guild".formatted(command.getFeature().getName())) missingPermissions.add(permission);
.build()).setEphemeral(true).queue();
return;
} }
} }
if (!missingPermissions.isEmpty()) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You are missing the following permissions to execute this command:\n" +
missingPermissions.stream().map(perm -> "`" + perm.name() + "`").collect(Collectors.joining(", ")))
.build())
.setEphemeral(true)
.queue();
return;
}
}
// Execute the command // Execute the command
executor.execute(guild, user, event.getChannel(), event.getMember(), event.getInteraction()); try {
log.info("Executed command \"{}\" for user \"{}\" (took: {}ms)", commandName, user.getName(), System.currentTimeMillis() - before); command.execute(guild, user, event.getChannel(), event.getMember(), event.getInteraction());
log.info("Executed command \"{}\" for user \"{}\" (took: {}ms)", command.getInfo().getName(), user.getName(), System.currentTimeMillis() - before);
} catch (Exception ex) { } catch (Exception ex) {
log.error("An error occurred while executing command \"{}\"", commandName, ex); log.error("An error occurred while executing command \"{}\"", command.getInfo().getName(), ex);
event.replyEmbeds(EmbedUtils.genericInteractionError(ex).build()).setEphemeral(true).queue(); event.replyEmbeds(EmbedUtils.genericInteractionError(ex).build()).setEphemeral(true).queue();
} }
} }

@ -2,7 +2,6 @@ package cc.fascinated.bat.service;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
import cc.fascinated.bat.features.base.commands.server.feature.FeatureCommand;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
@ -42,21 +41,16 @@ public class FeatureService {
@PostConstruct @PostConstruct
public void init() { public void init() {
context.getBeansOfType(Feature.class) for (Feature feature : context.getBeansOfType(Feature.class).values()) {
.values() features.put(feature.getName().toLowerCase(), feature);
.forEach((feature) -> { }
features.put(feature.getName().toLowerCase(), feature);
});
context.getBeansOfType(BatCommand.class) for (BatCommand command : context.getBeansOfType(BatCommand.class).values()) {
.values() if (command.getFeature() == null) {
.forEach((command) -> { log.error("Command \"{}\" does not belong to a feature, not registering it...", command.getInfo().getName());
if (command.getFeature() == null) { }
log.error("Command \"{}\" does not belong to a feature, not registering it...", command.getCommandInfo().name()); }
}
});
commandService.registerCommand(context.getBean(FeatureCommand.class));
commandService.registerSlashCommands(); // Register all slash commands commandService.registerSlashCommands(); // Register all slash commands
} }

@ -29,7 +29,7 @@ bat:
# Sentry Configuration # Sentry Configuration
sentry: sentry:
dsn: "CHANGE_ME" dsn: ""
tracesSampleRate: 1.0 tracesSampleRate: 1.0
environment: "development" environment: "development"