示例#1
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);
            });
        }
示例#2
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));
        }
 public StateManagementBot(ConversationState conversationState, UserState userState)
 {
     _conversationState = conversationState;
     _userState         = userState;
 }
        public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
            : base(configuration, logger)
        {
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                logger.LogError($"Exception caught : {exception.Message}");

                // Send a catch-all apology to the user.
                var errorMessage = MessageFactory.Text(ErrorMsgText, ErrorMsgText, InputHints.ExpectingInput);
                await turnContext.SendActivityAsync(errorMessage);

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }
            };
        }
示例#5
0
        public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
            : base(configuration, logger)
        {
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

                // Send a message to the user
                await turnContext.SendActivityAsync("The bot encounted an error or bug.");

                await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }

                // Send a trace activity, which will be displayed in the Bot Framework Emulator
                await SendTraceActivityAsync(turnContext, exception);
            };
        }
        public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
            : base(configuration: configuration, new ConfigurationCredentialProvider(configuration), logger: logger, authConfig: new AuthenticationConfiguration {
            ClaimsValidator = new AllowedCallersClaimsValidator(new List <string> { "*" })
        })
        {
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                // NOTE: In production environment, you should consider logging this to
                // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
                // to add telemetry capture to your bot.
                logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

                // Send a message to the user
                await turnContext.SendActivityAsync("The bot encountered an error or bug.");

                await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }

                // Send a trace activity, which will be displayed in the Bot Framework Emulator
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
            };
        }
示例#7
0
 public WeatherCardBot(ConversationState conversationState, UserState userState, MainDialog dialog, ILogger <DialogBot <MainDialog> > logger)
     : base(conversationState, userState, dialog, logger)
 {
 }
示例#8
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/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/>
        public void ConfigureServices(IServiceCollection services)
        {
            // Add botConfiguration singleton
            // See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.
            var secretKey   = Configuration.GetSection("botFileSecret")?.Value;
            var botFilePath = Configuration.GetSection("botFilePath")?.Value;
            var botConfig   = BotConfiguration.Load(botFilePath ?? @".\CafeBot.bot", secretKey);

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

            // Add BotServices singleton
            services.AddSingleton(sp => new BotServices(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();

            // 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);
            services.AddSingleton(dataStore);
            var userState         = new UserState(dataStore);
            var conversationState = new ConversationState(dataStore);

            services.AddSingleton(userState);
            services.AddSingleton(conversationState);

            // The BotStateSet enables read() and write() in parallel on multiple BotState instances.
            services.AddSingleton(new BotStateSet(userState, conversationState));

            // Add the bot with options
            services.AddBot <CafeBot>(options =>
            {
                // Load the connected services from .bot file.
                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}'.");
                }

                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 <CafeBot>();
                options.OnTurnError = async(context, exception) =>
                {
                    logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };

                // Automatically save state at the end of a turn.
                options.Middleware
                .Add(new AutoSaveStateMiddleware(userState, conversationState));
            });
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="WelcomeUserStateAccessors"/> class.
 /// Contains the <see cref="UserState"/> and associated <see cref="IStatePropertyAccessor{T}"/>.
 /// </summary>
 /// <param name="userState">The state object that stores the counter.</param>
 public WelcomeUserStateAccessors(UserState userState, ConversationState conversationState)
 {
     UserState = userState ?? throw new ArgumentNullException(nameof(userState));
 }
示例#10
0
        public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, TranslationMiddleware translationMiddleware, ConversationState conversationState = null)
            : base(configuration, logger)
        {
            if (translationMiddleware == null)
            {
                throw new NullReferenceException(nameof(translationMiddleware));
            }

            // Add translation middleware to the adapter's middleware pipeline
            Use(translationMiddleware);

            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

                // Send a message to the user
                //await SendWithoutMiddleware("The bot encounted an error or bug.");
                //await SendWithoutMiddleware("To continue to run this bot, please fix the bot source code.");
                await SendWithoutMiddleware(turnContext, configuration["InternalErrorResponse"]);

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }

                // Send a trace activity, which will be displayed in the Bot Framework Emulator
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
            };
        }
示例#11
0
        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}");
            }

            // Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
            BotConfiguration botConfig = null;

            try
            {
                botConfig = BotConfiguration.Load(botFilePath, 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.
    ";
                throw new InvalidOperationException(msg);
            }

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

            // Add BotServices singleton.
            // Create the connected services from .bot file.
            services.AddSingleton(sp => new BotServices(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();
            }

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

            // 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);

            var userState = new UserState(dataStore);

            services.AddSingleton(userState);

            services.AddBot <BasicBot>(options =>
            {
                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 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.");
                };
            });
        }
        public AdapterWithErrorHandler(IConfiguration configuration, IHttpClientFactory httpClientFactory, ILogger <IBotFrameworkHttpAdapter> logger, ConversationState conversationState)
            : base(configuration, httpClientFactory, logger)
        {
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                // NOTE: In production environment, you should consider logging this to
                // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
                // to add telemetry capture to your bot.
                logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

                // Send a message to the user
                var errorMessageText = "The bot encountered an error or bug.";
                var errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput);
                await turnContext.SendActivityAsync(errorMessage);

                errorMessageText = "To continue to run this bot, please fix the bot source code.";
                errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
                await turnContext.SendActivityAsync(errorMessage);

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }

                // Send a trace activity, which will be displayed in the Bot Framework Emulator
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
            };
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CustomPromptBotAccessors"/> class.
 /// Contains the state management and associated accessor objects.
 /// </summary>
 /// <param name="conversationState">The state object that stores the conversation state.</param>
 /// <param name="userState">The state object that stores the user state.</param>
 public CustomPromptBotAccessors(ConversationState conversationState, UserState userState)
 {
     ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
     UserState         = userState ?? throw new ArgumentNullException(nameof(userState));
 }
