mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-11-27 17:23:00 +00:00
Bot: Added Plumb support, fixed tests
Merged Merged
This commit is contained in:
parent
9e59402591
commit
67430c6d7a
|
@ -83,10 +83,7 @@ type MethodContext struct {
|
|||
MethodName string
|
||||
|
||||
// Command is the Discord command used to call the method.
|
||||
Command string // hidden if empty
|
||||
|
||||
// Hidden is true if the method has a hidden nameflag.
|
||||
// Hidden bool
|
||||
Command string // plumb if empty
|
||||
|
||||
// Variadic is true if the function is a variadic one or if the last
|
||||
// argument accepts multiple strings.
|
||||
|
|
30
bot/ctx.go
30
bot/ctx.go
|
@ -217,39 +217,23 @@ func (ctx *Context) Subcommands() []*Subcommand {
|
|||
return ctx.subcommands
|
||||
}
|
||||
|
||||
// FindMethod finds a method based on the struct and method name. The queried
|
||||
// FindCommand finds a command based on the struct and method name. The queried
|
||||
// names will have their flags stripped.
|
||||
//
|
||||
// Example
|
||||
//
|
||||
// // Find a command from the main context:
|
||||
// cmd := ctx.FindMethod("", "Method")
|
||||
// cmd := ctx.FindCommand("", "Method")
|
||||
// // Find a command from a subcommand:
|
||||
// cmd = ctx.FindMethod("Starboard", "Reset")
|
||||
// cmd = ctx.FindCommand("Starboard", "Reset")
|
||||
//
|
||||
func (ctx *Context) FindMethod(structname, methodname string) *MethodContext {
|
||||
func (ctx *Context) FindCommand(structname, methodname string) *MethodContext {
|
||||
if structname == "" {
|
||||
for _, c := range ctx.Methods {
|
||||
if c.MethodName == methodname {
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return ctx.Subcommand.FindCommand(methodname)
|
||||
}
|
||||
|
||||
for _, sub := range ctx.subcommands {
|
||||
if sub.StructName != structname {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, c := range sub.Methods {
|
||||
if c.MethodName == methodname {
|
||||
return c
|
||||
}
|
||||
if sub.StructName == structname {
|
||||
return sub.FindCommand(methodname)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ Call:
|
|||
// findCommand filters.
|
||||
func (ctx *Context) findCommand(parts []string) ([]string, *MethodContext, *Subcommand, error) {
|
||||
// Main command entrypoint cannot have plumb.
|
||||
for _, c := range ctx.Methods {
|
||||
for _, c := range ctx.Commands {
|
||||
if c.Command == parts[0] {
|
||||
return parts[1:], c, ctx.Subcommand, nil
|
||||
}
|
||||
|
@ -299,15 +299,16 @@ func (ctx *Context) findCommand(parts []string) ([]string, *MethodContext, *Subc
|
|||
continue
|
||||
}
|
||||
|
||||
// If there's no second argument, TODO call Help.
|
||||
|
||||
if s.plumbed != nil {
|
||||
// Only actually plumb if we actually have a plumbed handler AND
|
||||
// 1. We only have one command handler OR
|
||||
// 2. We only have the subcommand name but no command.
|
||||
if s.plumbed != nil && (len(s.Commands) == 1 || len(parts) <= 2) {
|
||||
return parts[1:], s.plumbed, s, nil
|
||||
}
|
||||
|
||||
if len(parts) >= 2 {
|
||||
for _, c := range s.Methods {
|
||||
if c.event == typeMessageCreate && c.Command == parts[1] {
|
||||
for _, c := range s.Commands {
|
||||
if c.Command == parts[1] {
|
||||
return parts[2:], c, s, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ func TestSubcommandPlumb(t *testing.T) {
|
|||
// Try call exactly what's in the Plumb example:
|
||||
m := &gateway.MessageCreateEvent{
|
||||
Message: discord.Message{
|
||||
Content: "hasPlumb test command",
|
||||
Content: "hasPlumb",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,50 @@ func TestSubcommandPlumb(t *testing.T) {
|
|||
if p.NotPlumbed {
|
||||
t.Fatal("Normal method called for hasPlumb")
|
||||
}
|
||||
}
|
||||
|
||||
type onlyPlumb struct {
|
||||
Ctx *Context
|
||||
Plumbed string
|
||||
}
|
||||
|
||||
func (h *onlyPlumb) Setup(sub *Subcommand) {
|
||||
sub.SetPlumb("Plumber")
|
||||
}
|
||||
|
||||
func (h *onlyPlumb) Plumber(_ *gateway.MessageCreateEvent, c RawArguments) error {
|
||||
h.Plumbed = string(c)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestSubcommandOnlyPlumb(t *testing.T) {
|
||||
var state = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
c, err := New(state, &testc{})
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new context:", err)
|
||||
}
|
||||
c.HasPrefix = NewPrefix("")
|
||||
|
||||
p := &onlyPlumb{}
|
||||
|
||||
_, err = c.RegisterSubcommand(p)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to register hasPlumb:", err)
|
||||
}
|
||||
|
||||
// Try call exactly what's in the Plumb example:
|
||||
m := &gateway.MessageCreateEvent{
|
||||
Message: discord.Message{
|
||||
Content: "onlyPlumb test command",
|
||||
},
|
||||
}
|
||||
|
||||
if err := c.callCmd(m); err != nil {
|
||||
t.Fatal("Failed to call message:", err)
|
||||
}
|
||||
|
||||
if p.Plumbed != "test command" {
|
||||
t.Fatal("Unexpected custom argument for plumbed:", p.Plumbed)
|
||||
|
|
|
@ -103,7 +103,7 @@ func TestContext(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("find commands", func(t *testing.T) {
|
||||
cmd := ctx.FindMethod("", "NoArgs")
|
||||
cmd := ctx.FindCommand("", "NoArgs")
|
||||
if cmd == nil {
|
||||
t.Fatal("Failed to find NoArgs")
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ func TestContext(t *testing.T) {
|
|||
t.Fatal("Unexpected call error:", err)
|
||||
}
|
||||
|
||||
if cmd := ctx.FindMethod("testc", "Noop"); cmd == nil {
|
||||
if cmd := ctx.FindCommand("testc", "Noop"); cmd == nil {
|
||||
t.Fatal("Failed to find subcommand Noop")
|
||||
}
|
||||
})
|
||||
|
|
|
@ -82,9 +82,10 @@ type Subcommand struct {
|
|||
// Commands can actually return either a string, an embed, or a
|
||||
// SendMessageData, with error as the second argument.
|
||||
|
||||
// All registered method contexts, including commands:
|
||||
Methods []*MethodContext
|
||||
plumbed *MethodContext
|
||||
// All registered method contexts:
|
||||
Events []*MethodContext
|
||||
Commands []*MethodContext
|
||||
plumbed *MethodContext
|
||||
|
||||
// Global middlewares.
|
||||
globalmws []*MiddlewareContext
|
||||
|
@ -136,9 +137,9 @@ func (sub *Subcommand) NeedsName() {
|
|||
sub.Command = lowerFirstLetter(sub.StructName)
|
||||
}
|
||||
|
||||
// FindMethod finds the MethodContext. It panics if methodName is not found.
|
||||
func (sub *Subcommand) FindMethod(methodName string) *MethodContext {
|
||||
for _, c := range sub.Methods {
|
||||
// FindCommand finds the MethodContext. It panics if methodName is not found.
|
||||
func (sub *Subcommand) FindCommand(methodName string) *MethodContext {
|
||||
for _, c := range sub.Commands {
|
||||
if c.MethodName == methodName {
|
||||
return c
|
||||
}
|
||||
|
@ -149,7 +150,7 @@ func (sub *Subcommand) FindMethod(methodName string) *MethodContext {
|
|||
// ChangeCommandInfo changes the matched methodName's Command and Description.
|
||||
// Empty means unchanged. The returned bool is true when the command is found.
|
||||
func (sub *Subcommand) ChangeCommandInfo(methodName, cmd, desc string) bool {
|
||||
for _, c := range sub.Methods {
|
||||
for _, c := range sub.Commands {
|
||||
if c.MethodName != methodName || !c.isEvent(typeMessageCreate) {
|
||||
continue
|
||||
}
|
||||
|
@ -316,7 +317,11 @@ func (sub *Subcommand) parseCommands() error {
|
|||
}
|
||||
|
||||
// Append.
|
||||
sub.Methods = append(sub.Methods, cctx)
|
||||
if cctx.event == typeMessageCreate {
|
||||
sub.Commands = append(sub.Commands, cctx)
|
||||
} else {
|
||||
sub.Events = append(sub.Events, cctx)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -339,7 +344,7 @@ func (sub *Subcommand) AddMiddleware(methodName string, middleware interface{})
|
|||
sub.globalmws = append(sub.globalmws, mw)
|
||||
} else {
|
||||
// Append middleware to that individual function.
|
||||
sub.FindMethod(method).addMiddleware(mw)
|
||||
sub.FindCommand(method).addMiddleware(mw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,10 +368,10 @@ func (sub *Subcommand) eventCallers(evT reflect.Type) (callers []caller) {
|
|||
}
|
||||
|
||||
// Search for specific handlers.
|
||||
for _, cctx := range sub.Methods {
|
||||
for _, cctx := range sub.Events {
|
||||
// We only take middlewares and callers if the event matches and is not
|
||||
// a MessageCreate. The other function already handles that.
|
||||
if cctx.event != typeMessageCreate && cctx.isEvent(evT) {
|
||||
if cctx.isEvent(evT) {
|
||||
// Add the command's middlewares first.
|
||||
for _, mw := range cctx.middlewares {
|
||||
// Concrete struct to interface conversion done implicitly.
|
||||
|
@ -387,7 +392,7 @@ func (sub *Subcommand) SetPlumb(methodName string) {
|
|||
panic("SetPlumb called on a main command with sub.Command empty.")
|
||||
}
|
||||
|
||||
method := sub.FindMethod(methodName)
|
||||
method := sub.FindCommand(methodName)
|
||||
method.Command = ""
|
||||
sub.plumbed = method
|
||||
}
|
||||
|
|
|
@ -29,8 +29,11 @@ func TestSubcommand(t *testing.T) {
|
|||
}
|
||||
|
||||
// !!! CHANGE ME
|
||||
if len(sub.Methods) < 8 {
|
||||
t.Fatal("too low sub.Methods len", len(sub.Methods))
|
||||
if len(sub.Commands) < 8 {
|
||||
t.Fatal("too low sub.Methods len", len(sub.Commands))
|
||||
}
|
||||
if len(sub.Events) < 1 {
|
||||
t.Fatal("No events found.")
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -39,7 +42,7 @@ func TestSubcommand(t *testing.T) {
|
|||
foundNoArgs bool
|
||||
)
|
||||
|
||||
for _, this := range sub.Methods {
|
||||
for _, this := range sub.Commands {
|
||||
switch this.Command {
|
||||
case "send":
|
||||
foundSend = true
|
||||
|
|
Loading…
Reference in a new issue