add prototype choices implementation
Some checks failed
github-mirror / push-github (push) Successful in 5s
Build / Gradle-Build (push) Successful in 50s
Test / Gradle-Test (push) Failing after 41s

This commit is contained in:
2024-12-13 10:50:30 +01:00
parent d8504a7cde
commit 69b27e4554
7 changed files with 126 additions and 3 deletions

View File

@@ -0,0 +1,5 @@
package net.tomatentum.marinara.interaction.annotation;
public @interface AutoComplete {
}

View File

@@ -0,0 +1,5 @@
package net.tomatentum.marinara.interaction.commands;
public interface ChoiceValueProvider<T> {
T getChoiceValue();
}

View File

@@ -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
}
}

View File

@@ -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.SlashCommandOption;
import net.tomatentum.marinara.interaction.commands.annotation.SlashCommandOptionChoice;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommand;
import net.tomatentum.marinara.interaction.commands.annotation.SubCommandGroup;
@@ -11,6 +12,13 @@ public record ExecutableSlashCommandDefinition(
SubCommandGroup subCommandGroup,
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
public final boolean equals(Object o) {
if (!(o instanceof ExecutableSlashCommandDefinition))

View File

@@ -14,4 +14,10 @@ public @interface SlashCommandOption {
public String description() default "";
public SlashCommandOptionType type() default SlashCommandOptionType.STRING;
public boolean required() default false;
public SlashCommandOptionChoice[] choices() default {};
public Class<? extends Enum<?>> choiceEnum() default PlaceHolderEnum.class;
public static enum PlaceHolderEnum {
}
}

View 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 "";
}