示例#14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DialogInterruptionsBotAccessors"/> class.
 /// Contains the <see cref="ConversationState"/> and associated <see cref="IStatePropertyAccessor{T}"/>.
 /// </summary>
 /// <param name="conversationState">The state object that stores the dialog state.</param>
 /// <param name="userState">The state object that stores the user state.</param>
 public DialogInterruptionsBotAccessors(ConversationState conversationState, UserState userState)
 {
     ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
     UserState         = userState ?? throw new ArgumentNullException(nameof(userState));
 }
示例#15
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="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 <CardsBot>(options =>
            {
                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})"));

                // 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 <CardsBot>();

                // 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();

                // 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 = "<DEFAULT-CONTAINER>";
                // 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);

                options.State.Add(conversationState);
            });

            // Create and register state accessors.
            // Accessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton <CardsBotAccessors>(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 custom state property accessors.
                // State property accessors enable components to read and write individual properties,
                // without having to pass the entire state object.
                var accessors = new CardsBotAccessors(conversationState)
                {
                    ConversationDialogState = conversationState.CreateProperty <DialogState>(CardsBotAccessors.DialogStateName),
                };

                return(accessors);
            });
        }
示例#16
0
 public AuthBot(ConversationState conversationState, UserState userState, T dialog, ILogger <DialogBot <T> > logger)
     : base(conversationState, userState, dialog, logger)
 {
 }
        public AdapterWithErrorHandler(ICredentialProvider credentialProvider, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
            : base(credentialProvider)
        {
            // combine path for cross platform support
            string[] paths    = { ".", "Resources", "AdapterWithErrorHandler.lg" };
            string   fullPath = Path.Combine(paths);

            _lgEngine   = new TemplateEngine().AddFile(fullPath);
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                logger.LogError($"Exception caught : {exception.Message}");

                // Send a catch-all apology to the user.
                await turnContext.SendActivityAsync(ActivityFactory.CreateActivity(_lgEngine.EvaluateTemplate("SomethingWentWrong", exception).ToString()));

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }
            };
        }
示例#18
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/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/>
        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}");
            }

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

            // Initialize Bot Connected Services clients.
            var connectedServices = new BotServices(botConfig);

            services.AddSingleton(sp => connectedServices);

            services.AddSingleton(sp => botConfig);

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

                // 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}'.");
                }

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

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

                // 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();

                // 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 = "<DEFAULT-CONTAINER>";
                // 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);

                options.State.Add(conversationState);
            });
        }
示例#19
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;
            var secretKey   = "CNjqDnw4n9d8zTXmmrywJybwHQ+K1Ke0AmmTWTS5854=";
            var botFilePath = "./sq7ofg.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, 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.
    ";
                throw new InvalidOperationException(msg);
            }

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

            // Add BotServices singleton.
            // Create the connected services from .bot file.
            services.AddSingleton(sp => new BotServices(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();
            }

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

            // Memory Storage 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/
            // 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);

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

            services.AddSingleton(conversationState);

            var userState = new UserState(dataStore);

            services.AddSingleton(userState);

            services.AddBot <BasicBot>(options =>
            {
                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 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.");
                };
            });
        }
        public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
            : base(configuration, logger)
        {
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                logger.LogError($"Exception caught : {exception.Message}");

                // Send a catch-all apology to the user.
                await turnContext.SendActivityAsync("Sorry, it looks like something went wrong.");

                await turnContext.SendActivityAsync("To run this sample make sure you have the LUIS and QnA models deployed.");

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError($"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }
            };
        }
示例#21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BotAccessors"/> class.
 /// Contains the <see cref="ConversationState"/> and associated <see cref="IStatePropertyAccessor{T}"/>.
 /// </summary>
 /// <param name="conversationState">The state object that stores the dialog state.</param>
 public BotAccessors(ConversationState conversationState)
 {
     ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
 }
示例#22
0
        public AdapterWithErrorHandler(IConfiguration configuration, ILogger <BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)
            : base(configuration, logger)
        {
            OnTurnError = async(turnContext, exception) =>
            {
                // Log any leaked exception from the application.
                logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

                // Send a message to the user
                var errorMessageText = "Oops! Something went wrong!";
                var errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
                await turnContext.SendActivityAsync(errorMessage);

                errorMessageText = "Could you please refresh the page and start over.";
                errorMessage     = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
                await turnContext.SendActivityAsync(errorMessage);

                if (conversationState != null)
                {
                    try
                    {
                        // Delete the conversationState for the current conversation to prevent the
                        // bot from getting stuck in a error-loop caused by being in a bad state.
                        // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                        await conversationState.DeleteAsync(turnContext);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
                    }
                }

                // Send a trace activity, which will be displayed in the Bot Framework Emulator
                await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
            };
        }
示例#23
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
                await promptValidatorContext.Context.SendActivityAsync(newReservation.GetMissingPropertyReadOut());
                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));
        }