Move command functions under a bot struct

This commit is contained in:
Ryan Cavicchioni 2022-09-06 21:33:59 -05:00
parent 8606ed0200
commit 5651df37ef
Signed by: ryanc
GPG Key ID: 877EEDAF9245103D
16 changed files with 284 additions and 275 deletions

47
bot/bot.go Normal file
View File

@ -0,0 +1,47 @@
package bot
import "github.com/bwmarrin/discordgo"
type Bot struct {
Session *discordgo.Session
Config Config
}
func NewBot(s *discordgo.Session, config Config) *Bot {
return &Bot{Session: s, Config: config}
}
func (b *Bot) RegisterCommands() {
AddCommand(&Command{
Name: "coin",
Func: b.CoinCommand(),
})
AddCommand(&Command{
Name: "deal",
Func: b.DealCommand(),
NArgs: 1,
})
AddCommand(&Command{
Name: "ping",
Func: b.PingCommand(),
})
AddCommand(&Command{
Name: "roll",
Func: b.RollCommand(),
NArgs: 1,
})
AddCommand(&Command{
Name: "time",
Func: b.TimeCommand(),
NArgs: 1,
})
AddCommand(&Command{
Name: "version",
Func: b.VersionCommand(),
})
AddCommand(&Command{
Name: "weather",
Func: b.WeatherCommand(),
NArgs: 1,
})
}

31
bot/coin.go Normal file
View File

@ -0,0 +1,31 @@
package bot
import (
"git.kill0.net/chill9/beepboop/lib"
"github.com/bwmarrin/discordgo"
)
type Coin bool
func (c *Coin) Flip() bool {
*c = Coin(lib.Itob(lib.RandInt(0, 1)))
return bool(*c)
}
func (b *Bot) CoinCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
var (
c Coin
msg string
)
if c.Flip() {
msg = "heads"
} else {
msg = "tails"
}
b.Session.ChannelMessageSend(m.ChannelID, msg)
return nil
}
}

View File

@ -20,11 +20,11 @@ type (
Command struct { Command struct {
Name string Name string
Config Config Config Config
Func func(cmd *Command, args []string) error Func CommandFunc
NArgs int NArgs int
Session *discordgo.Session
Message *discordgo.MessageCreate
} }
CommandFunc func(args []string, m *discordgo.MessageCreate) error
) )
func init() { func init() {
@ -55,7 +55,7 @@ func GetCommand(name string) (*Command, bool) {
return cmd, ok return cmd, ok
} }
func NewCommandHandler(config Config) func(s *discordgo.Session, m *discordgo.MessageCreate) { func NewCommandHandler(bot *Bot) func(s *discordgo.Session, m *discordgo.MessageCreate) {
return func(s *discordgo.Session, m *discordgo.MessageCreate) { return func(s *discordgo.Session, m *discordgo.MessageCreate) {
var cmd *Command var cmd *Command
@ -63,24 +63,21 @@ func NewCommandHandler(config Config) func(s *discordgo.Session, m *discordgo.Me
return return
} }
if !lib.HasCommand(m.Content, config.Prefix) { if !lib.HasCommand(m.Content, bot.Config.Prefix) {
return return
} }
cmdName, arg := lib.SplitCommandAndArg(m.Content, config.Prefix) cmdName, arg := lib.SplitCommandAndArg(m.Content, bot.Config.Prefix)
cmd, ok := GetCommand(cmdName) cmd, ok := GetCommand(cmdName)
args := lib.SplitArgs(arg, cmd.NArgs) args := lib.SplitArgs(arg, cmd.NArgs)
if ok { if ok {
cmd.Config = config cmd.Config = bot.Config
cmd.Name = cmdName
cmd.Session = s
cmd.Message = m
log.Debugf("command: %v, args: %v, nargs: %d", cmd.Name, args, len(args)) log.Debugf("command: %v, args: %v, nargs: %d", cmd.Name, args, len(args))
cmd.Func(cmd, args) cmd.Func(args, m)
return return
} }

View File

@ -1,29 +0,0 @@
package commands
import (
"git.kill0.net/chill9/beepboop/bot"
"git.kill0.net/chill9/beepboop/lib"
)
type Coin bool
func (c *Coin) Flip() bool {
*c = Coin(lib.Itob(lib.RandInt(0, 1)))
return bool(*c)
}
func CoinCommand(cmd *bot.Command, args []string) error {
var (
c Coin
msg string
)
if c.Flip() {
msg = "heads"
} else {
msg = "tails"
}
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, msg)
return nil
}

View File

@ -1,10 +0,0 @@
package commands
import (
"git.kill0.net/chill9/beepboop/bot"
)
func PingCommand(cmd *bot.Command, args []string) error {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, "pong")
return nil
}

View File

@ -1,34 +0,0 @@
package commands
import (
"fmt"
"time"
"git.kill0.net/chill9/beepboop/bot"
log "github.com/sirupsen/logrus"
)
func TimeCommand(cmd *bot.Command, args []string) error {
var (
t time.Time
tz string
)
now := time.Now()
if len(args) == 1 {
tz = args[0]
loc, err := time.LoadLocation(tz)
if err != nil {
log.Warnf("failed to load location: %s", err)
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, err.Error())
return nil
}
t = now.In(loc)
} else {
t = now
}
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, fmt.Sprint(t))
return nil
}

