func FormBotCoffeeContext(config c.CoffeeConfig, store *db.MainDb, coffeeHouseConfiguration *CoffeeHouseConfiguration, configStore *db.ConfigurationStorage) *m.BotContext {
	commandsGenerator := func(in *s.InPkg) (*[]s.OutCommand, error) {
		lastOrder, err := store.Orders.GetByOwnerLast(in.From, config.Chat.CompanyId)
		if err != nil {
			log.Printf("COFFEE BOT error getting last order for %v is: %v", in.From, err)
			return nil, err
		}
		var isFirst, isActive bool
		if lastOrder != nil {
			isFirst = false
			isActive = lastOrder.Active
		}
		commands := getCommands(coffeeHouseConfiguration, isFirst, isActive)
		return commands, nil
	}

	result := m.BotContext{}
	result.RequestProcessors = map[string]s.RequestCommandProcessor{
		"commands": &RequestCommandsProcessor{CommandsFunc: commandsGenerator},
	}
	result.MessageProcessors = map[string]s.MessageCommandProcessor{
		"":            m.NewFuncTextBodyProcessor(store, commandsGenerator, config.Chat.CompanyId, nil),
		"information": m.NewUpdatableInformationProcessor(configStore, commandsGenerator, config.Chat.CompanyId),
		"order_bake":  &OrderBakeProcessor{Storage: store, CompanyName: config.Chat.CompanyId, CommandsFunc: commandsGenerator},
		"order_drink": &OrderDrinkProcessor{Storage: store, CompanyName: config.Chat.CompanyId, CommandsFunc: commandsGenerator},
		"cancel":      &CancelOrderProcessor{Storage: store, CompanyName: config.Chat.CompanyId, CommandsFunc: commandsGenerator},
		"repeat":      &RepeatOrderProcessor{Storage: store, CompanyName: config.Chat.CompanyId, CommandsFunc: commandsGenerator},
	}
	return &result
}
func FormTaxiBotContext(im *ExternalApiMixin, db_handler *d.MainDb, cfgStore *d.ConfigurationStorage, tc c.TaxiConfig, ah AddressHandler, cc *CarsCache) *m.BotContext {
	context := m.BotContext{}
	context.Check = func() (detail string, ok bool) {
		ok = im.API.IsConnected()
		if !ok {
			detail = "Ошибка в подключении к сервису такси. Попробуйте позже."
		} else {
			return "", db_handler.Check()
		}
		return detail, ok
	}
	context.Commands = EnsureAvailableCommands(GetCommands(tc.DictUrl), tc.AvailableCommands)

	context.Name = tc.Name
	context.RequestProcessors = map[string]s.RequestCommandProcessor{
		"commands": &TaxiCommandsProcessor{MainDb: *db_handler, context: &context},
	}

	commandsGenerator := func(in *s.InPkg) (*[]s.OutCommand, error) {
		command, err := form_commands(in.From, *db_handler, &context)
		return command, err
	}

	context.MessageProcessors = map[string]s.MessageCommandProcessor{
		"information":      m.NewUpdatableInformationProcessor(cfgStore, commandsGenerator, tc.Chat.CompanyId),
		"new_order":        &TaxiNewOrderProcessor{ExternalApiMixin: *im, MainDb: *db_handler, context: &context, AddressHandler: ah, Config: tc},
		"cancel_order":     &TaxiCancelOrderProcessor{ExternalApiMixin: *im, MainDb: *db_handler, context: &context, alert_phone: tc.Information.Phone},
		"calculate_price":  &TaxiCalculatePriceProcessor{ExternalApiMixin: *im, context: &context, AddressHandler: ah, Config: tc},
		"feedback":         &TaxiFeedbackProcessor{ExternalApiMixin: *im, MainDb: *db_handler, context: &context},
		"write_dispatcher": &TaxiWriteDispatcherMessageProcessor{ExternalApiMixin: *im, MainDb: *db_handler},
		"callback_request": &TaxiCallbackRequestMessageProcessor{ExternalApiMixin: *im},
		"where_it":         &TaxiWhereItMessageProcessor{ExternalApiMixin: *im, MainDb: *db_handler, context: &context},
		"car_position":     &TaxiCarPositionMessageProcessor{ExternalApiMixin: *im, MainDb: *db_handler, context: &context, Cars: NewCarInfoProvider(cc)},
		"":                 &TaxiWriteDispatcherMessageProcessor{ExternalApiMixin: *im, MainDb: *db_handler},
	}
	context.Settings = make(map[string]interface{})
	context.Settings["not_send_price"] = tc.Api.NotSendPrice
	if tc.Markups != nil {
		context.Settings["markups"] = *tc.Markups
	}
	if tc.Api.Data.RefreshOrdersTimeStep != 0 {
		context.Settings["refresh_orders_time_step"] = time.Duration(tc.Api.Data.RefreshOrdersTimeStep) * time.Second
	} else {
		context.Settings["refresh_orders_time_step"] = 10 * time.Second
	}

	return &context
}
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
}