v0.11.1
⚠️ Attention: This version introduces breaking changes!
If you are using these interface type checks shown below, you might need to replaceken.Command
withken.SlashCommand
for appropriate type checking.var _ ken.SlashCommand = (*TestCommand)(nil)
This version allows to also handle user and message commands using the same middleware pipeline as used for slash commands. Therefore, 3 new interfaces have been introduced to define slash, user and message commands.
slashcommand.go
// SlashCommand defines a callable slash command.
type SlashCommand interface {
Command
// Version returns the commands semantic version.
Version() string
// Options returns an array of application
// command options.
Options() []*discordgo.ApplicationCommandOption
}
usercommand.go
// UserCommand defines a callable user command.
type UserCommand interface {
Command
// TypeUser is used to differenciate between
// UserCommand and MessageCommand which have
// the same structure otherwise.
//
// This method must only be implemented and
// will never be called by ken, so it can be
// completely empty.
TypeUser()
}
messagecommand.go
// MessageCommand defines a callable message command.
type MessageCommand interface {
Command
// TypeMessage is used to differenciate between
// UserCommand and MessageCommand which have
// the same structure otherwise.
//
// This method must only be implemented and
// will never be called by ken, so it can be
// completely empty.
TypeMessage()
}
As you can see, all three of them extend the Command
interface.
command.go
type Command interface {
// Name returns the unique name of the command.
Name() string
// Description returns a brief text which concisely
// describes the commands purpose.
Description() string
// Run is called on command invokation getting
// passed the invocation context.
//
// When something goes wrong during command
// execution, you can return an error which is
// then handled by Ken's OnCommandError handler.
Run(ctx *Ctx) (err error)
}
func toApplicationCommand(c Command) *discordgo.ApplicationCommand {
switch cm := c.(type) {
case UserCommand:
return &discordgo.ApplicationCommand{
Name: cm.Name(),
Type: discordgo.UserApplicationCommand,
}
case MessageCommand:
return &discordgo.ApplicationCommand{
Name: cm.Name(),
Type: discordgo.MessageApplicationCommand,
}
case SlashCommand:
return &discordgo.ApplicationCommand{
Name: cm.Name(),
Type: discordgo.ChatApplicationCommand,
Description: cm.Description(),
Version: cm.Version(),
Options: cm.Options(),
}
default:
panic(fmt.Sprintf("Command type not implemented for command: %s", cm.Name()))
}
}
This allows to register user and message commands using the same Ken#RegisterCommand
endpoint as before.
To differentiate between user and message commands - because they effectively have the same API structure - there are the two shallow methods TypeUser()
and TypeMessage()
. These have absolutely no programmatically purpose and are only there for type differentiation. I know, this is kinda janky but otherwise this approach would hardly be possible this way at the moment.
This also allows the re-usage of existing code from slash commands in user commands. To view a "real world" example, please take a look at the implementation of the user slash command and userinfo user command implementation in shinpuru.