Kord-Extensions/kord-extensions

Converter function changes

gdude2002 opened this issue · 3 comments

Now that Kord supports autocomplete for slash commands, I think it's a good time to revisit the converter API - specifically, how you specify them for command arguments.

Currently, converters are specified like this:

inner class GreetArguments : Arguments() {
    val target by user("user", "Person you'd like to greet")

    val message by defaultingString("message", "Message you'd like to send", defaultValue = "Hello there!") { arg, value ->
        if (value.contains("goodbye", true)) throw DiscordRelayedException("You can't say goodbye in a greeting!")
    }
}

While this works for simple use-cases, I think we can do a lot better with a builder-style DSL instead:

inner class GreetArguments : Arguments() {
    val target by user {
        name = "user"
        description = "Person you'd like to greet"
    }

    val message by defaultingString {
        name = "message"
        description = "Message you'd like to send"

        default = "Hello there!"

        check {
            failIf("You can't say goodbye in a greeting!") { value.contains("goodbye", true) }
        }
    }
}

Not only would this bring validation more in line with what we expect from predicates in KordEx, but I think it makes for a much more sensible and future-proof API.


This is obviously a large breaking change to the converter system. What do people think?

So, this a very nice proposition, streamlining the API (it looks like a slash command dsl)

It would even open up to an easier syntax for own simple converters, which convert simple Discord Datatypes (string, number etc) to your own, so that you have access to them.

E.g.: My usecase would be to convert a certain String of characters to codes that only make sense inside my application.
would be

val message by defaulting<String> { // or however it would look like
        name = "message"
        description = "Message you'd like to send"

        default = "Hello there!"

        check {
            failIf("You can't say goodbye in a greeting!") { value.contains("goodbye", true) }
        }
        convert { str ->
            MyDatatype(str)
        }
    }

I don't think there's actually a good way to do this in Kotlin's type system, though a wrapping converter could work, I think. Not entirely sure.

Looks good to me 👍