grim/wasdead

Move the commands back to kong (again)
draft
2019-05-11, Gary Kramlich
b81ba75f65cb
Parents 5c237823f4c9
Children e42b44a80cf1
Move the commands back to kong (again)
--- a/discord/command_help.go Fri May 10 23:42:03 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-package discord
-
-import (
- "fmt"
- "strings"
-
- "github.com/bwmarrin/discordgo"
-)
-
-type commandHelp struct{}
-
-func (cmd *commandHelp) Help() string {
- return "Displays this help message"
-}
-
-func createField(name string, cmd Command) *discordgo.MessageEmbedField {
- return &discordgo.MessageEmbedField{
- Name: name,
- Value: fmt.Sprintf("\nUsage: **%s**\n%s", name, cmd.Help()),
- }
-
-}
-
-func (cmd *commandHelp) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
- embed := &discordgo.MessageEmbed{
- Author: &discordgo.MessageEmbedAuthor{
- Name: "WasDead",
- },
- Description: "Command Help",
- }
-
- if len(args) == 0 {
- for _, name := range commands.Keys() {
- icmd, _ := commands.Get(name)
-
- cmd := icmd.(Command)
-
- embed.Fields = append(embed.Fields, createField(name, cmd))
- }
- } else if len(args) == 1 {
- name := args[0]
-
- icmd, found := commands.Get(strings.ToLower(name))
- if !found {
- return nil, fmt.Errorf("command %s not found", name)
- }
-
- cmd := icmd.(Command)
- embed.Fields = append(embed.Fields, createField(name, cmd))
- } else {
- return nil, fmt.Errorf("unsupported number of arguments")
- }
-
- return embed, nil
-}
--- a/discord/command_set_channel.go Fri May 10 23:42:03 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-package discord
-
-import (
- "fmt"
-
- "github.com/bwmarrin/discordgo"
-
- "bitbucket.org/TheToyz/nowdead/database"
-)
-
-type commandSetChannel struct{}
-
-func (cmd *commandSetChannel) Help() string {
- return "sets the channel to send automatic announcements to"
-}
-
-func (cmd *commandSetChannel) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
- guild, err := database.LoadGuild(m.GuildID)
- if err != nil {
- return nil, err
- }
-
- if guild.Channel != m.ChannelID {
- guild.Channel = m.ChannelID
- guild.Save()
-
- return fmt.Sprintf("Set <#%s> as the announcement channel", m.ChannelID), nil
- }
-
- return fmt.Sprintf("<#%s> is already set as the announcement channel", m.ChannelID), nil
-}
--- a/discord/command_status.go Fri May 10 23:42:03 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-package discord
-
-import (
- "fmt"
- "strings"
-
- "github.com/bwmarrin/discordgo"
-
- "bitbucket.org/TheToyz/nowdead/presence"
-)
-
-type commandStatus struct{}
-
-func (cmd *commandStatus) Help() string {
- return "get the streaming status of a target"
-}
-
-func (cmd *commandStatus) Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error) {
- uri := ""
-
- 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 {
- p := c.getPresence(m.GuildID, mentioned.ID)
-
- if p != nil && p.Game != nil && p.Game.Type == discordgo.GameTypeStreaming {
- uri = p.Game.URL
- } else {
- return nil, fmt.Errorf("%s is not streaming", target)
- }
- }
- }
- } else {
- uri = "https://twitch.tv/" + target
- }
-
- presence, err := presence.GetPresence(uri)
- if err != nil {
- return nil, err
- }
-
- return presenceEmbed(presence), nil
-}
--- a/discord/command_uptime.go Fri May 10 23:42:03 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-package discord
-
-import (
- "fmt"
-
- "github.com/bwmarrin/discordgo"
- "github.com/dustin/go-humanize"
-)
-
-type commandUptime struct{}
-
-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/discord/commands.go Fri May 10 23:42:03 2019 -0500
+++ b/discord/commands.go Sat May 11 03:20:25 2019 -0500
@@ -4,35 +4,167 @@
"fmt"
"strings"
+ "github.com/alecthomas/kong"
"github.com/bwmarrin/discordgo"
- "github.com/iancoleman/orderedmap"
-)
+ "github.com/dustin/go-humanize"
-type Command interface {
- Run(args []string, c *DiscordClient, m *discordgo.MessageCreate) (interface{}, error)
- Help() string
-}
-
-var (
- commands = orderedmap.New()
+ "bitbucket.org/TheToyz/nowdead/database"
+ "bitbucket.org/TheToyz/nowdead/presence"
)
-func init() {
- commands.Set("help", &commandHelp{})
- commands.Set("set-channel", &commandSetChannel{})
- commands.Set("status", &commandStatus{})
- commands.Set("uptime", &commandUptime{})
+type Globals struct {
+ client *DiscordClient
+ msg *discordgo.MessageCreate
+ ctx *kong.Context
+}
+
+type Commands struct {
+ Globals
+
+ Help HelpCmd `kong:"cmd,help='displays this help message'"`
+ SetChannel SetChannelCmd `kong:"cmd,help='set the current channel as the channel to announce new streams'"`
+ Status StatusCmd `kong:"cmd,help='get the streaming status of someone'"`
+ Uptime UptimeCmd `kong:"cmd,help='display how long the bot has been running for'"`
+}
+
+type HelpCmd struct {
+ Command []string `kong:"arg,optional,help='command to get help on'"`
+}
+
+func (c *HelpCmd) Run(g *Globals) error {
+ ctx, err := kong.Trace(g.ctx.Kong, c.Command)
+ if err != nil {
+ return err
+ }
+
+ if ctx.Error != nil {
+ return ctx.Error
+ }
+
+ err = ctx.PrintUsage(true)
+ if err != nil {
+ return err
+ }
+
+ fmt.Fprintln(g.ctx.Stdout)
+
+ return nil
+}
+
+type SetChannelCmd struct{}
+
+func (c *SetChannelCmd) Run(g *Globals) error {
+ guild, err := database.LoadGuild(g.msg.GuildID)
+ if err != nil {
+ return err
+ }
+
+ resp := fmt.Sprintf("<#%s> is already set as the announcement channel", g.msg.ChannelID)
+
+ if guild.Channel != g.msg.ChannelID {
+ guild.Channel = g.msg.ChannelID
+ guild.Save()
+
+ resp = fmt.Sprintf("Set <#%s> as the announcement channel", g.msg.ChannelID)
+ }
+
+ g.client.sendChannel(g.msg.ChannelID, resp)
+
+ return nil
+}
+
+type StatusCmd struct {
+ Target string `kong:"arg"`
}
-func (c *DiscordClient) processCommand(args []string, m *discordgo.MessageCreate) (interface{}, error) {
- if len(args) == 0 {
- return nil, fmt.Errorf("no command specified")
+func (c *StatusCmd) Run(g *Globals) error {
+ uri := ""
+
+ if strings.HasPrefix(c.Target, "<@") {
+ mentionID := c.Target[2 : len(c.Target)-1]
+
+ for _, mentioned := range g.msg.Mentions {
+ if mentioned.ID == mentionID {
+ p := g.client.getPresence(g.msg.GuildID, mentioned.ID)
+
+ if p != nil && p.Game != nil && p.Game.Type == discordgo.GameTypeStreaming {
+ uri = p.Game.URL
+ } else {
+ g.client.sendChannel(
+ g.msg.ChannelID,
+ fmt.Sprintf("%s is not currently streaming", c.Target),
+ )
+ }
+ }
+ }
+ }
+
+ if uri == "" {
+ uri = "https://twitch.tv/" + c.Target
+ }
+
+ presence, err := presence.GetPresence(uri)
+ if err != nil {
+ return err
}
- name := strings.ToLower(args[0])
- if cmd, found := commands.Get(name); found {
- return cmd.(Command).Run(args[1:], c, m)
+ return g.client.sendPresenceChannel(g.msg.ChannelID, presence)
+}
+
+type UptimeCmd struct{}
+
+func (c *UptimeCmd) Run(g *Globals) error {
+ g.client.sendChannel(
+ g.msg.ChannelID,
+ fmt.Sprintf("Started %s", humanize.Time(g.client.started)),
+ )
+
+ return nil
+}
+
+func (c *DiscordClient) processCommand(args []string, m *discordgo.MessageCreate) error {
+ cmd := Commands{
+ Globals: Globals{
+ client: c,
+ msg: m,
+ },
}
- return "", fmt.Errorf("unknown command '%s'", args[0])
+ buf := &strings.Builder{}
+
+ parser, err := kong.New(
+ &cmd,
+ kong.Description("This bot auto announces when people start streaming"),
+ kong.Exit(func(int) {}),
+ kong.ConfigureHelp(kong.HelpOptions{
+ Compact: true,
+ }),
+ kong.Name("@wasdead"),
+ kong.NoDefaultHelp(),
+ kong.Writers(buf, buf),
+ )
+ if err != nil {
+ c.sendChannel(m.ChannelID, fmt.Sprintf("error: %v", err))
+ return err
+ }
+
+ ctx, err := parser.Parse(args)
+ if err != nil {
+ c.sendChannel(m.ChannelID, fmt.Sprintf("error: %v", err))
+ return err
+ }
+
+ cmd.Globals.ctx = ctx
+
+ err = ctx.Run(&cmd.Globals)
+ if err != nil {
+ c.sendChannel(m.ChannelID, fmt.Sprintf("error: %v", err))
+ return err
+ }
+
+ if buf.Len() > 0 {
+ c.sendChannel(m.ChannelID, fmt.Sprintf("```%s```", buf.String()))
+ }
+
+ return nil
}
--- a/discord/messages.go Fri May 10 23:42:03 2019 -0500
+++ b/discord/messages.go Sat May 11 03:20:25 2019 -0500
@@ -1,7 +1,6 @@
package discord
import (
- "fmt"
"regexp"
"strings"
@@ -24,17 +23,11 @@
args := splitRegex.Split(m.Content, -1)[1:]
// call parse commands
- output, err := c.processCommand(args, m)
+ 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))
+ c.sendChannel(m.ChannelID, err.Error())
}
}
--- a/twitch/twitch.go Fri May 10 23:42:03 2019 -0500
+++ b/twitch/twitch.go Sat May 11 03:20:25 2019 -0500
@@ -1,7 +1,7 @@
package twitch
import (
- "errors"
+ "fmt"
"net/url"
"strings"
@@ -44,7 +44,7 @@
}
if len(users.Data.Users) <= 0 || len(streams.Data.Streams) <= 0 {
- return presence.Presence{}, errors.New("user not found")
+ return presence.Presence{}, fmt.Errorf("user %q not found", username)
}
user := users.Data.Users[0]