123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- package discordbot
- import (
- "github.com/bwmarrin/discordgo"
- )
- type SlashRouter struct {
- registeredCommands []*discordgo.ApplicationCommand
- commands []*discordgo.ApplicationCommand
- commandHandlers map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate)
- guildIDs []string
- existingCommands []Command
- }
- type SlashRouteOptions struct {
- Name string // match name that should trigger this route handler
- Description string // short description of this route
- Callback SlashHandler
- Options []*discordgo.ApplicationCommandOption // Array of application command options for the command
- }
- // Handler is the function signature required for a message route handler.
- type SlashHandler func(s *discordgo.Session, i *discordgo.InteractionCreate)
- func NewSlashRouter() *SlashRouter {
- r := &SlashRouter{}
- r.commandHandlers = make(map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate))
- return r
- }
- func (r *SlashRouter) RegisterGuild(guildID string) {
- r.guildIDs = append(r.guildIDs, guildID)
- }
- type Command struct {
- applicationID string
- guildID string
- commandID string
- name string
- }
- func (r *SlashRouter) GetExistingCommand(appID, guildID, name string) (string, bool) {
- for _, cmd := range r.existingCommands {
- if cmd.applicationID == appID && cmd.guildID == guildID && cmd.name == name {
- return cmd.commandID, true
- }
- }
- return "", false
- }
- func (r *SlashRouter) LoadExistingCommands(s *discordgo.Session) error {
- logHandler.Info("Loading Existing Commands")
- for _, guildID := range r.guildIDs {
- logHandler.Infof("Getting applications for %s", guildID)
- cmds, err := s.ApplicationCommands(s.State.User.ID, guildID)
- if err != nil {
- r.existingCommands = nil
- return err
- }
- for _, cmd := range cmds {
- newCommand := Command{
- applicationID: cmd.ApplicationID,
- guildID: cmd.GuildID,
- commandID: cmd.ID,
- name: cmd.Name,
- }
- r.existingCommands = append(r.existingCommands, newCommand)
- }
- }
- logHandler.Infof("Loaded %d commands", len(r.existingCommands))
- return nil
- }
- func (r *SlashRouter) Register(name string, options SlashRouteOptions) error {
- if name == "" {
- return ErrRegisterRouteNameRequired
- }
- if options.Callback == nil {
- return ErrRegisterCallbackRequired
- }
- command := discordgo.ApplicationCommand{
- Name: name,
- Description: options.Description,
- Options: options.Options,
- }
- r.commands = append(r.commands, &command)
- r.commandHandlers[name] = options.Callback
- return nil
- }
- func (r *SlashRouter) GenerateCommands(s *discordgo.Session) error {
- r.registeredCommands = make([]*discordgo.ApplicationCommand, len(r.commands))
- s.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
- if h, ok := r.commandHandlers[i.ApplicationCommandData().Name]; ok {
- h(s, i)
- }
- })
- for _, guildID := range r.guildIDs {
- for i, v := range r.commands {
- var cmd *discordgo.ApplicationCommand
- var err error
- if cmdID, exists := r.GetExistingCommand(s.State.User.ID, guildID, v.Name); exists {
- logHandler.Infof("Updating the existing command - %s", v.Name)
- cmd, err = s.ApplicationCommandEdit(s.State.User.ID, guildID, cmdID, v)
- } else {
- logHandler.Infof("Creating a new command - %s", v.Name)
- cmd, err = s.ApplicationCommandCreate(s.State.User.ID, guildID, v)
- }
- if err != nil {
- logHandler.Errorf("Cannot create '%v' command: %v", v.Name, err)
- return err
- }
- r.registeredCommands[i] = cmd
- }
- }
- return nil
- }
- func (r *SlashRouter) CleanCommands(s *discordgo.Session) error {
- for _, guildID := range r.guildIDs {
- for _, v := range r.registeredCommands {
- err := s.ApplicationCommandDelete(s.State.User.ID, guildID, v.ID)
- if err != nil {
- logHandler.Errorf("Cannot delete '%v' command: %v", v.Name, err)
- return err
- }
- }
- }
- return nil
- }
- // Create a Router
- // Added commands the bot will support
- func (bot *Bot) AddSlashCommands(guildID string, commands *[]discordgo.ApplicationCommand) error {
- err := bot.session.Open()
- if err != nil {
- return err
- }
- defer bot.session.Close()
- existingCommands, err := bot.session.ApplicationCommands(bot.session.State.User.ID, guildID)
- if err != nil {
- logHandler.WithError(err).Errorf("Failed to retrieve application commands from the server %s for user %s", guildID, bot.session.State.User.ID)
- return err
- }
- var find = func(name string, commands []*discordgo.ApplicationCommand) bool {
- for _, command := range commands {
- if command.Name == name {
- return true
- }
- }
- return false
- }
- for _, newCommand := range *commands {
- if exists := find(newCommand.Name, existingCommands); !exists {
- cmd, err := bot.session.ApplicationCommandCreate(bot.session.State.User.ID, guildID, &newCommand)
- if err != nil {
- logHandler.WithError(err).Errorf("Failed to create command %s", newCommand.Name)
- return err
- }
- logHandler.Infof("New Command for %s added, new command id is %s", newCommand.Name, cmd.ID)
- }
- }
- return nil
- }
- func (bot *Bot) RemoveSlashCommands(guildID string) error {
- err := bot.session.Open()
- if err != nil {
- return err
- }
- defer bot.session.Close()
- existingCommands, err := bot.session.ApplicationCommands(bot.session.State.User.ID, guildID)
- if err != nil {
- logHandler.WithError(err).Errorf("Failed to retrieve application commands from the server %s for user %s", guildID, bot.session.State.User.ID)
- return err
- }
- for _, existingCommand := range existingCommands {
- if err := bot.session.ApplicationCommandDelete(bot.session.State.User.ID, guildID, existingCommand.ID); err != nil {
- logHandler.WithError(err).Errorf("Failed to delete command %s", existingCommand.Name)
- return err
- }
- }
- return nil
- }
|