feat(commands): handling of sub commands
This commit is contained in:
@@ -2,8 +2,11 @@ package bot
|
||||
|
||||
import (
|
||||
"dislate/internals/discord/bot/commands"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"slices"
|
||||
|
||||
dgo "github.com/bwmarrin/discordgo"
|
||||
)
|
||||
@@ -13,16 +16,72 @@ func (b *Bot) registerCommands() error {
|
||||
commands.NewManageChannel(b.db),
|
||||
}
|
||||
|
||||
rcs := make([]*dgo.ApplicationCommand, len(cs))
|
||||
handlers := make(map[string]func(*dgo.Session, *dgo.InteractionCreate), len(cs))
|
||||
|
||||
for i, v := range cs {
|
||||
cmd, err := b.session.ApplicationCommandCreate(b.session.State.User.ID, "", v.Info())
|
||||
if err != nil {
|
||||
return err
|
||||
for _, v := range cs {
|
||||
var cmd *dgo.ApplicationCommand
|
||||
var err error
|
||||
subCmds := make(map[string]commands.Command)
|
||||
|
||||
sb := v.Subcommands()
|
||||
|
||||
if len(sb) == 0 {
|
||||
cmd, err = b.session.ApplicationCommandCreate(b.session.State.User.ID, "", v.Info())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
subCmdsOpts := make([]*dgo.ApplicationCommandOption, len(sb))
|
||||
for i, sb := range sb {
|
||||
subCmds[sb.Info().Name] = sb
|
||||
subCmdsOpts[i] = &dgo.ApplicationCommandOption{
|
||||
Type: dgo.ApplicationCommandOptionSubCommand,
|
||||
Name: sb.Info().Name,
|
||||
Description: sb.Info().Description,
|
||||
Options: sb.Info().Options,
|
||||
}
|
||||
}
|
||||
info := v.Info()
|
||||
info.Options = subCmdsOpts
|
||||
|
||||
cmd, err = b.session.ApplicationCommandCreate(b.session.State.User.ID, "", info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
handlers[cmd.Name] = func(s *dgo.Session, ic *dgo.InteractionCreate) {
|
||||
b.logger.Debug("Handling command",
|
||||
slog.String("id", ic.Interaction.ID),
|
||||
slog.String("name", ic.Interaction.ApplicationCommandData().Name),
|
||||
)
|
||||
|
||||
opts := ic.Interaction.ApplicationCommandData().Options
|
||||
isSub := slices.IndexFunc(opts, func(o *dgo.ApplicationCommandInteractionDataOption) bool {
|
||||
return o.Type == dgo.ApplicationCommandOptionSubCommand
|
||||
})
|
||||
if isSub != -1 {
|
||||
sc := opts[isSub]
|
||||
|
||||
err := subCmds[sc.Name].Handle(s, ic)
|
||||
|
||||
if err != nil {
|
||||
_ = s.InteractionRespond(ic.Interaction, &dgo.InteractionResponse{
|
||||
Type: dgo.InteractionResponseDeferredChannelMessageWithSource,
|
||||
Data: &dgo.InteractionResponseData{
|
||||
Content: fmt.Sprintf("Error while trying to handle sub command: %s", err.Error()),
|
||||
Flags: dgo.MessageFlagsEphemeral,
|
||||
},
|
||||
})
|
||||
b.logger.Error("Failed to handle sub command",
|
||||
slog.String("name", sc.Name),
|
||||
slog.String("err", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err := v.Handle(s, ic)
|
||||
if err != nil {
|
||||
_ = s.InteractionRespond(ic.Interaction, &dgo.InteractionResponse{
|
||||
@@ -39,7 +98,6 @@ func (b *Bot) registerCommands() error {
|
||||
)
|
||||
}
|
||||
}
|
||||
rcs[i] = cmd
|
||||
|
||||
b.logger.Info("Registered command",
|
||||
slog.String("name", cmd.Name),
|
||||
|
||||
@@ -1,23 +1,51 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"dislate/internals/guilddb"
|
||||
gdb "dislate/internals/guilddb"
|
||||
"dislate/internals/translator/lang"
|
||||
|
||||
dgo "github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
|
||||
type ManageChannel struct {
|
||||
db guilddb.GuildDB
|
||||
db gdb.GuildDB
|
||||
}
|
||||
|
||||
func NewManageChannel(db guilddb.GuildDB) ManageChannel {
|
||||
func NewManageChannel(db gdb.GuildDB) ManageChannel {
|
||||
return ManageChannel{db}
|
||||
}
|
||||
func (c ManageChannel) Info() *dgo.ApplicationCommand {
|
||||
var permissions int64 = dgo.PermissionManageChannels
|
||||
|
||||
return &dgo.ApplicationCommand{
|
||||
Name: "channel",
|
||||
Description: "Manages a channel options",
|
||||
Name: "channel",
|
||||
Description: "Manages a channel options",
|
||||
DefaultMemberPermissions: &permissions,
|
||||
}
|
||||
}
|
||||
func (c ManageChannel) Subcommands() []Command {
|
||||
return []Command{ChannelsInfo(c)}
|
||||
}
|
||||
func (c ManageChannel) Handle(s *dgo.Session, i *dgo.InteractionCreate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ChannelsInfo struct {
|
||||
db gdb.GuildDB
|
||||
}
|
||||
|
||||
func (c ChannelsInfo) Info() *dgo.ApplicationCommand {
|
||||
var permissions int64 = dgo.PermissionManageChannels
|
||||
|
||||
return &dgo.ApplicationCommand{
|
||||
Name: "info",
|
||||
Description: "Get information about a channel",
|
||||
DefaultMemberPermissions: &permissions,
|
||||
Options: []*dgo.ApplicationCommandOption{{
|
||||
Type: dgo.ApplicationCommandOptionChannel,
|
||||
Name: "channel",
|
||||
@@ -28,12 +56,36 @@ func (c ManageChannel) Info() *dgo.ApplicationCommand {
|
||||
}},
|
||||
}
|
||||
}
|
||||
func (c ManageChannel) Handle(s *dgo.Session, i *dgo.InteractionCreate) error {
|
||||
err := s.InteractionRespond(i.Interaction, &dgo.InteractionResponse{
|
||||
func (c ChannelsInfo) Handle(s *dgo.Session, ic *dgo.InteractionCreate) error {
|
||||
opts := getOptions(ic)
|
||||
|
||||
var err error
|
||||
|
||||
var dch *dgo.Channel
|
||||
if c, ok := opts["channel"]; ok {
|
||||
dch = c.ChannelValue(s)
|
||||
} else {
|
||||
dch, err = s.Channel(ic.ChannelID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ch, err := getChannel(c.db, dch.GuildID, dch.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := getChannelInfo(c.db, ch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.InteractionRespond(ic.Interaction, &dgo.InteractionResponse{
|
||||
Type: dgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &dgo.InteractionResponseData{
|
||||
Content: "Hello world!",
|
||||
Flags: dgo.MessageFlagsEphemeral,
|
||||
Embeds: []*dgo.MessageEmbed{info},
|
||||
Flags: dgo.MessageFlagsEphemeral,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -43,3 +95,43 @@ func (c ManageChannel) Handle(s *dgo.Session, i *dgo.InteractionCreate) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
func (c ChannelsInfo) Subcommands() []Command {
|
||||
return []Command{}
|
||||
}
|
||||
|
||||
func getChannel(db guilddb.GuildDB, guildID, channelID string) (gdb.Channel, error) {
|
||||
ch, err := db.Channel(guildID, channelID)
|
||||
if err != nil && errors.Is(err, gdb.ErrNotFound) {
|
||||
if err := db.ChannelInsert(gdb.NewChannel(guildID, channelID, lang.EN)); err != nil {
|
||||
return gdb.Channel{}, err
|
||||
}
|
||||
ch, err = db.Channel(guildID, channelID)
|
||||
if err != nil {
|
||||
return gdb.Channel{}, err
|
||||
}
|
||||
} else if err != nil {
|
||||
return gdb.Channel{}, err
|
||||
}
|
||||
|
||||
return ch, nil
|
||||
}
|
||||
|
||||
func getChannelInfo(db guilddb.GuildDB, ch gdb.Channel) (*dgo.MessageEmbed, error) {
|
||||
group, err := db.ChannelGroup(ch.GuildID, ch.ID)
|
||||
if err != nil && !errors.Is(err, gdb.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := make([]string, len(group))
|
||||
for i, gi := range group {
|
||||
g[i] = "<#" + gi.ID + ">"
|
||||
}
|
||||
|
||||
return &dgo.MessageEmbed{Title: "Channel Information",
|
||||
Fields: []*dgo.MessageEmbedField{
|
||||
{Name: "ID", Value: ch.ID, Inline: true},
|
||||
{Name: "Language", Value: string(ch.Language), Inline: true},
|
||||
{Name: "Linked Channels", Value: strings.Join(g, ", "), Inline: true},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
type Command interface {
|
||||
Info() *dgo.ApplicationCommand
|
||||
Handle(s *dgo.Session, i *dgo.InteractionCreate) error
|
||||
Subcommands() []Command
|
||||
}
|
||||
func getOptions(i *dgo.InteractionCreate) map[string]*dgo.ApplicationCommandInteractionDataOption {
|
||||
opts := i.ApplicationCommandData().Options
|
||||
|
||||
Reference in New Issue
Block a user