Exemplo n.º 1
0
 public DialogBase(StateAccessors state, DialogSet dialogs, IApiInterface api, IConfiguration configuration)
 {
     this.state         = state;
     this.dialogs       = dialogs;
     this.api           = api;
     this.configuration = configuration;
 }
Exemplo n.º 2
0
        public SearchCompanyDataDialog(StateAccessors accessors, ILoggerFactory loggerFactory, BotServices botServices, IServiceProvider serviceProvider) : base(nameof(SearchCompanyDataDialog))
        {
            _accessors       = accessors;
            _loggerFactory   = loggerFactory;
            _botServices     = botServices;
            _serviceProvider = serviceProvider;

            _companyService = (CompanyService)_serviceProvider.GetService(typeof(CompanyService));

            var waterfallSteps = new WaterfallStep[]
            {
                InitializeStateStepAsync,
                AskForCompanyFullNameStepAsync,
                SearchCompanyStepAsync,
                ResultHandlerStepAsync,
                EndSearchDialogStepAsync
            };

            var culture = CulturedBot.Culture?.Name;

            AddDialog(new WaterfallDialog(_searchCompanyDataWaterfall, waterfallSteps));
            AddDialog(new TextPrompt(_companyNamePrompt));
            AddDialog(new TextPrompt(_retryFetchingMinimumDataFromUserPrompt /*, defaultLocale: culture*/));
            AddDialog(new TextPrompt(_confirmForwardingPrompt /*, defaultLocale: culture*/));
        }
Exemplo n.º 3
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940.
        // AddSingleton - Same for every object and every request.
        // AddScoped - Same within a request but different across different requests.
        // AddTransient - Always different. New instance for every controller and service.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add the configuration.
            services.AddSingleton(this.configuration);

            // Add the API interface.
            // Cosmos recommends a singleton for the lifetime of the application.
            // Other types may need to be scoped to the request (like Entity Framework).
            var api = new CosmosInterface(this.configuration);

            services.AddSingleton(api);

            // Add the state accessors.
            var state = StateAccessors.Create(this.configuration);

            services.AddSingleton(state);

            // Add the translator.
            var translator = new Translator(this.configuration);

            services.AddSingleton(translator);

            // Configure the bot.
            services.AddBot <TheBot>(options =>
            {
                // Load the configuration settings.
                options.CredentialProvider = new SimpleCredentialProvider(
                    this.configuration.MicrosoftAppId(),
                    this.configuration.MicrosoftAppPassword());

                // Catches any errors that occur during a conversation turn and logs them.
                options.OnTurnError = async(context, exception) =>
                {
                    Debug.WriteLine(exception.Message);

                    await context.TraceActivityAsync("Exception", exception);

                    if (!configuration.IsProduction())
                    {
                        await context.SendActivityAsync(exception.Message);
                        await context.SendActivityAsync(exception.StackTrace);
                    }

                    await context.SendActivityAsync(Phrases.Exceptions.Error);
                };

                // Auto-save the state after each turn.
                // This should be the first middleware called in order to catch state changes by any other middleware or the bot.
                options.Middleware.Add(new AutoSaveStateMiddleware(state.ConversationState));

                // Trim the incoming message.
                options.Middleware.Add(new TrimIncomingMessageMiddleware());

                // Make sure the user object is available.
                options.Middleware.Add(new CreateUserMiddleware(api));

                // Translate the messages if necessary.
                options.Middleware.Add(new TranslationMiddleware(api, state, translator));
            });
        }
Exemplo n.º 4
0
        public TheBot(IConfiguration configuration, StateAccessors state, CosmosInterface api)
        {
            this.configuration = configuration;

            this.state   = state ?? throw new ArgumentNullException(nameof(state));
            this.dialogs = new DialogSet(state.DialogContextAccessor);

            this.api = api ?? throw new ArgumentNullException(nameof(api));

            // Register prompts.
            Prompt.Register(this.dialogs, this.configuration, this.api);
        }
