Add Choices and Autocomplete #8
lib/src/main/java/net/tomatentum/marinara/interaction
annotation
commands
wrapper/javacord/src/main/java/net/tomatentum/marinara/wrapper/javacord
@ -0,0 +1,5 @@
|
|||||||
|
package net.tomatentum.marinara.interaction.annotation;
|
||||||
|
|
||||||
|
public @interface AutoComplete {
|
||||||
|
|
||||||
|
}
|
5
lib/src/main/java/net/tomatentum/marinara/interaction/commands/ChoiceValueProvider.java
Normal file
5
lib/src/main/java/net/tomatentum/marinara/interaction/commands/ChoiceValueProvider.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package net.tomatentum.marinara.interaction.commands;
|
||||||
|
|
||||||
|
public interface ChoiceValueProvider<T> {
|
||||||
|
T getChoiceValue();
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package net.tomatentum.marinara.interaction.commands;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.leangen.geantyref.AnnotationFormatException;
|
||||||
|
import io.leangen.geantyref.GenericTypeReflector;
|
||||||
|
import io.leangen.geantyref.TypeFactory;
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
||||||
|
|
||||||
|
public record EnumChoices(Class<? extends Enum<?>> enumClass, ChoiceType type, SlashCommandOptionChoice[] choices) {
|
||||||
|
|
||||||
|
private static Method method;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
method = ChoiceValueProvider.class.getMethod("getChoiceValue");
|
||||||
|
} catch (NoSuchMethodException | SecurityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EnumChoices of(Class<? extends Enum<?>> enumClass) {
|
||||||
|
if (!ChoiceValueProvider.class.isAssignableFrom(enumClass))
|
||||||
|
throw new IllegalArgumentException("Provided class needs to implement the ChoiceValueProvider interface.");
|
||||||
|
ChoiceType type = parseChoiceType(enumClass);
|
||||||
|
SlashCommandOptionChoice[] choices = parseChoices(enumClass, type);
|
||||||
|
return new EnumChoices(enumClass, type, choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChoiceType parseChoiceType(Class<? extends Enum<?>> enumClass) {
|
||||||
|
ParameterizedType type = (ParameterizedType) GenericTypeReflector.getExactSuperType(enumClass, ChoiceValueProvider.class);
|
||||||
|
Type typeParam = type.getActualTypeArguments()[0];
|
||||||
|
|
||||||
|
if (!(typeParam instanceof Class<?>))
|
||||||
|
throw new IllegalArgumentException("ChoiceValueProvider need either a String or Number type parameter.");
|
||||||
|
|
||||||
|
if (String.class.isAssignableFrom((Class<?>) typeParam))
|
||||||
|
return ChoiceType.String;
|
||||||
|
else if (Number.class.isAssignableFrom((Class<?>) typeParam))
|
||||||
|
return ChoiceType.Number;
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException("ChoiceValueProvider need either a String or Number type parameter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SlashCommandOptionChoice[] parseChoices(Class<? extends Enum<?>> enumClass, ChoiceType type) {
|
||||||
|
Enum<? extends Enum<?>>[] constants = enumClass.getEnumConstants();
|
||||||
|
List<SlashCommandOptionChoice> choices = new ArrayList<>();
|
||||||
|
for (Enum<? extends Enum<?>> enumInstance : constants) {
|
||||||
|
Object value;
|
||||||
|
try {
|
||||||
|
value = method.invoke(enumInstance);
|
||||||
|
if (type.equals(ChoiceType.String))
|
||||||
|
choices.add(TypeFactory.annotation(SlashCommandOptionChoice.class, Map.of("name", enumInstance.name(), "stringValue", value)));
|
||||||
|
else if (type.equals(ChoiceType.Number))
|
||||||
|
choices.add(TypeFactory.annotation(SlashCommandOptionChoice.class, Map.of("name", enumInstance.name(), "longValue", value)));
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException | AnnotationFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return choices.toArray(new SlashCommandOptionChoice[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum ChoiceType {
|
||||||
|
String,
|
||||||
|
Number
|
||||||
|
}
|
||||||
|
}
|
8
lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java
8
lib/src/main/java/net/tomatentum/marinara/interaction/commands/ExecutableSlashCommandDefinition.java
@ -2,6 +2,7 @@ package net.tomatentum.marinara.interaction.commands;
|
|||||||
|
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
|
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
|
||||||
|
|
||||||
@ -11,6 +12,13 @@ public record ExecutableSlashCommandDefinition(
|
|||||||
SubCommandGroup subCommandGroup,
|
SubCommandGroup subCommandGroup,
|
||||||
SlashCommandOption[] options) {
|
SlashCommandOption[] options) {
|
||||||
|
|
||||||
|
public static SlashCommandOptionChoice[] getActualChoices(SlashCommandOption option) {
|
||||||
|
SlashCommandOptionChoice[] choices = option.choices();
|
||||||
|
if (choices.length <= 0)
|
||||||
|
choices = EnumChoices.of(option.choiceEnum()).choices();
|
||||||
|
return choices;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object o) {
|
public final boolean equals(Object o) {
|
||||||
if (!(o instanceof ExecutableSlashCommandDefinition))
|
if (!(o instanceof ExecutableSlashCommandDefinition))
|
||||||
|
@ -14,4 +14,10 @@ public @interface SlashCommandOption {
|
|||||||
public String description() default "";
|
public String description() default "";
|
||||||
public SlashCommandOptionType type() default SlashCommandOptionType.STRING;
|
public SlashCommandOptionType type() default SlashCommandOptionType.STRING;
|
||||||
public boolean required() default false;
|
public boolean required() default false;
|
||||||
|
public SlashCommandOptionChoice[] choices() default {};
|
||||||
|
public Class<? extends Enum<?>> choiceEnum() default PlaceHolderEnum.class;
|
||||||
|
|
||||||
|
public static enum PlaceHolderEnum {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
7
lib/src/main/java/net/tomatentum/marinara/interaction/commands/annotation/SlashCommandOptionChoice.java
Normal file
7
lib/src/main/java/net/tomatentum/marinara/interaction/commands/annotation/SlashCommandOptionChoice.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package net.tomatentum.marinara.interaction.commands.annotation;
|
||||||
|
|
||||||
|
public @interface SlashCommandOptionChoice {
|
||||||
|
public String name();
|
||||||
|
public long longValue() default Long.MAX_VALUE;
|
||||||
|
public String stringValue() default "";
|
||||||
|
}
|
@ -22,6 +22,7 @@ import net.tomatentum.marinara.interaction.commands.ExecutableSlashCommandDefini
|
|||||||
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
import net.tomatentum.marinara.interaction.commands.SlashCommandDefinition;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommand;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOption;
|
||||||
|
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
|
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
|
||||||
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
|
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
|
||||||
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
|
import net.tomatentum.marinara.interaction.commands.option.SlashCommandOptionType;
|
||||||
@ -121,18 +122,35 @@ public class JavacordWrapper extends LibraryWrapper {
|
|||||||
private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) {
|
private org.javacord.api.interaction.SlashCommandOption convertSubCommandGroupDef(SlashCommandDefinition def, SubCommandGroup subGroup) {
|
||||||
SubCommand[] subCommands = def.getSubCommands(subGroup.name());
|
SubCommand[] subCommands = def.getSubCommands(subGroup.name());
|
||||||
org.javacord.api.interaction.SlashCommandOption[] convertedSubCommands = (org.javacord.api.interaction.SlashCommandOption[]) Arrays.stream(subCommands).map(this::convertSubCommandDef).toArray();
|
org.javacord.api.interaction.SlashCommandOption[] convertedSubCommands = (org.javacord.api.interaction.SlashCommandOption[]) Arrays.stream(subCommands).map(this::convertSubCommandDef).toArray();
|
||||||
return org.javacord.api.interaction.SlashCommandOption.createWithOptions(org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND_GROUP, subGroup.name(), subGroup.description(), Arrays.asList(convertedSubCommands));
|
return org.javacord.api.interaction.SlashCommandOption.createWithOptions(
|
||||||
|
org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND_GROUP,
|
||||||
|
subGroup.name(),
|
||||||
|
subGroup.description(),
|
||||||
|
Arrays.asList(convertedSubCommands));
|
||||||
}
|
}
|
||||||
|
|
||||||
private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SubCommand sub) {
|
private org.javacord.api.interaction.SlashCommandOption convertSubCommandDef(SubCommand sub) {
|
||||||
List<org.javacord.api.interaction.SlashCommandOption> convertedOptions = new ArrayList<>();
|
List<org.javacord.api.interaction.SlashCommandOption> convertedOptions = new ArrayList<>();
|
||||||
Arrays.stream(sub.options()).map(this::convertOptionDef).forEach(convertedOptions::add);
|
Arrays.stream(sub.options()).map(this::convertOptionDef).forEach(convertedOptions::add);
|
||||||
return org.javacord.api.interaction.SlashCommandOption.createWithOptions(org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND, sub.name(), sub.description(), convertedOptions);
|
return org.javacord.api.interaction.SlashCommandOption.createWithOptions(
|
||||||
|
org.javacord.api.interaction.SlashCommandOptionType.SUB_COMMAND,
|
||||||
|
sub.name(),
|
||||||
|
sub.description(),
|
||||||
|
convertedOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private org.javacord.api.interaction.SlashCommandOption convertOptionDef(SlashCommandOption option) {
|
private org.javacord.api.interaction.SlashCommandOption convertOptionDef(SlashCommandOption option) {
|
||||||
org.javacord.api.interaction.SlashCommandOptionType type = Enum.valueOf(org.javacord.api.interaction.SlashCommandOptionType.class, option.type().toString());
|
org.javacord.api.interaction.SlashCommandOptionType type = Enum.valueOf(org.javacord.api.interaction.SlashCommandOptionType.class, option.type().toString());
|
||||||
return org.javacord.api.interaction.SlashCommandOption.create(type, option.name(), option.description(), option.required());
|
|
||||||
|
List<org.javacord.api.interaction.SlashCommandOptionChoice> choices = new ArrayList<>();
|
||||||
|
for (SlashCommandOptionChoice choice : ExecutableSlashCommandDefinition.getActualChoices(option)) {
|
||||||
|
if (choice.stringValue().isEmpty())
|
||||||
|
choices.add(org.javacord.api.interaction.SlashCommandOptionChoice.create(choice.name(), choice.longValue()));
|
||||||
|
else
|
||||||
|
choices.add(org.javacord.api.interaction.SlashCommandOptionChoice.create(choice.name(), choice.stringValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return org.javacord.api.interaction.SlashCommandOption.createWithChoices(type, option.name(), option.description(), option.required(), choices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getOptionValue(SlashCommandInteractionOption option, SlashCommandOptionType type) {
|
private Object getOptionValue(SlashCommandInteractionOption option, SlashCommandOptionType type) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user