pepebot/discord/mux/server.go

115 lines
2.9 KiB
Go
Raw Normal View History

2021-06-04 09:54:28 +02:00
package mux
2021-06-03 11:29:34 +02:00
import (
"strings"
2021-06-04 09:54:28 +02:00
"sync"
2021-06-03 11:29:34 +02:00
"github.com/bwmarrin/discordgo"
)
type Command interface {
Execute(s *discordgo.Session, m *discordgo.MessageCreate)
}
2021-06-04 16:07:19 +02:00
func NotFound(s *discordgo.Session, m *discordgo.MessageCreate) {
return
}
func NotFoundHandler() Command { return HandlerFunc(NotFound) }
2021-06-03 12:50:42 +02:00
type HandlerFunc func(s *discordgo.Session, m *discordgo.MessageCreate)
func (f HandlerFunc) Execute(s *discordgo.Session, m *discordgo.MessageCreate) {
f(s, m)
}
2021-06-03 11:29:34 +02:00
/* The CommandMux struct is a type of mux for Discord commands. It's modelled after the net/http ServeMux */
type CommandMux struct {
2021-06-04 09:54:28 +02:00
mu sync.RWMutex
2021-06-03 11:29:34 +02:00
m map[string]muxEntry
2021-06-04 09:54:28 +02:00
Prefix string
2021-06-03 11:29:34 +02:00
}
2021-06-03 12:50:42 +02:00
func NewCommandMux() *CommandMux { return new(CommandMux) }
2021-06-03 14:07:11 +02:00
func (c *CommandMux) removeFirst(command string) string {
2021-06-03 12:50:42 +02:00
split := strings.SplitN(strings.TrimSpace(command), " ", 2)
if len(split) > 1 {
2021-06-03 14:07:11 +02:00
return split[1]
2021-06-03 12:50:42 +02:00
}
2021-06-03 14:07:11 +02:00
return ""
2021-06-03 12:50:42 +02:00
}
2021-06-03 14:07:11 +02:00
func (c *CommandMux) firstCommand(command string) string {
2021-06-03 12:50:42 +02:00
split := strings.SplitN(strings.TrimSpace(command), " ", 2)
if len(split) > 0 {
2021-06-03 14:07:11 +02:00
return split[0]
2021-06-03 12:50:42 +02:00
}
2021-06-03 14:07:11 +02:00
return ""
2021-06-03 12:50:42 +02:00
}
2021-06-03 11:29:34 +02:00
func (c *CommandMux) Handler(m *discordgo.MessageCreate) (cmd Command, pattern string) {
2021-06-04 09:54:28 +02:00
c.mu.RLock()
defer c.mu.RUnlock()
if strings.HasPrefix(m.Content, c.Prefix) {
2021-06-03 12:50:42 +02:00
/* Special case for this bot alone. It has a command that is only it's prefix
So we check if the whole message is only the prefix before proceding.
So please don't forget to add the command, since it's totally hardcoded here. */
2021-06-04 09:54:28 +02:00
if strings.TrimSpace(m.Content) == c.Prefix {
return c.m[c.Prefix].h, c.m[c.Prefix].pattern
2021-06-03 12:50:42 +02:00
}
2021-06-03 11:29:34 +02:00
2021-06-03 14:07:11 +02:00
m := c.removeFirst(m.Content) /* Here the prefix is removed, so we're left with only the first keyword */
cmd, ok := c.m[c.firstCommand(m)]
2021-06-03 12:50:42 +02:00
if ok {
return cmd.h, cmd.pattern
}
2021-06-03 11:29:34 +02:00
}
2021-06-03 12:50:42 +02:00
/* Here is where I might add the whole checking for bad words part */
return nil, ""
2021-06-03 11:29:34 +02:00
}
func (c *CommandMux) Execute(s *discordgo.Session, m *discordgo.MessageCreate) {
2021-06-03 12:50:42 +02:00
h, _ := c.Handler(m)
if h == nil {
2021-06-03 14:07:11 +02:00
//log.Printf("There exists no handler for %s\n", m.Content)
2021-06-03 12:50:42 +02:00
return
}
h.Execute(s, m)
}
func (c *CommandMux) Handle(pattern string, handler Command) {
2021-06-04 09:54:28 +02:00
c.mu.Lock()
defer c.mu.Unlock()
2021-06-03 12:50:42 +02:00
if pattern == "" {
panic("commandmux: invalid pattern")
}
if handler == nil {
panic("commandmux: nil handler")
}
if _, exist := c.m[pattern]; exist {
panic("commandmux: multiple registrations for " + pattern)
}
2021-06-03 11:29:34 +02:00
2021-06-03 12:50:42 +02:00
if c.m == nil {
c.m = make(map[string]muxEntry)
}
e := muxEntry{h: handler, pattern: pattern}
c.m[pattern] = e
}
func (c *CommandMux) HandleFunc(pattern string, handler func(s *discordgo.Session, m *discordgo.MessageCreate)) {
if handler == nil {
panic("commandmux: nil handler")
}
c.Handle(pattern, HandlerFunc(handler))
2021-06-03 11:29:34 +02:00
}
/* The muxEntry struct contains the actual Command implementation as well as the pattern (discord command)
it will be matched against */
type muxEntry struct {
h Command
pattern string
}