From 09ae9fbb077ea729d78773413a30001eb9428471 Mon Sep 17 00:00:00 2001 From: "diamondburned (Forefront)" Date: Mon, 6 Apr 2020 13:25:42 -0700 Subject: [PATCH] Bot: Added a Prefixer API which breaks the old Prefix string API --- _example/advanced_bot/main.go | 2 +- _example/simple/main.go | 4 +--- _example/undeleter/main.go | 4 +--- bot/ctx.go | 30 +++++++++++++++++++++++++----- bot/ctx_call.go | 26 +++++++++++--------------- bot/error.go | 25 +++++++++---------------- bot/subcommand.go | 5 ++--- 7 files changed, 50 insertions(+), 46 deletions(-) diff --git a/_example/advanced_bot/main.go b/_example/advanced_bot/main.go index 937e426..d8e8ab4 100644 --- a/_example/advanced_bot/main.go +++ b/_example/advanced_bot/main.go @@ -18,7 +18,7 @@ func main() { commands := &Bot{} wait, err := bot.Start(token, commands, func(ctx *bot.Context) error { - ctx.Prefix = "!" + ctx.HasPrefix = bot.NewPrefix("!", "~") // Subcommand demo, but this can be in another package. ctx.MustRegisterSubcommand(&Debug{}) diff --git a/_example/simple/main.go b/_example/simple/main.go index 0a32044..e27a212 100644 --- a/_example/simple/main.go +++ b/_example/simple/main.go @@ -29,8 +29,6 @@ func main() { log.Fatalln("Failed to connect:", err) } - defer s.Close() - u, err := s.Me() if err != nil { log.Fatalln("Failed to get myself:", err) @@ -38,7 +36,7 @@ func main() { log.Println("Started as", u.Username) - // Block until a fatal error or SIGINT. + // Block until a fatal error or SIGINT. Wait also calls Close(). if err := s.Wait(); err != nil { log.Fatalln("Gateway fatal error:", err) } diff --git a/_example/undeleter/main.go b/_example/undeleter/main.go index b268ff2..ab1d7ff 100644 --- a/_example/undeleter/main.go +++ b/_example/undeleter/main.go @@ -39,8 +39,6 @@ func main() { log.Fatalln("Failed to connect:", err) } - defer s.Close() - u, err := s.Me() if err != nil { log.Fatalln("Failed to get myself:", err) @@ -48,7 +46,7 @@ func main() { log.Println("Started as", u.Username) - // Block until a fatal error or SIGINT. + // Block until a fatal error or SIGINT. Wait also calls Close(). if err := s.Wait(); err != nil { log.Fatalln("Gateway fatal error:", err) } diff --git a/bot/ctx.go b/bot/ctx.go index 6279a8b..e5b5091 100644 --- a/bot/ctx.go +++ b/bot/ctx.go @@ -12,6 +12,23 @@ import ( "github.com/pkg/errors" ) +// Prefixer checks a message if it starts with the desired prefix. By default, +// NewPrefix() is used. +type Prefixer func(*gateway.MessageCreateEvent) (prefix string, ok bool) + +// NewPrefix creates a simple prefix checker using strings. As the default +// prefix is "!", the function is called as NewPrefix("!"). +func NewPrefix(prefixes ...string) Prefixer { + return func(msg *gateway.MessageCreateEvent) (string, bool) { + for _, prefix := range prefixes { + if strings.HasPrefix(msg.Content, prefix) { + return prefix, true + } + } + return "", false + } +} + // TODO: add variadic arguments // Context is the bot state for commands and subcommands. @@ -56,8 +73,9 @@ type Context struct { // Descriptive help body Description string - // The prefix for commands - Prefix string + // Called to check a message's prefix. The default prefix is "!". Refer to + // NewPrefix(). + HasPrefix Prefixer // FormatError formats any errors returned by anything, including the method // commands or the reflect functions. This also includes invalid usage @@ -152,7 +170,7 @@ func New(s *state.State, cmd interface{}) (*Context, error) { ctx := &Context{ Subcommand: c, State: s, - Prefix: "~", + HasPrefix: NewPrefix("~"), FormatError: func(err error) string { // Escape all pings, including @everyone. return strings.Replace(err.Error(), "@", "@\u200b", -1) @@ -176,6 +194,8 @@ func (ctx *Context) Wait() error { return ctx.Session.Wait() } +// Subcommands returns the slice of subcommands. To add subcommands, use +// RegisterSubcommand(). func (ctx *Context) Subcommands() []*Subcommand { // Getter is not useless, refer to the struct doc for reason. return ctx.subcommands @@ -348,7 +368,7 @@ func (ctx *Context) help(hideAdmin bool) string { continue } - help.WriteString(indent + ctx.Prefix + cmd.Command) + help.WriteString(indent + cmd.Command) switch { case len(cmd.Usage()) > 0: @@ -364,7 +384,7 @@ func (ctx *Context) help(hideAdmin bool) string { var subcommands = ctx.Subcommands() for _, sub := range subcommands { - if help := sub.Help(ctx.Prefix, indent, hideAdmin); help != "" { + if help := sub.Help(indent, hideAdmin); help != "" { subHelp.WriteString(help) } } diff --git a/bot/ctx_call.go b/bot/ctx_call.go index 1e96fc1..e5c59c0 100644 --- a/bot/ctx_call.go +++ b/bot/ctx_call.go @@ -114,13 +114,13 @@ func (ctx *Context) callCmd(ev interface{}) error { func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error { // check if prefix - if !strings.HasPrefix(mc.Content, ctx.Prefix) { - // not a command, ignore + pf, ok := ctx.HasPrefix(mc) + if !ok { return nil } // trim the prefix before splitting, this way multi-words prefices work - content := mc.Content[len(ctx.Prefix):] + content := mc.Content[len(pf):] if content == "" { return nil // just the prefix only @@ -197,7 +197,6 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error { return &ErrUnknownCommand{ Command: args[1], Parent: args[0], - Prefix: ctx.Prefix, ctx: s.Commands, } } @@ -213,7 +212,6 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error { return &ErrUnknownCommand{ Command: args[0], - Prefix: ctx.Prefix, ctx: ctx.Commands, } } @@ -292,11 +290,10 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error { } return &ErrInvalidUsage{ - Args: args, - Prefix: ctx.Prefix, - Index: len(args) - 1, - Err: err, - Ctx: cmd, + Args: args, + Index: len(args) - 1, + Err: err, + Ctx: cmd, } } @@ -306,11 +303,10 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent) error { v, err := cmd.Arguments[i-start].fn(args[i]) if err != nil { return &ErrInvalidUsage{ - Args: args, - Prefix: ctx.Prefix, - Index: i, - Err: err.Error(), - Ctx: cmd, + Args: args, + Index: i, + Err: err.Error(), + Ctx: cmd, } } diff --git a/bot/error.go b/bot/error.go index 6662c1d..931a09b 100644 --- a/bot/error.go +++ b/bot/error.go @@ -8,8 +8,6 @@ type ErrUnknownCommand struct { Command string Parent string - Prefix string - // TODO: list available commands? // Here, as a reminder ctx []*CommandContext @@ -20,7 +18,7 @@ func (err *ErrUnknownCommand) Error() string { } var UnknownCommandString = func(err *ErrUnknownCommand) string { - var header = "Unknown command: " + err.Prefix + var header = "Unknown command: " if err.Parent != "" { header += err.Parent + " " + err.Command } else { @@ -31,9 +29,7 @@ var UnknownCommandString = func(err *ErrUnknownCommand) string { } type ErrInvalidUsage struct { - Args []string - Prefix string - + Args []string Index int Err string @@ -55,16 +51,13 @@ var InvalidUsageString = func(err *ErrInvalidUsage) string { return "Missing arguments. Refer to help." } - body := "Invalid usage at " + err.Prefix - - // Write the first part - body += strings.Join(err.Args[:err.Index], " ") - - // Write the wrong part - body += " __" + err.Args[err.Index] + "__ " - - // Write the last part - body += strings.Join(err.Args[err.Index+1:], " ") + body := "Invalid usage at " + + // Write the first part + strings.Join(err.Args[:err.Index], " ") + + // Write the wrong part + " __" + err.Args[err.Index] + "__ " + + // Write the last part + strings.Join(err.Args[err.Index+1:], " ") if err.Err != "" { body += "\nError: " + err.Err diff --git a/bot/subcommand.go b/bot/subcommand.go index 7855b9c..316412c 100644 --- a/bot/subcommand.go +++ b/bot/subcommand.go @@ -173,7 +173,7 @@ func (sub *Subcommand) ChangeCommandInfo(methodName, cmd, desc string) bool { return false } -func (sub *Subcommand) Help(prefix, indent string, hideAdmin bool) string { +func (sub *Subcommand) Help(indent string, hideAdmin bool) string { if sub.Flag.Is(AdminOnly) && hideAdmin { return "" } @@ -205,8 +205,7 @@ func (sub *Subcommand) Help(prefix, indent string, hideAdmin bool) string { continue } - commands += indent + indent + - prefix + sub.Command + " " + cmd.Command + commands += indent + indent + sub.Command + " " + cmd.Command switch { case len(cmd.Usage()) > 0: