Skip to content
/ wire Public

— a command & interaction framework for kord

Notifications You must be signed in to change notification settings

keia-bot/wire

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

🧵 Keia • Wire

Currently working on getting an open-source release underway!
Join our Discord Server for more information.

An i18n-first interaction & message command framework for Kord.

💾 Example

Setup

object MyI18nProvider : I18nProvider {
    override fun getStrings(specifier: String): Map<String, Locale> = TODO()

    override fun getString(specifier: String, locale: Locale): String = TODO()

    override fun interpolate(format: String, locale: String, arguments: Map<String, Any?>): String
}

suspend fun main() {
  val kord = Kord()

  // the Kord#wire extension automatically creates event listeners
  val wire = kord.wire {
    i18n = MyI18nProvider

    // enable support for interaction-based commands
    interactionCommands()

    // enable support for message-based commands
    messageCommands {
      // this disables the message content intent and requires
      // that a mention be used as the prefix.
      mentionOnly = true

      //
      providePrefixes { ctx ->
        ctx.guildOrNull
          ?.let { findGuildPrefixes(it.id) } 
          ?: listOf("!")
      }
    }
  }

  // add our commands
  wire.add(MyCommand)

  // register our commands with Discord (only applicable to interaction commands.)
  wire.register()

  // login to discord.
  kord.login {
    val ourIntents = Intent.Guilds
    intents = wire.intents + ourIntents
  }
}

Commands

1. Create a command

As chat-input commands are forbidden to have a base-command (/my-command) along side sub-commands (/my-command sub-command), Wire has two separate root-command types, Single and Nested. Due to this fact, message-based commands must also suffer from this issue.

object MyCommand : Command.Single() {
  override suspend fun execute(ctx: FinalCommandContext) {
    ctx.respondEmbed("Hi ${ctx.user.mention}!")    
  }
}

2. Using Parameters

Wire has a very simple parameter api that allows for them to be easily shared between interactions and messages.

object MyCommand : Command.Single("my-command") {
  enum class Fizz {
    Fizz,
    Buzz,
    FizzBuzz
  }

  // string values with min/max length
  private val P_MESSAGE = p.text("message") {
    min = 5
    max = 30
  }

  // optional values
  private val P_QUOTED = p.optional(p.bool("quoted"))

  // provide completions through static entries or a callback.
  private val P_FOOBAR = p.text("test") {
    // static choices
    choices("foo" to "bar", "bar" to "foo")

    // callback choices
    autocomplete { ctx, term ->
      mapOf("foo" to "bar", "bar" to "foo", "something" to term)
    } 
  }

  // enum values using their name (enumName) or ordinal (enumOrdinal)
  // (this is a custom parameter type!)
  private val P_FIZZ_BUZZ = p.enumOrdinal<Fizz>("fizzbuzz")

  override val parameters get() = setOf(P_MESSAGE, P_QUOTED, P_FOOBAR, P_FIZZ_BUZZ)

  override suspend fun execute(ctx: FinalCommandContext) {
    val message = ctx.args[P_MESSAGE]

    // CommandContext#ta automatically prepends the translation path for this command to
    // the specifier you provide use Context#t if you need absolute specifiers.
    val translated = ctx.ta(
        "response", // commands.my-command.response
        "message" to if (ctx.args[P_QUOTED] == true) "'$message'" else message,
        "fizz" to ctx.args[P_FIZZ_BUZZ].name,
        "foo" to ctx.args[P_FOOBAR]
    )

    ctx.respondEmbed(translated)
  }
}

3. Creating Parameter Types

Wire supports creating custom parameter types using a base type and transform function.

@JvmInline
value class Percentage(val value: Float)

// A custom type that converts a `text` parameter to a Percentage object.
// The `InvalidParameterException` type can be thrown to report validation issues to the user.
val PercentageType = ParameterType.Custom(
  { value -> Percentage(value.removeSuffix("%").toFloat()) },
  PT.text()
);

Have any questions? Join our Discord Server!

dimensional fun © 2024