From 34f7b18773bb245323a768f2792cf1d3e3df8dd2 Mon Sep 17 00:00:00 2001 From: Dynxsty Date: Sun, 20 Feb 2022 03:34:30 +0100 Subject: [PATCH 1/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8dac59db..f8013911 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ An very easy-to-use Interaction Handler for JDA! ```gradle plugins { id 'java' - id 'jitpack' + maven { url 'https://jitpack.io' } } dependencies { From 828d88a113cc5ec9b231adef1cf2816fef8fefeb Mon Sep 17 00:00:00 2001 From: Dynxsty Date: Sun, 20 Feb 2022 04:03:28 +0100 Subject: [PATCH 2/6] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f8013911..bd6255bf 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ An very easy-to-use Interaction Handler for JDA! ## Maven ```xml - com.dynxsty - dih4jda + com.github.DynxstyGIT + DIH4JDA ${DIH4JDA_VERSION} ``` @@ -23,7 +23,7 @@ plugins { dependencies { [...] - implementation 'com.dynxsty:dih4jda:${DIH4JDA_VERSION}' + implementation 'com.github.DynxstyGIT:DIH4JDA:${DIH4JDA_VERSION}' implementation 'org.reflections:reflections:0.10.2' implementation 'net.dv8tion:JDA:5.0.0-alpha.5' } From 08c375f861db9f7fbc43f4d21a21a75c2b8c7eb2 Mon Sep 17 00:00:00 2001 From: Dynxsty Date: Sun, 20 Feb 2022 15:26:06 +0100 Subject: [PATCH 3/6] First attempt of adding support for context menu commands --- .../java/com/dynxsty/dih4jda/DIH4JDA.java | 15 +- .../dih4jda/commands/InteractionHandler.java | 426 ++++++++++++++++++ .../dih4jda/commands/SlashCommandHandler.java | 269 ----------- .../commands/dto/GlobalSlashCommand.java | 3 - .../commands/dto/GuildSlashCommand.java | 3 - .../context/IMessageContextCommand.java | 7 + .../context/IUserContextCommand.java | 7 + .../context/MessageContextInteraction.java | 21 + .../context/UserContextInteraction.java | 21 + .../context/dao/BaseContextCommand.java | 23 + .../context/dao/GlobalContextCommand.java | 4 + .../context/dao/GuildContextCommand.java | 4 + .../slash}/ISlashCommand.java | 2 +- .../slash}/SlashCommandInteraction.java | 2 +- .../slash/dao/BaseSlashCommand.java} | 6 +- .../slash/dao/GlobalSlashCommand.java | 3 + .../slash/dao/GuildSlashCommand.java | 3 + .../slash/dao}/SlashSubcommand.java | 2 +- .../slash/dao}/SlashSubcommandGroup.java | 2 +- .../exceptions/InvalidParentException.java | 11 + 20 files changed, 546 insertions(+), 288 deletions(-) create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java delete mode 100644 src/main/java/com/dynxsty/dih4jda/commands/SlashCommandHandler.java delete mode 100644 src/main/java/com/dynxsty/dih4jda/commands/dto/GlobalSlashCommand.java delete mode 100644 src/main/java/com/dynxsty/dih4jda/commands/dto/GuildSlashCommand.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IMessageContextCommand.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IUserContextCommand.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/MessageContextInteraction.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/UserContextInteraction.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/BaseContextCommand.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GlobalContextCommand.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GuildContextCommand.java rename src/main/java/com/dynxsty/dih4jda/commands/{ => interactions/slash}/ISlashCommand.java (81%) rename src/main/java/com/dynxsty/dih4jda/commands/{ => interactions/slash}/SlashCommandInteraction.java (92%) rename src/main/java/com/dynxsty/dih4jda/commands/{dto/SlashCommand.java => interactions/slash/dao/BaseSlashCommand.java} (91%) create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GlobalSlashCommand.java create mode 100644 src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GuildSlashCommand.java rename src/main/java/com/dynxsty/dih4jda/commands/{dto => interactions/slash/dao}/SlashSubcommand.java (88%) rename src/main/java/com/dynxsty/dih4jda/commands/{dto => interactions/slash/dao}/SlashSubcommandGroup.java (93%) create mode 100644 src/main/java/com/dynxsty/dih4jda/exceptions/InvalidParentException.java diff --git a/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java b/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java index 94711100..eed2fea8 100644 --- a/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java +++ b/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java @@ -1,9 +1,10 @@ package com.dynxsty.dih4jda; -import com.dynxsty.dih4jda.commands.SlashCommandHandler; +import com.dynxsty.dih4jda.commands.InteractionHandler; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.events.ReadyEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.internal.utils.JDALogger; import org.jetbrains.annotations.NotNull; import java.util.concurrent.CompletableFuture; @@ -14,6 +15,8 @@ public class DIH4JDA extends ListenerAdapter { public String commandsPackage; public long ownerId; + public static final org.slf4j.Logger log = JDALogger.getLog(DIH4JDA.class); + /** * Constructs a new DIH4JDA instance * @param jda The {@link JDA} instance the handler is to be used for. @@ -28,21 +31,19 @@ protected DIH4JDA(JDA jda, String commandsPackage, long ownerId) { } /** - * Ran once the {@link JDA} instance fires the {@link ReadyEvent}. Mainly does the following two things; - *
    - *
  1. Creates a new {@link SlashCommandHandler} instance
  2. - *
  3. Register the Slash commands, depending on the {@link SlashCommandType}, either by looping through all guilds or by registering global slash commands with the JDA instance.
  4. - *
+ * Ran once the {@link JDA} instance fires the {@link ReadyEvent}. + * * @param event The {@link ReadyEvent} that was fired. */ @Override public void onReady(@NotNull ReadyEvent event) { if (commandsPackage == null) return; - SlashCommandHandler handler = new SlashCommandHandler(commandsPackage); + InteractionHandler handler = new InteractionHandler(commandsPackage); this.jda.addEventListener(handler); CompletableFuture.runAsync(() -> { try { handler.registerSlashCommands(this.jda); + handler.registerContextCommands(this.jda); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java b/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java new file mode 100644 index 00000000..553f4a06 --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java @@ -0,0 +1,426 @@ +package com.dynxsty.dih4jda.commands; + +import com.dynxsty.dih4jda.commands.interactions.context.IMessageContextCommand; +import com.dynxsty.dih4jda.commands.interactions.context.IUserContextCommand; +import com.dynxsty.dih4jda.commands.interactions.context.MessageContextInteraction; +import com.dynxsty.dih4jda.commands.interactions.context.UserContextInteraction; +import com.dynxsty.dih4jda.commands.interactions.context.dao.BaseContextCommand; +import com.dynxsty.dih4jda.commands.interactions.context.dao.GlobalContextCommand; +import com.dynxsty.dih4jda.commands.interactions.context.dao.GuildContextCommand; +import com.dynxsty.dih4jda.commands.interactions.slash.ISlashCommand; +import com.dynxsty.dih4jda.commands.interactions.slash.SlashCommandInteraction; +import com.dynxsty.dih4jda.commands.interactions.slash.dao.*; +import com.dynxsty.dih4jda.exceptions.InvalidParentException; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; +import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData; +import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.reflections.Reflections; + +import java.util.*; +import java.util.concurrent.CompletableFuture; + +import static com.dynxsty.dih4jda.DIH4JDA.log; + +public class InteractionHandler extends ListenerAdapter { + + private final String commandsPackage; + private final Map slashCommandIndex; + private final Map messageContextIndex; + private final Map userContextIndex; + + private final List> guildCommands; + private final List> globalCommands; + + private final List> guildContexts; + private final List> globalContexts; + + /** + * Constructs a new {@link InteractionHandler} from the supplied commands package. + * + * @param commandsPackage The package that houses the command classes. + */ + public InteractionHandler(String commandsPackage) { + this.guildCommands = new ArrayList<>(); + this.globalCommands = new ArrayList<>(); + this.guildContexts = new ArrayList<>(); + this.globalContexts = new ArrayList<>(); + this.slashCommandIndex = new HashMap<>(); + this.messageContextIndex = new HashMap<>(); + this.userContextIndex = new HashMap<>(); + this.commandsPackage = commandsPackage; + } + + /** + * Registers all slash commands. Loops through all classes found in the commands package that is a subclass of {@link BaseSlashCommand}. + * Goes through these steps with every iteration; + *
    + *
  1. Checks if the class is missing {@link CommandData} and doesn't register if it is.
  2. + *
  3. Checks if the class is neither a subclass of {@link SlashSubcommand} nor {@link SlashSubcommandGroup} and registers it as regular command.
  4. + *
  5. Checks if the class is a subclass of {@link SlashSubcommandGroup} if it is, the SlashCommandGroup is validated and another loop is fired following the two steps above for the group's sub commands.
  6. + *
  7. Checks if the class is a subclass of {@link SlashSubcommand}, if it is, it is registered as a sub command.
  8. + *
+ * + * @param jda The {@link JDA} instance. + * @throws Exception if anything goes wrong. + */ + public void registerSlashCommands(JDA jda) throws Exception { + Reflections commands = new Reflections(this.commandsPackage); + Set> classes = commands.getSubTypesOf(BaseSlashCommand.class); + for (Class c : classes) { + if (c.getSuperclass().equals(GlobalSlashCommand.class)) { + globalCommands.add(c); + } else if (c.getSuperclass().equals(GuildSlashCommand.class)) { + guildCommands.add(c); + } + } + if (!this.guildCommands.isEmpty()) { + for (Guild guild : jda.getGuilds()) { + registerGuildCommand(guild); + } + } + if (!this.globalCommands.isEmpty()) { + registerGlobalCommand(jda); + } + } + + /** + * Registers a single Guild Command. + * + * @param guild The command's guild. + * @throws Exception If an error occurs. + */ + private void registerGuildCommand(@NotNull Guild guild) throws Exception { + CommandListUpdateAction updateAction = guild.updateCommands(); + for (Class slashCommandClass : this.guildCommands) { + BaseSlashCommand instance = (BaseSlashCommand) this.getClassInstance(guild, slashCommandClass); + updateAction = registerCommand(updateAction, instance, slashCommandClass, guild); + } + log.info(String.format("[%s] Queuing Guild SlashCommands", guild.getName())); + updateAction.queue(); + } + + /** + * Registers a single Global Command. + * + * @throws Exception If an error occurs. + */ + private void registerGlobalCommand(@NotNull JDA jda) throws Exception { + CommandListUpdateAction updateAction = jda.updateCommands(); + for (Class slashCommandClass : this.globalCommands) { + BaseSlashCommand instance = (BaseSlashCommand) this.getClassInstance(null, slashCommandClass); + updateAction = this.registerCommand(updateAction, instance, slashCommandClass, null); + } + log.info("[*] Queuing Global SlashCommands"); + updateAction.queue(); + } + + /** + * Registers a single Command. + * + * @param action The {@link CommandListUpdateAction}. + * @param command The base command's instance. + * @param commandClass The base command's class. + * @param guild The current guild (if available) + * @return The new {@link CommandListUpdateAction}. + * @throws Exception If an error occurs. + */ + private CommandListUpdateAction registerCommand(CommandListUpdateAction action, @NotNull BaseSlashCommand command, Class commandClass, @Nullable Guild guild) throws Exception { + if (command.getCommandData() == null) { + log.warn(String.format("Class %s is missing CommandData. It will be ignored.", commandClass.getName())); + return null; + } + SlashCommandData commandData = command.getCommandData(); + if (command.getSubcommandGroupClasses() != null) { + commandData = registerSubcommandGroup(command, command.getSubcommandGroupClasses(), guild); + } else if (command.getSubcommandClasses() != null) { + commandData = registerSubcommand(command, command.getSubcommandClasses(), guild); + } else { + slashCommandIndex.put(getFullCommandName(commandData.getName(), null, null), + new SlashCommandInteraction((ISlashCommand) command, command.getCommandPrivileges())); + log.info(String.format("\t[*] Registered command: /%s", command.getCommandData().getName())); + } + action.addCommands(commandData); + return action; + } + + /** + * Registers a single Command Group. + * + * @param command The base command's instance. + * @param groupClasses All slash command group classes. + * @param guild The current guild (if available) + * @return The new {@link CommandListUpdateAction}. + * @throws Exception If an error occurs. + */ + private SlashCommandData registerSubcommandGroup(@NotNull BaseSlashCommand command, Class @NotNull [] groupClasses, @Nullable Guild guild) throws Exception { + SlashCommandData data = command.getCommandData(); + for (Class group : groupClasses) { + SlashSubcommandGroup instance = (SlashSubcommandGroup) this.getClassInstance(guild, group); + if (instance.getSubcommandGroupData() == null) { + log.warn(String.format("Class %s is missing SubcommandGroupData. It will be ignored.", group.getName())); + continue; + } + if (instance.getSubcommandClasses() == null) { + log.warn(String.format("SubcommandGroup %s is missing Subcommands. It will be ignored.", instance.getSubcommandGroupData().getName())); + continue; + } + SubcommandGroupData groupData = registerSubcommand(command, instance.getSubcommandGroupData(), instance.getSubcommandClasses(), guild); + data.addSubcommandGroups(groupData); + } + return data; + } + + /** + * Registers a single Sub Command for a Subcommand Group. + * + * @param command The base command's instance. + * @param data The subcommand group's data. + * @param subClasses All sub command classes. + * @param guild The current guild (if available) + * @return The new {@link CommandListUpdateAction}. + * @throws Exception If an error occurs. + */ + private SubcommandGroupData registerSubcommand(BaseSlashCommand command, SubcommandGroupData data, Class @NotNull [] subClasses, @Nullable Guild guild) throws Exception { + for (Class sub : subClasses) { + SlashSubcommand instance = (SlashSubcommand) this.getClassInstance(guild, sub); + if (instance.getSubcommandData() == null) { + log.warn(String.format("Class %s is missing SubcommandData. It will be ignored.", sub.getName())); + continue; + } + slashCommandIndex.put(getFullCommandName(command.getCommandData().getName(), data.getName(), instance.getSubcommandData().getName()), + new SlashCommandInteraction((ISlashCommand) instance, command.getCommandPrivileges())); + log.info(String.format("\t[*] Registered command: /%s", getFullCommandName(command.getCommandData().getName(), data.getName(), instance.getSubcommandData().getName()))); + data.addSubcommands(instance.getSubcommandData()); + } + return data; + } + + /** + * Registers a single Sub Command. + * + * @param command The base command's instance. + * @param subClasses All sub command classes. + * @param guild The current guild (if available) + * @return The new {@link CommandListUpdateAction}. + * @throws Exception If an error occurs. + */ + private SlashCommandData registerSubcommand(@NotNull BaseSlashCommand command, Class @NotNull [] subClasses, @Nullable Guild guild) throws Exception { + SlashCommandData data = command.getCommandData(); + for (Class sub : subClasses) { + SlashSubcommand instance = (SlashSubcommand) this.getClassInstance(guild, sub); + if (instance.getSubcommandData() == null) { + log.warn(String.format("Class %s is missing SubcommandData. It will be ignored.", sub.getName())); + continue; + } + slashCommandIndex.put(getFullCommandName(data.getName(), data.getName(), instance.getSubcommandData().getName()), + new SlashCommandInteraction((ISlashCommand) instance, command.getCommandPrivileges())); + log.info(String.format("\t[*] Registered command: /%s %s", data.getName(), instance.getSubcommandData().getName())); + data.addSubcommands(instance.getSubcommandData()); + } + return data; + } + + /** + * Registers all context commands. Loops through all classes found in the commands package that is a subclass of {@link BaseContextCommand}. + * + * @param jda The {@link JDA} instance. + * @throws Exception if anything goes wrong. + */ + public void registerContextCommands(JDA jda) throws Exception { + Reflections commands = new Reflections(this.commandsPackage); + Set> classes = commands.getSubTypesOf(BaseContextCommand.class); + for (Class c : classes) { + if (c.getSuperclass().equals(GlobalContextCommand.class)) { + globalContexts.add(c); + } else if (c.getSuperclass().equals(GuildContextCommand.class)) { + guildContexts.add(c); + } + } + if (!this.guildContexts.isEmpty()) { + for (Guild guild : jda.getGuilds()) { + registerGuildContext(guild); + } + } + if (!this.globalContexts.isEmpty()) { + registerGlobalContext(jda); + } + } + + /** + * Registers a single Guild Context Command. + * + * @param guild The context command's guild. + * @throws Exception If an error occurs. + */ + private void registerGuildContext(@NotNull Guild guild) throws Exception { + CommandListUpdateAction updateAction = guild.updateCommands(); + for (Class contextCommandClass : this.guildContexts) { + BaseContextCommand instance = (BaseContextCommand) this.getClassInstance(guild, contextCommandClass); + updateAction = registerContext(updateAction, instance, contextCommandClass, guild); + } + log.info(String.format("[%s] Queuing Guild Context Commands", guild.getName())); + updateAction.queue(); + } + + /** + * Registers a single Global Context Command. + * + * @throws Exception If an error occurs. + */ + private void registerGlobalContext(@NotNull JDA jda) throws Exception { + CommandListUpdateAction updateAction = jda.updateCommands(); + for (Class contextCommandClass : this.globalContexts) { + BaseContextCommand instance = (BaseContextCommand) this.getClassInstance(null, contextCommandClass); + updateAction = this.registerContext(updateAction, instance, contextCommandClass, null); + } + log.info("[Global] Queuing Global Context Commands"); + updateAction.queue(); + } + + /** + * Registers a single Context Command. + * + * @param action The {@link CommandListUpdateAction}. + * @param command The base context command's instance. + * @param commandClass The base context command's class. + * @param guild The current guild (if available) + * @return The new {@link CommandListUpdateAction}. + * @throws Exception If an error occurs. + */ + private CommandListUpdateAction registerContext(CommandListUpdateAction action, @NotNull BaseContextCommand command, Class commandClass, @Nullable Guild guild) throws Exception { + if (command.getCommandData() == null) { + log.warn(String.format("Class %s is missing CommandData. It will be ignored.", commandClass.getName())); + return null; + } + CommandData commandData = command.getCommandData(); + if (commandData.getType() == Command.Type.MESSAGE) { + messageContextIndex.put(commandData.getName(), new MessageContextInteraction((IMessageContextCommand) command)); + } else if (commandData.getType() == Command.Type.USER) { + userContextIndex.put(commandData.getName(), new UserContextInteraction((IUserContextCommand) command)); + } else { + log.error(String.format("Invalid Command Type \"%s\" for Context Command! This command will be ignored.", commandData.getType())); + return action; + } + log.info(String.format("\t[*] Registered context command: %s", command.getCommandData().getName())); + action.addCommands(commandData); + return action; + } + + /** + * Handles a single {@link SlashCommandInteraction}. + * If a {@link SlashCommandInteractionEvent} is fired the corresponding class is found and the command is executed. + * + * @param event The {@link SlashCommandInteractionEvent} that was fired. + */ + private void handleSlashCommand(SlashCommandInteractionEvent event) { + try { + SlashCommandInteraction command = slashCommandIndex.get(getFullCommandName(event.getName(), event.getSubcommandGroup(), event.getSubcommandName())); + command.getHandler().handleSlashCommandInteraction(event); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Handles a single {@link UserContextInteraction}. + * If a {@link UserContextInteractionEvent} is fired the corresponding class is found and the command is executed. + * + * @param event The {@link UserContextInteractionEvent} that was fired. + */ + private void handleUserContextCommand(UserContextInteractionEvent event) { + try { + UserContextInteraction context = userContextIndex.get(event.getName()); + context.getHandler().handleUserContextInteraction(event); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Handles a single {@link MessageContextInteraction}. + * If a {@link MessageContextInteractionEvent} is fired the corresponding class is found and the command is executed. + * + * @param event The {@link MessageContextInteractionEvent} that was fired. + */ + private void handleMessageContextCommand(MessageContextInteractionEvent event) { + try { + MessageContextInteraction context = messageContextIndex.get(event.getName()); + context.getHandler().handleMessageContextInteraction(event); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Used to create one command name out of the SlashCommand, SlashSubCommandGroup and SlashSubCommand + * + * @param first The SlashCommand's name. + * @param second The SlashSubCommandGroup's name. + * @param third The SlashSubCommand's name. + * @return One combined string. + */ + @Contract(pure = true) + private @NotNull String getFullCommandName(String first, String second, String third) { + return String.format("%s %s %s", first, second, third); + } + + /** + * Creates a new Instance of the given class. + * + * @param guild The slash command's guild. (if available) + * @param clazz The slash command's class. + * @return The Instance as a generic Object. + * @throws Exception If an error occurs. + */ + private Object getClassInstance(Guild guild, Class clazz) throws Exception { + if (guild != null || !clazz.getSuperclass().equals(GlobalSlashCommand.class)) { + try { + return clazz.getConstructor(Guild.class).newInstance(guild); + } catch (NoSuchMethodException ignored) { + } + } + return clazz.getConstructor().newInstance(); + } + + /** + * Fired if Discord reports a {@link SlashCommandInteractionEvent}. + * + * @param event The {@link SlashCommandInteractionEvent} that was fired. + */ + @Override + public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) { + CompletableFuture.runAsync(() -> this.handleSlashCommand(event)); + } + + + /** + * Fired if Discord reports a {@link UserContextInteractionEvent}. + * + * @param event The {@link UserContextInteractionEvent} that was fired. + */ + @Override + public void onUserContextInteraction(@NotNull UserContextInteractionEvent event) { + CompletableFuture.runAsync(() -> this.handleUserContextCommand(event)); + } + + /** + * Fired if Discord reports a {@link MessageContextInteractionEvent}. + * + * @param event The {@link MessageContextInteractionEvent} that was fired. + */ + @Override + public void onMessageContextInteraction(@NotNull MessageContextInteractionEvent event) { + CompletableFuture.runAsync(() -> this.handleMessageContextCommand(event)); + } +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/SlashCommandHandler.java b/src/main/java/com/dynxsty/dih4jda/commands/SlashCommandHandler.java deleted file mode 100644 index b9f5175b..00000000 --- a/src/main/java/com/dynxsty/dih4jda/commands/SlashCommandHandler.java +++ /dev/null @@ -1,269 +0,0 @@ -package com.dynxsty.dih4jda.commands; - -import com.dynxsty.dih4jda.commands.dto.*; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.interactions.commands.build.CommandData; -import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; -import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData; -import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction; -import net.dv8tion.jda.internal.utils.JDALogger; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.reflections.Reflections; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -public class SlashCommandHandler extends ListenerAdapter { - - private final String commandsPackage; - private final HashMap slashCommandIndex; - - private final List> guild; - private final List> global; - - private final org.slf4j.Logger log = JDALogger.getLog(this.getClass()); - - /** - * Constructs a new {@link SlashCommandHandler} from the supplied commands package. - * - * @param commandsPackage The package that houses the command classes. - */ - public SlashCommandHandler(String commandsPackage) { - this.guild = new ArrayList<>(); - this.global = new ArrayList<>(); - this.slashCommandIndex = new HashMap<>(); - this.commandsPackage = commandsPackage; - } - - /** - * Registers all slash commands. Loops through all classes found in the commands package that is a subclass of {@link SlashCommand}. - * Goes through these steps with every iteration; - *
    - *
  1. Checks if the class is missing {@link CommandData} and doesn't register if it is.
  2. - *
  3. Checks if the class is neither a subclass of {@link SlashSubcommand} nor {@link SlashSubcommandGroup} and registers it as regular command.
  4. - *
  5. Checks if the class is a subclass of {@link SlashSubcommandGroup} if it is, the SlashCommandGroup is validated and another loop is fired following the two steps above for the group's sub commands.
  6. - *
  7. Checks if the class is a subclass of {@link SlashSubcommand}, if it is, it is registered as a sub command.
  8. - *
- * - * @param jda The {@link JDA} instance. - * @throws Exception if anything goes wrong. - */ - public void registerSlashCommands(JDA jda) throws Exception { - Reflections commands = new Reflections(this.commandsPackage); - Set> classes = commands.getSubTypesOf(SlashCommand.class); - for (Class c : classes) { - if (c.getSuperclass().equals(GlobalSlashCommand.class)) { - global.add(c); - } else if (c.getSuperclass().equals(GuildSlashCommand.class)) { - guild.add(c); - } - } - if (!this.guild.isEmpty()) { - for (Guild guild : jda.getGuilds()) { - registerGuildCommand(guild); - } - } - if (!this.global.isEmpty()) { - registerGlobalCommand(jda); - } - } - - /** - * Registers a single Guild Command. - * - * @param guild The command's guild. - * @throws Exception If an error occurs. - */ - private void registerGuildCommand(@NotNull Guild guild) throws Exception { - CommandListUpdateAction updateAction = guild.updateCommands(); - for (Class slashCommandClass : this.guild) { - SlashCommand instance = (SlashCommand) this.getClassInstance(guild, slashCommandClass); - updateAction = registerCommand(updateAction, instance, slashCommandClass, guild); - } - log.info(String.format("[%s] Queuing Guild SlashCommands", guild.getName())); - updateAction.queue(); - } - - /** - * Registers a single Global Command. - * - * @throws Exception If an error occurs. - */ - private void registerGlobalCommand(@NotNull JDA jda) throws Exception { - CommandListUpdateAction updateAction = jda.updateCommands(); - for (Class slashCommandClass : this.global) { - SlashCommand instance = (SlashCommand) this.getClassInstance(null, slashCommandClass); - updateAction = this.registerCommand(updateAction, instance, slashCommandClass, null); - } - log.info("[*] Queuing Global SlashCommands"); - updateAction.queue(); - } - - /** - * Registers a single Command. - * - * @param action The {@link CommandListUpdateAction}. - * @param command The base command's instance. - * @param commandClass The base command's class. - * @param guild The current guild (if available) - * @return The new {@link CommandListUpdateAction}. - * @throws Exception If an error occurs. - */ - private CommandListUpdateAction registerCommand(CommandListUpdateAction action, @NotNull SlashCommand command, Class commandClass, @Nullable Guild guild) throws Exception { - if (command.getCommandData() == null) { - log.warn(String.format("Class %s is missing CommandData. It will be ignored.", commandClass.getName())); - return null; - } - SlashCommandData commandData = command.getCommandData(); - if (command.getSubcommandGroupClasses() != null) { - commandData = registerSubcommandGroup(command, command.getSubcommandGroupClasses(), guild); - } else if (command.getSubcommandClasses() != null) { - commandData = registerSubcommand(command, command.getSubcommandClasses(), guild); - } else { - slashCommandIndex.put(getFullCommandName(commandData.getName(), null, null), - new SlashCommandInteraction((ISlashCommand) command, command.getCommandPrivileges())); - log.info(String.format("[*] Registered command: /%s", command.getCommandData().getName())); - } - action.addCommands(commandData); - return action; - } - - /** - * Registers a single Command Group. - * - * @param command The base command's instance. - * @param groupClasses All slash command group classes. - * @param guild The current guild (if available) - * @return The new {@link CommandListUpdateAction}. - * @throws Exception If an error occurs. - */ - private SlashCommandData registerSubcommandGroup(@NotNull SlashCommand command, Class @NotNull [] groupClasses, @Nullable Guild guild) throws Exception { - SlashCommandData data = command.getCommandData(); - for (Class group : groupClasses) { - SlashSubcommandGroup instance = (SlashSubcommandGroup) this.getClassInstance(guild, group); - if (instance.getSubcommandGroupData() == null) { - log.warn(String.format("Class %s is missing SubcommandGroupData. It will be ignored.", group.getName())); - continue; - } - if (instance.getSubcommandClasses() == null) { - log.warn(String.format("SubcommandGroup %s is missing Subcommands. It will be ignored.", instance.getSubcommandGroupData().getName())); - continue; - } - SubcommandGroupData groupData = registerSubcommand(command, instance.getSubcommandGroupData(), instance.getSubcommandClasses(), guild); - data.addSubcommandGroups(groupData); - } - return data; - } - - /** - * Registers a single Sub Command for a Subcommand Group. - * - * @param command The base command's instance. - * @param data The subcommand group's data. - * @param subClasses All sub command classes. - * @param guild The current guild (if available) - * @return The new {@link CommandListUpdateAction}. - * @throws Exception If an error occurs. - */ - private SubcommandGroupData registerSubcommand(SlashCommand command, SubcommandGroupData data, Class @NotNull [] subClasses, @Nullable Guild guild) throws Exception { - for (Class sub : subClasses) { - SlashSubcommand instance = (SlashSubcommand) this.getClassInstance(guild, sub); - if (instance.getSubcommandData() == null) { - log.warn(String.format("Class %s is missing SubcommandData. It will be ignored.", sub.getName())); - continue; - } - slashCommandIndex.put(getFullCommandName(command.getCommandData().getName(), data.getName(), instance.getSubcommandData().getName()), - new SlashCommandInteraction((ISlashCommand) instance, command.getCommandPrivileges())); - log.info(String.format("[*] Registered command: /%s", getFullCommandName(command.getCommandData().getName(), data.getName(), instance.getSubcommandData().getName()))); - data.addSubcommands(instance.getSubcommandData()); - } - return data; - } - - /** - * Registers a single Sub Command. - * - * @param command The base command's instance. - * @param subClasses All sub command classes. - * @param guild The current guild (if available) - * @return The new {@link CommandListUpdateAction}. - * @throws Exception If an error occurs. - */ - private SlashCommandData registerSubcommand(@NotNull SlashCommand command, Class @NotNull [] subClasses, @Nullable Guild guild) throws Exception { - SlashCommandData data = command.getCommandData(); - for (Class sub : subClasses) { - SlashSubcommand instance = (SlashSubcommand) this.getClassInstance(guild, sub); - if (instance.getSubcommandData() == null) { - log.warn(String.format("Class %s is missing SubcommandData. It will be ignored.", sub.getName())); - continue; - } - slashCommandIndex.put(getFullCommandName(data.getName(), data.getName(), instance.getSubcommandData().getName()), - new SlashCommandInteraction((ISlashCommand) instance, command.getCommandPrivileges())); - log.info(String.format("[*] Registered command: /%s %s", data.getName(), instance.getSubcommandData().getName())); - data.addSubcommands(instance.getSubcommandData()); - } - return data; - } - - /** - * If a {@link SlashCommandInteractionEvent} is fired the corresponding class is found and the command is executed. - * - * @param event The {@link SlashCommandInteractionEvent} that was fired. - */ - private void handleCommand(SlashCommandInteractionEvent event) { - try { - SlashCommandInteraction command = slashCommandIndex.get(getFullCommandName(event.getName(), event.getSubcommandGroup(), event.getSubcommandName())); - command.getHandler().handleSlashCommandInteraction(event); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Used to create one command name out of the SlashCommand, SlashSubCommandGroup and SlashSubCommand - * - * @param first The SlashCommand's name. - * @param second The SlashSubCommandGroup's name. - * @param third The SlashSubCommand's name. - * @return One combined string. - */ - @Contract(pure = true) - private @NotNull String getFullCommandName(String first, String second, String third) { - return String.format("%s %s %s", first, second, third); - } - - /** - * Creates a new Instance of the given class. - * - * @param guild The slash command's guild. (if available) - * @param clazz The slash command's class. - * @return The Instance as a generic Object. - * @throws Exception If an error occurs. - */ - private Object getClassInstance(Guild guild, Class clazz) throws Exception { - if (guild != null || !clazz.getSuperclass().equals(GlobalSlashCommand.class)) { - try { - return clazz.getConstructor(Guild.class).newInstance(guild); - } catch (NoSuchMethodException ignored) {} - } - return clazz.getConstructor().newInstance(); - } - - /** - * Fired if Discord reports a {@link SlashCommandInteractionEvent}. - * - * @param event The {@link SlashCommandInteractionEvent} that was fired. - */ - @Override - public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) { - CompletableFuture.runAsync(() -> handleCommand(event)); - } -} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/dto/GlobalSlashCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/dto/GlobalSlashCommand.java deleted file mode 100644 index 1255bd9c..00000000 --- a/src/main/java/com/dynxsty/dih4jda/commands/dto/GlobalSlashCommand.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.dynxsty.dih4jda.commands.dto; - -public abstract class GlobalSlashCommand extends SlashCommand {} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/dto/GuildSlashCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/dto/GuildSlashCommand.java deleted file mode 100644 index b6ff7036..00000000 --- a/src/main/java/com/dynxsty/dih4jda/commands/dto/GuildSlashCommand.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.dynxsty.dih4jda.commands.dto; - -public abstract class GuildSlashCommand extends SlashCommand {} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IMessageContextCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IMessageContextCommand.java new file mode 100644 index 00000000..1f683da5 --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IMessageContextCommand.java @@ -0,0 +1,7 @@ +package com.dynxsty.dih4jda.commands.interactions.context; + +import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent; + +public interface IMessageContextCommand { + void handleMessageContextInteraction(MessageContextInteractionEvent event); +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IUserContextCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IUserContextCommand.java new file mode 100644 index 00000000..dfdb0fed --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/IUserContextCommand.java @@ -0,0 +1,7 @@ +package com.dynxsty.dih4jda.commands.interactions.context; + +import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent; + +public interface IUserContextCommand { + void handleUserContextInteraction(UserContextInteractionEvent event); +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/MessageContextInteraction.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/MessageContextInteraction.java new file mode 100644 index 00000000..63ad1eb4 --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/MessageContextInteraction.java @@ -0,0 +1,21 @@ +package com.dynxsty.dih4jda.commands.interactions.context; + +/** + * Represents a single Slash Command Interaction. + */ +public class MessageContextInteraction { + + private IMessageContextCommand handler; + + public MessageContextInteraction(IMessageContextCommand handler) { + this.setHandler(handler); + } + + public IMessageContextCommand getHandler() { + return handler; + } + + public void setHandler(IMessageContextCommand handler) { + this.handler = handler; + } +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/UserContextInteraction.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/UserContextInteraction.java new file mode 100644 index 00000000..a1391e1e --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/UserContextInteraction.java @@ -0,0 +1,21 @@ +package com.dynxsty.dih4jda.commands.interactions.context; + +/** + * Represents a single Slash Command Interaction. + */ +public class UserContextInteraction { + + private IUserContextCommand handler; + + public UserContextInteraction(IUserContextCommand handler) { + this.setHandler(handler); + } + + public IUserContextCommand getHandler() { + return handler; + } + + public void setHandler(IUserContextCommand handler) { + this.handler = handler; + } +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/BaseContextCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/BaseContextCommand.java new file mode 100644 index 00000000..a53b9f56 --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/BaseContextCommand.java @@ -0,0 +1,23 @@ +package com.dynxsty.dih4jda.commands.interactions.context.dao; + +import com.dynxsty.dih4jda.DIH4JDA; +import net.dv8tion.jda.api.interactions.commands.Command; +import net.dv8tion.jda.api.interactions.commands.build.CommandData; + +public class BaseContextCommand { + private CommandData commandData; + + public CommandData getCommandData() { + return commandData; + } + + public void setCommandData(CommandData commandData) { + if (commandData.getType() == Command.Type.MESSAGE || commandData.getType() == Command.Type.USER) { + this.commandData = commandData; + } else { + DIH4JDA.log.error( + String.format("Invalid Command Type \"%s\" for Context Command! This command will be ignored.", commandData.getType()) + ); + } + } +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GlobalContextCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GlobalContextCommand.java new file mode 100644 index 00000000..e7284406 --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GlobalContextCommand.java @@ -0,0 +1,4 @@ +package com.dynxsty.dih4jda.commands.interactions.context.dao; + +public class GlobalContextCommand extends BaseContextCommand { +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GuildContextCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GuildContextCommand.java new file mode 100644 index 00000000..916af6fc --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/context/dao/GuildContextCommand.java @@ -0,0 +1,4 @@ +package com.dynxsty.dih4jda.commands.interactions.context.dao; + +public class GuildContextCommand extends BaseContextCommand { +} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/ISlashCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/ISlashCommand.java similarity index 81% rename from src/main/java/com/dynxsty/dih4jda/commands/ISlashCommand.java rename to src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/ISlashCommand.java index 2228bfdb..5fcf1b7f 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/ISlashCommand.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/ISlashCommand.java @@ -1,4 +1,4 @@ -package com.dynxsty.dih4jda.commands; +package com.dynxsty.dih4jda.commands.interactions.slash; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; diff --git a/src/main/java/com/dynxsty/dih4jda/commands/SlashCommandInteraction.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/SlashCommandInteraction.java similarity index 92% rename from src/main/java/com/dynxsty/dih4jda/commands/SlashCommandInteraction.java rename to src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/SlashCommandInteraction.java index 949a5640..3d531ff4 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/SlashCommandInteraction.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/SlashCommandInteraction.java @@ -1,4 +1,4 @@ -package com.dynxsty.dih4jda.commands; +package com.dynxsty.dih4jda.commands.interactions.slash; import net.dv8tion.jda.api.interactions.commands.privileges.CommandPrivilege; diff --git a/src/main/java/com/dynxsty/dih4jda/commands/dto/SlashCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/BaseSlashCommand.java similarity index 91% rename from src/main/java/com/dynxsty/dih4jda/commands/dto/SlashCommand.java rename to src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/BaseSlashCommand.java index 17507486..cfbca663 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/dto/SlashCommand.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/BaseSlashCommand.java @@ -1,4 +1,4 @@ -package com.dynxsty.dih4jda.commands.dto; +package com.dynxsty.dih4jda.commands.interactions.slash.dao; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.interactions.commands.privileges.CommandPrivilege; @@ -6,7 +6,9 @@ /** * A SlashCommand object with getters, setters, a constructor and a toString method. */ -public abstract class SlashCommand { +public abstract class BaseSlashCommand { + protected BaseSlashCommand() {} + private SlashCommandData commandData; private Class[] subcommandClasses; private Class[] subcommandGroupClasses; diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GlobalSlashCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GlobalSlashCommand.java new file mode 100644 index 00000000..1a2d6177 --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GlobalSlashCommand.java @@ -0,0 +1,3 @@ +package com.dynxsty.dih4jda.commands.interactions.slash.dao; + +public abstract class GlobalSlashCommand extends BaseSlashCommand {} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GuildSlashCommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GuildSlashCommand.java new file mode 100644 index 00000000..4cadcb5b --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/GuildSlashCommand.java @@ -0,0 +1,3 @@ +package com.dynxsty.dih4jda.commands.interactions.slash.dao; + +public abstract class GuildSlashCommand extends BaseSlashCommand {} diff --git a/src/main/java/com/dynxsty/dih4jda/commands/dto/SlashSubcommand.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/SlashSubcommand.java similarity index 88% rename from src/main/java/com/dynxsty/dih4jda/commands/dto/SlashSubcommand.java rename to src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/SlashSubcommand.java index f7b66f62..d14723b1 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/dto/SlashSubcommand.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/SlashSubcommand.java @@ -1,4 +1,4 @@ -package com.dynxsty.dih4jda.commands.dto; +package com.dynxsty.dih4jda.commands.interactions.slash.dao; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; diff --git a/src/main/java/com/dynxsty/dih4jda/commands/dto/SlashSubcommandGroup.java b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/SlashSubcommandGroup.java similarity index 93% rename from src/main/java/com/dynxsty/dih4jda/commands/dto/SlashSubcommandGroup.java rename to src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/SlashSubcommandGroup.java index aa540a0c..125c044e 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/dto/SlashSubcommandGroup.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/interactions/slash/dao/SlashSubcommandGroup.java @@ -1,4 +1,4 @@ -package com.dynxsty.dih4jda.commands.dto; +package com.dynxsty.dih4jda.commands.interactions.slash.dao; import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData; diff --git a/src/main/java/com/dynxsty/dih4jda/exceptions/InvalidParentException.java b/src/main/java/com/dynxsty/dih4jda/exceptions/InvalidParentException.java new file mode 100644 index 00000000..30e153bc --- /dev/null +++ b/src/main/java/com/dynxsty/dih4jda/exceptions/InvalidParentException.java @@ -0,0 +1,11 @@ +package com.dynxsty.dih4jda.exceptions; + +public class InvalidParentException extends DIH4JDAException { + public InvalidParentException(String message) { + super(message); + } + + public InvalidParentException(String message, Throwable t) { + super(message, t); + } +} From 2ac91094de6bee818be6c0773be9e43439c510c2 Mon Sep 17 00:00:00 2001 From: Dynxsty Date: Sun, 20 Feb 2022 17:17:19 +0100 Subject: [PATCH 4/6] Added support for Context Menu Commands --- README.md | 2 - .../java/com/dynxsty/dih4jda/DIH4JDA.java | 27 ++++-- .../dih4jda/commands/InteractionHandler.java | 90 +++++++++---------- 3 files changed, 61 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index bd6255bf..9d029264 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,6 @@ plugins { dependencies { [...] implementation 'com.github.DynxstyGIT:DIH4JDA:${DIH4JDA_VERSION}' - implementation 'org.reflections:reflections:0.10.2' - implementation 'net.dv8tion:JDA:5.0.0-alpha.5' } ``` diff --git a/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java b/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java index eed2fea8..38ca3df3 100644 --- a/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java +++ b/src/main/java/com/dynxsty/dih4jda/DIH4JDA.java @@ -11,9 +11,9 @@ public class DIH4JDA extends ListenerAdapter { - public JDA jda; - public String commandsPackage; - public long ownerId; + private final JDA jda; + private final String commandsPackage; + private final long ownerId; public static final org.slf4j.Logger log = JDALogger.getLog(DIH4JDA.class); @@ -37,16 +37,27 @@ protected DIH4JDA(JDA jda, String commandsPackage, long ownerId) { */ @Override public void onReady(@NotNull ReadyEvent event) { - if (commandsPackage == null) return; - InteractionHandler handler = new InteractionHandler(commandsPackage); - this.jda.addEventListener(handler); + if (getCommandsPackage() == null) return; + InteractionHandler handler = new InteractionHandler(getCommandsPackage()); + this.getJDA().addEventListener(handler); CompletableFuture.runAsync(() -> { try { - handler.registerSlashCommands(this.jda); - handler.registerContextCommands(this.jda); + handler.register(this.jda); } catch (Exception e) { e.printStackTrace(); } }); } + + public JDA getJDA() { + return this.jda; + } + + public String getCommandsPackage() { + return this.commandsPackage; + } + + public long getOwnerId() { + return this.ownerId; + } } diff --git a/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java b/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java index 553f4a06..aa893614 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java @@ -10,7 +10,6 @@ import com.dynxsty.dih4jda.commands.interactions.slash.ISlashCommand; import com.dynxsty.dih4jda.commands.interactions.slash.SlashCommandInteraction; import com.dynxsty.dih4jda.commands.interactions.slash.dao.*; -import com.dynxsty.dih4jda.exceptions.InvalidParentException; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent; @@ -61,6 +60,24 @@ public InteractionHandler(String commandsPackage) { this.commandsPackage = commandsPackage; } + public void register(JDA jda) throws Exception { + this.registerSlashCommands(); + this.registerContextCommands(jda); + + for (Guild guild : jda.getGuilds()) { + List commands = new ArrayList<>(); + commands.addAll(registerGuildCommand(guild)); + commands.addAll(registerGuildContext(guild)); + CommandListUpdateAction action = guild.updateCommands(); + action.addCommands(commands).queue(); + } + List commands = new ArrayList<>(); + commands.addAll(registerGlobalCommand(jda)); + commands.addAll(registerGlobalContext()); + CommandListUpdateAction action = jda.updateCommands(); + action.addCommands(commands).queue(); + } + /** * Registers all slash commands. Loops through all classes found in the commands package that is a subclass of {@link BaseSlashCommand}. * Goes through these steps with every iteration; @@ -71,10 +88,8 @@ public InteractionHandler(String commandsPackage) { *
  • Checks if the class is a subclass of {@link SlashSubcommand}, if it is, it is registered as a sub command.
  • * * - * @param jda The {@link JDA} instance. - * @throws Exception if anything goes wrong. */ - public void registerSlashCommands(JDA jda) throws Exception { + private void registerSlashCommands() { Reflections commands = new Reflections(this.commandsPackage); Set> classes = commands.getSubTypesOf(BaseSlashCommand.class); for (Class c : classes) { @@ -84,14 +99,6 @@ public void registerSlashCommands(JDA jda) throws Exception { guildCommands.add(c); } } - if (!this.guildCommands.isEmpty()) { - for (Guild guild : jda.getGuilds()) { - registerGuildCommand(guild); - } - } - if (!this.globalCommands.isEmpty()) { - registerGlobalCommand(jda); - } } /** @@ -100,14 +107,14 @@ public void registerSlashCommands(JDA jda) throws Exception { * @param guild The command's guild. * @throws Exception If an error occurs. */ - private void registerGuildCommand(@NotNull Guild guild) throws Exception { - CommandListUpdateAction updateAction = guild.updateCommands(); + private List registerGuildCommand(@NotNull Guild guild) throws Exception { + List commands = new ArrayList<>(); for (Class slashCommandClass : this.guildCommands) { BaseSlashCommand instance = (BaseSlashCommand) this.getClassInstance(guild, slashCommandClass); - updateAction = registerCommand(updateAction, instance, slashCommandClass, guild); + commands.add(this.registerCommand(instance, slashCommandClass, guild)); } log.info(String.format("[%s] Queuing Guild SlashCommands", guild.getName())); - updateAction.queue(); + return commands; } /** @@ -115,27 +122,26 @@ private void registerGuildCommand(@NotNull Guild guild) throws Exception { * * @throws Exception If an error occurs. */ - private void registerGlobalCommand(@NotNull JDA jda) throws Exception { - CommandListUpdateAction updateAction = jda.updateCommands(); + private List registerGlobalCommand(@NotNull JDA jda) throws Exception { + List commands = new ArrayList<>(); for (Class slashCommandClass : this.globalCommands) { BaseSlashCommand instance = (BaseSlashCommand) this.getClassInstance(null, slashCommandClass); - updateAction = this.registerCommand(updateAction, instance, slashCommandClass, null); + commands.add(this.registerCommand(instance, slashCommandClass, null)); } log.info("[*] Queuing Global SlashCommands"); - updateAction.queue(); + return commands; } /** * Registers a single Command. * - * @param action The {@link CommandListUpdateAction}. * @param command The base command's instance. * @param commandClass The base command's class. * @param guild The current guild (if available) * @return The new {@link CommandListUpdateAction}. * @throws Exception If an error occurs. */ - private CommandListUpdateAction registerCommand(CommandListUpdateAction action, @NotNull BaseSlashCommand command, Class commandClass, @Nullable Guild guild) throws Exception { + private SlashCommandData registerCommand(@NotNull BaseSlashCommand command, Class commandClass, @Nullable Guild guild) throws Exception { if (command.getCommandData() == null) { log.warn(String.format("Class %s is missing CommandData. It will be ignored.", commandClass.getName())); return null; @@ -150,8 +156,7 @@ private CommandListUpdateAction registerCommand(CommandListUpdateAction action, new SlashCommandInteraction((ISlashCommand) command, command.getCommandPrivileges())); log.info(String.format("\t[*] Registered command: /%s", command.getCommandData().getName())); } - action.addCommands(commandData); - return action; + return commandData; } /** @@ -235,9 +240,8 @@ private SlashCommandData registerSubcommand(@NotNull BaseSlashCommand command, C * Registers all context commands. Loops through all classes found in the commands package that is a subclass of {@link BaseContextCommand}. * * @param jda The {@link JDA} instance. - * @throws Exception if anything goes wrong. */ - public void registerContextCommands(JDA jda) throws Exception { + private void registerContextCommands(JDA jda) { Reflections commands = new Reflections(this.commandsPackage); Set> classes = commands.getSubTypesOf(BaseContextCommand.class); for (Class c : classes) { @@ -247,14 +251,6 @@ public void registerContextCommands(JDA jda) throws Exception { guildContexts.add(c); } } - if (!this.guildContexts.isEmpty()) { - for (Guild guild : jda.getGuilds()) { - registerGuildContext(guild); - } - } - if (!this.globalContexts.isEmpty()) { - registerGlobalContext(jda); - } } /** @@ -263,14 +259,14 @@ public void registerContextCommands(JDA jda) throws Exception { * @param guild The context command's guild. * @throws Exception If an error occurs. */ - private void registerGuildContext(@NotNull Guild guild) throws Exception { - CommandListUpdateAction updateAction = guild.updateCommands(); + private List registerGuildContext(@NotNull Guild guild) throws Exception { + List commands = new ArrayList<>(); for (Class contextCommandClass : this.guildContexts) { BaseContextCommand instance = (BaseContextCommand) this.getClassInstance(guild, contextCommandClass); - updateAction = registerContext(updateAction, instance, contextCommandClass, guild); + commands.add(this.registerContext(instance, contextCommandClass, guild)); } log.info(String.format("[%s] Queuing Guild Context Commands", guild.getName())); - updateAction.queue(); + return commands; } /** @@ -278,27 +274,26 @@ private void registerGuildContext(@NotNull Guild guild) throws Exception { * * @throws Exception If an error occurs. */ - private void registerGlobalContext(@NotNull JDA jda) throws Exception { - CommandListUpdateAction updateAction = jda.updateCommands(); + private List registerGlobalContext() throws Exception { + List commands = new ArrayList<>(); for (Class contextCommandClass : this.globalContexts) { BaseContextCommand instance = (BaseContextCommand) this.getClassInstance(null, contextCommandClass); - updateAction = this.registerContext(updateAction, instance, contextCommandClass, null); + commands.add(this.registerContext(instance, contextCommandClass, null)); } - log.info("[Global] Queuing Global Context Commands"); - updateAction.queue(); + log.info("[*] Queuing Global Context Commands"); + return commands; } /** * Registers a single Context Command. * - * @param action The {@link CommandListUpdateAction}. * @param command The base context command's instance. * @param commandClass The base context command's class. * @param guild The current guild (if available) * @return The new {@link CommandListUpdateAction}. * @throws Exception If an error occurs. */ - private CommandListUpdateAction registerContext(CommandListUpdateAction action, @NotNull BaseContextCommand command, Class commandClass, @Nullable Guild guild) throws Exception { + private CommandData registerContext(@NotNull BaseContextCommand command, Class commandClass, @Nullable Guild guild) throws Exception { if (command.getCommandData() == null) { log.warn(String.format("Class %s is missing CommandData. It will be ignored.", commandClass.getName())); return null; @@ -310,11 +305,10 @@ private CommandListUpdateAction registerContext(CommandListUpdateAction action, userContextIndex.put(commandData.getName(), new UserContextInteraction((IUserContextCommand) command)); } else { log.error(String.format("Invalid Command Type \"%s\" for Context Command! This command will be ignored.", commandData.getType())); - return action; + return null; } log.info(String.format("\t[*] Registered context command: %s", command.getCommandData().getName())); - action.addCommands(commandData); - return action; + return commandData; } /** From b0644cf92a6d0bf8cb50cacc6d808acc6db95da7 Mon Sep 17 00:00:00 2001 From: Dynxsty Date: Sun, 20 Feb 2022 17:21:11 +0100 Subject: [PATCH 5/6] Added null check for command data --- .../com/dynxsty/dih4jda/commands/InteractionHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java b/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java index aa893614..fe670617 100644 --- a/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java +++ b/src/main/java/com/dynxsty/dih4jda/commands/InteractionHandler.java @@ -278,7 +278,10 @@ private List registerGlobalContext() throws Exception { List commands = new ArrayList<>(); for (Class contextCommandClass : this.globalContexts) { BaseContextCommand instance = (BaseContextCommand) this.getClassInstance(null, contextCommandClass); - commands.add(this.registerContext(instance, contextCommandClass, null)); + CommandData data = this.registerContext(instance, contextCommandClass, null); + if (data != null) { + commands.add(data); + } } log.info("[*] Queuing Global Context Commands"); return commands; From 0bceed3ba4bebb467401260d039979b6b1dafada Mon Sep 17 00:00:00 2001 From: Dynxsty Date: Sun, 20 Feb 2022 17:24:05 +0100 Subject: [PATCH 6/6] updated version number --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4f93ff89..9fe28d00 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ plugins { group 'com.dynxsty' archivesBaseName = 'dih4jda' -version '1.0_001' +version '1.1' publishing { publications {