All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.freya022.botcommands.api.parameters.Resolvers.kt Maven / Gradle / Ivy

Go to download

A Kotlin-first (and Java) framework that makes creating Discord bots a piece of cake, using the JDA library.

There is a newer version: 3.0.0-alpha.18
Show newest version
package io.github.freya022.botcommands.api.parameters

import io.github.freya022.botcommands.api.commands.application.slash.annotations.SlashOption
import io.github.freya022.botcommands.api.commands.prefixed.BaseCommandEvent
import io.github.freya022.botcommands.api.core.service.annotations.Resolver
import io.github.freya022.botcommands.api.parameters.Resolvers.toHumanName
import io.github.freya022.botcommands.internal.commands.application.slash.SlashCommandInfo
import io.github.freya022.botcommands.internal.commands.prefixed.TextCommandVariation
import io.github.freya022.botcommands.internal.components.ComponentDescriptor
import net.dv8tion.jda.api.entities.Guild
import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
import net.dv8tion.jda.api.interactions.commands.Command.Choice
import net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload
import net.dv8tion.jda.api.interactions.commands.OptionMapping
import net.dv8tion.jda.api.interactions.commands.OptionType
import java.util.*
import java.util.regex.Pattern
import kotlin.reflect.KParameter

internal class EnumResolver> internal constructor(
    e: Class,
    private val values: Array,
    private val nameFunction: EnumNameFunction
) :
    ClassParameterResolver, E>(e),
    RegexParameterResolver, E>,
    SlashParameterResolver, E>,
    ComponentParameterResolver, E> {

    //region Regex
    override val pattern: Pattern = Pattern.compile("(?i)(${values.joinToString("|") { Pattern.quote(nameFunction.apply(it)) }})(?-i)")

    override val testExample: String = values.first().name

    override fun getHelpExample(parameter: KParameter, event: BaseCommandEvent, isID: Boolean): String {
        return nameFunction.apply(values.first())
    }

    override suspend fun resolveSuspend(
        variation: TextCommandVariation,
        event: MessageReceivedEvent,
        args: Array
    ): E = values.first { it.name.contentEquals(args[0], ignoreCase = true) }
    //endregion

    //region Slash
    override val optionType: OptionType = OptionType.STRING

    override fun getPredefinedChoices(guild: Guild?): Collection {
        return values.map { Choice(nameFunction.apply(it), it.name) }
    }

    override suspend fun resolveSuspend(
        info: SlashCommandInfo,
        event: CommandInteractionPayload,
        optionMapping: OptionMapping
    ): E = values.first { it.name == optionMapping.asString }
    //endregion

    //region Component
    override suspend fun resolveSuspend(
        descriptor: ComponentDescriptor,
        event: GenericComponentInteractionCreateEvent,
        arg: String
    ): E = values.first { it.name == arg }
    //endregion

    override fun toString(): String {
        return "EnumResolver(values=${values.contentToString()}, nameFunction=$nameFunction)"
    }
}

fun interface EnumNameFunction> {
    fun apply(value: E): String
}

/**
 * Utility factories to create commonly used parameter resolvers.
 */
object Resolvers {
    /**
     * Creates an enum resolver for [text][RegexParameterResolver]/[slash][SlashParameterResolver] commands,
     * as well as [component data][ComponentParameterResolver].
     *
     * The created resolver needs to be registered either by calling [ResolverContainer.addResolver],
     * or by using a service factory with [Resolver] as such:
     *
     * ```java
     * public class EnumResolvers {
     *     // Resolver for DAYS/HOURS/MINUTES, where the displayed name is given by 'Resolvers#toHumanName'
     *     @Resolver
     *     public ParameterResolver timeUnitResolver() {
     *         return Resolvers.enumResolver(TimeUnit.class, TimeUnit.values());
     *     }
     *
     *     ...other resolvers...
     * }
     * ```
     *
     * **Note:** You have to enable [SlashOption.usePredefinedChoices] in order for the choices to appear.
     *
     * @param values       the accepted enumeration values
     * @param nameFunction the function transforming the enum value into the display name
     */
    @JvmStatic
    @JvmOverloads
    fun > enumResolver(
        e: Class,
        values: Array,
        nameFunction: EnumNameFunction = EnumNameFunction { it.toHumanName() }
    ): ClassParameterResolver<*, E> {
        return EnumResolver(e, values, nameFunction)
    }

    @JvmStatic
    @JvmOverloads
    fun > toHumanName(value: E, locale: Locale = Locale.ROOT): String {
        return value.name.lowercase(locale).replaceFirstChar { it.uppercaseChar() }
    }
}

/**
 * Creates an enum resolver for [text][RegexParameterResolver]/[slash][SlashParameterResolver] commands,
 * as well as [component data][ComponentParameterResolver].
 *
 * The created resolver needs to be registered either by calling [ResolverContainer.addResolver],
 * or by using a service factory with [Resolver] as such:
 *
 * ```kt
 * object EnumResolvers {
 *     // Resolver for DAYS/HOURS/MINUTES, where the displayed name is given by 'Resolvers.Enum#toHumanName'
 *     @Resolver
 *     fun timeUnitResolver() = enumResolver(TimeUnit.DAYS, TimeUnit.HOURS, TimeUnit.MINUTES)
 *
 *     ...other resolvers...
 * }
 * ```
 *
 * **Note:** You have to enable [SlashOption.usePredefinedChoices] in order for the choices to appear.
 *
 * @param values       the accepted enumeration values
 * @param nameFunction the function transforming the enum value into the display name
 */
inline fun > enumResolver(
    vararg values: E = enumValues(),
    noinline nameFunction: (e: E) -> String = { it.toHumanName() }
): ClassParameterResolver<*, E> = Resolvers.enumResolver(E::class.java, values, nameFunction)

fun > E.toHumanName(locale: Locale = Locale.ROOT): String = toHumanName(this, locale)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy