Example #1
0
        protected override async Task OnTeamsSigninVerifyStateAsync(ITurnContext <IInvokeActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with signin/verifystate from an Invoke Activity.");

            await Dialog.RunAsync(turnContext, ConversationState.CreateProperty <DialogState>(nameof(DialogState)), cancellationToken);
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            // Create the Bot Framework Adapter.
            services.AddSingleton <IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

            // Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
            services.AddTransient <IBot, PictureBot>();

            //init bot
            services.AddBot <PictureBot>(options =>
            {
                //read appsettings.json
                var secretKey   = Configuration.GetSection("MicrosoftAppId")?.Value;
                var botFilePath = Configuration.GetSection("MicrosoftAppPassword")?.Value;

                options.CredentialProvider = new SimpleCredentialProvider(secretKey, botFilePath);
            });


            services.AddSingleton <PictureBotAccessors>(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");
                }

                //read Cosmos DB settings from appsettings.json
                CosmosDbStorage _myStorage = new CosmosDbStorage(new CosmosDbStorageOptions
                {
                    AuthKey          = Configuration.GetSection("CosmosDB").GetValue <string>("Key"),
                    CollectionId     = Configuration.GetSection("CosmosDB").GetValue <string>("CollectionName"),
                    CosmosDBEndpoint = new Uri(Configuration.GetSection("CosmosDB").GetValue <string>("EndpointURI")),
                    DatabaseId       = Configuration.GetSection("CosmosDB").GetValue <string>("DatabaseName"),
                });

                var conversationState = new ConversationState(_myStorage);
                var userState         = new UserState(_myStorage);

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new PictureBotAccessors(conversationState, userState)
                {
                    PictureState        = conversationState.CreateProperty <PictureState>(PictureBotAccessors.PictureStateName),
                    DialogStateAccessor = conversationState.CreateProperty <DialogState>("DialogState"),
                };

                return(accessors);
            });


            // Create and register a LUIS recognizer.
            services.AddSingleton(sp =>
            {
                // Get LUIS information
                var luisApp = new LuisApplication(
                    "XXXX",
                    "XXXX",
                    "https://westus.api.cognitive.microsoft.com/");

                // Specify LUIS options. These may vary for your bot.
                var luisPredictionOptions = new LuisPredictionOptions
                {
                    IncludeAllIntents = true,
                };

                // Create the recognizer
                var recognizer = new LuisRecognizer(luisApp, luisPredictionOptions, true, null);
                return(recognizer);
            });
        }
Example #3
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 <see cref="IServiceCollection"/> of service descriptors.</param>
        public void ConfigureServices(IServiceCollection services)
        {
            var secretKey   = Configuration.GetSection("botFileSecret")?.Value;
            var botFilePath = Configuration.GetSection("botFilePath")?.Value;

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

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

            // Add BotServices singleton.
            // Create the connected services from .bot file.
            services.AddSingleton(sp => new BotServices(botConfig));

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

            // Create and add conversation state.
            var conversationState = new ConversationState(dataStore);

            services.AddSingleton(conversationState);

            // Create and register state accesssors.
            // Acessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton <BotAccessors>(sp =>
            {
                var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new BotAccessors(conversationState)
                {
                    DialogStateAccessor = conversationState.CreateProperty <DialogState>(BotAccessors.DialogStateAccessorName),
                };

                return(accessors);
            });

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

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

            // For production bots use the Azure Blob or
            // Azure CosmosDB storage providers. For the Azure
            // based storage providers, add the Microsoft.Bot.Builder.Azure
            // Nuget package to your solution. That package is found at:
            // https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
            // Un-comment the following lines to use Azure Blob Storage
            // // Storage configuration name or ID from the .bot file.
            // const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>";
            // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
            // if (!(blobConfig is BlobStorageService blobStorageConfig))
            // {
            //    throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'.");
            // }
            // // Default container name.
            // const string DefaultBotContainer = "botstate";
            // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
            // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);

            var userState = new UserState(dataStore);

            services.AddSingleton(userState);

            services.AddBot <BasicBot>(options =>
            {
                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

                // Catches any errors that occur during a conversation turn and logs them to currently
                // configured ILogger.
                ILogger logger      = _loggerFactory.CreateLogger <BasicBot>();
                options.OnTurnError = async(context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };
            });
        }