View File

@ -1,23 +0,0 @@
package commands
import (
"fmt"
"runtime"
"git.kill0.net/chill9/beepboop/bot"
)
const (
SourceURI = "https://git.kill0.net/chill9/bb"
)
func VersionCommand(cmd *bot.Command, args []string) error {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, fmt.Sprintf(
"go version: %s\nplatform: %s\nos: %s\nsource: %s\n",
runtime.Version(),
runtime.GOARCH,
runtime.GOOS,
SourceURI,
))
return nil
}

View File

@ -1,67 +0,0 @@
package commands
import (
"fmt"
"git.kill0.net/chill9/beepboop/bot"
"git.kill0.net/chill9/beepboop/lib/weather"
log "github.com/sirupsen/logrus"
)
type WeatherHandler struct {
Config bot.Config
Name string
}
func NewWeatherHandler(s string) *WeatherHandler {
return &WeatherHandler{Name: s}
}
func (h *WeatherHandler) SetConfig(config bot.Config) {
h.Config = config
}
func WeatherCommand(cmd *bot.Command, args []string) error {
var (
err error
loc string
w weather.Weather
)
if len(args) != 1 {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, "help: `!weather <CITY>,<STATE>,<COUNTRY>`")
return nil
}
loc = args[0]
if cmd.Config.OpenWeatherMapToken == "" {
log.Error("OpenWeather token is not set")
return nil
}
wc := weather.NewClient(cmd.Config.OpenWeatherMapToken)
log.Debugf("weather requested for '%s'", loc)
w, err = wc.Get(loc)
if err != nil {
log.Errorf("weather client error: %v", err)
return nil
}
log.Debugf("weather returned for '%s': %+v", loc, w)
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, fmt.Sprintf(
"%s (%.1f, %.1f) — C:%.1f F:%.1f K:%.1f",
loc,
w.Coord.Lat,
w.Coord.Lon,
w.Main.Temp.Celcius(),
w.Main.Temp.Fahrenheit(),
w.Main.Temp.Kelvin(),
))
return nil
}

View File

