138 lines
3.3 KiB
Go
138 lines
3.3 KiB
Go
|
package bot
|
||
|
|
||
|
import (
|
||
|
"code.lowsec.club/okawari/go-discord-bot/lib/commands"
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"github.com/bwmarrin/discordgo"
|
||
|
"github.com/rs/zerolog"
|
||
|
"github.com/rs/zerolog/log"
|
||
|
)
|
||
|
|
||
|
type Bot struct {
|
||
|
discord *discordgo.Session
|
||
|
logger zerolog.Logger
|
||
|
guildId string
|
||
|
commands []struct {
|
||
|
Command *commands.SlashCommand
|
||
|
removeOnClose bool
|
||
|
}
|
||
|
registeredCmds []*discordgo.ApplicationCommand
|
||
|
ctx context.Context
|
||
|
}
|
||
|
|
||
|
func (b *Bot) AddCommand(command commands.SlashCommand, removeOnClose bool) *Bot {
|
||
|
b.commands = append(b.commands, struct {
|
||
|
Command *commands.SlashCommand
|
||
|
removeOnClose bool
|
||
|
}{Command: &command, removeOnClose: removeOnClose})
|
||
|
|
||
|
return b
|
||
|
}
|
||
|
|
||
|
func (b *Bot) AddCommands(commands []commands.SlashCommand, removeOnClose bool) *Bot {
|
||
|
for _, cmd := range commands {
|
||
|
b.AddCommand(cmd, removeOnClose)
|
||
|
}
|
||
|
|
||
|
return b
|
||
|
}
|
||
|
|
||
|
func (b *Bot) registerCommand(command commands.SlashCommand, removeOnClose bool) error {
|
||
|
acc := command.CreateCommand()
|
||
|
logger := b.logger.With().Str("cmd", acc.Name).Logger()
|
||
|
|
||
|
registeredCmd, err := b.discord.ApplicationCommandCreate(b.discord.State.User.ID, b.guildId, acc)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
logger.Debug().Msg("Command registered")
|
||
|
|
||
|
if removeOnClose == true {
|
||
|
b.registeredCmds = append(b.registeredCmds, registeredCmd)
|
||
|
}
|
||
|
|
||
|
b.discord.AddHandler(func(s *discordgo.Session, r *discordgo.InteractionCreate) {
|
||
|
logger = logger.With().
|
||
|
Str("user", r.Member.Nick).
|
||
|
Str("component", "Handler").
|
||
|
Logger()
|
||
|
if r.ApplicationCommandData().ID == registeredCmd.ID {
|
||
|
ctx := logger.WithContext(b.ctx)
|
||
|
command.Handle(ctx, s, r)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (b *Bot) Open() error {
|
||
|
b.discord.AddHandler(b.onReady())
|
||
|
return b.discord.Open()
|
||
|
}
|
||
|
|
||
|
func (b *Bot) onReady() func(s *discordgo.Session, r *discordgo.Ready) {
|
||
|
return func(s *discordgo.Session, r *discordgo.Ready) {
|
||
|
log.Info().
|
||
|
Str("user", fmt.Sprintf("%v#%v", s.State.User.Username, s.State.User.Discriminator)).
|
||
|
Msg("Logged inn")
|
||
|
|
||
|
log.Info().Int("commands", len(b.commands)).Msg("Registering commands")
|
||
|
for _, cmd := range b.commands {
|
||
|
err := b.registerCommand(*cmd.Command, cmd.removeOnClose)
|
||
|
if err != nil {
|
||
|
b.logger.Fatal().Err(err).Msg("Unable to register command")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *Bot) Close() {
|
||
|
b.logger.Debug().Msg("Shutting down")
|
||
|
|
||
|
b.logger.Debug().Int("commands", len(b.registeredCmds)).Msg("Registered commands")
|
||
|
|
||
|
for _, cmd := range b.registeredCmds {
|
||
|
log.Info().
|
||
|
Str("name", cmd.Name).
|
||
|
Msg("Unregistering command")
|
||
|
|
||
|
err := b.discord.ApplicationCommandDelete(b.discord.State.User.ID, b.guildId, cmd.ID)
|
||
|
if err != nil {
|
||
|
log.Error().
|
||
|
Err(err).
|
||
|
Str("name", cmd.Name).Msg("Failed to unregister command")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
err := b.discord.Close()
|
||
|
if err != nil {
|
||
|
b.logger.Error().Err(err).Msg("Unable to close discord")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func New(ctx context.Context, name string, token string) (*Bot, error) {
|
||
|
|
||
|
discord, err := discordgo.New("Bot " + token)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("unable to create discord bot: %s", err)
|
||
|
}
|
||
|
|
||
|
return (&Bot{
|
||
|
discord: discord,
|
||
|
logger: log.With().Str("bot", name).Logger(),
|
||
|
ctx: ctx,
|
||
|
guildId: "758249214160797706",
|
||
|
commands: make([]struct {
|
||
|
Command *commands.SlashCommand
|
||
|
removeOnClose bool
|
||
|
}, 0),
|
||
|
registeredCmds: make([]*discordgo.ApplicationCommand, 0),
|
||
|
}), nil
|
||
|
}
|
||
|
|
||
|
func (b *Bot) init() *Bot {
|
||
|
|
||
|
return b
|
||
|
}
|