feat(lib,bot): command registration handleling

This commit is contained in:
Guz
2024-11-25 14:49:57 -03:00
parent 4ad8d4a7f3
commit aed504ae21
2 changed files with 187 additions and 2 deletions

View File

@@ -6,6 +6,10 @@ import (
type Bot struct {
session *discordgo.Session
chatCommandHandlers chatCommandHandlers
messageCommandHandlers messageCommandHandlers
userCommandHandlers userCommandHandlers
}
func Start(token string) (*Bot, error) {
@@ -22,8 +26,13 @@ func Start(token string) (*Bot, error) {
bot := &Bot{
session: s,
chatCommandHandlers: chatCommandHandlers{},
messageCommandHandlers: messageCommandHandlers{},
userCommandHandlers: userCommandHandlers{},
}
bot.session.AddHandler(bot.handleInteraction)
return bot, nil
}
@@ -34,6 +43,35 @@ func (b *Bot) Stop() error {
return nil
}
func (b *Bot) HandleCommand(c Command) {
b.commands = append(b.commands, c)
func (b *Bot) handleInteraction(s *discordgo.Session, ic *discordgo.InteractionCreate) {
var err error
switch ic.Type {
case discordgo.InteractionApplicationCommand:
err = b.handleApplicationCommand(s, ic)
}
_, err = s.ChannelMessageSend(ic.ChannelID, err.Error())
panic(err) // TODO: handle error
}
func (b *Bot) handleApplicationCommand(
s *discordgo.Session,
ic *discordgo.InteractionCreate,
) error {
data := ic.ApplicationCommandData()
var err error
if data.CommandType == discordgo.ChatApplicationCommand {
err = b.chatCommandHandlers[sessionCommandID{data.ID, ic.GuildID}].Handle(
ChatCommandCtx{},
)
} else if data.CommandType == discordgo.MessageApplicationCommand {
err = b.messageCommandHandlers[sessionCommandID{data.ID, ic.GuildID}].Handle(MessageCommandCtx{})
} else if data.CommandType == discordgo.UserApplicationCommand {
err = b.userCommandHandlers[sessionCommandID{data.ID, ic.GuildID}].Handle(UserCommandCtx{})
}
return err
}

147
lib/bot_commands.go Normal file
View File

@@ -0,0 +1,147 @@
package bot
import (
"fmt"
"github.com/bwmarrin/discordgo"
)
type commandID struct {
Name string
GuildID string
}
type sessionCommandID struct {
ID string
GuildID string
}
type (
chatCommandHandlers map[sessionCommandID]Handler[ChatCommandCtx]
messageCommandHandlers map[sessionCommandID]Handler[MessageCommandCtx]
userCommandHandlers map[sessionCommandID]Handler[UserCommandCtx]
)
func (b *Bot) MustHandleCommand(c Command, guildID ...string) {
if err := b.HandleCommand(c, guildID...); err != nil {
panic(err)
}
}
func (b *Bot) HandleCommand(c Command, guildID ...string) error {
var g string
if len(guildID) > 0 {
g = guildID[0]
}
if err := c.Validate(); err != nil {
return fmt.Errorf("failed to handle command %q: %v", c.ApplicationCommand().Name, err)
}
sessionCmd, err := b.sessionCommand(c.ApplicationCommand().Name, g)
if err != nil {
return err
}
return b.updateCommand(c, sessionCmd, g)
}
func (b *Bot) updateCommand(
botCmd Command,
sessionCmd *discordgo.ApplicationCommand,
guildID ...string,
) error {
var err error
var g string
if len(guildID) > 0 {
g = guildID[0]
}
if sessionCmd == nil {
sessionCmd, err = b.session.ApplicationCommandCreate(
b.session.State.User.ID,
g,
botCmd.ApplicationCommand(),
)
if err != nil {
return err
}
} else {
sessionCmd, err = b.session.ApplicationCommandEdit(
b.session.State.User.ID,
g,
sessionCmd.ID,
botCmd.ApplicationCommand(),
)
if err != nil {
return err
}
}
switch botCmd.ApplicationCommand().Type {
case discordgo.ChatApplicationCommand:
if c, ok := botCmd.(*ChatCommand); ok {
b.chatCommandHandlers[sessionCommandID{sessionCmd.ID, g}] = c.Handler
} else {
return err
}
case discordgo.MessageApplicationCommand:
if c, ok := botCmd.(*MessageCommand); ok {
b.messageCommandHandlers[sessionCommandID{sessionCmd.ID, g}] = c.Handler
} else {
return err
}
case discordgo.UserApplicationCommand:
if c, ok := botCmd.(*UserCommand); ok {
b.userCommandHandlers[sessionCommandID{sessionCmd.ID, g}] = c.Handler
} else {
return err
}
}
return nil
}
func (b *Bot) sessionCommand(
name string,
guildID ...string,
) (*discordgo.ApplicationCommand, error) {
var g string
if len(guildID) > 0 {
g = guildID[0]
}
sessionCmds, err := b.sessionCommands(g)
if err != nil {
return nil, err
}
cmd, ok := sessionCmds[commandID{Name: name, GuildID: g}]
if !ok {
return nil, nil
}
return cmd, nil
}
func (b *Bot) sessionCommands(
guildID ...string,
) (map[commandID]*discordgo.ApplicationCommand, error) {
var g string
if len(guildID) > 0 {
g = guildID[0]
}
appCmds, err := b.session.ApplicationCommands(b.session.State.User.ID, g)
if err != nil {
return nil, err
}
cmds := make(map[commandID]*discordgo.ApplicationCommand, len(appCmds))
for _, c := range appCmds {
cmds[commandID{Name: c.Name, GuildID: g}] = c
}
return cmds, err
}