Exemplo n.º 5
0
        public CreateOpportunityDialog(StateAccessors accessors, ILoggerFactory loggerFactory,
                                       BotServices botServices, IServiceProvider serviceProvider) : base(nameof(CreateOpportunityDialog))
        {
            _accessors       = accessors;
            _loggerFactory   = loggerFactory;
            _botServices     = botServices;
            _serviceProvider = serviceProvider;

            _leadService        = (LeadService)_serviceProvider.GetService(typeof(LeadService));
            _opportunityService = (OpportunityService)_serviceProvider.GetService(typeof(OpportunityService));
            _productService     = (ProductService)_serviceProvider.GetService(typeof(ProductService));

            var waterfallSteps = new WaterfallStep[]
            {
                //Start of dialog
                InitializeStateStepAsync,
                //Searching for lead
                AskForLeadFullNameStepAsync,
                SearchLeadStepAsync,
                LeadResultHandlerStepAsync,
                //Searching for product
                AskForProductNameStepAsync,
                SearchProductStepAsync,
                ProductResultHandlerStepAsync,
                //Checking the closing date
                AskForClosingDateStepAsync,
                SearchClosingDateStepAsync,
                ClosingDateResultHandlerStepAsync,
                //Checking for comment
                AskIfUserWantsToCommentStepAsync,
                AskToCommentStepAsync,
                FetchingCommentFromUserStepAsync,
                //End of Dialog
                EndSearchDialogStepAsync
            };

            var culture = CulturedBot.Culture?.Name;

            AddDialog(new WaterfallDialog(_createOpportunityDataWaterfall, waterfallSteps));
            //Searching for lead
            AddDialog(new TextPrompt(_leadFullNamePrompt));
            AddDialog(new TextPrompt(_retryFetchingLeadFromUserPrompt /*, defaultLocale: culture*/));
            //Searching for product
            AddDialog(new TextPrompt(_productNamePrompt));
            AddDialog(new TextPrompt(_retryFetchingProductFromUserPrompt /*, defaultLocale: culture*/));
            //Checking the closing date
            AddDialog(new TextPrompt(_closingDatePrompt));
            AddDialog(new TextPrompt(_retryFetchingClosingDateFromUserPrompt /*, defaultLocale: culture*/));
            //Checking for comment
            AddDialog(new TextPrompt(_commentPrompt /*, defaultLocale: culture*/));
            AddDialog(new TextPrompt(_fetchingCommentFromUserPrompt));
        }
