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 af9f7bb..3dcab35 100644 --- a/core/src/main/java/fr/traqueur/commands/api/CommandManager.java +++ b/core/src/main/java/fr/traqueur/commands/api/CommandManager.java @@ -49,7 +49,7 @@ public abstract class CommandManager { /** * The argument converters registered in the command manager. */ - private final Map> typeConverters; + private final Map, ArgumentConverter.Wrapper> typeConverters; /** * The tab completer registered in the command manager. @@ -202,7 +202,7 @@ public void unregisterCommand(Command command, boolean subcommands) { * @param The type of the argument. */ public void registerConverter(Class typeClass, ArgumentConverter converter) { - this.typeConverters.put(typeClass.getName().toLowerCase(), new ArgumentConverter.Wrapper<>(typeClass, converter)); + this.typeConverters.put(typeClass, new ArgumentConverter.Wrapper<>(typeClass, converter)); } /** @@ -251,8 +251,8 @@ public Map>> getCompleters() { * @param type The type to check. * @return true if a TabCompleter is registered for this type. */ - public boolean hasTabCompleterForType(String type) { - ArgumentConverter.Wrapper wrapper = this.typeConverters.get(type.toLowerCase()); + public boolean hasTabCompleterForType(Class type) { + ArgumentConverter.Wrapper wrapper = this.typeConverters.get(type); return wrapper != null && wrapper.converter() instanceof TabCompleter; } @@ -263,8 +263,8 @@ public boolean hasTabCompleterForType(String type) { * @return The TabCompleter for this type, or null if none exists. */ @SuppressWarnings("unchecked") - public TabCompleter getTabCompleterForType(String type) { - ArgumentConverter.Wrapper wrapper = this.typeConverters.get(type.toLowerCase()); + public TabCompleter getTabCompleterForType(Class type) { + ArgumentConverter.Wrapper wrapper = this.typeConverters.get(type); if (wrapper != null && wrapper.converter() instanceof TabCompleter) { return (TabCompleter) wrapper.converter(); } @@ -411,7 +411,7 @@ private void addCompletionsForLabel(String[] labelParts) { private void addCompletionForArgs(String label, int commandSize, List> args) { for (int i = 0; i < args.size(); i++) { Argument arg = args.get(i); - String type = arg.type().key(); + Class type = arg.type().key(); ArgumentConverter.Wrapper entry = this.typeConverters.get(type); TabCompleter argConverter = arg.tabCompleter(); if (argConverter != null) { diff --git a/core/src/main/java/fr/traqueur/commands/api/arguments/Argument.java b/core/src/main/java/fr/traqueur/commands/api/arguments/Argument.java index a287103..85d8862 100644 --- a/core/src/main/java/fr/traqueur/commands/api/arguments/Argument.java +++ b/core/src/main/java/fr/traqueur/commands/api/arguments/Argument.java @@ -43,7 +43,7 @@ public Argument(String name, ArgumentType type) { } public String canonicalName() { - return this.name + ":" + this.type.key(); + return this.name + ":" + this.type.key().getSimpleName().toLowerCase(); } diff --git a/core/src/main/java/fr/traqueur/commands/api/arguments/ArgumentType.java b/core/src/main/java/fr/traqueur/commands/api/arguments/ArgumentType.java index fc36b71..6ece82e 100644 --- a/core/src/main/java/fr/traqueur/commands/api/arguments/ArgumentType.java +++ b/core/src/main/java/fr/traqueur/commands/api/arguments/ArgumentType.java @@ -9,7 +9,7 @@ static ArgumentType of(Class clazz) { return new Simple(clazz); } - String key(); + Class key(); /** * Check if this is the infinite type. @@ -23,8 +23,8 @@ default boolean isInfinite() { record Simple(Class clazz) implements ArgumentType { @Override - public String key() { - return clazz.getName().toLowerCase(); + public Class key() { + return clazz; } } @@ -33,8 +33,8 @@ record Infinite() implements ArgumentType { public static final Infinite INSTANCE = new Infinite(); @Override - public String key() { - return "infinite"; + public Class key() { + return fr.traqueur.commands.api.arguments.Infinite.class; } } diff --git a/core/src/main/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParser.java b/core/src/main/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParser.java index 1abfdfc..9f66e4a 100644 --- a/core/src/main/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParser.java +++ b/core/src/main/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParser.java @@ -20,10 +20,10 @@ public class DefaultArgumentParser implements ArgumentParser> typeConverters; + private final Map, ArgumentConverter.Wrapper> typeConverters; private final Logger logger; - public DefaultArgumentParser(Map> typeConverters, Logger logger) { + public DefaultArgumentParser(Map, ArgumentConverter.Wrapper> typeConverters, Logger logger) { this.typeConverters = typeConverters; this.logger = logger; } @@ -80,7 +80,7 @@ public ParseResult parse(Command command, String[] rawArgs) { } private ParseResult parseSingle(Arguments arguments, Argument arg, String input) { - String typeKey = arg.type().key(); + Class typeKey = arg.type().key(); ArgumentConverter.Wrapper wrapper = typeConverters.get(typeKey); if (wrapper == null) { @@ -88,7 +88,7 @@ private ParseResult parseSingle(Arguments arguments, Argument arg, String inp ParseError.Type.TYPE_NOT_FOUND, arg.name(), input, - "No converter for type: " + typeKey + "No converter for type: " + typeKey.getSimpleName() )); } diff --git a/core/src/test/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParserTest.java b/core/src/test/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParserTest.java index fb2fcc4..d76a38e 100644 --- a/core/src/test/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParserTest.java +++ b/core/src/test/java/fr/traqueur/commands/impl/parsing/DefaultArgumentParserTest.java @@ -22,16 +22,16 @@ class DefaultArgumentParserTest { @BeforeEach void setUp() { - Map> converters = new HashMap<>(); - converters.put("string", new ArgumentConverter.Wrapper<>(String.class, s -> s)); - converters.put("integer", new ArgumentConverter.Wrapper<>(Integer.class, s -> { + Map, ArgumentConverter.Wrapper> converters = new HashMap<>(); + converters.put(String.class, new ArgumentConverter.Wrapper<>(String.class, s -> s)); + converters.put(Integer.class, new ArgumentConverter.Wrapper<>(Integer.class, s -> { try { return Integer.valueOf(s); } catch (NumberFormatException e) { return null; } })); - converters.put("double", new ArgumentConverter.Wrapper<>(Double.class, s -> { + converters.put(Double.class, new ArgumentConverter.Wrapper<>(Double.class, s -> { try { return Double.valueOf(s); } catch (NumberFormatException e) { diff --git a/jda/src/main/java/fr/traqueur/commands/jda/JDAPlatform.java b/jda/src/main/java/fr/traqueur/commands/jda/JDAPlatform.java index 7d97aeb..341b29d 100644 --- a/jda/src/main/java/fr/traqueur/commands/jda/JDAPlatform.java +++ b/jda/src/main/java/fr/traqueur/commands/jda/JDAPlatform.java @@ -7,6 +7,8 @@ import fr.traqueur.commands.api.resolver.SenderResolver; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.*; @@ -288,20 +290,56 @@ private boolean hasTabCompleter(Argument arg) { * @param type The type string. * @return The corresponding OptionType. */ - private OptionType mapToOptionType(String type) { - return switch (type.toLowerCase()) { - case "integer", "int", "long" -> OptionType.INTEGER; - case "boolean" -> OptionType.BOOLEAN; - case "user", "member" -> OptionType.USER; - case "role" -> OptionType.ROLE; - case "channel", "guildchannelunion" -> OptionType.CHANNEL; - case "double", "float" -> OptionType.NUMBER; - case "attachment" -> OptionType.ATTACHMENT; - case "mentionable" -> OptionType.MENTIONABLE; + private OptionType mapToOptionType(Class type) { + return switch (type) { + + // INTEGER + case Class t when t == int.class + || t == Integer.class + || t == long.class + || t == Long.class + -> OptionType.INTEGER; + + // BOOLEAN + case Class t when t == boolean.class + || t == Boolean.class + -> OptionType.BOOLEAN; + + // USER / MEMBER + case Class t when User.class.isAssignableFrom(t) + || Member.class.isAssignableFrom(t) + -> OptionType.USER; + + // ROLE + case Class t when Role.class.isAssignableFrom(t) + -> OptionType.ROLE; + + // CHANNEL (tous types de channels) + case Class t when GuildChannel.class.isAssignableFrom(t) + -> OptionType.CHANNEL; + + // NUMBER + case Class t when t == double.class + || t == Double.class + || t == float.class + || t == Float.class + -> OptionType.NUMBER; + + // ATTACHMENT + case Class t when Message.Attachment.class.isAssignableFrom(t) + -> OptionType.ATTACHMENT; + + // MENTIONABLE + case Class t when IMentionable.class.isAssignableFrom(t) + -> OptionType.MENTIONABLE; + default -> OptionType.STRING; }; } + + + /** * Synchronize all registered commands with Discord globally. * This may take up to 1 hour to update.