/// <summary>
        /// Initializes a new instance of the <see cref="JuanCarlosBot"/> class.
        /// </summary>
        /// <param name="services">Services configured from the ".bot" file.</param>
        /// <param name="statePropertyAccessor"> Bot state accessor object.</param>
        /// <param name="promptBotAccessors"> Prompt state accessor object.</param>
        public JuanCarlosBot(BotServices services, WelcomeUserStateAccessors statePropertyAccessor, CustomPromptBotAccessors promptBotAccessors)
        {
            _services = services ?? throw new System.ArgumentNullException(nameof(services));

            if (!_services.QnAServices.ContainsKey(QnAMakerKey))
            {
                throw new System.ArgumentException($"Invalid configuration. Please check your '.bot' file for a QnA service named '{DispatchKey}'.");
            }

            if (!_services.LuisServices.ContainsKey(CampusDispatchKey))
            {
                throw new System.ArgumentException($"Invalid configuration. Please check your '.bot' file for a Luis service named '{CampusDispatchKey}'.");
            }

            _welcomeUserStateAccessors = statePropertyAccessor ?? throw new System.ArgumentNullException("state accessor can't be null");
            _promptAccessors           = promptBotAccessors ?? throw new System.ArgumentNullException(nameof(_promptAccessors));

            //// Create the dialog set and add the prompts, including custom validation.
            //_dialogSet = new DialogSet(_welcomeUserStateAccessors.DialogStateAccessor);
            //_dialogSet.Add(new NumberPrompt<int>(PartySizePrompt, PartySizeValidatorAsync));
            //_dialogSet.Add(new ChoicePrompt(LocationPrompt));
            //_dialogSet.Add(new DateTimePrompt(ReservationDatePrompt, DateValidatorAsync));

            //// Define the steps of the waterfall dialog and add it to the set.
            //WaterfallStep[] steps = new WaterfallStep[]
            //{
            //    PromptForPartySizeAsync,
            //    //PromptForLocationAsync,
            //    //PromptForReservationDateAsync,
            //    //AcknowledgeReservationAsync,
            //};
            //_dialogSet.Add(new WaterfallDialog(ReservationDialog, steps));
        }
Exemple #2
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">Specifies the contract for a collection of service descriptors.</param>
        /// <seealso cref="IServiceCollection"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection"/>
        public void ConfigureServices(IServiceCollection services)
        {
            //var secretKey = Configuration.GetSection("botFileSecret")?.Value;
            //var botFilePath = Configuration.GetSection("botFilePath")?.Value;
            //if (!File.Exists(botFilePath))
            //{
            //    throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}");
            //}

            var botFilePath = @"appsettings.json";

            // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
            var botConfig = BotConfiguration.Load(botFilePath ?? @".\nlp-with-dispatch.bot", string.Empty);

            services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}"));

            // Retrieve current endpoint.
            var environment = _isProduction ? "production" : "development";
            var service     = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);

            if (!(service is EndpointService endpointService))
            {
                throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
            }

            var connectedServices = InitBotServices(botConfig);

            services.AddSingleton(sp => connectedServices);

            services.AddBot <JuanCarlosBot>(options =>
            {
                var appId                  = Configuration.GetSection("MicrosoftAppId").Value;
                var appPassword            = Configuration.GetSection("MicrosoftAppPassword").Value;
                options.CredentialProvider = new SimpleCredentialProvider(appId, appPassword);
                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

                // Creates a logger for the application to use.
                ILogger logger = _loggerFactory.CreateLogger <JuanCarlosBot>();

                // Catches any errors that occur during a conversation turn and logs them.
                options.OnTurnError = async(context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    //await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };

                // The Memory Storage used here is for local bot debugging only. When the bot
                // is restarted, everything stored in memory will be gone.
                IStorage dataStore = new MemoryStorage();
            });

            // Create conversation and user state with in-memory storage provider.
            IStorage          storage           = new MemoryStorage();
            ConversationState conversationState = new ConversationState(storage);
            UserState         userState         = new UserState(storage);

            // Create and register state accessors.
            // Accessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton <CustomPromptBotAccessors>(sp =>
            {
                // Create the custom state accessor.
                return(new CustomPromptBotAccessors(conversationState, userState)
                {
                    ConversationFlowAccessor = conversationState.CreateProperty <ConversationFlow>(CustomPromptBotAccessors.ConversationFlowName),
                    UserProfileAccessor = userState.CreateProperty <UserProfile>(CustomPromptBotAccessors.UserProfileName),
                });
            });

            // Create and register state accessors.
            // Accessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton <WelcomeUserStateAccessors>(sp =>
            {
                var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors");
                }

                if (conversationState == null)
                {
                    throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
                }

                if (userState == null)
                {
                    throw new InvalidOperationException("UserState must be defined and added before adding user-scoped state accessors.");
                }

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new WelcomeUserStateAccessors(userState, conversationState)
                {
                    WelcomeUserState    = userState.CreateProperty <WelcomeUserState>(WelcomeUserStateAccessors.WelcomeUserName),
                    DialogStateAccessor = conversationState.CreateProperty <DialogState>(DialogPromptBotAccessors.DialogStateAccessorKey),
                    ReservationAccessor = conversationState.CreateProperty <JuanCarlosBot.Reservation>(DialogPromptBotAccessors.ReservationAccessorKey),
                };

                return(accessors);
            });
        }