Example #4
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> specifies the contract for a collection of service descriptors.</param>
        /// <seealso cref="IStatePropertyAccessor{T}"/>
        public void ConfigureServices(IServiceCollection services)
        {
            var secretKey   = Configuration.GetSection("botFileSecret")?.Value;
            var botFilePath = Configuration.GetSection("botFilePath")?.Value;

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

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

            // 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 State object.
            // The Conversation State object is where we persist anything at the conversation-scope.
            var conversationState = new ConversationState(dataStore);

            // Create and register state accesssors.
            // Acessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton <DialogPromptBotAccessors>(sp =>
            {
                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new DialogPromptBotAccessors(conversationState)
                {
                    DialogStateAccessor =
                        conversationState.CreateProperty <DialogState>(
                            DialogPromptBotAccessors.DialogStateAccessorKey),
                    ReservationAccessor =
                        conversationState.CreateProperty <DialogPromptBot.Reservation>(
                            DialogPromptBotAccessors.ReservationAccessorKey),
                };

                return(accessors);
            });

            services.AddBot <DialogPromptBot>(options =>
            {
                // Retrieve current endpoint.
                var environment = _isProduction ? "production" : "development";
                var service     = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault();
                if (!(service is EndpointService endpointService))
                {
                    throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
                }

                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);

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

                // 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.");
                };
            });
        }
Example #5
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 <see cref="IServiceCollection"/> of service descriptors.</param>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/azure/bot-service/bot-service-manage-channels?view=azure-bot-service-4.0"/>
        public void ConfigureServices(IServiceCollection services)
        {
            // Memory Storage is for local bot debugging only. When the bot
            // is restarted, everything stored in memory will be gone.
            IStorage dataStore         = new MemoryStorage();
            var      conversationState = new ConversationState(dataStore);
            var      userState2        = new UserState(dataStore);

            // For production bots use the Azure Blob or
            // Azure CosmosDB storage providers. For the Azure
            // based storage providers, add the Microsoft.Bot.Builder.Azure
            // Nuget package to your solution. That package is found at:
            // https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
            // Un-comment the following lines to use Azure Blob Storage
            // // Storage configuration name or ID from the .bot file.
            // const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>";
            // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
            // if (!(blobConfig is BlobStorageService blobStorageConfig))
            // {
            //    throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'.");
            // }
            // // Default container name.
            // const string DefaultBotContainer = "<DEFAULT-CONTAINER>";
            // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
            // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);
            // Create and add conversation state.
            //var conversationState = new ConversationState(dataStore);
            //services.AddSingleton(conversationState);
            // The dialogset will need a state store accessor. Since the state accessor is only going to be used by the FoodBotDialogSet, use 
            // AddSingleton to register and inline create the FoodBotDialogSet, at the same time creating the the property accessor in the
            // conversation state
            //services.AddSingleton(sp => new EchoBotDialogSet(conversationState.CreateProperty<DialogState>("ECHOBOTDIALOGSTATE")));
            services.AddBot <WelcomeUserBot>(options =>
            {
                var appId                  = Configuration.GetSection("MicrosoftAppId").Value;
                var appPassword            = Configuration.GetSection("MicrosoftAppPassword").Value;
                options.CredentialProvider = new SimpleCredentialProvider(appId, appPassword);
                // Catches any errors that occur during a conversation turn and logs them to currently
                // configured ILogger.
                ILogger logger      = _loggerFactory.CreateLogger <WelcomeUserBot>();
                options.OnTurnError = async(context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };
                // IStorage dataStore2 = new MemoryStorage();
                // var userState = new UserState(dataStore2);
                options.State.Add(userState2);
            });
            // 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");
                }
                var userState = options.State.OfType <UserState>().FirstOrDefault();
                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),
                };
                return(accessors);
            });

            services.AddSingleton <BotState>(conversationState);
            // The dialogset will need a state store accessor. Since the state accessor is only going to be used by the FoodBotDialogSet, use
            // AddSingleton to register and inline create the FoodBotDialogSet, at the same time creating the the property accessor in the
            // conversation state
            services.AddSingleton(sp => new WelcomeUserBotDialogSet(conversationState.CreateProperty <DialogState>("WELCOMEBOTDIALOGSTATE2")));
            services.AddSingleton <IStatePropertyAccessor <DialogState> >(conversationState.CreateProperty <DialogState>("WELCOMEBOTDIALOGSTATE"));
            services.AddSingleton <WelcomeUserBotDialogSet>();
        }
