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