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 @@
- "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{
- 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{
- Description: "Command Help",
- for _, name := range commands.Keys() {
- icmd, _ := commands.Get(name)
- embed.Fields = append(embed.Fields, createField(name, cmd))
- } else if len(args) == 1 {
- icmd, found := commands.Get(strings.ToLower(name))
- return nil, fmt.Errorf("command %s not found", name)
- embed.Fields = append(embed.Fields, createField(name, cmd))
- return nil, fmt.Errorf("unsupported number of arguments")
--- 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 @@
- "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 guild.Channel != m.ChannelID {
- guild.Channel = m.ChannelID
- 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 @@
- "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) {
- return nil, fmt.Errorf("invalid target")
- 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 {
- return nil, fmt.Errorf("%s is not streaming", target)
- uri = "https://twitch.tv/" + target
- presence, err := presence.GetPresence(uri)
- 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 @@
- "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 @@
+ "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)
- commands = orderedmap.New()
+ "bitbucket.org/TheToyz/nowdead/database" + "bitbucket.org/TheToyz/nowdead/presence"
- commands.Set("help", &commandHelp{})
- commands.Set("set-channel", &commandSetChannel{})
- commands.Set("status", &commandStatus{})
- commands.Set("uptime", &commandUptime{})
+ msg *discordgo.MessageCreate + 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'"` + 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) + err = ctx.PrintUsage(true) + fmt.Fprintln(g.ctx.Stdout) +type SetChannelCmd struct{} +func (c *SetChannelCmd) Run(g *Globals) error { + guild, err := database.LoadGuild(g.msg.GuildID) + 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 + resp = fmt.Sprintf("Set <#%s> as the announcement channel", g.msg.ChannelID) + g.client.sendChannel(g.msg.ChannelID, resp) + Target string `kong:"arg"` -func (c *DiscordClient) processCommand(args []string, m *discordgo.MessageCreate) (interface{}, error) {
- return nil, fmt.Errorf("no command specified")
+func (c *StatusCmd) Run(g *Globals) error { + 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 { + fmt.Sprintf("%s is not currently streaming", c.Target), + uri = "https://twitch.tv/" + c.Target + presence, err := presence.GetPresence(uri) - 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) +func (c *UptimeCmd) Run(g *Globals) error { + fmt.Sprintf("Started %s", humanize.Time(g.client.started)), +func (c *DiscordClient) processCommand(args []string, m *discordgo.MessageCreate) error { - return "", fmt.Errorf("unknown command '%s'", args[0])
+ buf := &strings.Builder{} + parser, err := kong.New( + kong.Description("This bot auto announces when people start streaming"), + kong.Exit(func(int) {}), + kong.ConfigureHelp(kong.HelpOptions{ + kong.Writers(buf, buf), + c.sendChannel(m.ChannelID, fmt.Sprintf("error: %v", err)) + ctx, err := parser.Parse(args) + c.sendChannel(m.ChannelID, fmt.Sprintf("error: %v", err)) + err = ctx.Run(&cmd.Globals) + c.sendChannel(m.ChannelID, fmt.Sprintf("error: %v", err)) + c.sendChannel(m.ChannelID, fmt.Sprintf("```%s```", buf.String())) --- 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 @@
@@ -24,17 +23,11 @@
args := splitRegex.Split(m.Content, -1)[1:]
- output, err := c.processCommand(args, m)
+ err := c.processCommand(args, m) log.Warnf("error processing %#v: %v", m.Content, err)
- output = fmt.Sprintf("error: %v", err)
- 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 @@
@@ -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]