func process_message_pkg(buff *s.OutPkg, in *s.InPkg, context *BotContext) (*s.OutPkg, bool, error) { var err error var isDeferred bool if in.Message.Type == "error" { log.Printf("error because type of message is error:\n %+v", in.Message.Error) return buff, false, errors.New(fmt.Sprintf("Error because type of message id: %+v is error", in.Message.ID)) } in_commands := in.Message.Commands for _, command := range *in_commands { action := command.Action if commandProcessor, ok := context.MessageProcessors[action]; ok { log.Printf("BOT found [%v] action", action) buff, isDeferred, err = process_message(commandProcessor, buff, in) } else { err = errors.New("Команда не поддерживается.") buff.Message = &s.OutMessage{ Thread: in.Message.Thread, ID: u.GenStringId(), Type: "chat", Body: err.Error(), } } } return buff, isDeferred, err }
func process_request_pkg(buff *s.OutPkg, in *s.InPkg, context *BotContext) (*s.OutPkg, error) { if in.Request.Type == "error" { log.Printf("error because type of request is error:\n %+v", in.Request) return buff, errors.New("error because request type is error") } action := in.Request.Query.Action buff.Request = &s.OutRequest{ID: u.GenStringId(), Type: "result"} buff.Request.Query.Action = action buff.Request.Type = "result" if commandProcessor, ok := context.RequestProcessors[action]; ok { requestResult := commandProcessor.ProcessRequest(in) if requestResult.Error != nil { err := requestResult.Error return buff, err } else { //normal our request forming buff.Request.Query.Result = *requestResult.Commands if requestResult.Type != "" { buff.Request.Type = requestResult.Type } } } else { err := errors.New("Команда не поддерживается.") return buff, err } return buff, nil }
func send_key(key string, userData *s.InUserData) string { out := s.InPkg{UserData: userData, Message: &s.InMessage{Type: "chat", ID: utils.GenStringId(), Thread: utils.GenStringId(), Body: &key}, From: userData.Name} in, err := test.POST(address, &out) if err != nil { log.Printf("Error: %v", err) return "" } return strings.TrimSpace(in.Message.Body) }
func notify_cancel_order(taxiContext *TaxiContext, botContext *m.BotContext, db_order *d.OrderWrapper) { taxiContext.Notifier.Notify(s.OutPkg{ To: db_order.Whom, Message: &s.OutMessage{ ID: u.GenStringId(), Type: "chat", Body: "Ваш заказ отменен!", Commands: botContext.Commands["commands_at_not_created_order"], }, }) }
func sendNewOrder(from, to string) { street_from := get_street(from, "street_from") house_from := s.InField{Data: s.InFieldData{Value: "1"}, Type: "text", Name: "house_from"} street_to := get_street(to, "street_to") house_to := s.InField{Data: s.InFieldData{Value: "1"}, Type: "text", Name: "house_from"} entrance := s.InField{Type: "number", Name: "entrance"} form := s.InForm{Fields: []s.InField{street_from, street_to, house_from, house_to, entrance}} command := s.InCommand{Action: "new_order", Form: form} out := s.InPkg{ UserData: &userData, Message: &s.InMessage{Type: "chat", ID: utils.GenStringId(), Thread: utils.GenStringId(), Commands: &[]s.InCommand{command}}, From: userData.Name, } in, err := test.POST(address, &out) log.Printf("RESULT: %s\nerr?:%v", in.Message.Body, err) }
func FormNotification(context *TaxiContext, ow *d.OrderWrapper, previous_state int, car_info CarInfo, deliv_time time.Time) *s.OutPkg { var text string switch ow.OrderState { case ORDER_ASSIGNED: if previous_state != ORDER_ASSIGNED { text = fmt.Sprintf("%v %v, время подачи %v.", nominated, car_info, deliv_time.Format("15:04")) } case ORDER_CAR_SET_OUT: if previous_state != ORDER_CAR_SET_OUT { if previous_state != ORDER_ASSIGNED { text = fmt.Sprintf("%v %v. %v, время подачи %v", nominated, car_info, car_set_out, deliv_time.Format("15:04")) } else { text = fmt.Sprintf("%v, время подачи %v", car_set_out, deliv_time.Format("15:04")) } } case ORDER_CLIENT_WAIT: if previous_state == ORDER_CREATED { text = fmt.Sprintf("%v %v %v %v.", car_arrived, good_passage, nominated, car_info) } else { text = fmt.Sprintf("%v %v", car_arrived, good_passage) } case ORDER_IN_PROCESS: if u.In(previous_state, []int{ORDER_CLIENT_WAIT, ORDER_DOWNTIME}) { return nil } else if previous_state == ORDER_CREATED { text = fmt.Sprintf("%v %v %v %v.", car_arrived, good_passage, nominated, car_info) } else { text = fmt.Sprintf("%v %v", car_arrived, good_passage) } case ORDER_PAYED: text = order_end context.DataBase.Orders.SetActive(ow.OrderId, ow.Source, false) case ORDER_CANCELED: if !u.In(previous_state, []int{ORDER_PAYED, ORDER_NOT_PAYED}) { text = order_end } else { text = order_canceled } context.DataBase.Orders.SetActive(ow.OrderId, ow.Source, false) } if text != "" { out := s.OutPkg{To: ow.Whom, Message: &s.OutMessage{ID: u.GenStringId(), Type: "chat", Body: text}} return &out } return nil }
func process_message(commandProcessor s.MessageCommandProcessor, buff *s.OutPkg, in *s.InPkg) (*s.OutPkg, bool, error) { messageResult := commandProcessor.ProcessMessage(in) buff.Message = &s.OutMessage{ Thread: in.Message.Thread, ID: u.GenStringId(), Type: "chat", } if messageResult.Type != "" { buff.Message.Type = messageResult.Type } buff.Message.Body = messageResult.Body buff.Message.Commands = messageResult.Commands log.Printf("message result\ntype: %+v \nbody:%+v\ncommands:%+v\ndeffered?: %+v", messageResult.Type, buff.Message.Body, buff.Message.Commands, messageResult.IsDeferred) return buff, messageResult.IsDeferred, messageResult.Error }
func FormBotController(context *BotContext, db *db.MainDb) controllerHandler { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "I can not work with non POST methods", 405) return } log.Printf("have requests %+v", r) out := &s.OutPkg{} var in *s.InPkg var isError, isDeferred bool var global_error, request_error, message_error error check := context.Check if check != nil { if detail, ok := check(); !ok { out.Message = &s.OutMessage{Type: "chat", Thread: "0", ID: u.GenStringId(), Body: fmt.Sprintln(detail)} PutOutPackage(w, out, true, false) return } } in, global_error = FormInPackage(r) if in != nil { out.To = in.From if in.Request != nil { out, request_error = process_request_pkg(out, in, context) } if in.Message != nil { storedMessage, _ := db.Messages.GetMessageByMessageId(in.Message.ID) log.Printf("BOT in message id %v", in.Message.ID) if storedMessage != nil { log.Printf("BOT: Have duplicate message. Will be quiet ignoring it...") return } if in.Message.Error != nil { if val, ok := ERRORS_MAP[in.Message.Error.Condition]; ok { _, err_type := val() log.Printf("BOT: Here is error %v %v. For message id %v", in.Message.Error.Code, err_type, in.Message.ID) db.Messages.UpdateMessageStatus(in.Message.ID, err_type, in.Message.Error.Condition) } else { log.Printf("BOT: Error not in my errors map %v", in.Message.Error.Condition) db.Messages.UpdateMessageStatus(in.Message.ID, in.Message.Error.Type, in.Message.Error.Condition) } return } if in.Message.Commands == nil { if non_commands_processor, ok := context.MessageProcessors[""]; ok { out, isDeferred, message_error = process_message(non_commands_processor, out, in) } else { log.Printf("warn will sended message without commands: %+v\n from %v (userdata: %+v)", in.Message, in.From, in.UserData) } } else { out, isDeferred, message_error = process_message_pkg(out, in, context) } } if in.Message == nil && in.Request == nil { global_error = errors.New("Ничего не понятно!") } } if DEBUG { log.Printf("package processed!\nrequest:%+v\nmessage:%+v\nmessage\nrequest_error: %+v, message error: %+v", out.Request, out.Message, request_error, message_error) } if message_error != nil { out = &s.OutPkg{} out.Message = &s.OutMessage{Type: "error", Thread: "0", ID: u.GenStringId(), Body: fmt.Sprintf("%+v", message_error)} isError = true } else if global_error != nil { out = &s.OutPkg{} out.Message = &s.OutMessage{Type: "error", Thread: "0", ID: u.GenStringId(), Body: fmt.Sprintf("%+v", global_error)} isError = true } else if request_error != nil { out = &s.OutPkg{} out.Request = &s.OutRequest{Type: "error", ID: u.GenStringId()} out.Request.Query.Text = fmt.Sprintf("%+v", request_error) isError = true } PutOutPackage(w, out, isError, isDeferred) } }
func TestTaxiInfinityFail(t *testing.T) { conf := c.ReadTestConfigInRecursive() db := d.NewMainDb(conf.Main.Database.ConnString, conf.Main.Database.Name) taxi_conf := conf.Taxis["fake"] t.Logf("taxi api configuration for %+v:\n%v", taxi_conf.Name, taxi_conf.Api) external := i.GetTestInfAPI(taxi_conf.Api) external_api := external.(taxi.TaxiInterface) external_address_supplier := external.(taxi.AddressSupplier) apiMixin := taxi.ExternalApiMixin{API: external_api} carsCache := taxi.NewCarsCache(external_api) notifier := n.NewNotifier(conf.Main.CallbackAddr, taxi_conf.Chat.Key, db) address_handler, address_supplier := GetAddressInstruments(conf, taxi_conf.Name, external_address_supplier) configStore := d.NewConfigurationStorage(conf.Main.ConfigDatabase) botContext := taxi.FormTaxiBotContext(&apiMixin, db, configStore, taxi_conf, address_handler, carsCache) controller := m.FormBotController(botContext, db) t.Logf("Was create bot context: %+v\n", botContext) http.HandleFunc(fmt.Sprintf("/taxi/%v", taxi_conf.Name), controller) go func() { taxiContext := taxi.TaxiContext{API: external_api, DataBase: db, Cars: carsCache, Notifier: notifier} t.Logf("Will start order watcher for [%v]", botContext.Name) taxi.TaxiOrderWatch(&taxiContext, botContext) }() http.HandleFunc(fmt.Sprintf("/taxi/%v/streets", taxi_conf.Name), func(w http.ResponseWriter, r *http.Request) { geo.StreetsSearchController(w, r, address_supplier) }) go func() { server_address := fmt.Sprintf(":%v", conf.Main.Port) t.Logf("\nStart listen and serving at: %v\n", server_address) server := &http.Server{ Addr: server_address, } server.ListenAndServe() }() u.After(external_api.IsConnected, func() { inf_api := external.(*i.InfinityAPI) for i, _ := range inf_api.ConnStrings { inf_api.ConnStrings[i] += "w" } }) _, err := u.GET(taxi_conf.DictUrl, &map[string]string{"q": "лесос"}) if err != nil { t.Error("Error at getting street %v", err) } out_res, err := tu.POST(fmt.Sprintf("http://localhost:%v/taxi/%v", conf.Main.Port, taxi_conf.Name), &structs.InPkg{ Message: &structs.InMessage{ ID: u.GenStringId(), Commands: &[]structs.InCommand{ structs.InCommand{Action: "information", Title: "information"}, }, }, From: "test user", UserData: &structs.InUserData{Name: "TEST"}, }) if err != nil { t.Errorf("Error at unmarshal result info %v", err) } if out_res == nil { t.Error("Out info result is nil!") } else { if out_res.Message.Type != "chat" { t.Errorf("Out message type != chat, but == %v", out_res.Message.Type) } ch, _ := configStore.GetChatConfig(taxi_conf.Chat.CompanyId) if out_res.Message.Body != ch.Information { t.Errorf("Out message body != info in config, but == %v", out_res.Message.Body) } } }
func (n *Notifier) NotifyTextToMembers(text string) (*s.OutPkg, *db.MessageWrapper, error) { result := s.OutPkg{Message: &s.OutMessage{ID: utils.GenStringId(), Type: "chat", Body: text}} message, err := n.Notify(result) return &result, message, err }
func (n *Notifier) NotifyTextWithCommands(to, text string, commands *[]s.OutCommand) (*s.OutPkg, *db.MessageWrapper, error) { result := s.OutPkg{To: to, Message: &s.OutMessage{ID: utils.GenStringId(), Type: "chat", Body: text, Commands: commands}} message, err := n.Notify(result) return &result, message, err }