Exemplo n.º 6
0
        protected DialogTestBase(TestFixture fixture)
        {
            this.fixture = fixture;

            this.state   = StateAccessors.Create();
            this.dialogs = new DialogSet(state.DialogContextAccessor);

            this.adapter = new TestAdapter()
                           .Use(new TestSettingsMiddleware(fixture.Configuration))
                           .Use(new AutoSaveStateMiddleware(state.ConversationState))
                           .Use(new TrimIncomingMessageMiddleware())
                           .Use(new CreateUserMiddleware(fixture.Api))
                           .Use(new TranslationMiddleware(fixture.Api, this.state, fixture.Translator));

            Prompt.Register(this.dialogs, fixture.Configuration, fixture.Api);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="conversationState">The managed conversation state.</param>
        /// <param name="loggerFactory">A <see cref="ILoggerFactory"/> that is hooked to the Azure App Service provider.</param>
        /// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1#windows-eventlog-provider"/>
        public ProxiCallBot(BotServices services, StateAccessors accessors, IOptions <ServicesConfig> options, IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
        {
            _accessors       = accessors ?? throw new System.ArgumentNullException(nameof(accessors));
            _serviceProvider = serviceProvider;
            _loggerFactory   = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
            _services        = services ?? throw new ArgumentNullException(nameof(services));

            _servicesConfig = options.Value;

            _accountService = (AccountService)_serviceProvider.GetService(typeof(AccountService));

            Dialogs = new DialogSet(_accessors.DialogStateAccessor);
            Dialogs.Add(ActivatorUtilities.CreateInstance <SearchLeadDataDialog>(_serviceProvider));
            Dialogs.Add(ActivatorUtilities.CreateInstance <SearchCompanyDataDialog>(_serviceProvider));
            Dialogs.Add(ActivatorUtilities.CreateInstance <CreateOpportunityDialog>(_serviceProvider));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CarWashBot"/> class.
        /// </summary>
        /// <param name="accessors">The state accessors for managing bot state.</param>
        /// <param name="botConfig">The parsed .bot config file.</param>
        /// <param name="services">External services.</param>
        /// <param name="loggerFactory">Logger.</param>
        /// <param name="telemetryClient">Telemetry client.</param>
        public CarWashBot(StateAccessors accessors, BotConfiguration botConfig, BotServices services, ILoggerFactory loggerFactory, TelemetryClient telemetryClient)
        {
            _accessors = accessors ?? throw new ArgumentNullException(nameof(accessors));
            if (botConfig == null)
            {
                throw new ArgumentNullException(nameof(botConfig));
            }
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            _telemetryClient = telemetryClient;

            // Verify LUIS configuration.
            if (!services.LuisServices.ContainsKey(LuisConfiguration))
            {
                throw new InvalidOperationException($"Invalid configuration. Please check your '.bot' file for a LUIS service named '{LuisConfiguration}'.");
            }
            _luis = services.LuisServices[LuisConfiguration];

            // Verify QnAMaker configuration.
            if (!services.QnAServices.ContainsKey(QnAMakerConfiguration))
            {
                throw new ArgumentException($"Invalid configuration. Please check your '.bot' file for a QnA service named '{QnAMakerConfiguration}'.");
            }
            _qna = services.QnAServices[QnAMakerConfiguration];

            // Verify Storage configuration.
            if (!services.StorageServices.ContainsKey(StorageConfiguration))
            {
                throw new ArgumentException($"Invalid configuration. Please check your '.bot' file for a Storage service named '{StorageConfiguration}'.");
            }
            _storage = services.StorageServices[StorageConfiguration];

            Dialogs = new DialogSet(_accessors.DialogStateAccessor);
            Dialogs.Add(new NewReservationDialog(_accessors.NewReservationStateAccessor, telemetryClient));
            Dialogs.Add(new ConfirmDropoffDialog(_accessors.ConfirmDropoffStateAccessor, telemetryClient));
            Dialogs.Add(new CancelReservationDialog(_accessors.CancelReservationStateAccessor, telemetryClient));
            Dialogs.Add(new FindReservationDialog(telemetryClient));
            Dialogs.Add(new NextFreeSlotDialog(telemetryClient));
            Dialogs.Add(new AuthDialog(accessors.UserProfileAccessor, _storage, telemetryClient));
            Dialogs.Add(AuthDialog.LoginPromptDialog());

            // Dialogs.Add(FormDialog.FromForm(NewReservationForm.BuildForm));
        }
Exemplo n.º 9
0
        public GreetingDialog(
            ILogger <GreetingDialog> logger,
            StateAccessors accessors,
            IBotUserServices botUserServices)
            : base(GreetingDialogId)
        {
            _logger          = logger ?? throw new ArgumentNullException(nameof(logger));
            _accessors       = accessors ?? throw new ArgumentNullException(nameof(accessors));
            _botUserServices = botUserServices ?? throw new ArgumentNullException(nameof(botUserServices));

            InitialDialogId = Id;

            AddDialog(new WaterfallDialog(GreetingDialogId)
                      .AddStep(Step1CheckRegistrationAsync)
                      .AddStep(Step2GetCallNameAsync)
                      .AddStep(Step3ThankYouAsync));

            AddDialog(new TextPrompt(TextPromptId));
        }
Exemplo n.º 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProactiveMessage{T}"/> class.
        /// </summary>
        /// <param name="accessors">The state accessors for managing bot state.</param>
        /// <param name="adapterIntegration">The <see cref="BotFrameworkAdapter"/> connects the bot to the service endpoint of the given channel.</param>
        /// <param name="env">Provides information about the web hosting environment an application is running in.</param>
        /// <param name="services">External services.</param>
        /// <param name="queueName">Service Bus queue name.</param>
        /// <param name="dialogs">List of Types of other <see cref="Dialog"/>s used when sending out the proactive message.</param>
        /// <param name="telemetryClient">Telemetry client.</param>
        public ProactiveMessage(StateAccessors accessors, IAdapterIntegration adapterIntegration, IHostingEnvironment env, BotServices services, string queueName, Dialog[] dialogs, TelemetryClient telemetryClient)
        {
            _accessors           = accessors;
            _env                 = env;
            _botFrameworkAdapter = (BotFrameworkAdapter)adapterIntegration;
            _telemetryClient     = telemetryClient;

            _dialogs = new DialogSet(_accessors.DialogStateAccessor);
            foreach (var dialog in dialogs)
            {
                _dialogs.Add(dialog);
            }

            // Verify Endpoint configuration.
            var endpointConfig = env.IsProduction() ? CarWashBot.EndpointConfiguration : CarWashBot.EndpointConfigurationDev;

            if (!services.EndpointServices.ContainsKey(endpointConfig))
            {
                throw new ArgumentException($"Invalid configuration. Please check your '.bot' file for a Endpoint service named '{endpointConfig}'.");
            }

            _endpoint = services.EndpointServices[endpointConfig];

            // Verify Storage configuration.
            if (!services.StorageServices.ContainsKey(CarWashBot.StorageConfiguration))
            {
                throw new ArgumentException($"Invalid configuration. Please check your '.bot' file for a Storage service named '{CarWashBot.StorageConfiguration}'.");
            }

            var tableClient = services.StorageServices[CarWashBot.StorageConfiguration].CreateCloudTableClient();

            _table = tableClient.GetTableReference(CarWashBot.UserStorageTableName);

            // Verify ServiceBus configuration.
            if (!services.ServiceBusServices.ContainsKey(CarWashBot.ServiceBusConfiguration))
            {
                throw new ArgumentException($"Invalid configuration. Please check your '.bot' file for a Service Bus service named '{CarWashBot.ServiceBusConfiguration}'.");
            }

            _queueClient = new QueueClient(services.ServiceBusServices[CarWashBot.ServiceBusConfiguration], queueName, ReceiveMode.PeekLock, null);
        }
Exemplo n.º 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="VehicleArrivedMessage"/> class.
 /// </summary>
 /// <param name="configuration">CarWash app configuration.</param>
 /// <param name="accessors">The state accessors for managing bot state.</param>
 /// <param name="adapterIntegration">The <see cref="BotFrameworkAdapter"/> connects the bot to the service endpoint of the given channel.</param>
 /// <param name="env">Provides information about the web hosting environment an application is running in.</param>
 /// <param name="services">External services.</param>
 /// <param name="telemetryClient">Telemetry client.</param>
 public VehicleArrivedMessage(CarWashConfiguration configuration, StateAccessors accessors, IAdapterIntegration adapterIntegration, IHostingEnvironment env, BotServices services, TelemetryClient telemetryClient)
     : base(accessors, adapterIntegration, env, services, configuration.ServiceBusQueues.BotVehicleArrivedNotificationQueue, new Dialog[] { AuthDialog.LoginPromptDialog(), new FindReservationDialog(telemetryClient) }, telemetryClient)
 {
 }
Exemplo n.º 12
0
 public RequestDialog(StateAccessors state, DialogSet dialogs, IApiInterface api, IConfiguration configuration)
     : base(state, dialogs, api, configuration)
 {
     this.translator = new Translator(configuration);
 }
Exemplo n.º 13
0
 public UpdateDialog(StateAccessors state, DialogSet dialogs, IApiInterface api, IConfiguration configuration)
     : base(state, dialogs, api, configuration)
 {
 }
Exemplo n.º 14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WashStartedMessage"/> class.
 /// </summary>
 /// <param name="configuration">CarWash app configuration.</param>
 /// <param name="accessors">The state accessors for managing bot state.</param>
 /// <param name="adapterIntegration">The <see cref="BotFrameworkAdapter"/> connects the bot to the service endpoint of the given channel.</param>
 /// <param name="env">Provides information about the web hosting environment an application is running in.</param>
 /// <param name="services">External services.</param>
 public WashStartedMessage(CarWashConfiguration configuration, StateAccessors accessors, IAdapterIntegration adapterIntegration, IHostingEnvironment env, BotServices services)
     : base(accessors, adapterIntegration, env, services, configuration.ServiceBusQueues.BotWashStartedQueue, new Dialog[] { AuthDialog.LoginPromptDialog(), new FindReservationDialog() })
 {
 }
Exemplo n.º 15
0
 /// <summary>
 /// Initializes a new instance of the class.
 /// </summary>
 public MeetpupDialogBot(StateAccessors stateAccessors)
 {
     _stateAccessors = stateAccessors;
     ExecuteMainDialog(_stateAccessors.DlgState);
 }
Exemplo n.º 16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TranslationMiddleware"/> class.
 /// </summary>
 public TranslationMiddleware(IApiInterface api, StateAccessors state, Translator translator)
 {
     this.api        = api ?? throw new ArgumentNullException(nameof(api));
     this.state      = state ?? throw new ArgumentNullException(nameof(state));
     this.translator = translator ?? throw new ArgumentNullException(nameof(translator));
 }
Exemplo n.º 17
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 config = Configuration.Get <CarWashConfiguration>();

            services.AddSingleton(config);

            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.
            BotConfiguration botConfig;

            try
            {
                botConfig = BotConfiguration.Load(botFilePath ?? @".\carwashubot.bot", secretKey);
            }
            catch (Exception)
            {
                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 config file could not be loaded. ({botConfig})"));

            // 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 is EndpointService endpointService))
            {
                throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
            }

            // Configure AppInsights
            services.AddApplicationInsightsTelemetry(Configuration);

            // Configure SnapshotCollector from application settings
            services.Configure <SnapshotCollectorConfiguration>(Configuration.GetSection(nameof(SnapshotCollectorConfiguration)));

            // Add SnapshotCollector telemetry processor.
            services.AddSingleton <ITelemetryProcessorFactory>(sp => new SnapshotCollectorTelemetryProcessorFactory(sp));

            // Add proactive message services
            services.AddSingleton <DropoffReminderMessage, DropoffReminderMessage>();
            services.AddSingleton <WashStartedMessage, WashStartedMessage>();
            services.AddSingleton <WashCompletedMessage, WashCompletedMessage>();
            services.AddSingleton <CarWashCommentLeftMessage, CarWashCommentLeftMessage>();
            services.AddSingleton <VehicleArrivedMessage, VehicleArrivedMessage>();

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

            // Storage configuration name or ID from the .bot file.
            const string storageConfigurationId = "carwashstorage";
            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 AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);

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

            services.AddSingleton(conversationState);

            // Create and add user state.
            var userState = new UserState(dataStore);

            services.AddSingleton(userState);

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

                // Enable the show typing middleware.
                options.Middleware.Add(new ShowTypingMiddleware());

                // Enable the conversation transcript middleware.
                var transcriptStore = new AzureBlobTranscriptStore(blobStorageConfig.ConnectionString, "transcripts");
                options.Middleware.Add(new TranscriptLoggerWorkaroundMiddleware(transcriptStore));

                // Add Teams authentication workaround middleware.
                options.Middleware.Add(new TeamsAuthWorkaroundMiddleware());

                // Catches any errors that occur during a conversation turn and logs them to currently
                // configured ILogger.
                ILogger logger      = _loggerFactory.CreateLogger <CarWashBot>();
                options.OnTurnError = async(context, exception) =>
                {
                    var telemetryClient = new TelemetryClient();
                    telemetryClient.TrackException(exception);
                    logger.LogError($"Exception caught : {exception}");
                    await context.SendActivityAsync("Sorry, it looks like something went wrong.");
                };
            });

            // Create and register state accessors.
            // Accessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton(sp =>
            {
                if (conversationState == null)
                {
                    throw new InvalidOperationException("ConversationState must be defined and added before adding conversation-scoped state accessors.");
                }

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

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new StateAccessors(conversationState, userState);

                return(accessors);
            });
        }
Exemplo n.º 18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CarWashCommentLeftMessage"/> class.
 /// </summary>
 /// <param name="configuration">CarWash app configuration.</param>
 /// <param name="accessors">The state accessors for managing bot state.</param>
 /// <param name="adapterIntegration">The <see cref="BotFrameworkAdapter"/> connects the bot to the service endpoint of the given channel.</param>
 /// <param name="env">Provides information about the web hosting environment an application is running in.</param>
 /// <param name="services">External services.</param>
 /// <param name="telemetryClient">Telemetry client.</param>
 public CarWashCommentLeftMessage(CarWashConfiguration configuration, StateAccessors accessors, IAdapterIntegration adapterIntegration, IHostingEnvironment env, BotServices services, TelemetryClient telemetryClient)
     : base(accessors, adapterIntegration, env, services, configuration.ServiceBusQueues.BotCarWashCommentLeftQueue, new Dialog[] { AuthDialog.LoginPromptDialog(), new FindReservationDialog(telemetryClient) }, telemetryClient)
 {
     _telemetryClient = telemetryClient;
 }