@ -1,4 +1,4 @@
package commands package bot
import ( import (
"errors" "errors"
@ -7,16 +7,11 @@ import (
"strconv" "strconv"
"strings" "strings"
"git.kill0.net/chill9/beepboop/bot" "github.com/bwmarrin/discordgo"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
type ( type (
DealHandler struct {
config bot.Config
Name string
}
Card string Card string
Deck [52]Card Deck [52]Card
@ -50,7 +45,8 @@ func (d *Deck) Deal(n int) ([]Card, error) {
return hand, err return hand, err
} }
func DealCommand(cmd *bot.Command, args []string) error { func (b *Bot) DealCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
rand.Shuffle(len(deck), func(i, j int) { rand.Shuffle(len(deck), func(i, j int) {
deck[i], deck[j] = deck[j], deck[i] deck[i], deck[j] = deck[j], deck[i]
}) })
@ -58,7 +54,7 @@ func DealCommand(cmd *bot.Command, args []string) error {
log.Debugf("%+v", deck) log.Debugf("%+v", deck)
if len(args) != 1 { if len(args) != 1 {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, fmt.Sprintf("help: `!%s <n>`", cmd.Name)) b.Session.ChannelMessageSend(m.ChannelID, "help: `!deal <n>`")
return nil return nil
} }
@ -69,13 +65,14 @@ func DealCommand(cmd *bot.Command, args []string) error {
hand, err := deck.Deal(n) hand, err := deck.Deal(n)
if err != nil { if err != nil {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, fmt.Sprintf("error: %s\n", err)) b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf("error: %s\n", err))
return nil return nil
} }
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, JoinCards(hand, " ")) b.Session.ChannelMessageSend(m.ChannelID, JoinCards(hand, " "))
return nil return nil
} }
}
func JoinCards(h []Card, sep string) string { func JoinCards(h []Card, sep string) string {
var b []string var b []string

View File

@ -1,4 +1,4 @@
package commands package bot
import ( import (
"errors" "errors"
@ -7,9 +7,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"git.kill0.net/chill9/beepboop/bot"
"git.kill0.net/chill9/beepboop/lib" "git.kill0.net/chill9/beepboop/lib"
"github.com/bwmarrin/discordgo"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -78,7 +78,8 @@ func (r *Roll) RollDice() {
} }
} }
func RollCommand(cmd *bot.Command, args []string) error { func (b *Bot) RollCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
var ( var (
err error err error
msg, roll string msg, roll string
@ -89,7 +90,7 @@ func RollCommand(cmd *bot.Command, args []string) error {
r, err = ParseRoll(roll) r, err = ParseRoll(roll)
if err != nil { if err != nil {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, err.Error()) b.Session.ChannelMessageSend(m.ChannelID, err.Error())
return nil return nil
} }
@ -98,6 +99,7 @@ func RollCommand(cmd *bot.Command, args []string) error {
msg = fmt.Sprintf("🎲 %s = %d", lib.JoinInt(r.Rolls, " + "), r.Sum) msg = fmt.Sprintf("🎲 %s = %d", lib.JoinInt(r.Rolls, " + "), r.Sum)
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, msg) b.Session.ChannelMessageSend(m.ChannelID, msg)
return nil return nil
} }
}

12
bot/ping.go Normal file
View File

@ -0,0 +1,12 @@
package bot
import (
"github.com/bwmarrin/discordgo"
)
func (b *Bot) PingCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
b.Session.ChannelMessageSend(m.ChannelID, "pong")
return nil
}
}

View File

@ -1,9 +1,9 @@
package commands package bot
import ( import (
"git.kill0.net/chill9/beepboop/bot"
"git.kill0.net/chill9/beepboop/lib" "git.kill0.net/chill9/beepboop/lib"
"github.com/bwmarrin/discordgo"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -66,7 +66,8 @@ func (g *Gun) IsEmpty() bool {
return true return true
} }
func RouletteCommand(cmd *bot.Command, args []string) error { func (b *Bot) RouletteCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
if gun.IsEmpty() { if gun.IsEmpty() {
gun.Load(Bullets) gun.Load(Bullets)
log.Debugf("reloading gun: %+v\n", gun) log.Debugf("reloading gun: %+v\n", gun)
@ -74,9 +75,10 @@ func RouletteCommand(cmd *bot.Command, args []string) error {
log.Debugf("firing gun: %+v\n", gun) log.Debugf("firing gun: %+v\n", gun)
if gun.Fire() { if gun.Fire() {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, GunFireMessage) b.Session.ChannelMessageSend(m.ChannelID, GunFireMessage)
} else { } else {
cmd.Session.ChannelMessageSend(cmd.Message.ChannelID, GunClickMessage) b.Session.ChannelMessageSend(m.ChannelID, GunClickMessage)
} }
return nil return nil
} }
}

36
bot/time.go Normal file
View File

@ -0,0 +1,36 @@
package bot
import (
"fmt"
"time"
"github.com/bwmarrin/discordgo"
log "github.com/sirupsen/logrus"
)
func (b *Bot) TimeCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
var (
t time.Time
tz string
)
now := time.Now()
if len(args) == 1 {
tz = args[0]
loc, err := time.LoadLocation(tz)
if err != nil {
log.Warnf("failed to load location: %s", err)
b.Session.ChannelMessageSend(m.ChannelID, err.Error())
return nil
}
t = now.In(loc)
} else {
t = now
}
b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprint(t))
return nil
}
}

