Adding option resolvers
Option resolvers help you support other types for your command options, such as TimeUnit
, or any object of your own.
Slash command option resolvers specify which option type will be used on Discord, and will handle the conversion from the Discord value to the corresponding object.
The class implementing the resolver, or the function returning a resolver, must be annotated with @Resolver
.
Note
@Resolver
is one of the annotations that are considered as a service annotation.
This means that it behaves exactly the same as if you had used @BService
,
except here the annotation is more meaningful.
Implementation¶
For that, you need a class annotated with @Resolver
extending ClassParameterResolver
,
and implementing SlashParameterResolver
.
The first type parameter is the type of your resolver implementation, and the second type is what the resolver returns.
A TimeUnit
resolver
@Resolver
class TimeUnitResolver :
ClassParameterResolver<TimeUnitResolver, TimeUnit>(TimeUnit::class),
SlashParameterResolver<TimeUnitResolver, TimeUnit> {
override val optionType: OptionType = OptionType.STRING
// This is all you need to implement to support predefined choices
override fun getPredefinedChoices(guild: Guild?): Collection<Choice> {
return listOf(TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS)
// The Resolvers class helps us by providing resolvers for any enum type.
// We're just using the helper method to change an enum value to a more natural name.
.map { Choice(it.toHumanName(), it.name) }
}
override suspend fun resolveSuspend(
option: SlashCommandOption,
event: CommandInteractionPayload,
optionMapping: OptionMapping
): TimeUnit = enumValueOf<TimeUnit>(optionMapping.asString)
}
@Resolver
public class TimeUnitResolver
extends ClassParameterResolver<TimeUnitResolver, TimeUnit>
implements SlashParameterResolver<TimeUnitResolver, TimeUnit> {
public TimeUnitResolver() {
super(TimeUnit.class);
}
@NotNull
@Override
public OptionType getOptionType() {
return OptionType.STRING;
}
@NotNull
@Override
public Collection<Command.Choice> getPredefinedChoices(@Nullable Guild guild) {
return Stream.of(TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS)
// The Resolvers class helps us by providing resolvers for any enum type.
// We're just using the helper method to change an enum value to a more natural name.
.map(u -> new Command.Choice(Resolvers.toHumanName(u), u.name()))
.toList();
}
@Nullable
@Override
public TimeUnit resolve(@NotNull SlashCommandOption option, @NotNull CommandInteractionPayload event, @NotNull OptionMapping optionMapping) {
return TimeUnit.valueOf(optionMapping.getAsString());
}
}
As you can see, this defines the slash command's option to be a string, and provides predefined choices, letting you easily use them in your commands.
Creating resolvers for parametrized types
You can also extend TypedParameterResolver
for use with parametrized type,
Kotlin users can pass a KType directly, using typeOf
,
but Java users can use a KotlinTypeToken
instead.
Built-in resolver generators¶
The framework also provides functions in Resolvers
to do most of the work for some types,
all you need to do is declare a service factory with @Resolver
and use the provided methods.
Note
Currently there is only a factory for enum resolvers, but others might be added in the future.
How to easily make a resolver for an enum type
object TimeUnitResolverSimplified {
// The displayed name should be lowercase with the first letter uppercase, see Resolvers#toHumanName
@Resolver
fun getTimeUnitResolverSimplified() = enumResolver<TimeUnit>(TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS)
}
object
or have a no-arg constructor.
public class TimeUnitResolverSimplifiedJava {
@Resolver
public static ParameterResolver<?, TimeUnit> getTimeUnitResolverSimplified() {
// The displayed name should be lowercase with the first letter uppercase, see Resolvers#toHumanName
return Resolvers.enumResolver(TimeUnit.class, EnumSet.of(TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS)).build();
}
}