Example #1
0
        private void ConfigureBot(BotFrameworkOptions options, ICredentialProvider credentialProvider)
        {
            // Set the CredentialProvider for the bot. It uses this to authenticate with the QnA service in Azure
            options.CredentialProvider = credentialProvider
                                         ?? throw new InvalidOperationException("Falta información en el endpoint del archivo de configuración de arranque.");

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

            // Catches any errors that occur during a conversation turn and logs them.
            options.OnTurnError = async(context, exception) =>
            {
                logger.LogError($"Excepción atrapada : {exception}");
                await context.SendActivityAsync("Lo siento, parece que algo salió mal.");
            };

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

            options.State.Add(conversationState);
        }
Example #2
0
        /// <summary>
        /// Registers the type mappings with the Unity container.
        /// </summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>
        /// There is no need to register concrete types such as controllers or
        /// API controllers (unless you want to change the defaults), as Unity
        /// allows resolving a concrete type even if it was not previously
        /// registered.
        /// </remarks>
        public static void RegisterTypes(IUnityContainer container)
        {
            // NOTE: To load from web.config uncomment the line below.
            // Make sure to add a Unity.Configuration to the using statements.
            // container.LoadConfiguration();

            // TODO: Register your type's mappings here.
            // container.RegisterType<IProductRepository, ProductRepository>();

            var options = new BotFrameworkOptions();

            options.Middleware.Add(new ShowTypingMiddleware());

            var botFrameworkAdapter = new BotFrameworkAdapter(options.CredentialProvider)
            {
                OnTurnError = options.OnTurnError,
            };

            foreach (var middleware in options.Middleware)
            {
                botFrameworkAdapter.Use(middleware);
            }

            //return botFrameworkAdapter;

            var adapter = new InteceptorAdapter(botFrameworkAdapter);

            container.RegisterInstance <IAdapterIntegration>(adapter);

            container.RegisterType <IBot, TestBot>();
        }
Example #3
0
        private static void ConfigureBot <T>(BotFrameworkOptions options, ICredentialProvider credentialProvider, ILoggerFactory loggerFactory)
        {
            // Set the CredentialProvider for the bot. It uses this to authenticate with the QnA service in Azure
            options.CredentialProvider = credentialProvider
                                         ?? throw new InvalidOperationException("Missing endpoint information from bot configuration file.");

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

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

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

            // Create Conversation State object.
            // The Conversation State object is where we persist anything at the conversation-scope.
            var conversationState = new ConversationState(dataStore);

            options.State.Add(conversationState);
        }
Example #4
0
        public void EnsureDefaultPathsCorrect()
        {
            BotFrameworkOptions options = new BotFrameworkOptions();

            Assert.AreSame("/api", options.Paths.BasePath);
            Assert.AreSame("/messages", options.Paths.MessagesPath);
        }
 private void SetupFallbackErrorHandling(BotFrameworkOptions options, ILogger logger)
 {
     options.OnTurnError = async(context, exception) =>
     {
         logger.LogError($"Exception caught : {exception}");
         await context.SendActivityAsync(exception.ToString());
     };
 }
        public void Configure(BotFrameworkOptions options, ILoggerFactory loggerFactory, bool isProduction, IConfiguration configuration)
        {
            ILogger logger = loggerFactory.CreateLogger <Bot>();

            var botConfig = ReadBotConfiguration(configuration);

            SetupCredentialsProvider(isProduction, options, botConfig);
            SetupFallbackErrorHandling(options, logger);

            State = new ConversationState(new MemoryStorage()).ToMaybe();
        }
Example #7
0
        public void EnsureProperties()
        {
            BotFrameworkOptions options = new BotFrameworkOptions();

            Assert.IsNotNull(options.CredentialProvider);
            Assert.IsNotNull(options.HttpClient);
            Assert.IsNotNull(options.Middleware);
            Assert.IsNull(options.OnTurnError);
            Assert.IsNotNull(options.Paths);
            Assert.IsNotNull(options.State);
            Assert.IsNotNull(options.ConnectorClientRetryPolicy);
            Assert.IsNotNull(options.HttpClient);
        }
