Files
dislate/lib/command_chat.go

273 lines
8.2 KiB
Go

package bot
import (
"errors"
"fmt"
"slices"
"github.com/bwmarrin/discordgo"
)
type ChatCommand struct {
Name string
NameLocalizations *map[discordgo.Locale]string
DefaultMemberPermissions *int64
NSFW *bool
Description string
DescriptionLocalizations *map[discordgo.Locale]string
Options []ChatCommandOption
Handler Handler
}
func (c *ChatCommand) ApplicationCommand() *discordgo.ApplicationCommand {
requiredOpts := []*discordgo.ApplicationCommandOption{}
opts := []*discordgo.ApplicationCommandOption{}
for _, o := range c.Options {
opt := o.ApplicationCommandOption()
if opt.Required {
requiredOpts = append(requiredOpts, opt)
} else {
opts = append(opts, opt)
}
}
return &discordgo.ApplicationCommand{
Type: discordgo.ChatApplicationCommand,
Name: c.Name,
NameLocalizations: c.NameLocalizations,
DefaultMemberPermissions: c.DefaultMemberPermissions,
NSFW: c.NSFW,
Description: c.Description,
DescriptionLocalizations: c.DescriptionLocalizations,
Options: slices.Concat(requiredOpts, opts),
}
}
func (c *ChatCommand) Validate() (bool, error) {
switch {
case c.Name == "":
return false, errors.New("Required property \"Name\" is empty")
case c.Description == "":
return false, errors.New("Required property \"Description\" is empty")
case c.Handler == nil:
return false, errors.New("Required property \"Handler\" is empty")
}
for _, opt := range c.Options {
if ok, err := opt.Validate(); !ok {
return false, errors.Join(
fmt.Errorf("Option %q is not valid", opt.ApplicationCommandOption().Name),
err,
)
}
}
return true, nil
}
type ChatCommandOption interface {
ApplicationCommandOption() *discordgo.ApplicationCommandOption
Validate() (bool, error)
}
type ChatCommandStringOption struct {
Name string
NameLocalizations map[discordgo.Locale]string
Description string
DescriptionLocalizations map[discordgo.Locale]string
Required bool
Autocomplete bool
Choices []*ChatCommandStringOptionChoice
MinLength int
MaxLength int
}
type ChatCommandStringOptionChoice struct {
Name string
NameLocalizations map[discordgo.Locale]string
Value string
}
func (o *ChatCommandStringOption) ApplicationCommandOption() *discordgo.ApplicationCommandOption {
choices := make([]*discordgo.ApplicationCommandOptionChoice, len(o.Choices))
for i, v := range o.Choices {
choices[i] = &discordgo.ApplicationCommandOptionChoice{
Name: v.Name,
NameLocalizations: v.NameLocalizations,
Value: any(v.Value),
}
}
return &discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionString,
Name: o.Name,
NameLocalizations: o.NameLocalizations,
Description: o.Description,
DescriptionLocalizations: o.DescriptionLocalizations,
Required: o.Required,
Autocomplete: o.Autocomplete,
MinLength: &o.MinLength,
MaxLength: o.MaxLength,
Choices: choices,
}
}
func (o *ChatCommandStringOption) Validate() (bool, error) {
if o.MinLength > 6000 {
return false, errors.New(
"Property \"MinLength\" has value that exceeds the allowed limit of 6000",
)
} else if o.MaxLength > 6000 {
return false, errors.New(
"Property \"MaxLength\" has value that exceeds the allowed limit of 6000",
)
}
return validateOption(o)
}
type ChatCommandIntegerOption struct {
Name string
NameLocalizations map[discordgo.Locale]string
Description string
DescriptionLocalizations map[discordgo.Locale]string
Required bool
Autocomplete bool
Choices []*ChatCommandIntegerOptionChoice
MinValue int
MaxValue int
}
type ChatCommandIntegerOptionChoice struct {
Name string
NameLocalizations map[discordgo.Locale]string
Value int
}
func (o *ChatCommandIntegerOption) ApplicationCommandOption() *discordgo.ApplicationCommandOption {
choices := make([]*discordgo.ApplicationCommandOptionChoice, len(o.Choices))
for i, v := range o.Choices {
choices[i] = &discordgo.ApplicationCommandOptionChoice{
Name: v.Name,
NameLocalizations: v.NameLocalizations,
Value: any(v.Value),
}
}
minValue := float64(o.MinValue)
return &discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionInteger,
Name: o.Name,
NameLocalizations: o.NameLocalizations,
Description: o.Description,
DescriptionLocalizations: o.DescriptionLocalizations,
Required: o.Required,
Autocomplete: o.Autocomplete,
MinValue: &minValue,
MaxValue: float64(o.MaxValue),
Choices: choices,
}
}
func (o *ChatCommandIntegerOption) Validate() (bool, error) {
return validateOption(o)
}
type ChatCommandBooleanOption struct {
Name string
NameLocalizations map[discordgo.Locale]string
Description string
DescriptionLocalizations map[discordgo.Locale]string
Required bool
Autocomplete bool
Choices []*ChatCommandBooleanOptionChoice
}
type ChatCommandBooleanOptionChoice struct {
Name string
NameLocalizations map[discordgo.Locale]string
Value bool
}
func (o *ChatCommandBooleanOption) ApplicationCommandOption() *discordgo.ApplicationCommandOption {
choices := make([]*discordgo.ApplicationCommandOptionChoice, len(o.Choices))
for i, v := range o.Choices {
choices[i] = &discordgo.ApplicationCommandOptionChoice{
Name: v.Name,
NameLocalizations: v.NameLocalizations,
Value: any(v.Value),
}
}
return &discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionBoolean,
Name: o.Name,
NameLocalizations: o.NameLocalizations,
Description: o.Description,
DescriptionLocalizations: o.DescriptionLocalizations,
Required: o.Required,
Autocomplete: o.Autocomplete,
Choices: choices,
}
}
func (o *ChatCommandBooleanOption) Validate() (bool, error) {
return validateOption(o)
}
type ChatCommandUserOption struct {
Name string
NameLocalizations map[discordgo.Locale]string
Description string
DescriptionLocalizations map[discordgo.Locale]string
Required bool
Autocomplete bool
Choices []*ChatCommandUserOptionChoice
}
type ChatCommandUserOptionChoice = ChatCommandStringOptionChoice
func (o *ChatCommandUserOption) ApplicationCommandOption() *discordgo.ApplicationCommandOption {
choices := make([]*discordgo.ApplicationCommandOptionChoice, len(o.Choices))
for i, v := range o.Choices {
choices[i] = &discordgo.ApplicationCommandOptionChoice{
Name: v.Name,
NameLocalizations: v.NameLocalizations,
Value: any(v.Value),
}
}
return &discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionUser,
Name: o.Name,
NameLocalizations: o.NameLocalizations,
Description: o.Description,
DescriptionLocalizations: o.DescriptionLocalizations,
Required: o.Required,
Autocomplete: o.Autocomplete,
Choices: choices,
}
}
func (o *ChatCommandUserOption) Validate() (bool, error) {
return validateOption(o)
}
func validateOption(opt interface {
ApplicationCommandOption() *discordgo.ApplicationCommandOption
},
) (bool, error) {
o := opt.ApplicationCommandOption()
switch {
case o.Name == "":
return false, errors.New("Required property \"Name\" is empty")
case o.Description == "":
return false, errors.New("Required property \"Description\" is empty")
}
return true, nil
}