1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2025-07-23 13:20:51 +00:00

Compare commits

...

5 commits

4 changed files with 54 additions and 52 deletions

View file

@ -70,10 +70,9 @@ func (r ArgumentParts) Usage() string {
}
// CustomParser has a CustomParse method, which would be passed in the full
// message content with the prefix and command trimmed. This is used
// for commands that require more advanced parsing than the default parser.
//
// Keep in mind that this does not trim arguments before it.
// message content with the prefix, command, subcommand and space trimmed. This
// is used for commands that require more advanced parsing than the default
// parser.
type CustomParser interface {
CustomParse(arguments string) error
}
@ -101,8 +100,9 @@ type Argument struct {
// if nil, then manual
fn argumentValueFn
manual *reflect.Method
custom *reflect.Method
manual func(ManualParser, []string) error
custom func(CustomParser, string) error
}
func (a *Argument) Type() reflect.Type {
@ -132,9 +132,6 @@ func newArgument(t reflect.Type, variadic bool) (*Argument, error) {
// This shouldn't be variadic.
if !variadic && typeI.Implements(typeICusP) {
mt, _ := typeI.MethodByName("CustomParse")
// TODO: maybe ish?
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
@ -143,14 +140,12 @@ func newArgument(t reflect.Type, variadic bool) (*Argument, error) {
String: fromUsager(t),
rtype: t,
pointer: ptr,
custom: &mt,
custom: CustomParser.CustomParse,
}, nil
}
// This shouldn't be variadic either.
if !variadic && typeI.Implements(typeIManP) {
mt, _ := typeI.MethodByName("ParseContent")
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
@ -159,7 +154,7 @@ func newArgument(t reflect.Type, variadic bool) (*Argument, error) {
String: fromUsager(t),
rtype: t,
pointer: ptr,
manual: &mt,
manual: ManualParser.ParseContent,
}, nil
}

View file

@ -253,7 +253,7 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent, value refl
// If the argument wants all arguments:
case last.manual != nil:
// Call the manual parse method:
_, err = callWith(last.manual.Func, v, reflect.ValueOf(arguments))
err = last.manual(v.Interface().(ManualParser), arguments)
// If the argument wants all arguments in string:
case last.custom != nil:
@ -261,32 +261,14 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent, value refl
// have erroneous hanging quotes.
parseErr = nil
// Manual string seeking is a must here. This is because the string
// could contain multiple whitespaces, and the parser would not
// count them.
var seekTo = cmd.Command
// We can't rely on the plumbing behavior.
if sub.plumbed != nil {
seekTo = sub.Command
}
content = trimPrefixStringAndSlice(content, sub.Command, sub.Aliases)
// Seek to the string.
var i = strings.Index(content, seekTo)
// Edge case if the subcommand is the same as the command.
if cmd.Command == sub.Command {
// Seek again past the command.
i = strings.Index(content[i+len(seekTo):], seekTo)
}
if i > -1 {
// Seek past the substring.
i += len(seekTo)
content = strings.TrimSpace(content[i:])
if !sub.IsPlumbed() && cmd.Command != "" {
content = trimPrefixStringAndSlice(content, cmd.Command, cmd.Aliases)
}
// Call the method with the raw unparsed command:
_, err = callWith(last.custom.Func, v, reflect.ValueOf(content))
err = last.custom(v.Interface().(CustomParser), content)
}
// Check the returned error:
@ -367,20 +349,14 @@ func (ctx *Context) findCommand(parts []string) ([]string, *MethodContext, *Subc
return nil, nil, nil, Break
}
return nil, nil, nil, &ErrUnknownCommand{
Parts: parts,
Subcmd: s,
}
return nil, nil, nil, newErrUnknownCommand(s, parts)
}
if ctx.SilentUnknown.Command {
return nil, nil, nil, Break
}
return nil, nil, nil, &ErrUnknownCommand{
Parts: parts,
Subcmd: ctx.Subcommand,
}
return nil, nil, nil, newErrUnknownCommand(ctx.Subcommand, parts)
}
// searchStringAndSlice searches if str is equal to isString or any of the given
@ -399,6 +375,22 @@ func searchStringAndSlice(str string, isString string, otherStrings []string) bo
return false
}
// trimPrefixStringAndSlice behaves similarly to searchStringAndSlice, but it
// trims the prefix and the surrounding spaces after a match.
func trimPrefixStringAndSlice(str string, prefix string, prefixes []string) string {
if strings.HasPrefix(str, prefix) {
return strings.TrimSpace(str[len(prefix):])
}
for _, prefix := range prefixes {
if strings.HasPrefix(str, prefix) {
return strings.TrimSpace(str[len(prefix):])
}
}
return str
}
func errNoBreak(err error) error {
if errors.Is(err, Break) {
return nil

View file

@ -2,6 +2,7 @@ package bot
import (
"errors"
"fmt"
"strings"
)
@ -10,15 +11,28 @@ type ErrUnknownCommand struct {
Subcmd *Subcommand
}
func (err *ErrUnknownCommand) Error() string {
if len(err.Parts) > 2 {
err.Parts = err.Parts[:2]
func newErrUnknownCommand(s *Subcommand, parts []string) error {
if len(parts) > 2 {
parts = parts[:2]
}
return &ErrUnknownCommand{
Parts: parts,
Subcmd: s,
}
}
func (err *ErrUnknownCommand) Error() string {
return UnknownCommandString(err)
}
var UnknownCommandString = func(err *ErrUnknownCommand) string {
return "unknown command: " + strings.Join(err.Parts, " ")
// Subcommand check.
if err.Subcmd.StructName == "" || len(err.Parts) < 2 {
return "unknown command: " + err.Parts[0] + "."
}
return fmt.Sprintf("unknown %s subcommand: %s.", err.Parts[0], err.Parts[1])
}
var (

View file

@ -110,6 +110,7 @@ type SpeakingData struct {
Speaking SpeakingFlag `json:"speaking"`
Delay int `json:"delay"`
SSRC uint32 `json:"ssrc"`
UserID discord.UserID `json:"user_id,omitempty"`
}
// Speaking sends a Speaking operation (opcode 5) to the Gateway Gateway.