Example #6
0
        public BookTableDialog(BotServices services, IStatePropertyAccessor <ReservationProperty> reservationsAccessor, IStatePropertyAccessor <OnTurnProperty> onTurnAccessor, IStatePropertyAccessor <UserProfile> userProfileAccessor, ConversationState conversationState)
            : base(Name)
        {
            _services            = services ?? throw new ArgumentNullException(nameof(services));
            ReservationsAccessor = reservationsAccessor ?? throw new ArgumentNullException(nameof(reservationsAccessor));
            OnTurnAccessor       = onTurnAccessor ?? throw new ArgumentNullException(nameof(onTurnAccessor));
            UserProfileAccessor  = userProfileAccessor ?? throw new ArgumentNullException(nameof(userProfileAccessor));

            // Create accessors for child dialogs
            GetLocDialogAccessor  = conversationState.CreateProperty <DialogState>(GetLocationDialogState);
            ConfirmDialogAccessor = conversationState.CreateProperty <DialogState>(ConfirmDialogState);

            // Add dialogs
            // Water fall book table dialog
            var waterfallSteps = new WaterfallStep[]
            {
                GetAllRequiredPropertiesAsync,
                BookTableAsync,
            };

            AddDialog(new WaterfallDialog(BookTableWaterfall, waterfallSteps));

            // Get location, date, time & party size prompt.
            AddDialog(new GetLocationDateTimePartySizePrompt(
                          GetLocationDateTimePartySizePrompt,
                          services,
                          reservationsAccessor,
                          onTurnAccessor,
                          userProfileAccessor,
                          async(promptValidatorContext, cancellationToken) =>
            {
                // Validation and prompting logic.
                // Get reservation property.
                var newReservation = await reservationsAccessor.GetAsync(promptValidatorContext.Context, () => new ReservationProperty());

                // If we have a valid reservation, end this prompt.
                // Otherwise, get LG based on what's available in reservation property
                if (newReservation.HaveCompleteReservation())
                {
                    if (!newReservation.ReservationConfirmed)
                    {
                        if (newReservation.NeedsChange == true)
                        {
                            await promptValidatorContext.Context.SendActivityAsync("What would you like to change ?");
                        }
                        else
                        {
                            // Greet user with name if we have the user profile set.
                            var userProfile = await userProfileAccessor.GetAsync(promptValidatorContext.Context, () => null);

                            if (userProfile != null && !string.IsNullOrWhiteSpace(userProfile.UserName))
                            {
                                await promptValidatorContext.Context.SendActivityAsync($"Alright {userProfile.UserName} I have a table for {newReservation.ConfirmationReadOut()}");
                            }
                            else
                            {
                                await promptValidatorContext.Context.SendActivityAsync($"Ok. I have a table for {newReservation.ConfirmationReadOut()}");
                            }

                            await promptValidatorContext.Context.SendActivityAsync(MessageFactory.SuggestedActions(new List <string> {
                                "Yes", "No"
                            }, "Should I go ahead and book the table?"));
                        }
                    }
                    else
                    {
                        // Have complete reservation.
                        return(true);
                    }
                }
                else
                {
                    // Readout what has been understood already.
                    var groundedPropertiesReadout = newReservation.GetGroundedPropertiesReadOut();
                    if (!string.IsNullOrWhiteSpace(groundedPropertiesReadout))
                    {
                        await promptValidatorContext.Context.SendActivityAsync(groundedPropertiesReadout);
                    }
                }

                // Ask user for missing information
                var prompt = newReservation.GetMissingPropertyReadOut();
                if (!string.IsNullOrWhiteSpace(prompt))
                {
                    await promptValidatorContext.Context.SendActivityAsync(prompt);
                }

                return(false);
            }));

            // This dialog is interruptable. So add interruptionDispatcherDialog.
            AddDialog(new InterruptionDispatcher(onTurnAccessor, conversationState, userProfileAccessor, services));

            // When user decides to abandon this dialog, we need to confirm user action. Add confirmation prompt.
            AddDialog(new ConfirmPrompt(ConfirmCancelPrompt));
        }
