diff --git a/pkg/interact/interact.go b/pkg/interact/interact.go index a034a6045..a756e074f 100644 --- a/pkg/interact/interact.go +++ b/pkg/interact/interact.go @@ -3,43 +3,15 @@ package interact import ( "context" "fmt" - "reflect" - "strconv" - "strings" - "text/scanner" "time" log "github.com/sirupsen/logrus" ) -type Reply interface { - Message(message string) - AddButton(text string) - RemoveKeyboard() -} - -// Responder defines the logic of responding the message -type Responder func(message string, reply Reply, ctxObjects ...interface{}) error - type CustomInteraction interface { Commands(interact *Interact) } -type State string - -const ( - StatePublic State = "public" - StateAuthenticated State = "authenticated" -) - -type TextMessageResponder interface { - SetTextMessageResponder(responder Responder) -} - -type CommandResponder interface { - AddCommand(command *Command, responder Responder) -} - type Messenger interface { TextMessageResponder CommandResponder @@ -251,120 +223,3 @@ func (it *Interact) Start(ctx context.Context) error { return nil } -func parseCommand(src string) (args []string) { - var s scanner.Scanner - s.Init(strings.NewReader(src)) - s.Filename = "command" - for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() { - text := s.TokenText() - if text[0] == '"' && text[len(text)-1] == '"' { - text, _ = strconv.Unquote(text) - } - args = append(args, text) - } - - return args -} - -func parseFuncArgsAndCall(f interface{}, args []string, objects ...interface{}) (State, error) { - fv := reflect.ValueOf(f) - ft := reflect.TypeOf(f) - - argIndex := 0 - - var rArgs []reflect.Value - for i := 0; i < ft.NumIn(); i++ { - at := ft.In(i) - - switch k := at.Kind(); k { - - case reflect.Interface: - found := false - - for oi := 0; oi < len(objects); oi++ { - obj := objects[oi] - objT := reflect.TypeOf(obj) - objV := reflect.ValueOf(obj) - - fmt.Println( - at.PkgPath(), - at.Name(), - objT, "implements", at, "=", objT.Implements(at), - ) - - if objT.Implements(at) { - found = true - rArgs = append(rArgs, objV) - break - } - } - - if !found { - v := reflect.Zero(at) - rArgs = append(rArgs, v) - } - - case reflect.String: - av := reflect.ValueOf(args[argIndex]) - rArgs = append(rArgs, av) - argIndex++ - - case reflect.Bool: - bv, err := strconv.ParseBool(args[argIndex]) - if err != nil { - return "", err - } - av := reflect.ValueOf(bv) - rArgs = append(rArgs, av) - argIndex++ - - case reflect.Int64: - nf, err := strconv.ParseInt(args[argIndex], 10, 64) - if err != nil { - return "", err - } - - av := reflect.ValueOf(nf) - rArgs = append(rArgs, av) - argIndex++ - - case reflect.Float64: - nf, err := strconv.ParseFloat(args[argIndex], 64) - if err != nil { - return "", err - } - - av := reflect.ValueOf(nf) - rArgs = append(rArgs, av) - argIndex++ - } - } - - out := fv.Call(rArgs) - if ft.NumOut() == 0 { - return "", nil - } - - // try to get the error object from the return value - var state State - var err error - for i := 0; i < ft.NumOut(); i++ { - outType := ft.Out(i) - switch outType.Kind() { - case reflect.String: - if outType.Name() == "State" { - state = State(out[i].String()) - } - - case reflect.Interface: - o := out[i].Interface() - switch ov := o.(type) { - case error: - err = ov - - } - - } - } - return state, err -} diff --git a/pkg/interact/parse.go b/pkg/interact/parse.go new file mode 100644 index 000000000..54e2fbf7f --- /dev/null +++ b/pkg/interact/parse.go @@ -0,0 +1,128 @@ +package interact + +import ( + "fmt" + "reflect" + "strconv" + "strings" + "text/scanner" +) + +func parseFuncArgsAndCall(f interface{}, args []string, objects ...interface{}) (State, error) { + fv := reflect.ValueOf(f) + ft := reflect.TypeOf(f) + + argIndex := 0 + + var rArgs []reflect.Value + for i := 0; i < ft.NumIn(); i++ { + at := ft.In(i) + + switch k := at.Kind(); k { + + case reflect.Interface: + found := false + + for oi := 0; oi < len(objects); oi++ { + obj := objects[oi] + objT := reflect.TypeOf(obj) + objV := reflect.ValueOf(obj) + + fmt.Println( + at.PkgPath(), + at.Name(), + objT, "implements", at, "=", objT.Implements(at), + ) + + if objT.Implements(at) { + found = true + rArgs = append(rArgs, objV) + break + } + } + + if !found { + v := reflect.Zero(at) + rArgs = append(rArgs, v) + } + + case reflect.String: + av := reflect.ValueOf(args[argIndex]) + rArgs = append(rArgs, av) + argIndex++ + + case reflect.Bool: + bv, err := strconv.ParseBool(args[argIndex]) + if err != nil { + return "", err + } + av := reflect.ValueOf(bv) + rArgs = append(rArgs, av) + argIndex++ + + case reflect.Int64: + nf, err := strconv.ParseInt(args[argIndex], 10, 64) + if err != nil { + return "", err + } + + av := reflect.ValueOf(nf) + rArgs = append(rArgs, av) + argIndex++ + + case reflect.Float64: + nf, err := strconv.ParseFloat(args[argIndex], 64) + if err != nil { + return "", err + } + + av := reflect.ValueOf(nf) + rArgs = append(rArgs, av) + argIndex++ + } + } + + out := fv.Call(rArgs) + if ft.NumOut() == 0 { + return "", nil + } + + // try to get the error object from the return value + var state State + var err error + for i := 0; i < ft.NumOut(); i++ { + outType := ft.Out(i) + switch outType.Kind() { + case reflect.String: + if outType.Name() == "State" { + state = State(out[i].String()) + } + + case reflect.Interface: + o := out[i].Interface() + switch ov := o.(type) { + case error: + err = ov + + } + + } + } + return state, err +} + +func parseCommand(src string) (args []string) { + var s scanner.Scanner + s.Init(strings.NewReader(src)) + s.Filename = "command" + for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() { + text := s.TokenText() + if text[0] == '"' && text[len(text)-1] == '"' { + text, _ = strconv.Unquote(text) + } + args = append(args, text) + } + + return args +} + diff --git a/pkg/interact/reply.go b/pkg/interact/reply.go new file mode 100644 index 000000000..779e093a6 --- /dev/null +++ b/pkg/interact/reply.go @@ -0,0 +1,7 @@ +package interact + +type Reply interface { + Message(message string) + AddButton(text string) + RemoveKeyboard() +} diff --git a/pkg/interact/responder.go b/pkg/interact/responder.go new file mode 100644 index 000000000..f89dfd7a8 --- /dev/null +++ b/pkg/interact/responder.go @@ -0,0 +1,12 @@ +package interact + +// Responder defines the logic of responding the message +type Responder func(message string, reply Reply, ctxObjects ...interface{}) error + +type TextMessageResponder interface { + SetTextMessageResponder(responder Responder) +} + +type CommandResponder interface { + AddCommand(command *Command, responder Responder) +} diff --git a/pkg/interact/state.go b/pkg/interact/state.go new file mode 100644 index 000000000..3bf517db6 --- /dev/null +++ b/pkg/interact/state.go @@ -0,0 +1,8 @@ +package interact + +type State string + +const ( + StatePublic State = "public" + StateAuthenticated State = "authenticated" +)