grim/wasdead

Overhaul the commands, again
draft
2019-04-08, Gary Kramlich
14a3ef1fae60
Parents 56a40cda5296
Children f8a2c08e2a39
Overhaul the commands, again
--- a/discord/commands.go Mon Apr 08 18:55:23 2019 -0700
+++ b/discord/commands.go Mon Apr 08 22:52:18 2019 -0500
@@ -4,51 +4,34 @@
"fmt"
"strings"
- "github.com/alecthomas/kong"
"github.com/bwmarrin/discordgo"
- log "github.com/sirupsen/logrus"
+ "github.com/iancoleman/orderedmap"
)
-type commands struct {
- UptimeCommand uptimeCommand `kong:"cmd,name='uptime'"`
- StatusCommand statusCommand `kong:"cmd,name='status'"`
- SetChannelCommand setChannelCommand `kong:"cmd,name='setchannel'"`
+type Command interface {
+ Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error)
+ Help() string
}
-func (c *DiscordClient) messageHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
- // ignore messages for ourselves
- if m.Author.ID == s.State.User.ID {
- return
- }
+var (
+ commands = orderedmap.New()
+)
- if !strings.HasPrefix(m.Content, c.mentionString) {
- return
+func init() {
+ commands.Set("set-channel", &commandSetChannel{})
+ commands.Set("status", &commandStatus{})
+ commands.Set("uptime", &commandUptime{})
+}
+
+func (c *DiscordClient) processCommand(args []string, m *discordgo.MessageCreate) (interface{}, error) {
+ if len(args) == 0 {
+ return nil, fmt.Errorf("no command specified")
}
- cli := commands{}
- parser, err := kong.New(
- &cli,
- kong.Exit(func(int) {}),
- )
- if err != nil {
- c.sendChannel(m.ChannelID, "failed to parse command")
- log.Warnf("error creating parser: %v", err)
- return
+ name := strings.ToLower(args[0])
+ if cmd, found := commands.Get(name); found {
+ return cmd.(Command).Run(args[1:], c, m)
}
- args := strings.Split(m.Content, " ")[1:]
- ctx, err := parser.Parse(args)
- if err != nil {
- c.sendChannel(m.ChannelID, "failed to parse command")
- log.Warnf("error parsing command: %#v : %v", args, err)
- return
- }
-
- err = ctx.Run(c, m)
-
- if err != nil {
- c.sendChannel(m.ChannelID, fmt.Sprintf("%v", err))
- log.Debugf("finished running command: '%v'", err)
- return
- }
+ return "", fmt.Errorf("unknown command '%s'", args[0])
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/discord/messages.go Mon Apr 08 22:52:18 2019 -0500
@@ -0,0 +1,40 @@
+package discord
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+
+ "github.com/bwmarrin/discordgo"
+ log "github.com/sirupsen/logrus"
+)
+
+var splitRegex = regexp.MustCompile(`\s+`)
+
+func (c *DiscordClient) messageHandler(s *discordgo.Session, m *discordgo.MessageCreate) {
+ // ignore messages for ourselves
+ if m.Author.ID == s.State.User.ID {
+ return
+ }
+
+ if !strings.HasPrefix(m.Content, c.mentionString) {
+ return
+ }
+
+ args := splitRegex.Split(m.Content, -1)[1:]
+
+ // call parse commands
+ output, err := c.processCommand(args, m)
+
+ if err != nil {
+ log.Warnf("error processing %#v: %v", m.Content, err)
+ output = fmt.Sprintf("error: %v", err)
+ }
+
+ switch output.(type) {
+ case string:
+ c.sendChannel(m.ChannelID, output.(string))
+ case *discordgo.MessageEmbed:
+ c.client.ChannelMessageSendEmbed(m.ChannelID, output.(*discordgo.MessageEmbed))
+ }
+}
--- a/discord/presence.go Mon Apr 08 18:55:23 2019 -0700
+++ b/discord/presence.go Mon Apr 08 22:52:18 2019 -0500
@@ -44,35 +44,39 @@
func (c *DiscordClient) sendPresenceChannel(channelID string, presence presence.Presence) error {
_, err := c.client.ChannelMessageSendEmbed(
channelID,
- &discordgo.MessageEmbed{
- Image: &discordgo.MessageEmbedImage{
- URL: presence.ProfileImageURL,
- },
- Author: &discordgo.MessageEmbedAuthor{
- URL: presence.URL,
- Name: fmt.Sprintf("%s is now live", presence.Username),
- },
- Thumbnail: &discordgo.MessageEmbedThumbnail{
- URL: presence.ThumbnailURL,
- },
- Fields: []*discordgo.MessageEmbedField{
- &discordgo.MessageEmbedField{
- Name: "Title",
- Value: presence.Title,
- },
- &discordgo.MessageEmbedField{
- Name: "Viewers",
- Value: humanize.Comma(presence.Viewers),
- Inline: true,
- },
- &discordgo.MessageEmbedField{
- Name: "Language",
- Value: presence.Language,
- Inline: true,
- },
- },
- },
+ presenceEmbed(presence),
)
return err
}
+
+func presenceEmbed(presence presence.Presence) *discordgo.MessageEmbed {
+ return &discordgo.MessageEmbed{
+ Image: &discordgo.MessageEmbedImage{
+ URL: presence.ProfileImageURL,
+ },
+ Author: &discordgo.MessageEmbedAuthor{
+ URL: presence.URL,
+ Name: fmt.Sprintf("%s is now live", presence.Username),
+ },
+ Thumbnail: &discordgo.MessageEmbedThumbnail{
+ URL: presence.ThumbnailURL,
+ },
+ Fields: []*discordgo.MessageEmbedField{
+ &discordgo.MessageEmbedField{
+ Name: "Title",
+ Value: presence.Title,
+ },
+ &discordgo.MessageEmbedField{
+ Name: "Viewers",
+ Value: humanize.Comma(presence.Viewers),
+ Inline: true,
+ },
+ &discordgo.MessageEmbedField{
+ Name: "Language",
+ Value: presence.Language,
+ Inline: true,
+ },
+ },
+ }
+}
--- a/discord/set_channel_command.go Mon Apr 08 18:55:23 2019 -0700
+++ b/discord/set_channel_command.go Mon Apr 08 22:52:18 2019 -0500
@@ -6,15 +6,14 @@
"github.com/bwmarrin/discordgo"
)
-type setChannelCommand struct {
- //Channel string `kong:"required,name='channel'"`
+type commandSetChannel struct{}
+
+func (cmd *commandSetChannel) Help() string {
+ return "sets the channel to send automatic announcements to"
}
-func (cmd *setChannelCommand) Run(c *DiscordClient, m *discordgo.MessageCreate) error {
+func (cmd *commandSetChannel) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
c.db.SetChannel(m.GuildID, m.ChannelID)
- return c.sendChannel(
- m.ChannelID,
- fmt.Sprintf("Set <#%s> as the announcement channel", m.ChannelID),
- )
+ return fmt.Sprintf("Set <#%s> as the announcement channel", m.ChannelID), nil
}
--- a/discord/status_command.go Mon Apr 08 18:55:23 2019 -0700
+++ b/discord/status_command.go Mon Apr 08 22:52:18 2019 -0500
@@ -5,21 +5,27 @@
"strings"
"github.com/bwmarrin/discordgo"
- log "github.com/sirupsen/logrus"
"bitbucket.org/TheToyz/nowdead/presence"
)
-type statusCommand struct {
- Target string `kong:"arg,required,name='target'"`
+type commandStatus struct{}
+
+func (cmd *commandStatus) Help() string {
+ return "get the streaming status of a target"
}
-func (cmd *statusCommand) Run(c *DiscordClient, m *discordgo.MessageCreate) error {
- log.Debug("running status command")
+func (cmd *commandStatus) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
uri := ""
- if strings.HasPrefix(cmd.Target, "<@") {
- mentionID := cmd.Target[2 : len(cmd.Target)-1]
+ if len(args) != 1 {
+ return nil, fmt.Errorf("invalid target")
+ }
+
+ target := args[0]
+
+ if strings.HasPrefix(target, "<@") {
+ mentionID := target[2 : len(target)-1]
for _, mentioned := range m.Mentions {
if mentioned.ID == mentionID {
@@ -28,18 +34,18 @@
if p != nil && p.Game != nil && p.Game.Type == discordgo.GameTypeStreaming {
uri = p.Game.URL
} else {
- return fmt.Errorf("%s is not streaming", cmd.Target)
+ return nil, fmt.Errorf("%s is not streaming", target)
}
}
}
} else {
- uri = "https://twitch.tv/" + cmd.Target
+ uri = "https://twitch.tv/" + target
}
presence, err := presence.GetPresence(uri)
if err != nil {
- return err
+ return nil, err
}
- return c.sendPresenceChannel(m.ChannelID, presence)
+ return presenceEmbed(presence), nil
}
--- a/discord/uptime_command.go Mon Apr 08 18:55:23 2019 -0700
+++ b/discord/uptime_command.go Mon Apr 08 22:52:18 2019 -0500
@@ -7,11 +7,12 @@
"github.com/dustin/go-humanize"
)
-type uptimeCommand struct{}
+type commandUptime struct{}
-func (cmd *uptimeCommand) Run(c *DiscordClient, m *discordgo.MessageCreate) error {
- return c.sendChannel(
- m.ChannelID,
- fmt.Sprintf("Started %s", humanize.Time(c.started)),
- )
+func (cmd *commandUptime) Help() string {
+ return "the amount of time the bot has been running"
}
+
+func (cmd *commandUptime) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
+ return fmt.Sprintf("Started %s", humanize.Time(c.started)), nil
+}
--- a/go.mod Mon Apr 08 18:55:23 2019 -0700
+++ b/go.mod Mon Apr 08 22:52:18 2019 -0500
@@ -10,6 +10,7 @@
github.com/bwmarrin/discordgo v0.19.0
github.com/dustin/go-humanize v1.0.0
github.com/go-redis/redis v6.15.2+incompatible
+ github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0
github.com/nicklaw5/helix v0.5.1
github.com/nicksnyder/go-i18n v1.10.0 // indirect
github.com/onsi/ginkgo v1.8.0 // indirect
--- a/go.sum Mon Apr 08 18:55:23 2019 -0700
+++ b/go.sum Mon Apr 08 22:52:18 2019 -0500
@@ -36,6 +36,8 @@
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
+github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=