Example #7
0
        /**
           * Constructor.
           *
           * @param {BotConfiguration} bot configuration
           * @param {ConversationState} conversationState
           * @param {StatePropertyAccessor} accessor for user profile property
           * @param {StatePropertyAccessor} accessor for on turn property
           * @param {StatePropertyAccessor} accessor for reservation property
           */
        public WhoAreYouDialog(
                        BotServices botServices,
                        ConversationState conversationState,
                        IStatePropertyAccessor<UserProfile> userProfileAccessor,
                        IStatePropertyAccessor<OnTurnProperty> onTurnAccessor,
                        IStatePropertyAccessor<ReservationProperty> reservationAccessor)
        : base(Name)
        {
            if (botServices == null)
            {
                throw new ArgumentNullException(nameof(botServices));
            }

            if (conversationState == null)
            {
                throw new ArgumentNullException(nameof(conversationState));
            }

            UserProfileAccessor = userProfileAccessor ?? throw new ArgumentNullException(nameof(userProfileAccessor));

            // Keep accessors for the steps to consume
            OnTurnAccessor = onTurnAccessor ?? throw new ArgumentNullException(nameof(onTurnAccessor));

            // Add dialogs
            var waterfallSteps = new WaterfallStep[]
            {
                AskForUserNameAsync,
                GreetUserAsync,
            };
            AddDialog(new WaterfallDialog(
               dialogStart,
               waterfallSteps));

            var turnCounterAccessor = conversationState.CreateProperty<CounterState>("turnCounter");

            // Add get user name prompt.
            AddDialog(new GetUserNamePrompt(
                askUserNamePrompt,
                botServices,
                userProfileAccessor,
                conversationState,
                onTurnAccessor,
                turnCounterAccessor,
                async (promptContext, cancellationToken) =>
                {
                    var userProfile = await userProfileAccessor.GetAsync(promptContext.Context);
                    var counter = await turnCounterAccessor.GetAsync(promptContext.Context);

                    // Prompt validator
                    // Examine if we have a user name and validate it.
                    if (userProfile != null && userProfile.UserName != null)
                    {
                        // We can only accept user names that up to two words.
                        if (userProfile.UserName.Split(" ").Length > 2)
                        {
                            await promptContext.Context.SendActivityAsync("Sorry, I can only accept two words for a name.");
                            await promptContext.Context.SendActivityAsync("You can always say 'My name is <your name>' to introduce yourself to me.");
                            await userProfileAccessor.SetAsync(promptContext.Context, new UserProfile("Human"));

                            // Set updated turn counter
                            await turnCounterAccessor.SetAsync(promptContext.Context, counter);
                            return false;
                        }
                        else
                        {
                            // Capitalize user name
                            userProfile.UserName = char.ToUpper(userProfile.UserName[0]) + userProfile.UserName.Substring(1);

                            // Create user profile and set it to state.
                            await userProfileAccessor.SetAsync(promptContext.Context, userProfile);
                            return true;
                        }
                    }

                    return false;
                }));

            // This dialog is interruptable, add interruptionDispatcherDialog
            AddDialog(new InterruptionDispatcher(onTurnAccessor, conversationState, userProfileAccessor, botServices));

            // When user decides to abandon this dialog, we need to confirm user action - add confirmation prompt
            AddDialog(new ConfirmPrompt(confirmCancelPrompt));
        }
