114 lines
2.8 KiB
Go
114 lines
2.8 KiB
Go
|
/*
|
||
|
* owobot - The coolest Discord bot ever written
|
||
|
* Copyright (C) 2023 owobot Contributors
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Affero General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU Affero General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Affero General Public License
|
||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
package commands
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
|
||
|
"github.com/bwmarrin/discordgo"
|
||
|
"go.elara.ws/logger/log"
|
||
|
"go.elara.ws/owobot/internal/util"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
mu = sync.Mutex{}
|
||
|
cmds = map[string]CmdFunc{}
|
||
|
acs = []*discordgo.ApplicationCommand{}
|
||
|
)
|
||
|
|
||
|
type CmdFunc func(s *discordgo.Session, i *discordgo.InteractionCreate) error
|
||
|
|
||
|
func Init(s *discordgo.Session) error {
|
||
|
s.AddHandler(onCmd)
|
||
|
_, err := s.ApplicationCommandBulkOverwrite(s.State.Application.ID, "", acs)
|
||
|
acs = nil // Allow the ACs to be GC'd
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func onCmd(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||
|
if i.Type != discordgo.InteractionApplicationCommand {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
data := i.ApplicationCommandData()
|
||
|
|
||
|
mu.Lock()
|
||
|
defer mu.Unlock()
|
||
|
cmdFn, ok := cmds[data.Name]
|
||
|
if !ok {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err := cmdFn(s, i)
|
||
|
if err != nil {
|
||
|
log.Warn("Error in command function").Str("cmd", data.Name).Err(err).Send()
|
||
|
sendError(s, i.Interaction, err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Register(s *discordgo.Session, fn CmdFunc, ac *discordgo.ApplicationCommand) {
|
||
|
// If the DM permission hasn't been explicitly set, assume false
|
||
|
if ac.DMPermission == nil {
|
||
|
ac.DMPermission = util.Pointer(false)
|
||
|
}
|
||
|
|
||
|
mu.Lock()
|
||
|
// Skip commands that already exist
|
||
|
if _, ok := cmds[ac.Name]; ok {
|
||
|
mu.Unlock()
|
||
|
return
|
||
|
}
|
||
|
cmds[ac.Name] = fn
|
||
|
mu.Unlock()
|
||
|
|
||
|
acs = append(acs, ac)
|
||
|
}
|
||
|
|
||
|
func sendError(s *discordgo.Session, i *discordgo.Interaction, serr error) {
|
||
|
err := util.RespondEphemeral(s, i, "ERROR: "+serr.Error())
|
||
|
if err != nil {
|
||
|
log.Warn("Error while trying to send error").Err(err).Send()
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// commandSync checks if any registered commands have been removed and, if so,
|
||
|
// deletes them.
|
||
|
func commandSync(s *discordgo.Session) error {
|
||
|
appCmds, err := s.ApplicationCommands(s.State.Application.ID, "")
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
deleted := 0
|
||
|
for _, appCmd := range appCmds {
|
||
|
if _, ok := cmds[appCmd.Name]; !ok {
|
||
|
err = s.ApplicationCommandDelete(appCmd.ApplicationID, "", appCmd.ID)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
deleted++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
log.Info("Command sync completed").Int("deleted", deleted).Send()
|
||
|
return nil
|
||
|
}
|