func WatchNotAnsweredMessages(mainStore *db.MainDb, configStorage *db.ConfigurationStorage, ntfAddress string) {
	for {
		configs, err := configStorage.GetAllChatsConfig()
		//log.Printf("WNAM found %v configs", len(configs))
		if err != nil {
			log.Printf("WNAM ERROR when get chat config %v", err)
			time.Sleep(10 * time.Second)
			continue
		}
		for _, config := range configs {
			notifier := n.NewNotifier(ntfAddress, config.Key, mainStore)
			for _, autoAnswerCfg := range config.AutoAnswers {
				if autoAnswerCfg.After != 0 {
					messages, err := mainStore.Messages.GetMessagesForAutoAnswer(config.CompanyId, autoAnswerCfg.After)
					if err != nil {
						log.Printf("CW ERROR AT REtrieving messages %v", err)
						continue
					}
					froms := map[string]bool{}
					for _, message := range messages {
						if _, ok := froms[message.From]; !ok {
							notifier.NotifyText(message.From, autoAnswerCfg.Text)
							mainStore.Messages.SetMessagesAutoAnswered(message.From, config.CompanyId, autoAnswerCfg.After)
							froms[message.From] = true
						}
					}
				}
			}
		}

		time.Sleep(10 * time.Second)
	}
}
示例#2
0
func FormQuestBotContext(conf c.Configuration, qConf c.QuestConfig, qs *QuestStorage, db *db.MainDb, cs *db.ConfigurationStorage) *m.BotContext {
	result := m.BotContext{}
	commandsGenerator := func(in *s.InPkg) (*[]s.OutCommand, error) {
		commands := getCommands(qConf.QuestTimes)
		return commands, nil
	}

	result.RequestProcessors = map[string]s.RequestCommandProcessor{
		"commands":&QuestCommandRequestProcessor{Storage:qs, Config:qConf},
	}

	result.MessageProcessors = map[string]s.MessageCommandProcessor{
		"information":m.NewUpdatableInformationProcessor(cs, commandsGenerator, qConf.Chat.CompanyId),
		"enroll": &QuestEnrollProcessor{Store:qs, Config:qConf},
		"":QuestMessageProcessor{Storage:qs, Config:qConf},
	}

	notifier := n.NewNotifier(conf.Main.CallbackAddr, qConf.Chat.Key, db)
	additionalNotifier := n.NewNotifier(conf.Main.CallbackAddr, qConf.AdditionalKey, db)
	go Run(qConf, qs, notifier, additionalNotifier)

	return &result
}
示例#3
0
func StartBot(db *d.MainDb, result chan string) c.Configuration {
	conf := c.ReadConfig()
	log.Printf("configuration for db:\nconnection string: %+v\ndatabase name: %+v", conf.Main.Database.ConnString, conf.Main.Database.Name)
	log.Printf("configuration for conf db:\nconnection string: %+v\ndatabase name: %+v", conf.Main.ConfigDatabase.ConnString, conf.Main.ConfigDatabase.Name)
	db.Users.AddOrUpdateUserObject(d.UserData{
		UserId:    "alesha",
		UserName:  "******",
		Password:  utils.PHash("sederfes100500"),
		Role:      users.MANAGER,
		BelongsTo: "klichat",
	})
	configStorage := d.NewConfigurationStorage(conf.Main.ConfigDatabase)
	questStorage := q.NewQuestStorage(conf.Main.Database.ConnString, conf.Main.Database.Name)

	fs := http.FileServer(http.Dir("static"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	for taxi_name, taxi_conf := range conf.Taxis {
		log.Printf("taxi api configuration for %+v:\n%v", taxi_conf.Name, taxi_conf.Api)
		external_api, external_address_supplier, err := GetTaxiAPIInstruments(taxi_conf.Api, taxi_name)

		if err != nil {
			log.Printf("Skip this taxi api [%+v]\nBecause: %v", taxi_conf.Api, err)
			continue
		}

		apiMixin := t.ExternalApiMixin{API: external_api}

		carsCache := t.NewCarsCache(external_api)
		notifier := n.NewNotifier(conf.Main.CallbackAddr, taxi_conf.Chat.Key, db)

		address_handler, address_supplier := GetAddressInstruments(conf, taxi_name, external_address_supplier)

		botContext := t.FormTaxiBotContext(&apiMixin, db, configStorage, taxi_conf, address_handler, carsCache)
		controller := m.FormBotController(botContext, db)

		log.Printf("Was create bot context: %+v\n", botContext)
		http.HandleFunc(fmt.Sprintf("/taxi/%v", taxi_conf.Name), controller)

		go func() {
			api, err := GetTaxiAPI(taxi_conf.Api, taxi_name+"_watch")
			if err != nil {
				log.Printf("Error at get api: %v for %v, will not use order watching", err, taxi_name)
			}
			cc := t.NewCarsCache(api)
			taxiContext := t.TaxiContext{API: api, DataBase: db, Cars: cc, Notifier: notifier}
			log.Printf("Will start order watcher for [%v]", botContext.Name)
			t.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)
		})
		if m.TEST {
			http.HandleFunc(fmt.Sprintf("/taxi/%v/streets/ext", taxi_conf.Name), func(w http.ResponseWriter, r *http.Request) {
				geo.StreetsSearchController(w, r, external_address_supplier)
			})
		}

		configStorage.SetChatConfig(taxi_conf.Chat, false)

		result <- fmt.Sprintf("taxi_%v", taxi_name)
	}

	for _, shop_conf := range conf.Shops {
		bot_context := sh.FormShopCommands(db, &shop_conf)
		shop_controller := m.FormBotController(bot_context, db)
		http.HandleFunc(fmt.Sprintf("/shop/%v", shop_conf.Name), shop_controller)
		result <- fmt.Sprintf("shops_%v", shop_conf.Name)
	}

	if conf.RuPost.WorkUrl != "" {
		log.Printf("will start ru post controller at: %v and will send requests to: %v", conf.RuPost.WorkUrl, conf.RuPost.ExternalUrl)
		rp_bot_context := rp.FormRPBotContext(conf)
		rp_controller := m.FormBotController(rp_bot_context, db)
		http.HandleFunc(conf.RuPost.WorkUrl, rp_controller)
		result <- "rupost"
	}

	for _, qConf := range conf.Quests {
		q_name := qConf.Chat.CompanyId
		log.Printf("Will handling quests controller for quest: %v", q_name)
		qb_controller := q.FormQuestBotContext(conf, qConf, questStorage, db, configStorage)
		q_controller := m.FormBotController(qb_controller, db)
		route := fmt.Sprintf("/quest/%v", q_name)
		log.Printf("Quest %v will handle at %v", q_name, route)
		http.HandleFunc(route, q_controller)

		configStorage.SetChatConfig(qConf.Chat, false)
		questStorage.SetMessageConfiguration(q.QuestMessageConfiguration{CompanyId: qConf.Chat.CompanyId}, false)

		result <- fmt.Sprintf("quest_%v", q_name)
	}
	if conf.Console.WebPort != "" && conf.Console.Chat.Key != "" {
		log.Printf("Will handling requests from /console at %v", conf.Console.WebPort)
		bc := cnsl.FormConsoleBotContext(conf, db, configStorage)
		cc := m.FormBotController(bc, db)
		http.HandleFunc("/console", cc)

		web.DefaultUrlMap.AddAccessory("klichat", "/klichat")

		configStorage.SetChatConfig(conf.Console.Chat, false)

		result <- "console"
	}

	if conf.Vote.DictUrl != "" {
		vdh, _ := v.NewVotingHandler(conf.Main.Database.ConnString, conf.Main.Database.Name)
		http.HandleFunc("/autocomplete/vote/name", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "name", []string{})
		})
		http.HandleFunc("/autocomplete/vote/city", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "city", conf.Vote.Cities)
		})
		http.HandleFunc("/autocomplete/vote/service", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "service", conf.Vote.Services)
		})
		http.HandleFunc("/autocomplete/vote/role", func(w http.ResponseWriter, r *http.Request) {
			v.AutocompleteController(w, r, vdh, "vote.voters.role", conf.Vote.Roles)
		})

		voteBot := v.FormVoteBotContext(conf, db)
		voteBotController := m.FormBotController(voteBot, db)
		log.Printf("Will handling requests for /vote")
		http.HandleFunc("/vote", voteBotController)
		result <- "vote"
	}

	if len(conf.Coffee) > 0 {
		for _, coffee_conf := range conf.Coffee {
			c_store := coffee.NewCoffeeConfigHandler(db)
			c_store.LoadFromConfig(coffee_conf)
			coffeeHouseConfiguration := coffee.NewCHCFromConfig(coffee_conf)

			cbc := coffee.FormBotCoffeeContext(coffee_conf, db, coffeeHouseConfiguration, configStorage)
			cntrl := m.FormBotController(cbc, db)
			route := fmt.Sprintf("/bot/coffee/%v", coffee_conf.Chat.CompanyId)
			http.HandleFunc(route, cntrl)
			log.Printf("will handling bot messages for coffee %v at %v", coffee_conf.Chat.CompanyId, route)

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/drink", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "drinks", coffee_conf.Chat.CompanyId)
			})

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/volume", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "volumes", coffee_conf.Chat.CompanyId)
			})

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/bake", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "bakes", coffee_conf.Chat.CompanyId)
			})

			http.HandleFunc(fmt.Sprintf("/autocomplete/coffee/%v/additive", coffee_conf.Chat.CompanyId), func(w http.ResponseWriter, r *http.Request) {
				coffee.AutocompleteController(w, r, c_store, "additives", coffee_conf.Chat.CompanyId)
			})
			var salt string
			if coffee_conf.Chat.UrlSalt != "" {
				salt = fmt.Sprintf("%v-%v", coffee_conf.Chat.CompanyId, coffee_conf.Chat.UrlSalt)
			} else {
				salt = coffee_conf.Chat.CompanyId
			}

			notifier := n.NewNotifier(conf.Main.CallbackAddr, coffee_conf.Chat.Key, db)
			notifier.SetFrom(coffee_conf.Chat.CompanyId)

			webRoute := fmt.Sprintf("/web/coffee/%v", salt)
			http.Handle(webRoute, coffee.GetChatMainHandler(webRoute, notifier, db, coffee_conf.Chat))
			web.DefaultUrlMap.AddAccessory(coffee_conf.Chat.CompanyId, webRoute)

			sr := func(s string) string {
				return fmt.Sprintf("%v%v", webRoute, s)
			}
			http.Handle(sr("/send"), chat.GetChatSendHandler(sr("/send"), notifier, db, coffee_conf.Chat, chat.NewChatStorage(db)))
			http.Handle(sr("/unread_messages"), chat.GetChatUnreadMessagesHandler(sr("/unread_messages"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/messages_read"), chat.GetChatMessageReadHandler(sr("/messages_read"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/contacts_change"), chat.GetChatContactsChangeHandler(sr("/contacts_change"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/delete_messages"), chat.GetChatDeleteMessagesHandler(sr("/delete_messages"), db, coffee_conf.Chat))

			http.Handle(sr("/config"), coffee.GetChatConfigHandler(sr("/config"), webRoute, db, coffee_conf.Chat))
			http.Handle(sr("/contacts"), coffee.GetChatContactsHandler(sr("/contacts"), notifier, db, coffee_conf.Chat))
			http.Handle(sr("/message_function"), coffee.GetMessageAdditionalFunctionsHandler(sr("/message_function"), notifier, db, coffee_conf.Chat, coffeeHouseConfiguration))
			//http.Handle(sr("/order_page"), coffee.GetOrdersPageFunctionHandler(sr("/order_page"), webRoute, db, coffee_conf.Chat, coffee_conf.Chat.CompanyId))
			//http.Handle(sr("/order_page_supply"), coffee.GetOrdersPageSupplierFunctionHandler(sr("/order_page_supply"), webRoute, db, coffee_conf.Chat, coffee_conf.Chat.CompanyId))
			http.Handle(sr("/logout"), coffee.GetChatLogoutHandler(sr("/logout"), webRoute, db, coffee_conf.Chat))

			log.Printf("I will handling web requests for coffee %v at : [%v]", coffee_conf.Chat.CompanyId, webRoute)
			db.Users.AddOrUpdateUserObject(d.UserData{
				UserId:      coffee_conf.Chat.User,
				UserName:    coffee_conf.Chat.User,
				ShowedName:  coffee_conf.Chat.Name,
				Password:    utils.PHash(coffee_conf.Chat.Password),
				BelongsTo:   coffee_conf.Chat.CompanyId,
				ReadRights:  []string{coffee_conf.Chat.CompanyId},
				WriteRights: []string{coffee_conf.Chat.CompanyId},
			})

			configStorage.SetChatConfig(coffee_conf.Chat, false)
		}
		result <- "coffee"
	}
	if len(conf.Chats) > 0 {
		for _, chat_conf := range conf.Chats {

			chatBotContext := chat.FormChatBotContext(db, configStorage, chat_conf.CompanyId)
			chatBotController := m.FormBotController(chatBotContext, db)
			route := fmt.Sprintf("/bot/chat/%v", chat_conf.CompanyId)
			http.HandleFunc(route, chatBotController)
			log.Printf("I will serving message for chat bot at : [%v]", route)

			notifier := n.NewNotifier(conf.Main.CallbackAddr, chat_conf.Key, db)
			notifier.SetFrom(chat_conf.CompanyId)

			var salt string
			if chat_conf.UrlSalt != "" {
				salt = fmt.Sprintf("%v-%v", chat_conf.CompanyId, chat_conf.UrlSalt)
			} else {
				salt = chat_conf.CompanyId
			}
			webRoute := fmt.Sprintf("/web/chat/%v", salt)
			http.Handle(webRoute, chat.GetChatMainHandler(webRoute, notifier, db, chat_conf))
			web.DefaultUrlMap.AddAccessory(chat_conf.CompanyId, webRoute)

			sr := func(s string) string {
				return fmt.Sprintf("%v%v", webRoute, s)
			}
			http.Handle(sr("/send"), chat.GetChatSendHandler(sr("/send"), notifier, db, chat_conf, chat.NewChatStorage(db)))
			http.Handle(sr("/unread_messages"), chat.GetChatUnreadMessagesHandler(sr("/unread_messages"), notifier, db, chat_conf))
			http.Handle(sr("/messages_read"), chat.GetChatMessageReadHandler(sr("/messages_read"), notifier, db, chat_conf))
			http.Handle(sr("/contacts"), chat.GetChatContactsHandler(sr("/contacts"), notifier, db, chat_conf))
			http.Handle(sr("/contacts_change"), chat.GetChatContactsChangeHandler(sr("/contacts_change"), notifier, db, chat_conf))
			http.Handle(sr("/config"), chat.GetChatConfigHandler(sr("/config"), webRoute, db, chat_conf))
			http.Handle(sr("/delete_messages"), chat.GetChatDeleteMessagesHandler(sr("/delete_messages"), db, chat_conf))
			http.Handle(sr("/logout"), chat.GetChatLogoutHandler(sr("/logout"), webRoute, db, chat_conf))

			log.Printf("I will handling web requests for chat at : [%v]", webRoute)

			db.Users.AddOrUpdateUserObject(d.UserData{
				UserName:    chat_conf.User,
				Password:    utils.PHash(chat_conf.Password),
				UserId:      chat_conf.User,
				BelongsTo:   chat_conf.CompanyId,
				ReadRights:  []string{chat_conf.CompanyId},
				WriteRights: []string{chat_conf.CompanyId},
			})

			configStorage.SetChatConfig(chat_conf, false)
		}
		result <- "chat"
	}

	go n.WatchUnreadMessages(db, configStorage, conf.Main.CallbackAddrMembers)
	go autoanswers.WatchNotAnsweredMessages(db, configStorage, conf.Main.CallbackAddr)

	server_address := fmt.Sprintf(":%v", conf.Main.Port)
	log.Printf("\nStart listen and serving at: %v\n", server_address)
	server := &http.Server{
		Addr: server_address,
	}
	result <- "listen"
	http.Handle("/", web.NewSessionAuthorisationHandler(db))
	log.Fatal(server.ListenAndServe())
	return conf
}
func main() {
	msngr.TEST = true
	msngr.DEBUG = true

	cnf := configuration.ReadConfig()
	cnf.SetLogFile("test.log")
	error_chan := make(chan structs.MessageError, 10)
	ha := tstu.HandleAddress("/notify", ":9876", error_chan)
	for {
		res := <-ha
		log.Printf("HANDLE ADDR %v", res)
		if res == "listen" {
			break
		}
	}

	main_db := db.NewMainDb(cnf.Main.Database.ConnString, cnf.Main.Database.Name)
	//start_bot_result := make(chan string, 100)
	//go i.StartBot(main_db, start_bot_result)
	//for {
	//	res := <-start_bot_result
	//	log.Printf("BOT ENGINE: %v", res)
	//	if res == "listen" {
	//		break
	//	}
	//
	//}
	merror := structs.MessageError{
		Code:      500,
		Type:      "wait",
		Condition: "resource-constraint",
	}
	error_chan <- merror
	ntfr := ntf.NewNotifier(cnf.Main.CallbackAddr, "test_key", main_db)
	out_pkg, err := ntfr.NotifyText("TEST", "TEST MESSAGE")
	log.Printf("> NTF OUT IS: %v,\n err: %v", out_pkg, err)
	result, err := tstu.POST(address, &structs.InPkg{
		Message: &structs.InMessage{
			ID:    out_pkg.Message.ID,
			Error: &merror,
			Body:  &out_pkg.Message.Body,
		},
		From:     out_pkg.To,
		UserData: &structs.InUserData{Name: "TEST"},
	})
	log.Printf("ANSWER must be empty %v, %v", result, err)
	mess := "hui"
	merror.Code = 404
	result, err = tstu.POST(address, &structs.InPkg{
		Message: &structs.InMessage{
			ID:    mess,
			Error: &merror,
			Body:  &mess,
		},
		From:     out_pkg.To,
		UserData: &structs.InUserData{Name: "TEST"},
	})
	log.Printf("ANSWER must be empty %v %v", result, err)

	//result_outs := []*structs.OutPkg{}
	//for _, i := range []int{1, 2, 3, 4, 5, 6, 7} {
	//	out, err := ntfr.NotifyText("TEST", fmt.Sprintf("NOTIFY TST MESSSAGE %v", i))
	//	if out != nil {
	//		result_outs = append(result_outs, out)
	//		mw, err := main_db.Messages.GetMessageByMessageId(out.Message.ID)
	//		log.Printf("ASSERT sended status notify message? %v Err? %v", mw.MessageStatus, err)
	//	}else {
	//		log.Printf("WARN sended status notify message? %+v Err? %v", out, err)
	//	}
	//
	//}
	//
	//for _, out := range result_outs {
	//	if out.Message != nil {
	//		in := &structs.InPkg{
	//			Message:&structs.InMessage{
	//				Body:&out.Message.Body,
	//				Type:"error",
	//				Error:&out.Message.Error,
	//			},
	//			From:out.To,
	//			UserData:&structs.InUserData{Name:"TEST"},
	//		}
	//		log.Printf("TST_ERR_MESS send: \n\t%+v", in)
	//		out_echo, err := tstu.POST(address, in)
	//		log.Printf("ASSERT out_echo nil? %v and err:%v", out_echo == nil, err)
	//	}
	//	mw, err := main_db.Messages.GetMessageByMessageId(out.Message.ID)
	//	log.Printf("ASSERT err? %v we have this message? %v They have similar errors?: %v\n...message:\n%+v", err == nil, mw != nil, mw.MessageStatus == "error", mw.MessageCondition == out.Message.Error.Condition, )
	//
	//}
}
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)
		}
	}

}