Example #8
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> specifies the contract for a collection of service descriptors.</param>
        /// <seealso cref="IStatePropertyAccessor{T}"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection"/>
        /// <seealso cref="https://docs.microsoft.com/en-us/azure/bot-service/bot-service-manage-channels?view=azure-bot-service-4.0"/>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddBot <EchoWithCounterBot>(options =>
            {
                var blobStore            = new AzureBlobTranscriptStore("DefaultEndpointsProtocol=https;AccountName=sq7ofgblobs;AccountKey=2k0LVUrttdcPB50R3DNIgZrB2ff1yapC6Iv0r/SeCKFW4D+bL2ezwy8zO0lCw/Adw2ysPSdsu13OZ07RtXufFw==;EndpointSuffix=core.windows.net", "bot-storage");
                var transcriptMiddleware = new TranscriptLoggerMiddleware(blobStore);
                options.Middleware.Add(transcriptMiddleware);
                // Creates a logger for the application to use.
                ILogger logger = _loggerFactory.CreateLogger <EchoWithCounterBot>();


                //var secretKey = Configuration.GetSection("botFileSecret")?.Value;
                //var botFilePath = Configuration.GetSection("botFilePath")?.Value;
                var secretKey   = "s0/1svAFPxOxUcTfsyoILPUcWLfJlACnsGlkzAotEGw=";
                var botFilePath = "./customerassistant.bot";
                if (!File.Exists(botFilePath))
                {
                    throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}");
                }
                // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
                BotConfiguration botConfig = null;
                try
                {
                    botConfig = BotConfiguration.Load(botFilePath ?? @".\BotConfiguration.bot", secretKey);
                }
                catch
                {
                    var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.
    - You can find the botFilePath and botFileSecret in the Azure App Service application settings.
    - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.
    - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.
    ";
                    logger.LogError(msg);
                    throw new InvalidOperationException(msg);
                }

                services.AddSingleton(sp => botConfig);

                // Retrieve current endpoint.
                var environment = _isProduction ? "production" : "development";
                var service     = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);
                if (service == null && _isProduction)
                {
                    // Attempt to load development environment
                    service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault();
                    logger.LogWarning("Attempting to load development endpoint in production environment.");
                }

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

                options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
                options.ChannelProvider    = new ConfigurationChannelProvider(Configuration);

                // Catches any errors that occur during a conversation turn and logs them.
                options.OnTurnError = async(context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    Console.WriteLine($"Exception: {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();

                // For production bots use the Azure Blob or
                // Azure CosmosDB storage providers. For the Azure
                // based storage providers, add the Microsoft.Bot.Builder.Azure
                // Nuget package to your solution. That package is found at:
                // https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
                // Uncomment the following lines to use Azure Blob Storage
                // Storage configuration name or ID from the .bot file.
                // const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>";
                // var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
                // if (!(blobConfig is BlobStorageService blobStorageConfig))
                // {
                //    throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'.");
                // }
                // // Default container name.
                // const string DefaultBotContainer = "botstate";
                // var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
                // IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);

                // Create Conversation State object.
                // The Conversation State object is where we persist anything at the conversation-scope.

                var conversationState = new ConversationState(dataStore);
                var userState         = new UserState(dataStore);

                options.State.Add(conversationState);

                services.AddSingleton <StateBotAccessors>(sp =>
                {
                    // Create the custom state accessor.
                    return(new StateBotAccessors(conversationState, userState)
                    {
                        ConversationDataAccessor = conversationState.CreateProperty <ConversationData>(StateBotAccessors.ConversationDataName),
                        UserProfileAccessor = userState.CreateProperty <UserData>(StateBotAccessors.UserProfileName),
                    });
                });
            });

            // Create and register state accessors.
            // Accessors created here are passed into the IBot-derived class on every turn.

            services.AddSingleton <EchoBotAccessors>(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");
                }

                var conversationState = options.State.OfType <ConversationState>().FirstOrDefault();
                if (conversationState == null)
                {
                    throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
                }

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new EchoBotAccessors(conversationState)
                {
                    CounterState = conversationState.CreateProperty <CounterState>(EchoBotAccessors.CounterStateName),
                };



                return(accessors);
            });
        }
Example #9
0
 public StateAccessors(ConversationState conversationState, UserState userState)
 {
     ConversationStateAccessors = conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
     UserStateAccessors = userState.CreateProperty<UserProfile>(nameof(UserProfile));
 }