25
bot/version.go Normal file
View File

@ -0,0 +1,25 @@
package bot
import (
"fmt"
"runtime"
"github.com/bwmarrin/discordgo"
)
const (
SourceURI = "https://git.kill0.net/chill9/bb"
)
func (b *Bot) VersionCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf(
"go version: %s\nplatform: %s\nos: %s\nsource: %s\n",
runtime.Version(),
runtime.GOARCH,
runtime.GOOS,
SourceURI,
))
return nil
}
}

56
bot/weather.go Normal file
View File

@ -0,0 +1,56 @@
package bot
import (
"fmt"
"git.kill0.net/chill9/beepboop/lib/weather"
"github.com/bwmarrin/discordgo"
log "github.com/sirupsen/logrus"
)
func (b *Bot) WeatherCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error {
var (
err error
loc string
w weather.Weather
)
if len(args) != 1 {
b.Session.ChannelMessageSend(m.ChannelID, "help: `!weather <CITY>,<STATE>,<COUNTRY>`")
return nil
}
loc = args[0]
if b.Config.OpenWeatherMapToken == "" {
log.Error("OpenWeather token is not set")
return nil
}
wc := weather.NewClient(b.Config.OpenWeatherMapToken)
log.Debugf("weather requested for '%s'", loc)
w, err = wc.Get(loc)
if err != nil {
log.Errorf("weather client error: %v", err)
return nil
}
log.Debugf("weather returned for '%s': %+v", loc, w)
b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf(
"%s (%.1f, %.1f) — C:%.1f F:%.1f K:%.1f",
loc,
w.Coord.Lat,
w.Coord.Lon,
w.Main.Temp.Celcius(),
w.Main.Temp.Fahrenheit(),
w.Main.Temp.Kelvin(),
))
return nil
}
}

View File

@ -11,7 +11,6 @@ import (
"syscall" "syscall"
"git.kill0.net/chill9/beepboop/bot" "git.kill0.net/chill9/beepboop/bot"
"git.kill0.net/chill9/beepboop/bot/commands"
"git.kill0.net/chill9/beepboop/bot/handler" "git.kill0.net/chill9/beepboop/bot/handler"
"git.kill0.net/chill9/beepboop/lib" "git.kill0.net/chill9/beepboop/lib"
@ -29,41 +28,6 @@ var (
} }
) )
func init() {
bot.AddCommand(&bot.Command{
Name: "coin",
Func: commands.CoinCommand,
})
bot.AddCommand(&bot.Command{
Name: "deal",
Func: commands.DealCommand,
NArgs: 1,
})
bot.AddCommand(&bot.Command{
Name: "ping",
Func: commands.PingCommand,
})
bot.AddCommand(&bot.Command{
Name: "roll",
Func: commands.RollCommand,
NArgs: 1,
})
bot.AddCommand(&bot.Command{
Name: "time",
Func: commands.TimeCommand,
NArgs: 1,
})
bot.AddCommand(&bot.Command{
Name: "version",
Func: commands.VersionCommand,
})
bot.AddCommand(&bot.Command{
Name: "weather",
Func: commands.WeatherCommand,
NArgs: 1,
})
}
func main() { func main() {
setupConfig() setupConfig()
@ -83,7 +47,10 @@ func main() {
dg.AddHandler(h.Handle) dg.AddHandler(h.Handle)
} }
dg.AddHandler(bot.NewCommandHandler(C)) b := bot.NewBot(dg, C)
b.RegisterCommands()
dg.AddHandler(bot.NewCommandHandler(b))
dg.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentsDirectMessages dg.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentsDirectMessages