New command system #7

Merged
Fascinated merged 3 commits from Rainnny/Bat:master into master 2024-07-04 12:58:35 +00:00
95 changed files with 603 additions and 560 deletions

22
pom.xml

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

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

@ -1,103 +1,123 @@
package cc.fascinated.bat.command;
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.NonNull;
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.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.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author Fascinated (fascinated7)
* @author Braydon
*/
@Getter
@Setter
public abstract class BatCommand implements BatCommandExecutor {
public abstract class BatCommand {
/**
* 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;
/**
* The command snowflake from Discord
*/
private long commandSnowflake;
@Setter(AccessLevel.PRIVATE) private SubcommandData subcommandData;
public BatCommand() {
this.commandInfo = getClass().getAnnotation(CommandInfo.class);
this.category = this.commandInfo.category();
this.botOwnerOnly = this.commandInfo.botOwnerOnly();
if (!getClass().isAnnotationPresent(CommandInfo.class)) {
throw new IllegalStateException("Missing @CommandInfo annotation in " + getClass().getSimpleName());
}
info = new InternalCommandInfo(getClass().getAnnotation(CommandInfo.class));
List<IntegrationType> integrationTypes = this.commandInfo.userInstall() ? List.of(IntegrationType.GUILD_INSTALL, IntegrationType.USER_INSTALL) :
List.of(IntegrationType.GUILD_INSTALL);
this.commandData = new CommandDataImpl(this.commandInfo.name(), this.commandInfo.description())
.setGuildOnly(this.commandInfo.guildOnly())
List<IntegrationType> integrationTypes = new ArrayList<>(Collections.singletonList(IntegrationType.GUILD_INSTALL));
if (info.isUserInstall()) {
integrationTypes.add(IntegrationType.USER_INSTALL);
}
commandData = new CommandDataImpl(info.getName(), info.getDescription())
.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) {
this.subCommands.put(subCommand.getCommandInfo().name().toLowerCase(), subCommand);
this.commandData.addSubcommands(subCommand.getCommandData());
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { }
/**
* 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 name the name of the option
* @param description the description of the option
* @param required whether the option is required
* @param options the options to add
*/
protected void addOption(OptionType optionType, String name, String description, boolean required) {
this.commandData.addOption(optionType, name, description, required);
protected final void addOptions(OptionData... options) {
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.Getter;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import java.util.Arrays;
import java.util.List;
/**
* @author Fascinated (fascinated7)
*/
@AllArgsConstructor
@Getter
public enum Category {
GENERAL(Emoji.fromUnicode("U+2699"), "General", false),
FUN(Emoji.fromFormatted("U+1F973"), "Fun", false),
SERVER(Emoji.fromFormatted("U+1F5A5"), "Server", false),
MODERATION(Emoji.fromFormatted("U+1F6E0"), "Moderation", false),
UTILITY(Emoji.fromFormatted("U+1F6E0"), "Utility", false),
MUSIC(Emoji.fromFormatted("U+1F3B5"), "Music", false),
MOVIES_TV(Emoji.fromFormatted("U+1F3A5"), "Movies & TV", false),
MESSAGES(Emoji.fromFormatted("U+1F4A3"), "Messages", false),
LOGS(Emoji.fromFormatted("U+1F4D1"), "Logs", false),
BEAT_SABER(Emoji.fromFormatted("U+1FA84"), "Beat Saber", false),
BOT_ADMIN(null, null, true);
GENERAL(Emoji.fromUnicode("U+2699"), "General"),
FUN(Emoji.fromFormatted("U+1F973"), "Fun"),
SERVER(Emoji.fromFormatted("U+1F5A5"), "Server"),
MODERATION(Emoji.fromFormatted("U+1F6E0"), "Moderation"),
UTILITY(Emoji.fromFormatted("U+1F6E0"), "Utility"),
MUSIC(Emoji.fromFormatted("U+1F3B5"), "Music"),
MOVIES_TV(Emoji.fromFormatted("U+1F3A5"), "Movies & TV"),
MESSAGES(Emoji.fromFormatted("U+1F4A3"), "Messages"),
LOGS(Emoji.fromFormatted("U+1F4D1"), "Logs"),
BEAT_SABER(Emoji.fromFormatted("U+1FA84"), "Beat Saber");
/**
* The emoji for the category
*/
private final Emoji emoji;
@NonNull private final Emoji emoji;
/**
* The name of the category
*/
private final String name;
/**
* If the category is hidden
*/
private final boolean hidden;
@NonNull private final String name;
/**
* Gets a category by its name
@ -54,13 +46,4 @@ public enum Category {
}
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;
/**
* Annotated at the top of a class to define
* the default values for a {@link BatCommand}.
*
* @author Fascinated (fascinated7)
*/
@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
*/
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);
for (BatCommand subCommand : command.getSubCommands().values()) {
subCommand.setFeature(this);
}
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -21,9 +22,18 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "afk", description = "Sets your AFK status")
public class AfkCommand extends BatCommand {
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
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
AfkProfile profile = guild.getProfile(AfkProfile.class);

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/
@Component("autoroles:add.sub")
@CommandInfo(name = "add", description = "Adds a role to the auto roles list")
public class AddSubCommand extends BatSubCommand {
public class AddSubCommand extends BatCommand {
@Autowired
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

@ -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)
public class AutoRoleCommand extends BatCommand {
public AutoRoleCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(ListSubCommand.class));
super.addSubCommand(context.getBean(AddSubCommand.class));
super.addSubCommand(context.getBean(RemoveSubCommand.class));
super.addSubCommand(context.getBean(ClearSubCommand.class));
super.addSubCommands(
context.getBean(ListSubCommand.class),
context.getBean(AddSubCommand.class),
context.getBean(RemoveSubCommand.class),
context.getBean(ClearSubCommand.class)
);
}
}

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -21,10 +22,10 @@ import org.springframework.stereotype.Component;
*/
@Component("autoroles:remove.sub")
@CommandInfo(name = "remove", description = "Removes a role from the auto roles list")
public class RemoveSubCommand extends BatSubCommand {
public class RemoveSubCommand extends BatCommand {
@Autowired
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

@ -1,7 +1,6 @@
package cc.fascinated.bat.features.base.commands.botadmin.premium;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
@ -12,11 +11,13 @@ import org.springframework.stereotype.Component;
* @author Fascinated (fascinated7)
*/
@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 {
@Autowired
public PremiumAdminCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(SetSubCommand.class));
super.addSubCommand(context.getBean(RemoveSubCommand.class));
super.addSubCommands(
context.getBean(SetSubCommand.class),
context.getBean(RemoveSubCommand.class)
);
}
}

@ -1,6 +1,6 @@
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.model.BatGuild;
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.OptionType;
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.stereotype.Component;
@ -20,13 +21,13 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "remove", description = "Remove premium from a guild")
public class RemoveSubCommand extends BatSubCommand {
public class RemoveSubCommand extends BatCommand {
private final GuildService guildService;
@Autowired
public RemoveSubCommand(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

@ -1,6 +1,6 @@
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.model.BatGuild;
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.OptionType;
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.stereotype.Component;
@ -20,14 +21,16 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "set", description = "Adds premium to a guild")
public class SetSubCommand extends BatSubCommand {
public class SetSubCommand extends BatCommand {
private final GuildService guildService;
@Autowired
public SetSubCommand(@NonNull GuildService guildService) {
this.guildService = guildService;
super.addOption(OptionType.STRING, "guild", "The guild id to set as premium", true);
super.addOption(OptionType.BOOLEAN, "infinite", "Whether the premium length should be infinite", true);
super.addOptions(
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

@ -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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -24,7 +25,7 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "lookupuser", description = "Lookup a user", userInstall = true)
public class LookupUserCommand extends BatCommand {
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

@ -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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -43,7 +44,7 @@ public class EightBallCommand extends BatCommand {
};
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "cat", description = "Get a random cat image")
public class CatSubCommand extends BatSubCommand {
public class CatSubCommand extends BatCommand {
@Override
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);

@ -1,6 +1,6 @@
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.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "dog", description = "Get a random dog image")
public class DogSubCommand extends BatSubCommand {
public class DogSubCommand extends BatCommand {
@Override
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);

@ -1,6 +1,6 @@
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.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "duck", description = "Get a random duck image")
public class DuckSubCommand extends BatSubCommand {
public class DuckSubCommand extends BatCommand {
@Override
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);

@ -1,6 +1,6 @@
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.common.EmbedUtils;
import cc.fascinated.bat.common.WebRequest;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "fox", description = "Get a random fox image")
public class FoxSubCommand extends BatSubCommand {
public class FoxSubCommand extends BatCommand {
@Override
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);

@ -16,9 +16,11 @@ import org.springframework.stereotype.Component;
public class ImageCommand extends BatCommand {
@Autowired
public ImageCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(CatSubCommand.class));
super.addSubCommand(context.getBean(DogSubCommand.class));
super.addSubCommand(context.getBean(FoxSubCommand.class));
super.addSubCommand(context.getBean(DuckSubCommand.class));
super.addSubCommands(
context.getBean(CatSubCommand.class),
context.getBean(DogSubCommand.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.command.BatCommand;
import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo;
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.events.interaction.component.StringSelectInteractionEvent;
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.LayoutComponent;
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.List;
import java.util.Map;
/**
* @author Fascinated (fascinated7)
@ -62,44 +59,45 @@ public class HelpCommand extends BatCommand implements EventListener {
event.reply("Invalid category selected.").queue();
return;
}
event.reply("hello this doesnt work yet").queue();
StringBuilder commands = new StringBuilder();
List<BatCommand> categoryCommands = commandService.getCommandsByCategory(category, true);
if (categoryCommands.isEmpty()) {
commands = new StringBuilder("No commands available in this category.");
} else {
for (BatCommand command : categoryCommands) {
if (!command.getSubCommands().isEmpty()) {
for (Map.Entry<String, BatSubCommand> entry : command.getSubCommands().entrySet()) {
BatSubCommand subCommand = entry.getValue();
SubcommandData commandData = subCommand.getCommandData();
commands.append("</%s %s:%s> - %s\n".formatted(
command.getCommandInfo().name(),
commandData.getName(),
subCommand.getCommandSnowflake(),
commandData.getDescription()
));
}
continue;
}
commands.append("</%s:%s> - %s\n".formatted(
command.getCommandInfo().name(),
command.getCommandSnowflake(),
command.getCommandInfo().description()
));
}
}
int subCommands = categoryCommands.stream().mapToInt(command -> command.getSubCommands().size()).sum();
event.editMessageEmbeds(EmbedUtils.genericEmbed()
.setAuthor("%s Category".formatted(category.getName()))
.setDescription("%s command%s (with %s sub-command%s)\n\n**Commands:**\n%s".formatted(
categoryCommands.size(),
categoryCommands.size() == 1 ? "" : "s",
subCommands,
subCommands == 1 ? "" : "s",
commands.toString()
)).build()).queue();
// StringBuilder commands = new StringBuilder();
// List<BatCommand> categoryCommands = commandService.getCommandsByCategory(category, true);
// if (categoryCommands.isEmpty()) {
// commands = new StringBuilder("No commands available in this category.");
// } else {
// for (BatCommand command : categoryCommands) {
// if (!command.getSubCommands().isEmpty()) {
// for (Map.Entry<String, BatSubCommand> entry : command.getSubCommands().entrySet()) {
// BatSubCommand subCommand = entry.getValue();
// SubcommandData commandData = subCommand.getCommandData();
// commands.append("</%s %s:%s> - %s\n".formatted(
// command.getCommandInfo().name(),
// commandData.getName(),
// subCommand.getCommandSnowflake(),
// commandData.getDescription()
// ));
// }
// continue;
// }
// commands.append("</%s:%s> - %s\n".formatted(
// command.getCommandInfo().name(),
// command.getCommandSnowflake(),
// command.getCommandInfo().description()
// ));
// }
// }
//
// int subCommands = categoryCommands.stream().mapToInt(command -> command.getSubCommands().size()).sum();
// event.editMessageEmbeds(EmbedUtils.genericEmbed()
// .setAuthor("%s Category".formatted(category.getName()))
// .setDescription("%s command%s (with %s sub-command%s)\n\n**Commands:**\n%s".formatted(
// categoryCommands.size(),
// categoryCommands.size() == 1 ? "" : "s",
// subCommands,
// subCommands == 1 ? "" : "s",
// commands.toString()
// )).build()).queue();
}
/**
@ -109,8 +107,8 @@ public class HelpCommand extends BatCommand implements EventListener {
*/
private MessageEmbed createHomeEmbed() {
StringBuilder categories = new StringBuilder();
for (Category category : Category.getCategories()) {
long commandCount = commandService.getCommandsByCategory(category, true).size();
for (Category category : Category.values()) {
long commandCount = commandService.getCommandsByCategory(category).size();
categories.append("➜ %s - **%s Command%s**\n".formatted(
category.getName(),
commandCount,
@ -140,9 +138,9 @@ public class HelpCommand extends BatCommand implements EventListener {
private LayoutComponent[] createHomeActions() {
List<SelectOption> options = new ArrayList<>();
options.add(SelectOption.of("Home", "home").withEmoji(Emoji.fromUnicode("U+1F3E0")));
options.addAll(Category.getCategories().stream().map(category ->
SelectOption.of(category.getName(), category.getName()).withEmoji(category.getEmoji()))
.toList());
for (Category category : Category.values()) {
options.add(SelectOption.of(category.getName(), category.getName()).withEmoji(category.getEmoji()));
}
return new LayoutComponent[]{
ActionRow.of(

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -19,9 +20,9 @@ import org.springframework.stereotype.Component;
*/
@Component("avatar:user.sub")
@CommandInfo(name = "user", description = "View the avatar of a user", guildOnly = false)
public class UserSubCommand extends BatSubCommand {
public class UserSubCommand extends BatCommand {
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

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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 org.springframework.stereotype.Component;
@ -20,9 +21,9 @@ import org.springframework.stereotype.Component;
*/
@Component("banner:user.sub")
@CommandInfo(name = "user", description = "View the banner of a user", guildOnly = false)
public class UserSubCommand extends BatSubCommand {
public class UserSubCommand extends BatCommand {
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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -20,9 +21,9 @@ import org.springframework.stereotype.Component;
*/
@Component
@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() {
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* @author Nick (okNick)
*/
@Component
@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() {
super.addOption(OptionType.STRING, "topic", "The topic to set", true);
super.addOption(OptionType.CHANNEL, "channel", "The channel to set the topic of", false);
super.addOptions(
new OptionData(OptionType.STRING, "topic", "The topic to set", true),
new OptionData(OptionType.CHANNEL, "channel", "The channel to set the topic of", false)
);
}
@Override
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)) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("<#%s> is not a text channel!".formatted(target.getId()))
@ -37,7 +42,7 @@ public class SetTopicSubCommand extends BatSubCommand {
return;
}
String topic = event.getOption("topic").getAsString();
String topic = Objects.requireNonNull(event.getOption("topic")).getAsString();
if (topic.length() > 1024) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("The topic must be 1024 characters or less!")

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -19,9 +20,9 @@ import org.springframework.stereotype.Component;
*/
@Component
@CommandInfo(name = "viewtopic", description = "View the topic of a channel")
public class ViewTopicSubCommand extends BatSubCommand {
public class ViewTopicSubCommand extends BatCommand {
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/
@Component("feature:disable.sub")
@CommandInfo(name = "disable", description = "Disables a feature")
public class DisableSubCommand extends BatSubCommand {
public class DisableSubCommand extends BatCommand {
@Autowired
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/
@Component("feature:enable.sub")
@CommandInfo(name = "enable", description = "Enables a feature")
public class EnableSubCommand extends BatSubCommand {
public class EnableSubCommand extends BatCommand {
@Autowired
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

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

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -24,10 +25,10 @@ import org.springframework.stereotype.Component;
*/
@Component("birthday:channel.sub")
@CommandInfo(name = "channel", description = "Sets the birthday notification channel", requiredPermissions = Permission.MANAGE_SERVER)
public class ChannelSubCommand extends BatSubCommand {
public class ChannelSubCommand extends BatCommand {
@Autowired
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/
@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)
public class MessageSubCommand extends BatSubCommand {
public class MessageSubCommand extends BatCommand {
@Autowired
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,10 +23,10 @@ import org.springframework.stereotype.Component;
*/
@Component("birthday:private.sub")
@CommandInfo(name = "private", description = "Changes whether your birthday is private or not")
public class PrivateSubCommand extends BatSubCommand {
public class PrivateSubCommand extends BatCommand {
@Autowired
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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -26,12 +27,12 @@ import java.util.Date;
*/
@Component("birthday:add.sub")
@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");
@Autowired
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -23,13 +24,13 @@ import org.springframework.stereotype.Component;
*/
@Component("birthday:view.sub")
@CommandInfo(name = "view", description = "Add your birthday to this guild")
public class ViewSubCommand extends BatSubCommand {
public class ViewSubCommand extends BatCommand {
private final UserService userService;
@Autowired
public ViewSubCommand(@NonNull 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

@ -15,6 +15,6 @@ import org.springframework.stereotype.Component;
public class DragCommand extends BatCommand {
@Autowired
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;
import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils;
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.OptionType;
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.buttons.Button;
import org.springframework.stereotype.Component;
@ -30,7 +31,7 @@ import java.util.Set;
*/
@Component
@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
*/
@ -40,7 +41,7 @@ public class RequestSubCommand extends BatSubCommand implements EventListener {
private final long checkInterval = Duration.ofSeconds(10).toMillis();
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(() -> {
Set<DragRequest> toRemove = new HashSet<>();

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.logging.command;
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.common.EmbedDescriptionBuilder;
import cc.fascinated.bat.common.EmbedUtils;
@ -30,7 +30,7 @@ import java.util.List;
*/
@Component("logs:list.sub")
@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
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
List<Button> buttons = new ArrayList<>();

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

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.logging.command;
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.common.EmbedDescriptionBuilder;
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
import java.util.List;
@ -25,9 +26,9 @@ import java.util.List;
*/
@Component("logs:remove.sub")
@CommandInfo(name = "remove", description = "Remove the channel for a log type")
public class RemoveSubCommand extends BatSubCommand {
public class RemoveSubCommand extends BatCommand {
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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
import cc.fascinated.bat.features.messagesnipe.MessageSnipeFeature;
@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
*/
@Component("messagesnipe:clear.sub")
@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
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
boolean cleared = MessageSnipeFeature.clearSnipedMessages(guild);

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

@ -13,7 +13,9 @@ import org.springframework.stereotype.Component;
@CommandInfo(name = "snipe", description = "Snipe messages")
public class MessageSnipeCommand extends BatCommand {
public MessageSnipeCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(DeletedSubCommand.class));
super.addSubCommand(context.getBean(ClearSubCommand.class));
super.addSubCommands(
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
import java.util.List;
@ -28,7 +29,7 @@ public class PurgeCommand extends BatCommand {
private final long MESSAGE_DELETE_DELAY = TimeUnit.SECONDS.toMillis(10);
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,13 +23,13 @@ import org.springframework.stereotype.Component;
*/
@Component("namehistory:guild.sub")
@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;
@Autowired
public GuildSubCommand(@NonNull 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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -22,13 +23,13 @@ import org.springframework.stereotype.Component;
*/
@Component("namehistory:user.sub")
@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;
@Autowired
public UserSubCommand(@NonNull 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

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

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
import java.util.Date;
@ -25,10 +26,12 @@ import java.util.concurrent.TimeUnit;
*/
@Component("reminder:set.sub")
@CommandInfo(name = "set", description = "Set a reminder.")
public class SetSubCommand extends BatSubCommand {
public class SetSubCommand extends BatCommand {
public SetSubCommand() {
super.addOption(OptionType.STRING, "reminder", "The reminder to set.", true);
super.addOption(OptionType.STRING, "time", "After how long should the reminder be sent. (eg: 5m)", true);
super.addOptions(
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -23,10 +24,10 @@ import org.springframework.stereotype.Component;
*/
@Component("scoresaber-number-one-feed:channel.sub")
@CommandInfo(name = "channel", description = "Sets the feed channel")
public class ChannelSubCommand extends BatSubCommand {
public class ChannelSubCommand extends BatCommand {
@Autowired
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

@ -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)
public class NumberOneFeedCommand extends BatCommand {
public NumberOneFeedCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(ChannelSubCommand.class));
super.addSubCommand(context.getBean(ResetSubCommand.class));
super.addSubCommands(
context.getBean(ChannelSubCommand.class),
context.getBean(ResetSubCommand.class)
);
}
}

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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")
@CommandInfo(name = "reset", description = "Resets the settings")
public class ResetSubCommand extends BatSubCommand {
public class ResetSubCommand extends BatCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
NumberOneScoreFeedProfile profile = guild.getProfile(NumberOneScoreFeedProfile.class);

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -21,12 +22,12 @@ import org.springframework.stereotype.Component;
*/
@Component("scoresaber:link.sub")
@CommandInfo(name = "link", description = "Links your ScoreSaber profile")
public class LinkSubCommand extends BatSubCommand {
public class LinkSubCommand extends BatCommand {
private final ScoreSaberService scoreSaberService;
@Autowired
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;
}

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

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -21,13 +22,13 @@ import org.springframework.stereotype.Component;
*/
@Component("scoresaber:user.sub")
@CommandInfo(name = "user", description = "Gets a ScoreSaber profile")
public class UserSubCommand extends BatSubCommand {
public class UserSubCommand extends BatCommand {
private final ScoreSaberService scoreSaberService;
private final UserService userService;
@Autowired
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.userService = userService;
}

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -23,10 +24,10 @@ import org.springframework.stereotype.Component;
*/
@Component("scoresaber-user-feed:channel.sub")
@CommandInfo(name = "channel", description = "Sets the feed channel")
public class ChannelSubCommand extends BatSubCommand {
public class ChannelSubCommand extends BatCommand {
@Autowired
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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
import cc.fascinated.bat.features.scoresaber.profile.guild.UserScoreFeedProfile;
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component;
*/
@Component("scoresaber-user-feed:reset.sub")
@CommandInfo(name = "reset", description = "Resets the settings")
public class ResetSubCommand extends BatSubCommand {
public class ResetSubCommand extends BatCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
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)
public class UserFeedCommand extends BatCommand {
public UserFeedCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(UserSubCommand.class));
super.addSubCommand(context.getBean(ChannelSubCommand.class));
super.addSubCommand(context.getBean(ResetSubCommand.class));
super.addSubCommands(
context.getBean(UserSubCommand.class),
context.getBean(ChannelSubCommand.class),
context.getBean(ResetSubCommand.class
));
}
}

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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.stereotype.Component;
@ -24,13 +25,13 @@ import org.springframework.stereotype.Component;
*/
@Component("scoresaber-user-feed:user.sub")
@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 UserService userService;
@Autowired
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.userService = userService;
}

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.spotify.command;
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.event.EventListener;
import cc.fascinated.bat.exception.BatException;
@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit;
@Component
@Log4j2(topic = "Spotify Current Command")
@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;
@Autowired

@ -2,7 +2,7 @@ package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Consts;
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.common.EmbedUtils;
import cc.fascinated.bat.event.EventListener;
@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@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;
@Autowired

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

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

@ -1,6 +1,6 @@
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.features.spotify.SpotifyFeature;
import cc.fascinated.bat.model.BatGuild;
@ -20,7 +20,7 @@ import org.springframework.stereotype.Component;
*/
@Component
@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 final SpotifyService spotifyService;

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

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

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -27,7 +28,7 @@ import java.util.Map;
@Component
@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 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.userCommands = new HashMap<>();
super.addOption(OptionType.STRING, "title", "The title of the movie", true);
super.addOption(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false);
super.addOption(OptionType.STRING, "primary_release_year", "Filter the results so that only the primary release dates have this value", false);
super.addOption(OptionType.STRING, "region", "An ISO 3166-1 code (US) to lookup movies from a specific region", false);
super.addOption(OptionType.STRING, "year", "Filter the results release dates to matches that include this value", false);
super.addOptions(
new OptionData(OptionType.STRING, "title", "The title of the movie", true),
new OptionData(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false),
new OptionData(OptionType.STRING, "primary_release_year", "Filter the results so that only the primary release dates have this value", false),
new OptionData(OptionType.STRING, "region", "An ISO 3166-1 code (US) to lookup movies from a specific region", false)
);
}
@Override

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -27,7 +28,7 @@ import java.util.Map;
@Component
@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 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.userCommands = new HashMap<>();
super.addOption(OptionType.STRING, "title", "The title of the series", true);
super.addOption(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", false);
super.addOption(OptionType.INTEGER, "first_air_year", "Filter the results so that only the first air year has this value", false);
super.addOption(OptionType.INTEGER, "year", "Filter the results release dates to matches that include this value", false);
addOptions(
new OptionData(OptionType.STRING, "title", "The title of the series", true),
new OptionData(OptionType.STRING, "language", "A locale code (en-US) to lookup movies in a specific language", 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

@ -1,6 +1,7 @@
package cc.fascinated.bat.features.tmdb.command;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.command.CommandInfo;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
@ -11,11 +12,13 @@ import org.springframework.stereotype.Component;
* @author Nick (okNick)
*/
@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 {
@Autowired
public TMDBCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(MovieSubCommand.class));
super.addSubCommand(context.getBean(SeriesSubCommand.class));
super.addSubCommands(
context.getBean(MovieSubCommand.class),
context.getBean(SeriesSubCommand.class)
);
}
}

@ -1,6 +1,6 @@
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.common.EmbedUtils;
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -20,9 +21,9 @@ import org.springframework.stereotype.Component;
*/
@Component("welcomer:channel.sub")
@CommandInfo(name = "channel", description = "Set the welcomer channel")
public class ChannelSubCommand extends BatSubCommand {
public class ChannelSubCommand extends BatCommand {
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

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

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.welcomer.command;
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.common.EmbedDescriptionBuilder;
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -22,12 +23,14 @@ import org.springframework.stereotype.Component;
*/
@Component("welcomer:embed.sub")
@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() {
super.addOption(OptionType.BOOLEAN, "ping-before-send", "Should we ping the user before sending the message?", true);
super.addOption(OptionType.STRING, "description", "The description of the embed", true);
super.addOption(OptionType.STRING, "color", "The color of the embed", true);
super.addOption(OptionType.STRING, "title", "The title of the embed (only set if you want a title)", false);
super.addOptions(
new OptionData(OptionType.BOOLEAN, "ping-before-send", "Should we ping the user before sending the message?", true),
new OptionData(OptionType.STRING, "description", "The description of the embed", true),
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

@ -1,7 +1,7 @@
package cc.fascinated.bat.features.welcomer.command;
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.common.EmbedDescriptionBuilder;
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.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import org.springframework.stereotype.Component;
/**
@ -22,9 +23,9 @@ import org.springframework.stereotype.Component;
*/
@Component("welcomer:message.sub")
@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() {
super.addOption(OptionType.STRING, "message", "The message to send", true);
super.addOptions(new OptionData(OptionType.STRING, "message", "The message to send", true));
}
@Override

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

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

@ -1,7 +1,8 @@
package cc.fascinated.bat.service;
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.config.Config;
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.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)
@ -59,11 +64,11 @@ public class CommandService extends ListenerAdapter {
* @param command The command to register
*/
public void registerCommand(@NonNull BatCommand command) {
String commandName = command.getCommandInfo().name().toLowerCase();
String commandName = command.getInfo().getName().toLowerCase();
if (commands.get(commandName) != null) {
return;
}
log.info("Registered command \"{}\"", command.getCommandInfo().name());
log.info("Registered command \"{}\"", command.getInfo().getName());
commands.put(commandName, command);
}
@ -90,8 +95,7 @@ public class CommandService extends ListenerAdapter {
// Unregister all commands that Discord has but we don't
jda.retrieveCommands().complete().forEach(command -> {
if (commands.containsKey(command.getName())
&& (commands.get(command.getName()).getCommandInfo().category().isHidden()
|| commands.get(command.getName()).getCommandInfo().botOwnerOnly())) {
|| commands.get(command.getName()).getInfo().isBotOwnerOnly()) {
jda.deleteCommandById(command.getId()).complete(); // Unregister the command on Discord
log.info("Unregistered hidden command \"{}\" from Discord", command.getName());
return;
@ -106,19 +110,19 @@ public class CommandService extends ListenerAdapter {
// Register all commands
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();
for (Command discordCommand : discordCommands) {
commands.get(discordCommand.getName()).setCommandSnowflake(discordCommand.getIdLong());
commands.get(discordCommand.getName()).setSnowflake(discordCommand.getIdLong());
if (!discordCommand.getSubcommands().isEmpty()) {
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) {
adminGuild.updateCommands().addCommands(commands.values().stream()
.filter(command -> command.getCategory().isHidden() || command.isBotOwnerOnly())
.filter(command -> command.getInfo().isBotOwnerOnly())
.map(BatCommand::getCommandData).toList()).complete();
} else {
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
* @return The commands
*/
public List<BatCommand> getCommandsByCategory(Category category, boolean hideHiddenCategories) {
return commands.values().stream().filter(command -> command.getCategory() == category && (hideHiddenCategories && !category.isHidden())).toList();
public List<BatCommand> getCommandsByCategory(Category category) {
return commands.values().stream().filter(command -> command.getInfo().getCategory() == category).toList();
}
@Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
long before = System.currentTimeMillis();
Guild discordGuild = event.getGuild();
if (event.getUser().isBot()) {
return;
}
String commandName = event.getName();
BatCommand command = commands.get(commandName);
long before = System.currentTimeMillis();
BatCommand command = commands.get(event.getName());
if (command == null) {
return;
}
boolean ranInsideGuild = discordGuild != null;
BatGuild guild = ranInsideGuild ? guildService.getGuild(discordGuild.getId()) : null;
String subcommandName = event.getSubcommandName();
if (subcommandName != null) { // Use the sub command if given
command = command.getSubCommands().get(subcommandName);
}
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()
.setDescription("You do not have permission to execute this command")
.build()).setEphemeral(true).queue();
return;
}
try {
BatCommandExecutor executor = null;
CommandInfo commandInfo = command.getCommandInfo();
List<Permission> requiredPermissions = new ArrayList<>();
// Check if the command is guild only and if it was not ran inside a guild
if (command.getInfo().isGuildOnly() && guild == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("This command can only be executed in a guild")
.build()).setEphemeral(true).queue();
return;
}
// No args provided, use the main command executor
if (event.getInteraction().getSubcommandName() == null) {
executor = command;
requiredPermissions.addAll(Arrays.asList(command.getCommandInfo().requiredPermissions()));
} 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) {
// Check if the feature is disabled in the guild
if (guild != null) {
FeatureProfile featureProfile = guild.getFeatureProfile();
if (featureProfile.isFeatureDisabled(command.getFeature())) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("Unable to find a command executor the command name ):")
.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")
.setDescription("The feature `%s` is disabled in this guild".formatted(command.getFeature().getName()))
.build()).setEphemeral(true).queue();
return;
}
}
// Check if the feature is disabled in the guild
if (guild != null) {
FeatureProfile featureProfile = guild.getFeatureProfile();
if (featureProfile.isFeatureDisabled(command.getFeature())) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("The feature `%s` is disabled in this guild".formatted(command.getFeature().getName()))
.build()).setEphemeral(true).queue();
return;
// Check if the user has the required permissions
if (guild != null && event.getMember() != null) {
List<Permission> missingPermissions = new ArrayList<>();
for (Permission permission : command.getInfo().getPermissions()) {
if (!event.getMember().hasPermission(permission)) {
missingPermissions.add(permission);
}
}
if (!missingPermissions.isEmpty()) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You are missing the following permissions to execute this command:\n" +
missingPermissions.stream().map(perm -> "`" + perm.name() + "`").collect(Collectors.joining(", ")))
.build())
.setEphemeral(true)
.queue();
return;
}
}
// Execute the command
executor.execute(guild, user, event.getChannel(), event.getMember(), event.getInteraction());
log.info("Executed command \"{}\" for user \"{}\" (took: {}ms)", commandName, user.getName(), System.currentTimeMillis() - before);
// Execute the command
try {
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) {
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();
}
}

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

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