refactor: remove old abstraction from codebase
This commit is contained in:
67
bot/bot.go
67
bot/bot.go
@@ -1,67 +0,0 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log/slog"
|
||||
|
||||
"forge.capytal.company/capytal/dislate/commands"
|
||||
"forge.capytal.company/capytal/dislate/db"
|
||||
"forge.capytal.company/capytal/dislate/translator"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type Bot struct {
|
||||
translator translator.Translator
|
||||
db *db.Queries
|
||||
logger *slog.Logger
|
||||
session *discordgo.Session
|
||||
}
|
||||
|
||||
func NewBot(
|
||||
token string,
|
||||
database *sql.DB,
|
||||
translator translator.Translator,
|
||||
log *slog.Logger,
|
||||
) (*Bot, error) {
|
||||
s, err := discordgo.New("Bot " + token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAllWithoutPrivileged)
|
||||
|
||||
db, err := db.Prepare(database)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Bot{
|
||||
session: s,
|
||||
db: db,
|
||||
translator: translator,
|
||||
logger: log,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Bot) Start() error {
|
||||
if err := b.session.Open(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ch := commands.NewCommandsHandler(b.logger, b.session)
|
||||
|
||||
COMMANDS := []commands.Command{
|
||||
&mockCommand{},
|
||||
}
|
||||
|
||||
if err := ch.UpdateCommands(COMMANDS); err != nil {
|
||||
return errors.Join(errors.New("Failed to update commands"), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bot) Stop() error {
|
||||
return b.session.Close()
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"forge.capytal.company/capytal/dislate/commands"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type mockCommand struct{}
|
||||
|
||||
func (c *mockCommand) Info() *discordgo.ApplicationCommand {
|
||||
return &discordgo.ApplicationCommand{
|
||||
Name: "mock",
|
||||
Type: discordgo.ChatApplicationCommand,
|
||||
Description: "this is a mock command used for testing",
|
||||
Options: []*discordgo.ApplicationCommandOption{{
|
||||
Name: "message",
|
||||
Description: "The message to respond",
|
||||
Type: discordgo.ApplicationCommandOptionString,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *mockCommand) Handle(
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
data discordgo.ApplicationCommandInteractionData,
|
||||
) error {
|
||||
if len(data.Options) == 0 {
|
||||
return errors.New("Option \"message\" is not defined")
|
||||
}
|
||||
|
||||
text, ok := data.Options[0].Value.(string)
|
||||
if !ok {
|
||||
return errors.New("Failed to convert \"message\" into string")
|
||||
}
|
||||
|
||||
if _, err := s.ChannelMessageSendComplex(ic.ChannelID, &discordgo.MessageSend{
|
||||
Content: "test component",
|
||||
Components: []discordgo.MessageComponent{
|
||||
discordgo.ActionsRow{
|
||||
Components: []discordgo.MessageComponent{
|
||||
c.Components()[0].Info(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.InteractionRespond(ic.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: fmt.Sprintf("Hello user! Your text is %q", text),
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *mockCommand) Components() []commands.Component {
|
||||
return []commands.Component{
|
||||
&mockButton{},
|
||||
}
|
||||
}
|
||||
|
||||
type mockButton struct{}
|
||||
|
||||
func (c *mockButton) Info() discordgo.MessageComponent {
|
||||
return &discordgo.Button{
|
||||
Label: "test button",
|
||||
CustomID: "mock-command-test-button",
|
||||
}
|
||||
}
|
||||
|
||||
func (c *mockButton) Handle(
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
data discordgo.MessageComponentInteractionData,
|
||||
) error {
|
||||
return s.InteractionRespond(ic.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
Data: &discordgo.InteractionResponseData{
|
||||
Content: fmt.Sprintf("Button clicked!"),
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type Command interface {
|
||||
Info() *discordgo.ApplicationCommand
|
||||
Handle(
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
data discordgo.ApplicationCommandInteractionData,
|
||||
) error
|
||||
}
|
||||
|
||||
type CommandWithComponents interface {
|
||||
Command
|
||||
Components() []Component
|
||||
}
|
||||
|
||||
type Component interface {
|
||||
Info() discordgo.MessageComponent
|
||||
Handle(
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
data discordgo.MessageComponentInteractionData,
|
||||
) error
|
||||
}
|
||||
|
||||
type (
|
||||
commandName = string
|
||||
commandId = string
|
||||
commandHandlerFunc = func(s *discordgo.Session, ic *discordgo.InteractionCreate, data discordgo.ApplicationCommandInteractionData) error
|
||||
|
||||
componentCustomId = string
|
||||
componentHandlerFunc = func(s *discordgo.Session, ic *discordgo.InteractionCreate, data discordgo.MessageComponentInteractionData) error
|
||||
)
|
||||
|
||||
type CommandsHandler struct {
|
||||
logger *slog.Logger
|
||||
session *discordgo.Session
|
||||
}
|
||||
|
||||
func NewCommandsHandler(logger *slog.Logger, session *discordgo.Session) *CommandsHandler {
|
||||
return &CommandsHandler{logger, session}
|
||||
}
|
||||
|
||||
func (h *CommandsHandler) UpdateCommands(
|
||||
commands []Command,
|
||||
guildID ...string,
|
||||
) error {
|
||||
var GUILD_ID string
|
||||
if len(guildID) > 0 {
|
||||
GUILD_ID = guildID[0]
|
||||
}
|
||||
|
||||
commandsMap, err := h.mapCommands(commands)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
APP_ID := h.session.State.User.ID
|
||||
if APP_ID == "" {
|
||||
return errors.New("User ID is not set in session state")
|
||||
}
|
||||
|
||||
registeredCommands, err := h.mapRegisteredCommmands(GUILD_ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := h.removeUnhandledCommands(commandsMap, registeredCommands, GUILD_ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commandInteractionHandlers := make(map[commandName]commandHandlerFunc, len(commandsMap))
|
||||
componentInteractionHandlers := make(map[componentCustomId]componentHandlerFunc)
|
||||
|
||||
for _, cmd := range commandsMap {
|
||||
var err error
|
||||
|
||||
appCmd, isRegistered := registeredCommands[cmd.Info().Name]
|
||||
|
||||
if !isRegistered {
|
||||
h.logger.Debug("Bot command is not registered in application, registering.",
|
||||
slog.String("command_name", cmd.Info().Name),
|
||||
slog.String("guild_id", GUILD_ID))
|
||||
|
||||
appCmd, err = h.session.ApplicationCommandCreate(APP_ID, GUILD_ID, cmd.Info())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else if y, err := equalToRegistered(cmd.Info(), appCmd); !y {
|
||||
h.logger.Debug("Bot command and registered command are different, deleting registered command for updating.",
|
||||
slog.String("command_name", cmd.Info().Name),
|
||||
slog.String("registered_command_id", appCmd.ID),
|
||||
slog.String("registered_command_name", appCmd.Name),
|
||||
slog.String("guild_id", GUILD_ID),
|
||||
slog.String("difference", err.Error()))
|
||||
|
||||
err = h.session.ApplicationCommandDelete(APP_ID, GUILD_ID, appCmd.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appCmd, err = h.session.ApplicationCommandCreate(APP_ID, GUILD_ID, cmd.Info())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if withCompsCmd, ok := cmd.(CommandWithComponents); ok {
|
||||
for _, comp := range withCompsCmd.Components() {
|
||||
var id string
|
||||
|
||||
if comp.Info().Type() == discordgo.ActionsRowComponent {
|
||||
// TODO
|
||||
} else if comp.Info().Type() == discordgo.ButtonComponent {
|
||||
button, ok := comp.Info().(*discordgo.Button)
|
||||
if !ok {
|
||||
return fmt.Errorf("Failed to convert ButtonComponent to Button struct on command %q", appCmd.Name)
|
||||
}
|
||||
|
||||
switch {
|
||||
case button.CustomID == "" && button.URL == "":
|
||||
return fmt.Errorf("Button component on command %q does not have a valid CustomID or URL", appCmd.Name)
|
||||
case button.CustomID != "" && button.URL != "":
|
||||
return fmt.Errorf("Button component on command %q has mutually exclusive CustomID and URL", appCmd.Name)
|
||||
case button.CustomID != "":
|
||||
id = button.CustomID
|
||||
case button.URL != "":
|
||||
id = button.URL
|
||||
}
|
||||
} else {
|
||||
j, err := comp.Info().MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var v struct{ CustomID string }
|
||||
if err := json.Unmarshal(j, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id = v.CustomID
|
||||
}
|
||||
|
||||
if _, ok := componentInteractionHandlers[id]; ok {
|
||||
return fmt.Errorf(
|
||||
"Component of ID %q used in command %q already exists!",
|
||||
id,
|
||||
appCmd.Name,
|
||||
)
|
||||
}
|
||||
|
||||
componentInteractionHandlers[id] = comp.Handle
|
||||
}
|
||||
}
|
||||
|
||||
commandInteractionHandlers[appCmd.Name] = cmd.Handle
|
||||
}
|
||||
|
||||
h.session.AddHandler(func(s *discordgo.Session, ic *discordgo.InteractionCreate) {
|
||||
h.handleInteraction(commandInteractionHandlers, componentInteractionHandlers, s, ic)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *CommandsHandler) mapCommands(commands []Command) (map[commandName]Command, error) {
|
||||
m := make(map[commandName]Command, len(commands))
|
||||
|
||||
for _, c := range commands {
|
||||
if n := c.Info().Name; n != "" {
|
||||
m[c.Info().Name] = c
|
||||
} else {
|
||||
return m, fmt.Errorf("Command doesn't have a valid name!")
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (h *CommandsHandler) mapRegisteredCommmands(
|
||||
guildID string,
|
||||
) (map[commandName]*discordgo.ApplicationCommand, error) {
|
||||
cmdMap := map[commandName]*discordgo.ApplicationCommand{}
|
||||
|
||||
registeredCommands, err := h.session.ApplicationCommands(h.session.State.User.ID, guildID)
|
||||
if err != nil {
|
||||
return cmdMap, err
|
||||
}
|
||||
for _, rc := range registeredCommands {
|
||||
cmdMap[rc.Name] = rc
|
||||
}
|
||||
|
||||
return cmdMap, nil
|
||||
}
|
||||
|
||||
func (h *CommandsHandler) removeUnhandledCommands(
|
||||
handledCommands map[commandName]Command,
|
||||
registeredCommands map[commandName]*discordgo.ApplicationCommand,
|
||||
guildID string,
|
||||
) error {
|
||||
for _, cmd := range registeredCommands {
|
||||
if _, isHandled := handledCommands[cmd.Name]; !isHandled {
|
||||
h.logger.Debug("Registered command no longer is being handled, deleting.",
|
||||
slog.String("registered_command_name", cmd.Name),
|
||||
slog.String("registered_command_id", cmd.ID),
|
||||
slog.String("guild_id", guildID))
|
||||
|
||||
err := h.session.ApplicationCommandDelete(h.session.State.User.ID, guildID, cmd.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delete(registeredCommands, cmd.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
// Helper function used inside equalToRegistered and equalToRegistered option,
|
||||
// THIS ISN'T SUPPOSED TO BE USED outside of said functions.
|
||||
func equal[T any](l, r T) bool {
|
||||
lv := reflect.ValueOf(l)
|
||||
|
||||
if lv.Kind() == reflect.Pointer {
|
||||
// If the local value is a nil-pointer, we assume it as the
|
||||
// zero-value of the underling value for comparison
|
||||
var v any
|
||||
if lv.IsNil() {
|
||||
v = reflect.Zero(lv.Type().Elem()).Interface()
|
||||
} else {
|
||||
v = lv.Elem().Interface()
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(r)
|
||||
|
||||
var rvv any
|
||||
if rv.IsNil() {
|
||||
rvv = reflect.Zero(rv.Type().Elem()).Interface()
|
||||
} else {
|
||||
rvv = rv.Elem().Interface()
|
||||
}
|
||||
|
||||
return equal(v, rvv)
|
||||
} else {
|
||||
return reflect.DeepEqual(l, r)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function used inside equalToRegistered and equalToRegistered option,
|
||||
// THIS ISN'T SUPPOSED TO BE USED outside of said functions.
|
||||
func val[T any](v *T) T {
|
||||
if v != nil {
|
||||
return *v
|
||||
} else {
|
||||
return *new(T)
|
||||
}
|
||||
}
|
||||
|
||||
func equalToRegistered(local, registered *discordgo.ApplicationCommand) (bool, error) {
|
||||
switch {
|
||||
case local.Type != registered.Type:
|
||||
return false, fmt.Errorf(
|
||||
"Type is not equal. Local: %#v Registered: %#v",
|
||||
local.Type,
|
||||
registered.Type,
|
||||
)
|
||||
|
||||
case local.Name != registered.Name:
|
||||
return false, fmt.Errorf(
|
||||
"Name is not equal. Local: %#v Registered: %#v",
|
||||
local.Name,
|
||||
registered.Name,
|
||||
)
|
||||
|
||||
case !equal(local.NameLocalizations, registered.NameLocalizations):
|
||||
return false, fmt.Errorf(
|
||||
"NameLocalizations is not equal. Local: *%#v Registered: *%#v",
|
||||
val(local.NameLocalizations),
|
||||
val(registered.NameLocalizations),
|
||||
)
|
||||
|
||||
// DEPRECATED FIELDS https://discord.com/developers/docs/interactions/application-commands
|
||||
//
|
||||
// case !equal(local.DefaultMemberPermissions, registered.DefaultMemberPermissions):
|
||||
// return false, fmt.Errorf(
|
||||
// "DefaultMemberPermissions is not equal. Local: *%#v Registered: *%#v",
|
||||
// val(local.DefaultMemberPermissions),
|
||||
// val(registered.DefaultMemberPermissions),
|
||||
// )
|
||||
//
|
||||
// case
|
||||
// !equal(local.DMPermission, registered.DMPermission):
|
||||
// return false, fmt.Errorf(
|
||||
// "DMPermission is not equal. Local: *%#v Registered: *%#v",
|
||||
// val(local.DMPermission),
|
||||
// val(registered.DMPermission),
|
||||
// )
|
||||
|
||||
case !equal(local.NSFW, registered.NSFW):
|
||||
return false, fmt.Errorf(
|
||||
"VALUE is not equal. Local: *%#v Registered: *%#v",
|
||||
val(local.NSFW),
|
||||
val(registered.NSFW),
|
||||
)
|
||||
|
||||
case local.Description != registered.Description:
|
||||
return false, fmt.Errorf(
|
||||
"Description is not equal. Local: %#v Registered: %#v",
|
||||
local.Description,
|
||||
registered.Description,
|
||||
)
|
||||
|
||||
case !equal(local.DescriptionLocalizations, registered.DescriptionLocalizations):
|
||||
return false, fmt.Errorf(
|
||||
"DescriptionLocalizations is not equal. Local: *%#v Registered: *%#v",
|
||||
val(local.DescriptionLocalizations),
|
||||
val(registered.DescriptionLocalizations),
|
||||
)
|
||||
|
||||
case len(local.Options) != len(registered.Options):
|
||||
return false, fmt.Errorf(
|
||||
"Options is not equal. Local: %#v Registered: %#v",
|
||||
local.Options,
|
||||
registered.Options,
|
||||
)
|
||||
|
||||
case len(local.Options) > 0 && len(registered.Options) > 0:
|
||||
for i, o := range local.Options {
|
||||
if ok, err := equalToRegisteredOption(o, registered.Options[i]); !ok {
|
||||
return ok, errors.Join(fmt.Errorf("Option element of index %v has difference", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func equalToRegisteredOption(local, registered *discordgo.ApplicationCommandOption) (bool, error) {
|
||||
switch {
|
||||
case local.Type != registered.Type:
|
||||
return false, fmt.Errorf(
|
||||
"Type is not equal. Local: %#v Registered: %#v",
|
||||
local.Type,
|
||||
registered.Type,
|
||||
)
|
||||
|
||||
case local.Name != registered.Name:
|
||||
return false, fmt.Errorf(
|
||||
"Name is not equal. Local: %#v Registered: %#v",
|
||||
local.Name,
|
||||
registered.Name,
|
||||
)
|
||||
|
||||
case local.Description != registered.Description:
|
||||
return false, fmt.Errorf(
|
||||
"Description is not equal. Local: %#v Registered: %#v",
|
||||
local.Description,
|
||||
registered.Description,
|
||||
)
|
||||
|
||||
case !equal(local.DescriptionLocalizations, registered.DescriptionLocalizations):
|
||||
return false, fmt.Errorf(
|
||||
"DescriptionLocalizations is not equal. Local: %#v Registered: %#v",
|
||||
local.DescriptionLocalizations,
|
||||
registered.DescriptionLocalizations,
|
||||
)
|
||||
|
||||
case !equal(local.ChannelTypes, registered.ChannelTypes):
|
||||
return false, fmt.Errorf(
|
||||
"ChannelTypes is not equal. Local: %#v Registered: %#v",
|
||||
local.ChannelTypes,
|
||||
registered.ChannelTypes,
|
||||
)
|
||||
|
||||
case local.Required != registered.Required:
|
||||
return false, fmt.Errorf(
|
||||
"Required is not equal. Local: %#v Registered: %#v",
|
||||
local.Required,
|
||||
registered.Required,
|
||||
)
|
||||
|
||||
case !equal(local.Choices, registered.Choices):
|
||||
return false, fmt.Errorf(
|
||||
"Choices is not equal. Local: %#v Registered: %#v",
|
||||
local.Choices,
|
||||
registered.Choices,
|
||||
)
|
||||
|
||||
case !equal(local.MinValue, registered.MinValue):
|
||||
return false, fmt.Errorf(
|
||||
"MinValue is not equal. Local: *%#v Registered: *%#v",
|
||||
val(local.MinValue),
|
||||
val(registered.MinValue),
|
||||
)
|
||||
|
||||
case local.MaxValue != registered.MaxValue:
|
||||
return false, fmt.Errorf(
|
||||
"MaxValue is not equal. Local: %#v Registered: %#v",
|
||||
local.MaxValue,
|
||||
registered.MaxValue,
|
||||
)
|
||||
|
||||
case !equal(local.MinLength, registered.MinLength):
|
||||
return false, fmt.Errorf(
|
||||
"MinLength is not equal. Local: *%#v Registered: *%#v",
|
||||
val(local.MinLength),
|
||||
val(registered.MinLength),
|
||||
)
|
||||
|
||||
case local.MaxLength != registered.MaxLength:
|
||||
return false, fmt.Errorf(
|
||||
"MaxLength is not equal. Local: %#v Registered: %#v",
|
||||
local.MaxLength,
|
||||
registered.MaxLength,
|
||||
)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func (h *CommandsHandler) handleInteraction(
|
||||
cmdsHandlers map[commandName]commandHandlerFunc,
|
||||
compsHandlers map[componentCustomId]componentHandlerFunc,
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
) {
|
||||
var userID string
|
||||
if ic.User != nil {
|
||||
userID = ic.User.ID
|
||||
} else {
|
||||
userID = ic.Member.User.ID
|
||||
}
|
||||
|
||||
switch ic.Type {
|
||||
case discordgo.InteractionApplicationCommand:
|
||||
h.handleCommandInteraction(cmdsHandlers, s, ic)
|
||||
case discordgo.InteractionMessageComponent:
|
||||
h.handleComponentInteraction(compsHandlers, s, ic)
|
||||
default:
|
||||
h.logger.Error("Application interaction is not a supported type!",
|
||||
slog.String("interaction_id", ic.ID),
|
||||
slog.String("interaction_type", ic.Type.String()),
|
||||
slog.String("interaction_user_id", userID),
|
||||
slog.String("interaction_guild_id", ic.GuildID),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *CommandsHandler) handleCommandInteraction(
|
||||
cmdsHandlers map[commandName]commandHandlerFunc,
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
) {
|
||||
var userID string
|
||||
if ic.User != nil {
|
||||
userID = ic.User.ID
|
||||
} else {
|
||||
userID = ic.Member.User.ID
|
||||
}
|
||||
|
||||
data := ic.ApplicationCommandData()
|
||||
|
||||
log := h.logger.With(
|
||||
slog.String("command_data_id", data.ID),
|
||||
slog.String("command_data_name", data.Name),
|
||||
slog.String("interaction_user_id", userID),
|
||||
slog.String("interaction_guild_id", ic.GuildID),
|
||||
)
|
||||
|
||||
if hf, ok := cmdsHandlers[data.Name]; ok {
|
||||
log.Debug("Handling application command.")
|
||||
|
||||
if err := hf(s, ic, data); err != nil {
|
||||
log.Error("Failed to run command, error returned.", slog.String("error", err.Error()))
|
||||
|
||||
_, err = s.ChannelMessageSendComplex(ic.ChannelID, &discordgo.MessageSend{
|
||||
Content: fmt.Sprintf(
|
||||
"<@%s>\nFailed to run command! Error message:\n```\n%s\n```",
|
||||
userID,
|
||||
err.Error(),
|
||||
),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(
|
||||
"Failed to send error message explaining error... somehow.",
|
||||
slog.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Debug("Command ran successfully.")
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Error("Application command interaction created without having a handler.")
|
||||
}
|
||||
}
|
||||
|
||||
func (h *CommandsHandler) handleComponentInteraction(
|
||||
compsHandlers map[componentCustomId]componentHandlerFunc,
|
||||
s *discordgo.Session,
|
||||
ic *discordgo.InteractionCreate,
|
||||
) {
|
||||
var userID string
|
||||
if ic.User != nil {
|
||||
userID = ic.User.ID
|
||||
} else {
|
||||
userID = ic.Member.User.ID
|
||||
}
|
||||
|
||||
data := ic.MessageComponentData()
|
||||
|
||||
log := h.logger.With(
|
||||
slog.String("component_data_custom_id", data.CustomID),
|
||||
slog.String("component_data_type", data.Type().String()),
|
||||
slog.String("interaction_user_id", userID),
|
||||
slog.String("interaction_guild_id", ic.GuildID),
|
||||
)
|
||||
|
||||
if hf, ok := compsHandlers[data.CustomID]; ok {
|
||||
log.Debug("Handling application component.")
|
||||
|
||||
if err := hf(s, ic, data); err != nil {
|
||||
log.Error(
|
||||
"Failed to handle component, error returned.",
|
||||
slog.String("error", err.Error()),
|
||||
)
|
||||
|
||||
_, err = s.ChannelMessageSendComplex(ic.ChannelID, &discordgo.MessageSend{
|
||||
Content: fmt.Sprintf(
|
||||
"<@%s>\nFailed to handle component! Error message:\n```\n%s\n```",
|
||||
userID,
|
||||
err.Error(),
|
||||
),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(
|
||||
"Failed to send error message explaining error... somehow.",
|
||||
slog.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Debug("Component handled successfully.")
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Error("Application component interaction created without having a handler.")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user