Example #8
0
        public void EnsureProperties()
        {
            BotFrameworkOptions options = new BotFrameworkOptions();

            Assert.IsNotNull(options.CredentialProvider);
            Assert.IsNull(options.HttpClient);
            Assert.IsNotNull(options.Middleware);
            Assert.IsNull(options.OnTurnError);
            Assert.IsNotNull(options.Paths);
#pragma warning disable 0618 // Disable the warning, as this test needs to be here.
            Assert.IsNotNull(options.State);
#pragma warning restore 0618
            Assert.IsNull(options.ConnectorClientRetryPolicy);
        }
Example #9
0
                public void WithConfigurationCallbackWithOptionsAndCustomAppCredentials()
                {
                    var serviceCollectionMock = new Mock <IServiceCollection>();
                    var registeredServices    = new List <ServiceDescriptor>();

                    serviceCollectionMock.Setup(sc => sc.Add(It.IsAny <ServiceDescriptor>())).Callback <ServiceDescriptor>(sd => registeredServices.Add(sd));
                    serviceCollectionMock.Setup(sc => sc.GetEnumerator()).Returns(() => registeredServices.GetEnumerator());

                    Func <ITurnContext, Exception, Task> onTurnError = (turnContext, exception) =>
                    {
                        return(Task.CompletedTask);
                    };

                    var middlewareMock = new Mock <IMiddleware>();

                    middlewareMock.Setup(m => m.OnTurnAsync(It.IsAny <TurnContext>(), It.IsAny <NextDelegate>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask);

                    var configAction = new Action <BotFrameworkOptions>(options =>
                    {
                        options.AppCredentials = new MockAppCredentials();
                        options.OnTurnError    = onTurnError;
                    });

                    serviceCollectionMock.Object.AddBot <ServiceRegistrationTestBot>(configAction);

                    VerifyStandardBotServicesAreRegistered(serviceCollectionMock);

                    var adapterServiceDescriptor = registeredServices.FirstOrDefault(sd => sd.ServiceType == typeof(IAdapterIntegration));

                    Assert.NotNull(adapterServiceDescriptor);

                    var mockOptions = new BotFrameworkOptions();

                    configAction(mockOptions);

                    var mockLog = new Mock <ILogger <IAdapterIntegration> >();

                    // The following tests the factory that was added to the ServiceDescriptor.
                    var serviceProviderMock = new Mock <IServiceProvider>();

                    serviceProviderMock.Setup(sp => sp.GetService(typeof(IOptions <BotFrameworkOptions>))).Returns(Options.Create(mockOptions));
                    serviceProviderMock.Setup(sp => sp.GetService(typeof(ILogger <IAdapterIntegration>))).Returns(mockLog.Object);

                    // Invoke the factory to create an adapter
                    var adapter = adapterServiceDescriptor.ImplementationFactory(serviceProviderMock.Object) as BotFrameworkAdapter;

                    // Make sure we have a BotFrameworkAdapter (the default added by the Add<IBot>).
                    Assert.NotNull(adapter);
                }
Example #10
0
        /// <summary>
        /// Configures the services. This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">The services.</param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddBot <EchoBot>(options =>
            {
                IStorage dataStore = new MemoryStorage();

                // --> Adding conversation state handler which understands a team as single conversation.
                options.State.Add(new TeamSpecificConversationState(dataStore));

                // Drop all activities not coming from Microsoft Teams.
                options.Middleware.Add(new DropNonTeamsActivitiesMiddleware());

                // --> Add Teams Middleware.
                options.Middleware.Add(
                    new TeamsMiddleware(
                        new ConfigurationCredentialProvider(this.Configuration)));

                options.CredentialProvider = new ConfigurationCredentialProvider(this.Configuration);
            });

            services.AddSingleton(sp =>
            {
                BotFrameworkOptions options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors");
                }

                TeamSpecificConversationState conversationState = options.State.OfType <TeamSpecificConversationState>().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 EchoStateAccessor(conversationState)
                {
                    CounterState = conversationState.CreateProperty <EchoState>(EchoStateAccessor.CounterStateName),
                };

                return(accessors);
            });
        }
        public async Task Post()
        {
            var activity = default(Activity);

            using (var bodyReader = new JsonTextReader(new StreamReader(Request.Body, Encoding.UTF8)))
            {
                activity = BotMessageSerializer.Deserialize <Activity>(bodyReader);
            }

            var options = new BotFrameworkOptions();

            var botFrameworkAdapter = new BotFrameworkAdapter(options.CredentialProvider);

            await botFrameworkAdapter.ProcessActivityAsync(
                Request.Headers["Authorization"],
                activity,
                OnTurnAsync,
                default(CancellationToken));
        }
        /// <summary>
        /// Adds and configures services for a <typeparamref name="TBot">specified bot type</typeparamref> to the <see cref="IServiceCollection" />.
        /// </summary>
        /// <typeparam name="TBot">A concrete type of <see cref="IBot"/ > that is to be registered and exposed to the Bot Framework.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/>.</param>
        /// <param name="configureAction">A callback that can further be used to configure the bot.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IServiceCollection AddBot <TBot, TBotState>(this IServiceCollection services)
            where TBot : class, IBot
            where TBotState : class, new()
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            services.AddTransient <IBot, TBot>();

            services.AddSingleton(sp =>
            {
                var environmentVariables = Environment.GetEnvironmentVariables();
                var options = new BotFrameworkOptions()
                {
                    CredentialProvider         = new FunctionsCredentialProvider(environmentVariables),
                    ConnectorClientRetryPolicy = new RetryPolicy(new BotFrameworkHttpStatusCodeErrorDetectionStrategy(), 3, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(1)),
                    HttpClient = new HttpClient(),
                };

                options.Middleware.Add(new CatchExceptionMiddleware <Exception>(async(context, exception) =>
                {
                    await context.TraceActivity("EchoBot Exception", exception);
                    await context.SendActivity("Sorry, it looks like something went wrong!");
                }));

                var memoryStore = new MemoryStorage();
                options.Middleware.Add(new ConversationState <TBotState>(memoryStore));

                var botFrameworkAdapter = new BotFrameworkAdapter(options.CredentialProvider, options.ConnectorClientRetryPolicy, options.HttpClient);
                foreach (var middleware in options.Middleware)
                {
                    botFrameworkAdapter.Use(middleware);
                }

                return(botFrameworkAdapter);
            });

            return(services);
        }
