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