From 2d4a240e561b2b07dc5f00aff2c2d52a47286dfb Mon Sep 17 00:00:00 2001 From: Traqueur_ Date: Sun, 30 Nov 2025 15:09:38 +0100 Subject: [PATCH 1/6] feat: add jda module --- .../traqueur/commands/api/CommandManager.java | 4 +- .../commands/api/arguments/Arguments.java | 23 +- jda-test-bot/build.gradle | 30 ++ .../fr/traqueur/commands/test/TestBot.java | 74 ++++ .../commands/test/commands/AdminCommand.java | 181 +++++++++ .../commands/test/commands/GreetCommand.java | 40 ++ .../commands/test/commands/MathCommand.java | 120 ++++++ .../commands/test/commands/PingCommand.java | 31 ++ .../test/commands/UserInfoCommand.java | 58 +++ jda/build.gradle | 35 ++ .../fr/traqueur/commands/jda/Command.java | 84 +++++ .../traqueur/commands/jda/CommandManager.java | 100 +++++ .../traqueur/commands/jda/JDAArguments.java | 267 +++++++++++++ .../fr/traqueur/commands/jda/JDAExecutor.java | 182 +++++++++ .../fr/traqueur/commands/jda/JDAPlatform.java | 357 ++++++++++++++++++ .../jda/arguments/AttachmentArgument.java | 50 +++ .../jda/arguments/ChannelArgument.java | 56 +++ .../jda/arguments/JDAArgumentConverter.java | 49 +++ .../jda/arguments/MemberArgument.java | 56 +++ .../commands/jda/arguments/RoleArgument.java | 56 +++ .../commands/jda/arguments/UserArgument.java | 60 +++ .../jda/requirements/GuildRequirement.java | 50 +++ .../requirements/PermissionRequirement.java | 58 +++ .../jda/requirements/RoleRequirement.java | 67 ++++ settings.gradle | 4 +- 25 files changed, 2087 insertions(+), 5 deletions(-) create mode 100644 jda-test-bot/build.gradle create mode 100644 jda-test-bot/src/main/java/fr/traqueur/commands/test/TestBot.java create mode 100644 jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/AdminCommand.java create mode 100644 jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/GreetCommand.java create mode 100644 jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/MathCommand.java create mode 100644 jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/PingCommand.java create mode 100644 jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/UserInfoCommand.java create mode 100644 jda/build.gradle create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/Command.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/CommandManager.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/JDAArguments.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/JDAExecutor.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/JDAPlatform.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/arguments/AttachmentArgument.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/arguments/ChannelArgument.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/arguments/JDAArgumentConverter.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/arguments/MemberArgument.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/arguments/RoleArgument.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/arguments/UserArgument.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/requirements/GuildRequirement.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/requirements/PermissionRequirement.java create mode 100644 jda/src/main/java/fr/traqueur/commands/jda/requirements/RoleRequirement.java diff --git a/core/src/main/java/fr/traqueur/commands/api/CommandManager.java b/core/src/main/java/fr/traqueur/commands/api/CommandManager.java index 7e7d041..69c903b 100644 --- a/core/src/main/java/fr/traqueur/commands/api/CommandManager.java +++ b/core/src/main/java/fr/traqueur/commands/api/CommandManager.java @@ -299,8 +299,8 @@ private void registerSubCommands(String parentLabel, List> subcomma return; } for (Command subcommand : subcommands) { + // getAliases() already returns [name, ...aliases], so no need to add the name again List aliasesSub = new ArrayList<>(subcommand.getAliases()); - aliasesSub.add(subcommand.getName()); for (String aliasSub : aliasesSub) { this.addCommand(subcommand, parentLabel + "." + aliasSub); this.registerSubCommands(parentLabel + "." + aliasSub, subcommand.getSubcommands()); @@ -318,8 +318,8 @@ private void unregisterSubCommands(String parentLabel, List> subcom return; } for (Command subcommand : subcommandsList) { + // getAliases() already returns [name, ...aliases], so no need to add the name again List aliasesSub = new ArrayList<>(subcommand.getAliases()); - aliasesSub.add(subcommand.getName()); for (String aliasSub : aliasesSub) { this.removeCommand(parentLabel + "." + aliasSub, true); this.unregisterSubCommands(parentLabel + "." + aliasSub, subcommand.getSubcommands()); diff --git a/core/src/main/java/fr/traqueur/commands/api/arguments/Arguments.java b/core/src/main/java/fr/traqueur/commands/api/arguments/Arguments.java index 6a34bdf..07f98d0 100644 --- a/core/src/main/java/fr/traqueur/commands/api/arguments/Arguments.java +++ b/core/src/main/java/fr/traqueur/commands/api/arguments/Arguments.java @@ -16,12 +16,12 @@ public class Arguments { /** * The map of the arguments. */ - private final Map arguments; + protected final Map arguments; /** * The logger of the class. */ - private final Logger logger; + protected final Logger logger; /** * Constructor of the class. @@ -374,4 +374,23 @@ public void add(String key, Class type, Object object) { ArgumentValue argumentValue = new ArgumentValue(type, object); this.arguments.put(key, argumentValue); } + + /** + * Check if an argument exists in the map. + * + * @param key The key of the argument. + * @return true if the argument exists, false otherwise. + */ + public boolean has(String key) { + return this.arguments.containsKey(key); + } + + /** + * Get the logger of the class. + * + * @return The logger of the class. + */ + protected Logger getLogger() { + return this.logger; + } } diff --git a/jda-test-bot/build.gradle b/jda-test-bot/build.gradle new file mode 100644 index 0000000..5e62de5 --- /dev/null +++ b/jda-test-bot/build.gradle @@ -0,0 +1,30 @@ +plugins { + id 'application' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation project(":jda") + implementation("net.dv8tion:JDA:5.2.1") { + exclude module: 'opus-java' + } +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +application { + mainClass = 'fr.traqueur.commands.test.TestBot' +} + +tasks.register('runBot', JavaExec) { + group = 'application' + description = 'Run the test Discord bot' + classpath = sourceSets.main.runtimeClasspath + mainClass = 'fr.traqueur.commands.test.TestBot' +} \ No newline at end of file diff --git a/jda-test-bot/src/main/java/fr/traqueur/commands/test/TestBot.java b/jda-test-bot/src/main/java/fr/traqueur/commands/test/TestBot.java new file mode 100644 index 0000000..71fc4cc --- /dev/null +++ b/jda-test-bot/src/main/java/fr/traqueur/commands/test/TestBot.java @@ -0,0 +1,74 @@ +package fr.traqueur.commands.test; + +import fr.traqueur.commands.jda.CommandManager; +import fr.traqueur.commands.test.commands.*; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.requests.GatewayIntent; + +import java.util.logging.Logger; + +/** + * Test bot to demonstrate the JDA CommandsAPI. + * + * To run this bot: + * 1. Set the DISCORD_BOT_TOKEN environment variable + * 2. Set the DISCORD_GUILD_ID environment variable (optional, for testing) + * 3. Run with: ./gradlew :jda-test-bot:runBot + */ +public class TestBot { + + private static final Logger LOGGER = Logger.getLogger(TestBot.class.getName()); + + public static void main(String[] args) { + String token = System.getenv("DISCORD_BOT_TOKEN"); + if (token == null || token.isEmpty()) { + LOGGER.severe("DISCORD_BOT_TOKEN environment variable not set!"); + LOGGER.info("Please set your Discord bot token with: export DISCORD_BOT_TOKEN=your_token_here"); + return; + } + + try { + new TestBot(token); + } catch (Exception e) { + LOGGER.severe("Failed to start bot: " + e.getMessage()); + e.printStackTrace(); + } + } + + public TestBot(String token) throws InterruptedException { + LOGGER.info("Starting Discord bot..."); + + // Build JDA instance + JDA jda = JDABuilder.createDefault(token) + .enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.MESSAGE_CONTENT) + .build() + .awaitReady(); + + LOGGER.info("Bot is ready! Logged in as: " + jda.getSelfUser().getAsTag()); + + // Create command manager + CommandManager commandManager = new CommandManager<>(this, jda, LOGGER); + commandManager.setDebug(true); + + // Register commands + LOGGER.info("Registering commands..."); + commandManager.registerCommand(new PingCommand(this)); + commandManager.registerCommand(new UserInfoCommand(this)); + commandManager.registerCommand(new MathCommand(this)); + commandManager.registerCommand(new GreetCommand(this)); + commandManager.registerCommand(new AdminCommand(this)); + + // Sync commands + String guildId = System.getenv("DISCORD_GUILD_ID"); + if (guildId != null && !guildId.isEmpty()) { + LOGGER.info("Syncing commands to guild " + guildId + " (instant update)..."); + commandManager.syncCommandsToGuild(guildId); + } else { + LOGGER.info("Syncing commands globally (may take up to 1 hour)..."); + commandManager.syncCommands(); + } + + LOGGER.info("Bot is fully operational!"); + } +} \ No newline at end of file diff --git a/jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/AdminCommand.java b/jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/AdminCommand.java new file mode 100644 index 0000000..f892eba --- /dev/null +++ b/jda-test-bot/src/main/java/fr/traqueur/commands/test/commands/AdminCommand.java @@ -0,0 +1,181 @@ +package fr.traqueur.commands.test.commands; + +import fr.traqueur.commands.api.arguments.Arguments; +import fr.traqueur.commands.jda.Command; +import fr.traqueur.commands.jda.JDAArguments; +import fr.traqueur.commands.test.TestBot; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; + +/** + * Admin command with subcommand groups to test JDAPlatform.addCommand() with parts.length >= 3 + * Structure: + * - /admin users kick + * - /admin users ban + * - /admin server info + * - /admin server settings