mirror of
https://github.com/Fluffy-Bean/Lynxie.git
synced 2025-05-14 08:02:17 +00:00
174 lines
3.4 KiB
Go
174 lines
3.4 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/Fluffy-Bean/lynxie/internal/color"
|
|
"github.com/Fluffy-Bean/lynxie/internal/errors"
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
type Callback func(h *Handler, args []string) errors.Error
|
|
|
|
type Bot struct {
|
|
Prefix string
|
|
token string
|
|
intents discordgo.Intent
|
|
commands map[string]Callback
|
|
aliases map[string]string
|
|
}
|
|
|
|
func NewBot(prefix, token string, intents discordgo.Intent) *Bot {
|
|
return &Bot{
|
|
Prefix: prefix,
|
|
token: token,
|
|
intents: intents,
|
|
commands: make(map[string]Callback),
|
|
aliases: make(map[string]string),
|
|
}
|
|
}
|
|
|
|
func (b *Bot) RegisterCommand(cmd string, f Callback) {
|
|
b.commands[cmd] = f
|
|
}
|
|
|
|
func (b *Bot) RegisterCommandAlias(alias, cmd string) {
|
|
b.aliases[alias] = cmd
|
|
}
|
|
|
|
func (b *Bot) Run() {
|
|
dg, err := discordgo.New("Bot " + b.token)
|
|
if err != nil {
|
|
fmt.Println("Could not create Discord session:", err)
|
|
|
|
return
|
|
}
|
|
|
|
dg.AddHandler(b.handler)
|
|
dg.Identify.Intents = b.intents
|
|
|
|
err = dg.Open()
|
|
if err != nil {
|
|
fmt.Println("Could not connect:", err)
|
|
|
|
return
|
|
}
|
|
|
|
fmt.Println("Bot is now running. Press CTRL-C to exit.")
|
|
|
|
sc := make(chan os.Signal, 1)
|
|
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
|
|
<-sc
|
|
|
|
dg.Close()
|
|
}
|
|
|
|
type Handler struct {
|
|
Session *discordgo.Session
|
|
Message *discordgo.MessageCreate
|
|
Reference *discordgo.MessageReference
|
|
}
|
|
|
|
func (b *Bot) handler(session *discordgo.Session, message *discordgo.MessageCreate) {
|
|
h := &Handler{
|
|
Session: session,
|
|
Message: message,
|
|
Reference: &discordgo.MessageReference{
|
|
ChannelID: message.ChannelID,
|
|
MessageID: message.ID,
|
|
},
|
|
}
|
|
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
printError(b, h, errors.Error{
|
|
Msg: "But the bot simply refused",
|
|
Err: fmt.Errorf("%v", r),
|
|
})
|
|
}
|
|
}()
|
|
|
|
if h.Message.Author.ID == h.Session.State.User.ID {
|
|
return
|
|
}
|
|
if h.Message.Author.Bot {
|
|
return
|
|
}
|
|
|
|
var cmd string
|
|
var args string
|
|
|
|
cmd = h.Message.Content
|
|
cmd = strings.TrimPrefix(cmd, b.Prefix)
|
|
cmd, args, _ = strings.Cut(cmd, " ")
|
|
|
|
alias, ok := b.aliases[cmd]
|
|
if ok {
|
|
cmd = alias
|
|
}
|
|
|
|
callback, ok := b.commands[cmd]
|
|
if !ok {
|
|
// Falling back to default help command
|
|
if cmd == "help" {
|
|
printHelp(b, h)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
_ = h.Session.ChannelTyping(h.Message.ChannelID)
|
|
|
|
err := callback(h, strings.Split(args, " "))
|
|
if !err.Ok() {
|
|
printError(b, h, err)
|
|
}
|
|
}
|
|
|
|
func printHelp(bot *Bot, h *Handler) {
|
|
var commands []string
|
|
|
|
for command := range bot.commands {
|
|
var found []string
|
|
for a, c := range bot.aliases {
|
|
if c == command {
|
|
found = append(found, a)
|
|
}
|
|
}
|
|
|
|
if len(found) > 0 {
|
|
commands = append(commands, fmt.Sprintf("%s (%s)", command, strings.Join(found, ", ")))
|
|
} else {
|
|
commands = append(commands, command)
|
|
}
|
|
}
|
|
|
|
_, _ = h.Session.ChannelMessageSendComplex(h.Message.ChannelID, &discordgo.MessageSend{
|
|
Embed: &discordgo.MessageEmbed{
|
|
Title: "Help",
|
|
Description: strings.Join(commands, "\n"),
|
|
Color: color.RGBToDiscord(255, 255, 255),
|
|
Footer: &discordgo.MessageEmbedFooter{
|
|
Text: "command (aliases...)",
|
|
},
|
|
},
|
|
Reference: h.Reference,
|
|
})
|
|
}
|
|
|
|
func printError(bot *Bot, h *Handler, e errors.Error) {
|
|
fmt.Println(e.Err)
|
|
|
|
_, _ = h.Session.ChannelMessageSendComplex(h.Message.ChannelID, &discordgo.MessageSend{
|
|
Embed: &discordgo.MessageEmbed{
|
|
Title: "Error",
|
|
Description: e.Msg,
|
|
Color: color.RGBToDiscord(255, 0, 0),
|
|
},
|
|
Reference: h.Reference,
|
|
})
|
|
}
|