Example #13
0
 private void GetCurrentEndpoint(BotFrameworkOptions options, BotConfiguration botConfiguration)
 {
     if (Environment.IsDevelopment())
     {
         var service = botConfiguration.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == "development");
         if (!(service is EndpointService endpointService))
         {
             throw new InvalidOperationException($"The .bot file does not contain a development endpoint.");
         }
         SetCredentials(options, endpointService);
     }
     else
     {
         var service = botConfiguration.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == "production");
         if (!(service is EndpointService endpointService))
         {
             throw new InvalidOperationException($"The .bot file does not contain a production endpoint.");
         }
         SetCredentials(options, endpointService);
     }
 }
Example #14
0
        private void ConfigureBot(BotFrameworkOptions options, 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 ?? @".\SplitwiseBot.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.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 <SplitwiseBot>();

            // 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);
            var userState         = new UserState(dataStore);

            options.State.Add(conversationState);
            options.State.Add(userState);
        }
Example #15
0
                public void WithConfigurationCallbackWithOptions()
                {
                    var serviceCollectionMock = new Mock <IServiceCollection>();
                    var registeredServices    = new List <ServiceDescriptor>();

                    serviceCollectionMock.Setup(sc => sc.Add(It.IsAny <ServiceDescriptor>())).Callback <ServiceDescriptor>(sd => registeredServices.Add(sd));
                    serviceCollectionMock.Setup(sc => sc.GetEnumerator()).Returns(() => registeredServices.GetEnumerator());

                    Func <ITurnContext, Exception, Task> OnTurnError = (turnContext, exception) =>
                    {
                        return(Task.CompletedTask);
                    };

                    var middlewareMock = new Mock <IMiddleware>();

                    middlewareMock.Setup(m => m.OnTurnAsync(It.IsAny <TurnContext>(), It.IsAny <NextDelegate>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask);

                    var configAction = new Action <BotFrameworkOptions>(options =>
                    {
                        options.OnTurnError = OnTurnError;
                        options.Middleware.Add(middlewareMock.Object);
                    });

                    serviceCollectionMock.Object.AddBot <ServiceRegistrationTestBot>(configAction);

                    VerifyStandardBotServicesAreRegistered(serviceCollectionMock);

                    var adapterServiceDescriptor = registeredServices.FirstOrDefault(sd => sd.ServiceType == typeof(IAdapterIntegration));

                    Assert.NotNull(adapterServiceDescriptor);

                    var mockOptions = new BotFrameworkOptions();

                    configAction(mockOptions);

                    var mockLog = new Mock <ILogger <IAdapterIntegration> >();

                    // The following tests the factory that was added to the ServiceDescriptor.
                    var serviceProviderMock = new Mock <IServiceProvider>();

                    serviceProviderMock.Setup(sp => sp.GetService(typeof(IOptions <BotFrameworkOptions>))).Returns(Options.Create(mockOptions));
                    serviceProviderMock.Setup(sp => sp.GetService(typeof(ILogger <IAdapterIntegration>))).Returns(mockLog.Object);

                    // Invoke the factory to create an adapter
                    var adapter = adapterServiceDescriptor.ImplementationFactory(serviceProviderMock.Object) as BotFrameworkAdapter;

                    // Make sure we have a BotFrameworkAdapter (the default added by the Add<IBot>).
                    Assert.NotNull(adapter);

                    // Now we have to run the adapter to test whether the middleware was actually added.
                    var activity = MessageFactory.Text("hi");

                    activity.ServiceUrl = "http://localhost";

                    var result = adapter.ProcessActivityAsync(
                        string.Empty,
                        activity,
                        (turnContext, ct) => { return(Task.CompletedTask); },
                        default(CancellationToken))
                                 .Result;

                    // Verify the mock middleware was actually invoked (the only indicator we have that it was added).
                    middlewareMock.Verify(m => m.OnTurnAsync(
                                              It.Is <TurnContext>(tc => true),
                                              It.Is <NextDelegate>(nd => true),
                                              It.Is <CancellationToken>(ct => true)), Times.Once());

                    // And make sure the error handler was added.
                    Assert.Equal(OnTurnError, adapter.OnTurnError);

                    // Make sure the configuration action was registered.
                    serviceCollectionMock.Verify(sc => sc.Add(It.Is <ServiceDescriptor>(sd => (sd.ImplementationInstance is ConfigureNamedOptions <BotFrameworkOptions>) && ((ConfigureNamedOptions <BotFrameworkOptions>)sd.ImplementationInstance).Action == configAction)));
                }
Example #16
0
        /// <summary>
        /// Configures the services. This method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">The services.</param>
        public void ConfigureServices(IServiceCollection services)
        {
            string secretKey   = this.Configuration.GetSection("botFileSecret")?.Value;
            string botFilePath = this.Configuration.GetSection("botFilePath")?.Value;

            // 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
            {
                string msg = "Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.\n" +
                             " - The botFileSecret is available under appsettings for your Azure Bot Service bot.\n" +
                             " - If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.\n" +
                             " - See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.\n\n";
                throw new InvalidOperationException(msg);
            }

            services.AddSingleton(sp => botConfig);

            // Retrieve current endpoint.
            string           environment = this.isProduction ? "production" : "development";
            ConnectedService botService  = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault();

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

            services.AddTransient <IActivityProcessor, TeamsActivityProcessor>();
            services.AddTransient <ITeamsConversationUpdateActivityHandler, TeamsConversationUpdateActivityHandler>();
            services.AddTransient <IMessageActivityHandler, MessageActivityHandler>();

            services.AddBot <AuditBot>(options =>
            {
                IStorage dataStore = new MemoryStorage();

                // --> Adding conversation state handler which understands a team as single conversation.
                options.State.Add(new TeamSpecificConversationState(dataStore));

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

                // Drop all activities not coming from Microsoft Teams.
                options.Middleware.Add(new DropNonTeamsActivitiesMiddleware());

                // --> Add Teams Middleware.
                options.Middleware.Add(
                    new TeamsMiddleware(
                        options.CredentialProvider));

                // Drop all non team messages.
                options.Middleware.Add(new DropChatActivitiesMiddleware());
            });

            services.AddSingleton(sp =>
            {
                BotFrameworkOptions options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors");
                }

                TeamSpecificConversationState conversationState = options.State.OfType <TeamSpecificConversationState>().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 AuditLogAccessor(conversationState)
                {
                    AuditLog = conversationState.CreateProperty <TeamOperationHistory>(AuditLogAccessor.AuditLogName),
                };

                return(accessors);
            });
        }
        private void SetupCredentialsProvider(bool isProduction, BotFrameworkOptions options, BotConfiguration botConfig)
        {
            var endpointService = GetEndpointService(isProduction, botConfig);

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