Exemplo n.º 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.Configure <MySettings>(Configuration);

            services.AddMvc();
//#if DEBUG
//      services.AddMvc();
//#else
//      services.AddMvc(mvcConfig =>
//    {
//        mvcConfig.Filters.Add(new BasicAuthFilter(Configuration["BasicAuthUsername"], Configuration["BasicAuthPassword"]));
//    });
//#endif

            // create luis recognizer
            var luisApplication = new LuisApplication(
                Configuration["LuisAppId"],
                Configuration["LuisAPIKey"],
                "https://" + Configuration["LuisAPIHostName"]);

            services.AddSingleton(new LuisRecognizer(luisApplication));

            // Create the credential provider to be used with the Bot Framework Adapter.
            services.AddSingleton <ICredentialProvider, ConfigurationCredentialProvider>();

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

            // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
            services.AddSingleton <IStorage, MemoryStorage>();

            // Create the User state. (Used in this bot's Dialog implementation.)
            services.AddSingleton <UserState>();

            // Create the Conversation state. (Used by the Dialog system itself.)
            services.AddSingleton <ConversationState>();

            // The Dialog that will be run by the bot.
            services.AddSingleton <ReservationDialog>();

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

            // Add the personality chat middleware
            var personalityChatOptions = new PersonalityChatMiddlewareOptions(
                respondOnlyIfChat: true,
                scoreThreshold: 0.5F,
                botPersona: PersonalityChatPersona.Humorous);

            services.AddSingleton(new PersonalityChatMiddleware(personalityChatOptions));

            // Add the translator speech middleware
            services.AddTransient <IBot, EchoBot>();

            // Create and register state accessors.
            // Accessors created here are passed into the IBot-derived class on every turn.
            services.AddSingleton(sp =>
            {
                // We need to grab the conversationState we added on the options in the previous step
                var options = sp.GetRequiredService <IOptions <BotFrameworkOptions> >().Value;
                if (options == null)
                {
                    throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the 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, userState)
                {
                    // Initialize Dialog State
                    ConversationDialogState = conversationState.CreateProperty <DialogState>("DialogState"),
                    ReservationState        = userState.CreateProperty <ReservationData>("ReservationState"),
                };

                return(accessors);
            });

            // Add QnA Maker here
            // We add the the QnA service to the connected services.
            // Create and register a QnA service and knowledgebase
            services.AddSingleton(sp =>
            {
                return(new QnAMaker(
                           new QnAMakerEndpoint
                {
                    EndpointKey = Configuration["QnAEndpointKey"],
                    Host = Configuration["QnAHostname"],
                    KnowledgeBaseId = Configuration["QnAKbId"],
                },
                           new QnAMakerOptions
                {
                    ScoreThreshold = 0.9f,
                    Top = 1,
                }));
            });
        }
Exemplo n.º 2
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            turnContext.Activity.RemoveRecipientMention();
            var commandName = turnContext.Activity.Text?.Trim();

            if (string.IsNullOrEmpty(commandName))
            {
                var value = turnContext.Activity.Value;
                return;
            }

            AdaptiveCard card = null;

            switch (commandName)
            {
            case "marks":
            {
                var result = AdaptiveCard.FromJson(File.ReadAllText(@".\Cards\json\MarksForm.json"));
                card = result.Card;
            }
            break;

            case "img-base64":
            {
                var result = AdaptiveCard.FromJson(File.ReadAllText(@".\Cards\json\ImageCard.json"));
                card = result.Card;
            }
            break;

            case "img":
            {
                var result = AdaptiveCard.FromJson(File.ReadAllText(@".\Cards\json\ImageCardUrl.json"));
                card = result.Card;
            }
            break;

            case "prompts":
            {
                await _promptDialog.RunAsync(turnContext,
                                             _conversationState.CreateProperty <DialogState>(nameof(DialogState)),
                                             cancellationToken);

                return;
            }

            case "carousel":
            {
                Activity replyToConversation = MessageFactory.Text("Should see in carousel format");
                replyToConversation.AttachmentLayout = AttachmentLayoutTypes.Carousel;
                replyToConversation.Attachments      = new List <Attachment>();

                var card1 = AdaptiveCard.FromJson(File.ReadAllText(@".\Cards\json\card1.json"));
                var card2 = AdaptiveCard.FromJson(File.ReadAllText(@".\Cards\json\card2.json"));

                replyToConversation.Attachments.Add(CreateApativeCardAttachment(card1.Card));
                replyToConversation.Attachments.Add(CreateApativeCardAttachment(card2.Card));

                await turnContext.SendActivityAsync(replyToConversation);

                return;
            }

            case "invoke":
            {
                var c = new HeroCard
                {
                    Title = "Task Module Demo",
                    Text  = "Click the below button to launch Task Module",

                    Buttons = new List <CardAction>
                    {
                        new CardAction
                        {
                            Type  = "invoke",
                            Title = "Open Task Module",
                            Text  = "Open Task Module",
                            Value = "{\"type\": \"task/fetch\", \"data\": \"alertform\"}"
                        },
                        new CardAction
                        {
                            Type  = "openUrl",
                            Title = "StageViewDeeplink",
                            Value = "https://teams.microsoft.com/l/stage/2a527703-1f6f-4559-a332-d8a7d288cd88/0?context={\"contentUrl\":\"https%3A%2F%2Fmicrosoft.sharepoint.com%2Fteams%2FLokisSandbox%2FSitePages%2FSandbox-Page.aspx\", \"websiteURL\":\"https%3A%2F%2Fmicrosoft.sharepoint.com%2Fteams%2FLokisSandbox%2FSitePages%2FSandbox-Page.aspx\", \"title\":\"Contoso\"}",
                        }
                    }
                };
                await turnContext.SendActivityAsync(MessageFactory.Attachment(c.ToAttachment()));

                return;
            }

            default:
                await turnContext.SendActivityAsync(MessageFactory.Text("Complete!"), cancellationToken);

                return;
            }
            await turnContext.SendActivityAsync(
                MessageFactory.Attachment(CreateApativeCardAttachment(card)),
                cancellationToken);
        }
Exemplo n.º 3
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)
        {
            // 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);

            services.AddSingleton(conversationState);

            var userState = new UserState(dataStore);

            services.AddSingleton(userState);

            services.AddSingleton <StateAccessor>(sp =>
            {
                // 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 StateAccessor
                {
                    ConversationDialogState = conversationState.CreateProperty <DialogState>(StateAccessor.DialogStateName),
                };

                return(accessors);
            });

            services.AddBot <Bot>(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 <Bot>();

                // 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.");
                };
            });
        }
Exemplo n.º 4
0
        public async Task OAuthPromptWithMagicCode()
        {
            var convoState  = new ConversationState(new MemoryStorage());
            var dialogState = convoState.CreateProperty <DialogState>("dialogState");

            var adapter = new TestAdapter()
                          .Use(new AutoSaveStateMiddleware(convoState));

            // Create new DialogSet.
            var dialogs = new DialogSet(dialogState);

            dialogs.Add(new OAuthPrompt("OAuthPrompt", new OAuthPromptSettings()
            {
                Text = "Please sign in", ConnectionName = ConnectionName, Title = "Sign in"
            }));

            BotCallbackHandler botCallbackHandler = async(turnContext, cancellationToken) =>
            {
                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                var results = await dc.ContinueDialogAsync(cancellationToken);

                if (results.Status == DialogTurnStatus.Empty)
                {
                    var options = new PromptOptions
                    {
                        Prompt = new Activity
                        {
                            Type = ActivityTypes.Message,
                            Text = "Please select an option."
                        },
                        RetryPrompt = new Activity
                        {
                            Type = ActivityTypes.Message,
                            Text = "Retrying - Please select an option."
                        }
                    };
                    await dc.PromptAsync("OAuthPrompt", options, cancellationToken);
                }
                else if (results.Status == DialogTurnStatus.Complete)
                {
                    if (results.Result is TokenResponse)
                    {
                        await turnContext.SendActivityAsync(MessageFactory.Text("Logged in."), cancellationToken);
                    }
                    else
                    {
                        await turnContext.SendActivityAsync(MessageFactory.Text("Failed."), cancellationToken);
                    }
                }
            };

            await new TestFlow(adapter, botCallbackHandler)
            .Send("hello")
            .AssertReply(activity =>
            {
                Assert.Single(((Activity)activity).Attachments);
                Assert.Equal(OAuthCard.ContentType, ((Activity)activity).Attachments[0].ContentType);

                Assert.Equal(InputHints.AcceptingInput, ((Activity)activity).InputHint);

                // Add a magic code to the adapter
                adapter.AddUserToken(ConnectionName, activity.ChannelId, activity.Recipient.Id, Token, MagicCode);
            })
            .Send(MagicCode)
            .AssertReply("Logged in.")
            .StartTestAsync();
        }
Exemplo n.º 5
0
        public async Task AutoSaveStateMiddleware_Chain()
        {
            var storage = new MemoryStorage();

            // setup userstate
            var userState    = new UserState(storage);
            var userProperty = userState.CreateProperty <int>("userCount");

            // setup convState
            var convState    = new ConversationState(storage);
            var convProperty = convState.CreateProperty <int>("convCount");
            var bss          = new AutoSaveStateMiddleware()
                               .Add(userState)
                               .Add(convState);
            var adapter = new TestAdapter(TestAdapter.CreateConversation(TestContext.TestName))
                          .Use(bss);

            const int          USER_INITITAL_COUNT        = 100;
            const int          CONVERSATION_INITIAL_COUNT = 10;
            BotCallbackHandler botLogic = async(context, cancellationToken) =>
            {
                // get userCount and convCount from botStateSet
                var userCount = await userProperty.GetAsync(context, () => USER_INITITAL_COUNT).ConfigureAwait(false);

                var convCount = await convProperty.GetAsync(context, () => CONVERSATION_INITIAL_COUNT).ConfigureAwait(false);

                if (context.Activity.Type == ActivityTypes.Message)
                {
                    if (context.Activity.Text == "get userCount")
                    {
                        await context.SendActivityAsync(context.Activity.CreateReply($"{userCount}"));
                    }
                    else if (context.Activity.Text == "get convCount")
                    {
                        await context.SendActivityAsync(context.Activity.CreateReply($"{convCount}"));
                    }
                }

                // increment userCount and set property using accessor.  To be saved later by AutoSaveStateMiddleware
                userCount++;
                await userProperty.SetAsync(context, userCount);

                // increment convCount and set property using accessor.  To be saved later by AutoSaveStateMiddleware
                convCount++;
                await convProperty.SetAsync(context, convCount);
            };

            await new TestFlow(adapter, botLogic)
            .Send("test1")
            .Send("get userCount")
            .AssertReply((USER_INITITAL_COUNT + 1).ToString())
            .Send("get userCount")
            .AssertReply((USER_INITITAL_COUNT + 2).ToString())
            .Send("get convCount")
            .AssertReply((CONVERSATION_INITIAL_COUNT + 3).ToString())
            .StartTestAsync();

            // new adapter on new conversation
            var bss2 = new AutoSaveStateMiddleware()
                       .Add(userState)
                       .Add(convState);

            adapter = new TestAdapter(new ConversationReference
            {
                ChannelId    = "test",
                ServiceUrl   = "https://test.com",
                User         = new ChannelAccount("user1", "User1"),
                Bot          = new ChannelAccount("bot", "Bot"),
                Conversation = new ConversationAccount(false, "convo2", "Conversation2"),
            })
                      .Use(bss2);

            await new TestFlow(adapter, botLogic)
            .Send("get userCount")
            .AssertReply((USER_INITITAL_COUNT + 4).ToString(), "user count should continue on new conversation")
            .Send("get convCount")
            .AssertReply((CONVERSATION_INITIAL_COUNT + 1).ToString(), "conversationCount for conversation2 should be reset")
            .StartTestAsync();
        }
        /// <summary>
        /// Processes an incoming activity.
        /// </summary>
        /// <param name="turnContext">Context object containing information for a single turn of conversation with a user.</param>
        /// <param name="next">The delegate to call to continue the bot middleware pipeline.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Grab the conversation data
            var conversationStateAccessors = _conversationState.CreateProperty <ConversationData>(nameof(ConversationData));
            var conversationData           = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

            string utterance        = null;
            string detectedLanguage = null;


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

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                utterance = ConvertToUtterance(turnContext);
                if (!String.IsNullOrEmpty(utterance))
                {
                    // Detect language
                    if (_configuration["SkipLanguageDetectionAfterInitialChoice"].ToLower() == "false")
                    {
                        detectedLanguage = await _translator.DetectTextRequestAsync(utterance, Consts.SupportedLanguages);

                        if (detectedLanguage != null)
                        {
                            if (detectedLanguage != conversationData.LanguagePreference)
                            {
                                conversationData.LanguageChangeDetected = true;
                                conversationData.LanguagePreference     = detectedLanguage;
                            }
                        }
                    }

                    conversationData.UserQuestion = turnContext.Activity.Text;
                    var translate = ShouldTranslateAsync(turnContext, conversationData.LanguagePreference, cancellationToken);

                    if (translate)
                    {
                        if (turnContext.Activity.Type == ActivityTypes.Message)
                        {
                            var specifiedTranslation = Util.GetTranslation(turnContext.Activity.Text, conversationData.LanguagePreference);
                            if (!String.IsNullOrEmpty(specifiedTranslation))
                            {
                                turnContext.Activity.Text = specifiedTranslation;
                            }
                            else
                            {
                                turnContext.Activity.Text = await _translator.TranslateAsync(turnContext.Activity.Text, _configuration["TranslateTo"], cancellationToken);
                            }
                            conversationData.TranslatedQuestion = turnContext.Activity.Text;
                        }
                    }
                }
                turnContext.OnSendActivities(async(newContext, activities, nextSend) =>
                {
                    // Grab the conversation data
                    var conversationStateAccessors = _conversationState.CreateProperty <ConversationData>(nameof(ConversationData));
                    var conversationData           = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

                    string userLanguage  = conversationData.LanguagePreference;
                    bool shouldTranslate = (userLanguage != _configuration["TranslateTo"]);

                    // Translate messages sent to the user to user language
                    if (shouldTranslate)
                    {
                        List <Task> tasks = new List <Task>();
                        foreach (Activity currentActivity in activities.Where(a => a.Type == ActivityTypes.Message))
                        {
                            var storedAnswer = currentActivity.Text;
                            conversationData.TranslatedAnswer = storedAnswer;
                            if (!Util.ShouldSkipTranslation(storedAnswer, userLanguage)) // Do not translated the stored non-English answer.
                            {
                                // Always return traditional Chinese to be consistent.
                                var langTranslateTo = (userLanguage == "zh-Hans") ? "zh-Hant" : userLanguage;
                                tasks.Add(TranslateMessageActivityAsync(conversationData, currentActivity.AsMessageActivity(), langTranslateTo, true));
                            }
                        }

                        if (tasks.Any())
                        {
                            await Task.WhenAll(tasks).ConfigureAwait(false);
                        }
                        // Log the questions (There are trace activities that pass through and we do not want to log.)
                        if ((conversationData.TranslatedAnswer != null) && !Util.IsDefaultFeedbackMessage(conversationData.TranslatedAnswer, userLanguage))
                        {
                            if (!String.IsNullOrEmpty(conversationData.UserQuestion))
                            {
                                await Util.Log(conversationData.UserQuestion, conversationData.UserAnswer, conversationData.TranslatedQuestion, conversationData.TranslatedAnswer, userLanguage);
                            }
                        }
                    }

                    return(await nextSend());
                });

                turnContext.OnUpdateActivity(async(newContext, activity, nextUpdate) =>
                {
                    // Grab the conversation data
                    var conversationStateAccessors = _conversationState.CreateProperty <ConversationData>(nameof(ConversationData));
                    var conversationData           = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

                    string userLanguage  = conversationData.LanguagePreference;
                    bool shouldTranslate = userLanguage != _configuration["TranslateTo"];

                    // Translate messages sent to the user to user language
                    if (activity.Type == ActivityTypes.Message)
                    {
                        if (shouldTranslate)
                        {
                            await TranslateMessageActivityAsync(conversationData, activity.AsMessageActivity(), userLanguage, false);
                        }
                    }

                    return(await nextUpdate());
                });
            }

            await next(cancellationToken).ConfigureAwait(false);
        }
Exemplo n.º 7
0
        public async Task BasicChoicePrompt()
        {
            var dialogs = new DialogSet();

            dialogs.Add("test-prompt", new ChoicePrompt(Culture.English)
            {
                Style = ListStyle.Inline
            });

            var promptOptions = new ChoicePromptOptions
            {
                Choices = new List <Choice>
                {
                    new Choice {
                        Value = "red"
                    },
                    new Choice {
                        Value = "green"
                    },
                    new Choice {
                        Value = "blue"
                    },
                }
            };

            dialogs.Add("test",
                        new WaterfallStep[]
            {
                async(dc, args, next) =>
                {
                    await dc.PromptAsync("test-prompt", "favorite color?", promptOptions);
                },
                async(dc, args, next) =>
                {
                    var choiceResult = (ChoiceResult)args;
                    await dc.Context.SendActivityAsync($"Bot received the choice '{choiceResult.Value.Value}'.");
                    await dc.EndAsync();
                }
            }
                        );

            ConversationState convoState = new ConversationState(new MemoryStorage());
            var testProperty             = convoState.CreateProperty <Dictionary <string, object> >("test", () => new Dictionary <string, object>());

            TestAdapter adapter = new TestAdapter()
                                  .Use(convoState);

            await new TestFlow(adapter, async(turnContext) =>
            {
                var state = await testProperty.GetAsync(turnContext);
                var dc    = dialogs.CreateContext(turnContext, state);

                await dc.ContinueAsync();

                if (!turnContext.Responded)
                {
                    await dc.BeginAsync("test");
                }
            })
            .Send("hello")
            .AssertReply("favorite color? (1) red, (2) green, or (3) blue")
            .Send("green")
            .AssertReply("Bot received the choice 'green'.")
            .StartTestAsync();
        }
Exemplo n.º 8
0
        public async void LuisDiscoveryTest()
        {
            // arrage
            var expectedIntent = "Sample";
            var expectedName   = "Sample";
            var expectedScore  = 100;
            var luisAppDetail  = new LuisAppDetail()
            {
                Intent = expectedIntent, Name = expectedName, Score = expectedScore
            };
            var luisDiscoveryResponse = new LuisDiscoveryResponse()
            {
                IsSucceded     = true,
                ResultId       = 100,
                LuisAppDetails = new List <LuisAppDetail>()
                {
                    luisAppDetail
                }
            };
            var jsonLuisDiscoveryResponse = JsonConvert.SerializeObject(luisDiscoveryResponse);

            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock
            .Protected()
            .Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()
                )
            .ReturnsAsync(new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new StringContent(jsonLuisDiscoveryResponse),
            })
            .Verifiable();

            var httpClient = new HttpClient(handlerMock.Object)
            {
                BaseAddress = new Uri("http://localhost/")
            };
            var storage           = new MemoryStorage();
            var userState         = new UserState(storage);
            var conversationState = new ConversationState(storage);
            var adapter           = new TestAdapter().Use(new AutoSaveStateMiddleware(conversationState));
            var dialogState       = conversationState.CreateProperty <DialogState>("dialogState");
            var dialogs           = new DialogSet(dialogState);
            var steps             = new WaterfallStep[]
            {
                async(step, cancellationToken) =>
                {
                    await step.Context.SendActivityAsync("response");

                    // act
                    ILuisRouterService luisRouterService = new LuisRouterService(httpClient, EnvironmentName, ContentRootPath, userState);
                    var result = await luisRouterService.LuisDiscoveryAsync(step, "TEXT", "APPLICATIONCODE", "ENCRYPTIONKEY");

                    var item = result.ToList().FirstOrDefault();

                    // assert
                    Assert.Equal(expectedIntent, item.Intent);
                    Assert.Equal(expectedName, item.Name);
                    Assert.Equal(expectedScore, item.Score);

                    return(Dialog.EndOfTurn);
                }
            };

            dialogs.Add(new WaterfallDialog(
                            "test",
                            steps));

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);
                await dc.ContinueDialogAsync(cancellationToken);
                if (!turnContext.Responded)
                {
                    await dc.BeginDialogAsync("test", null, cancellationToken);
                }
            })
            .Send("ask")
            .AssertReply("response")
            .StartTestAsync();
        }
        public async Task CallDialogDefinedInParentComponent()
        {
            var convoState  = new ConversationState(new MemoryStorage());
            var dialogState = convoState.CreateProperty <DialogState>("dialogState");

            var adapter = new TestAdapter()
                          .Use(new AutoSaveStateMiddleware(convoState));

            var options = new Dictionary <string, string> {
                { "value", "test" }
            };

            var childComponent = new ComponentDialog("childComponent");
            var childSteps     = new WaterfallStep[]
            {
                async(step, ct) =>
                {
                    await step.Context.SendActivityAsync("Child started.");

                    return(await step.BeginDialogAsync("parentDialog", options));
                },
                async(step, ct) =>
                {
                    Assert.AreEqual("test", (string)step.Result);
                    await step.Context.SendActivityAsync("Child finished.");

                    return(await step.EndDialogAsync());
                },
            };

            childComponent.AddDialog(new WaterfallDialog(
                                         "childDialog",
                                         childSteps));

            var parentComponent = new ComponentDialog("parentComponent");

            parentComponent.AddDialog(childComponent);
            var parentSteps = new WaterfallStep[]
            {
                async(step, dc) =>
                {
                    var stepOptions = step.Options as IDictionary <string, string>;
                    Assert.IsNotNull(stepOptions);
                    Assert.IsTrue(stepOptions.ContainsKey("value"));
                    await step.Context.SendActivityAsync($"Parent called with: {stepOptions["value"]}");

                    return(await step.EndDialogAsync(stepOptions["value"]));
                },
            };

            parentComponent.AddDialog(new WaterfallDialog(
                                          "parentDialog",
                                          parentSteps));

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                var dialogs = new DialogSet(dialogState);
                dialogs.Add(parentComponent);

                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);

                var results = await dc.ContinueDialogAsync(cancellationToken);
                if (results.Status == DialogTurnStatus.Empty)
                {
                    await dc.BeginDialogAsync("parentComponent", null, cancellationToken);
                }
                else if (results.Status == DialogTurnStatus.Complete)
                {
                    var value = (int)results.Result;
                    await turnContext.SendActivityAsync(MessageFactory.Text("Done"), cancellationToken);
                }
            })
            .Send("Hi")
            .AssertReply("Child started.")
            .AssertReply("Parent called with: test")
            .AssertReply("Child finished.")
            .StartTestAsync();
        }
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Running dialog with Message Activity.");

            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                string temp1   = turnContext.Activity.ChannelData.ToString();
                string boolean = "false";
                Logger.LogInformation(temp1.Length.ToString());
                int len = temp1.Length;
                if (len > 70)
                {
                    if (temp1.Substring(70, 4) != null)
                    {
                        boolean = temp1.Substring(70, 4);
                    }
                    Logger.LogInformation(temp1.Substring(70, 4));
                    if (boolean.Equals("true"))
                    {
                        boolean = "True";
                    }
                    else
                    {
                        boolean = "True";
                    }
                    Logger.LogInformation(boolean);
                    bool entry = System.Convert.ToBoolean(boolean);

                    if (entry)
                    {
                        JToken commandToken = JToken.Parse(turnContext.Activity.Value.ToString());

                        string command       = commandToken["action"].Value <string>();
                        string commandPrompt = command;



                        if (commandPrompt.Equals("order"))
                        {
                            string[] paths       = { ".", "Cards", "orderCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);

                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "inventory")
                        {
                            string[] paths       = { ".", "Cards", "InventoryCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "somethingelse")
                        {
                            commandPrompt = "somethingelse";
                            await Dialog.Run(turnContext, ConversationState.CreateProperty <DialogState>("DialogState"), cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "ordernumber")
                        {
                            string[] paths       = { ".", "Cards", "orderNumberCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "upsordernumber")
                        {
                            string[] paths       = { ".", "Cards", "upsOrderNumberCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "trackingnumber")
                        {
                            string[] paths       = { ".", "Cards", "trackingNumberCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "trackingnumber")
                        {
                            string[] paths       = { ".", "Cards", "trackingNumberCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "skunumber")
                        {
                            string[] paths       = { ".", "Cards", "skuNumberCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else if (command.ToLowerInvariant() == "ponumber")
                        {
                            string[] paths       = { ".", "Cards", "poNumberCard.json" };
                            string   fullPath    = Path.Combine(paths);
                            var      welcomeCard = CreateAdaptiveCardAttachment(fullPath);
                            var      response    = CreateResponse(turnContext.Activity, welcomeCard);
                            await turnContext.SendActivityAsync(response, cancellationToken);
                        }
                        else
                        {
                            await turnContext.SendActivityAsync($"I'm sorry, I didn't understand that. Please try again", cancellationToken : cancellationToken);
                        }
                    }
                }
                else
                {
                    await Dialog.Run(turnContext, ConversationState.CreateProperty <DialogState>("DialogState"), cancellationToken);
                }
            }

            // Run the Dialog with the new message Activity.
        }
Exemplo n.º 11
0
        public async void GetTokenTest()
        {
            // arrage
            var expectedToken    = "TOKEN";
            var identityResponse = new IdentityResponse()
            {
                token = expectedToken
            };
            var jsonIdentityResponse = JsonConvert.SerializeObject(identityResponse);

            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock
            .Protected()
            .Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()
                )
            .ReturnsAsync(new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content    = new StringContent(jsonIdentityResponse),
            })
            .Verifiable();

            var httpClient = new HttpClient(handlerMock.Object)
            {
                BaseAddress = new Uri("http://localhost/")
            };
            var storage           = new MemoryStorage();
            var userState         = new UserState(storage);
            var conversationState = new ConversationState(storage);
            var adapter           = new TestAdapter().Use(new AutoSaveStateMiddleware(conversationState));
            var dialogState       = conversationState.CreateProperty <DialogState>("dialogState");
            var dialogs           = new DialogSet(dialogState);
            var steps             = new WaterfallStep[]
            {
                async(step, cancellationToken) =>
                {
                    await step.Context.SendActivityAsync("response");

                    // act
                    ILuisRouterService luisRouterService = new LuisRouterService(httpClient, EnvironmentName, ContentRootPath, userState);
                    await luisRouterService.GetTokenAsync(step, "encrypted");

                    string token = await luisRouterService.TokenPreference.GetAsync(step.Context, () => { return(string.Empty); });

                    // assert
                    Assert.Equal(expectedToken, token);

                    return(Dialog.EndOfTurn);
                }
            };

            dialogs.Add(new WaterfallDialog(
                            "test",
                            steps));

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);
                await dc.ContinueDialogAsync(cancellationToken);
                if (!turnContext.Responded)
                {
                    await dc.BeginDialogAsync("test", null, cancellationToken);
                }
            })
            .Send("ask")
            .AssertReply("response")
            .StartTestAsync();
        }
Exemplo n.º 12
0
        public async Task ChoicePrompt()
        {
            var dialogs = new DialogSet();

            dialogs.Add("test-prompt", new Dialogs.ChoicePrompt(Culture.English)
            {
                Style = ListStyle.Inline
            });

            var promptOptions = new ChoicePromptOptions
            {
                Choices = new List <Choice>
                {
                    new Choice {
                        Value = "red"
                    },
                    new Choice {
                        Value = "green"
                    },
                    new Choice {
                        Value = "blue"
                    },
                },
                RetryPromptString = "I didn't catch that. Select a color from the list."
            };

            dialogs.Add("test",
                        new WaterfallStep[]
            {
                async(dc, args, next) =>
                {
                    await dc.PromptAsync("test-prompt", "favorite color?", promptOptions);
                },
                async(dc, args, next) =>
                {
                    var choiceResult = (ChoiceResult)args;
                    await dc.Context.SendActivityAsync($"Bot received the choice '{choiceResult.Value.Value}'.");
                    await dc.EndAsync();
                }
            }
                        );

            var activities = TranscriptUtilities.GetFromTestContext(TestContext);

            var convState    = new ConversationState(new MemoryStorage());
            var testProperty = convState.CreateProperty <Dictionary <string, object> >("test");

            var adapter = new TestAdapter()
                          .Use(convState);

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                if (turnContext.Activity.Type == ActivityTypes.Message)
                {
                    var state = await testProperty.GetAsync(turnContext, () => new Dictionary <string, object>());
                    var dc    = dialogs.CreateContext(turnContext, state);

                    await dc.ContinueAsync();

                    if (!turnContext.Responded)
                    {
                        await dc.BeginAsync("test");
                    }
                }
            })
            .Test(activities)
            .StartTestAsync();
        }
Exemplo n.º 13
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Reading settings
            Settings.MicrosoftAppId       = Configuration.GetSection("MicrosoftAppId")?.Value;
            Settings.MicrosoftAppPassword = Configuration.GetSection("MicrosoftAppPassword")?.Value;

            Settings.BotConversationStorageConnectionString = Configuration.GetSection("BotConversationStorageConnectionString")?.Value;
            Settings.BotConversationStorageKey                    = Configuration.GetSection("BotConversationStorageKey")?.Value;
            Settings.BotConversationStorageDatabaseId             = Configuration.GetSection("BotConversationStorageDatabaseId")?.Value;
            Settings.BotConversationStorageUserCollection         = Configuration.GetSection("BotConversationStorageUserCollection")?.Value;
            Settings.BotConversationStorageConversationCollection = Configuration.GetSection("BotConversationStorageConversationCollection")?.Value;
            Settings.LuisAppId01               = Configuration.GetSection("LuisAppId01")?.Value;
            Settings.LuisName01                = Configuration.GetSection("LuisName01")?.Value;
            Settings.LuisAuthoringKey01        = Configuration.GetSection("LuisAuthoringKey01")?.Value;
            Settings.LuisEndpoint01            = Configuration.GetSection("LuisEndpoint01")?.Value;
            Settings.QnAKbId01                 = Configuration.GetSection("QnAKbId01")?.Value;
            Settings.QnAName01                 = Configuration.GetSection("QnAName01")?.Value;
            Settings.QnAEndpointKey01          = Configuration.GetSection("QnAEndpointKey01")?.Value;
            Settings.QnAHostname01             = Configuration.GetSection("QnAHostname01")?.Value;
            Settings.TotalBestNextAnswers      = Configuration.GetSection("TotalBestNextAnswers")?.Value;
            Settings.HighConfidenceThreshold   = Configuration.GetSection("threshold1")?.Value.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
            Settings.MediumConfidenceThreshold = Configuration.GetSection("threshold2")?.Value.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
            Settings.LowConfidenceThreshold    = Configuration.GetSection("threshold3")?.Value.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
            Settings.TotalBestNextAnswers      = Configuration.GetSection("TotalBestNextAnswers")?.Value;


            // Add Application Insights services into service collection
            services.AddApplicationInsightsTelemetry();

            // Add the standard telemetry client
            services.AddSingleton <IBotTelemetryClient, BotTelemetryClient>();

            // Add ASP middleware to store the HTTP body, mapped with bot activity key, in the httpcontext.items
            // This will be picked by the TelemetryBotIdInitializer
            services.AddTransient <TelemetrySaveBodyASPMiddleware>();

            // Add telemetry initializer that will set the correlation context for all telemetry items
            services.AddSingleton <ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();

            // Add telemetry initializer that sets the user ID and session ID (in addition to other
            // bot-specific properties, such as activity ID)
            services.AddSingleton <ITelemetryInitializer, TelemetryBotIdInitializer>();

            // Adding storage
            CosmosDbStorage userstorage = new CosmosDbStorage(new CosmosDbStorageOptions
            {
                AuthKey          = Settings.BotConversationStorageKey,
                CollectionId     = Settings.BotConversationStorageUserCollection,
                CosmosDBEndpoint = new Uri(Settings.BotConversationStorageConnectionString),
                DatabaseId       = Settings.BotConversationStorageDatabaseId,
            });

            CosmosDbStorage conversationstorage = new CosmosDbStorage(new CosmosDbStorageOptions
            {
                AuthKey          = Settings.BotConversationStorageKey,
                CollectionId     = Settings.BotConversationStorageConversationCollection,
                CosmosDBEndpoint = new Uri(Settings.BotConversationStorageConnectionString),
                DatabaseId       = Settings.BotConversationStorageDatabaseId,
            });

            var userState         = new UserState(userstorage);
            var conversationState = new ConversationState(conversationstorage);

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


            // Adding MVC compatibility
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // Adding the credential provider to be used with the Bot Framework Adapter
            services.AddSingleton <ICredentialProvider, ConfigurationCredentialProvider>();

            // Adding the channel provider to be used with the Bot Framework Adapter
            services.AddSingleton <IChannelProvider, ConfigurationChannelProvider>();

            // Adding the Bot Framework Adapter with error handling enabled
            services.AddSingleton <IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

            // Adding middlewares
            services.AddSingleton(new AutoSaveStateMiddleware(userState, conversationState));
            services.AddSingleton(new ShowTypingMiddleware());

            // Adding accessors
            services.AddSingleton(sp =>
            {
                // We need to grab the conversationState we added on the options in the previous step
                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 luisServices = new Dictionary <string, LuisRecognizer>();
                var app          = new LuisApplication(Settings.LuisAppId01, Settings.LuisAuthoringKey01, Settings.LuisEndpoint01);
                var recognizer   = new LuisRecognizer(app);
                luisServices.Add(Settings.LuisName01, recognizer);

                var qnaEndpoint = new QnAMakerEndpoint()
                {
                    KnowledgeBaseId = Settings.QnAKbId01,
                    EndpointKey     = Settings.QnAEndpointKey01,
                    Host            = Settings.QnAHostname01,
                };

                var qnaOptions = new QnAMakerOptions
                {
                    ScoreThreshold = 0.3F
                };

                var qnaServices = new Dictionary <string, QnAMaker>();
                var qnaMaker    = new QnAMaker(qnaEndpoint, qnaOptions);
                qnaServices.Add(Settings.QnAName01, qnaMaker);

                // Create the custom state accessor.
                // State accessors enable other components to read and write individual properties of state.
                var accessors = new BotAccessors(loggerFactory, conversationState, userState, luisServices, qnaServices)
                {
                    ConversationDialogState   = conversationState.CreateProperty <DialogState>("DialogState"),
                    LastSearchPreference      = userState.CreateProperty <string>("LastSearchPreference"),
                    LastAnswerPreference      = userState.CreateProperty <string>("LastAnswerPreference"),
                    IsAuthenticatedPreference = userState.CreateProperty <bool>("IsAu`thenticatedPreference")
                };

                return(accessors);
            });

            services.AddTransient <IBot, BotAppBot>();
        }
Exemplo n.º 14
0
        /// <summary>
        /// Runs dialog system in the context of an ITurnContext.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="cancellationToken">cancelation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task <DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default(CancellationToken))
        {
            BotStateSet       botStateSet       = new BotStateSet();
            ConversationState conversationState = this.ConversationState ?? context.TurnState.Get <ConversationState>() ?? throw new ArgumentNullException($"{nameof(ConversationState)} is not found in the turn context. Have you called adapter.UseState() with a configured ConversationState object?");
            UserState         userState         = this.UserState ?? context.TurnState.Get <UserState>();

            if (conversationState != null)
            {
                botStateSet.Add(conversationState);
            }

            if (userState != null)
            {
                botStateSet.Add(userState);
            }

            // create property accessors
            var lastAccessProperty = conversationState.CreateProperty <DateTime>(LASTACCESS);
            var lastAccess         = await lastAccessProperty.GetAsync(context, () => DateTime.UtcNow, cancellationToken : cancellationToken).ConfigureAwait(false);

            // Check for expired conversation
            var now = DateTime.UtcNow;

            if (this.ExpireAfter.HasValue && (DateTime.UtcNow - lastAccess) >= TimeSpan.FromMilliseconds((double)this.ExpireAfter))
            {
                // Clear conversation state
                await conversationState.ClearStateAsync(context, cancellationToken : cancellationToken).ConfigureAwait(false);
            }

            lastAccess = DateTime.UtcNow;
            await lastAccessProperty.SetAsync(context, lastAccess, cancellationToken : cancellationToken).ConfigureAwait(false);

            // get dialog stack
            var         dialogsProperty = conversationState.CreateProperty <DialogState>(DIALOGS);
            DialogState dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken : cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(this.dialogSet, context, dialogState);

            // set DSM configuration
            dc.SetStateConfiguration(this.StateConfiguration ?? DialogStateManager.CreateStandardConfiguration(conversationState, userState));

            // load scopes
            await dc.GetState().LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            DialogTurnResult turnResult = null;

            if (dc.ActiveDialog == null)
            {
                // start root dialog
                turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
            }
            else
            {
                // Continue execution
                // - This will apply any queued up interruptions and execute the current/next step(s).
                turnResult = await dc.ContinueDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false);

                if (turnResult.Status == DialogTurnStatus.Empty)
                {
                    // restart root dialog
                    turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
                }
            }

            // save all state scopes to their respective stores.
            await dc.GetState().SaveAllChangesAsync(cancellationToken).ConfigureAwait(false);

            // save botstate changes
            await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false);

            // send trace of memory
            var snapshot      = dc.GetState().GetMemorySnapshot();
            var traceActivity = (Activity)Activity.CreateTraceActivity("BotState", "https://www.botframework.com/schemas/botState", snapshot, "Bot State");
            await dc.Context.SendActivityAsync(traceActivity).ConfigureAwait(false);

            return(new DialogManagerResult()
            {
                TurnResult = turnResult
            });
        }
Exemplo n.º 15
0
        public void ConfigureServices(IServiceCollection services)
        {
            IStorage dataStore;

            var environment = Configuration.GetSection("environment")?.Value == "production" ? "production" : "development";

            _isProduction = environment == "production";

            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(@".\PasswordBot.bot", secretKey);

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


            // The Memory Storage used here is for local bot debugging only. When the bot
            // is restarted, everything stored in memory will be gone.
            if (!_isProduction)
            {
                dataStore = new MemoryStorage();
            }
            else
            {
                // //Storage configuration name or ID from the .bot file.
                const string StorageConfigurationId = "blob";
                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 = "passwordnotificationbot";
                var          storageContainer    = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
                dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);
            }

            // Create PasswordNotificationState object.
            // The Password Notification State object is where we persist anything at the notification-scope.
            // Note: It's independent of any user or conversation.
            PasswordNotificationState notificationsState = new PasswordNotificationState(dataStore);

            // Make it available to our bot
            services.AddSingleton(sp => notificationsState);

            ConversationState conversationState       = new ConversationState(dataStore);
            UserState         userState               = new UserState(dataStore);
            DialogState       conversationDialogState = new DialogState();

            services.AddBot <PasswordBot>(options =>
            {
                // Retrieve current endpoint.
                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);
                options.ChannelProvider    = new ConfigurationChannelProvider(Configuration);

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

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

            services.AddSingleton <StateBotAccessors>(sp =>
            {
                return(new StateBotAccessors(conversationDialogState, conversationState, userState)
                {
                    // The dialogs will need a state store accessor. Creating it here once (on-demand) allows the dependency injection
                    // to hand it to our IBot class that is create per-request.
                    ConversationDataAccessor = conversationState.CreateProperty <ConversationData>(StateBotAccessors.ConversationDataName),
                    UserProfileAccessor = userState.CreateProperty <UserProfile>(StateBotAccessors.UserProfileName),
                    ConversationDialogStateAccessor = conversationState.CreateProperty <DialogState>(StateBotAccessors.ConversationDialogName),
                });
            });

            services.AddSingleton(sp =>
            {
                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}'.");
                }

                return((EndpointService)service);
            });
        }
Exemplo n.º 16
0
        /// <summary>
        /// Runs dialog system in the context of an ITurnContext.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task <DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default)
        {
            var botStateSet = new BotStateSet();

            // Preload TurnState with DM TurnState.
            foreach (var pair in InitialTurnState)
            {
                context.TurnState.Set(pair.Key, pair.Value);
            }

            // register DialogManager with TurnState.
            context.TurnState.Set(this);

            if (ConversationState == null)
            {
                ConversationState = context.TurnState.Get <ConversationState>() ?? throw new InvalidOperationException($"Unable to get an instance of {nameof(ConversationState)} from turnContext.");
            }
            else
            {
                context.TurnState.Set(ConversationState);
            }

            botStateSet.Add(ConversationState);

            if (UserState == null)
            {
                UserState = context.TurnState.Get <UserState>();
            }
            else
            {
                context.TurnState.Set(UserState);
            }

            if (UserState != null)
            {
                botStateSet.Add(UserState);
            }

            // create property accessors
            var lastAccessProperty = ConversationState.CreateProperty <DateTime>(LastAccess);
            var lastAccess         = await lastAccessProperty.GetAsync(context, () => DateTime.UtcNow, cancellationToken).ConfigureAwait(false);

            // Check for expired conversation
            if (ExpireAfter.HasValue && (DateTime.UtcNow - lastAccess) >= TimeSpan.FromMilliseconds((double)ExpireAfter))
            {
                // Clear conversation state
                await ConversationState.ClearStateAsync(context, cancellationToken).ConfigureAwait(false);
            }

            lastAccess = DateTime.UtcNow;
            await lastAccessProperty.SetAsync(context, lastAccess, cancellationToken).ConfigureAwait(false);

            // get dialog stack
            var dialogsProperty = ConversationState.CreateProperty <DialogState>(_dialogStateProperty);
            var dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(Dialogs, context, dialogState);

            // Call the common dialog "continue/begin" execution pattern shared with the classic RunAsync extension method
            var turnResult = await DialogExtensions.InternalRunAsync(context, _rootDialogId, dc, StateConfiguration, cancellationToken).ConfigureAwait(false);

            // save BotState changes
            await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false);

            return(new DialogManagerResult {
                TurnResult = turnResult
            });
        }
Exemplo n.º 17
0
 public void MainDialog_ConstructorValid()
 {
     var convoState          = new ConversationState(new MemoryStorage());
     var dialogStateProperty = convoState.CreateProperty <DialogState>("dialogstate");
     var mainDialog          = new MainDialog(dialogStateProperty);
 }
 public void initializeAccessors()
 {
     ConversationDataAccessor = ConversationState.CreateProperty <ConversationData>(ConversationDataId);
     DialogStateAccessor      = ConversationState.CreateProperty <DialogState>(DialogStateId);
     UserProfileAccessor      = UserState.CreateProperty <UserProfile>(UserProfileId);
 }
Exemplo n.º 19
0
        /// <summary>
        /// Runs dialog system in the context of an ITurnContext.
        /// </summary>
        /// <param name="context">turn context.</param>
        /// <param name="cancellationToken">cancelation token.</param>
        /// <returns>result of the running the logic against the activity.</returns>
        public async Task <DialogManagerResult> OnTurnAsync(ITurnContext context, CancellationToken cancellationToken = default(CancellationToken))
        {
            var botStateSet = new BotStateSet();

            // preload turnstate with DM turnstate
            foreach (var pair in this.TurnState)
            {
                context.TurnState.Set(pair.Key, pair.Value);
            }

            if (this.ConversationState == null)
            {
                this.ConversationState = context.TurnState.Get <ConversationState>() ?? throw new ArgumentNullException(nameof(this.ConversationState));
            }
            else
            {
                context.TurnState.Set(this.ConversationState);
            }

            botStateSet.Add(this.ConversationState);

            if (this.UserState == null)
            {
                this.UserState = context.TurnState.Get <UserState>();
            }

            if (this.UserState != null)
            {
                botStateSet.Add(this.UserState);
            }

            // create property accessors
            var lastAccessProperty = ConversationState.CreateProperty <DateTime>(LASTACCESS);
            var lastAccess         = await lastAccessProperty.GetAsync(context, () => DateTime.UtcNow, cancellationToken : cancellationToken).ConfigureAwait(false);

            // Check for expired conversation
            var now = DateTime.UtcNow;

            if (this.ExpireAfter.HasValue && (DateTime.UtcNow - lastAccess) >= TimeSpan.FromMilliseconds((double)this.ExpireAfter))
            {
                // Clear conversation state
                await ConversationState.ClearStateAsync(context, cancellationToken : cancellationToken).ConfigureAwait(false);
            }

            lastAccess = DateTime.UtcNow;
            await lastAccessProperty.SetAsync(context, lastAccess, cancellationToken : cancellationToken).ConfigureAwait(false);

            // get dialog stack
            var         dialogsProperty = ConversationState.CreateProperty <DialogState>(this.dialogStateProperty);
            DialogState dialogState     = await dialogsProperty.GetAsync(context, () => new DialogState(), cancellationToken : cancellationToken).ConfigureAwait(false);

            // Create DialogContext
            var dc = new DialogContext(this.Dialogs, context, dialogState);

            // get the dialogstatemanager configuration
            var dialogStateManager = new DialogStateManager(dc);
            await dialogStateManager.LoadAllScopesAsync(cancellationToken).ConfigureAwait(false);

            dc.Context.TurnState.Add(dialogStateManager);

            DialogTurnResult turnResult = null;

            // Loop as long as we are getting valid OnError handled we should continue executing the actions for the turn.
            //
            // NOTE: We loop around this block because each pass through we either complete the turn and break out of the loop
            // or we have had an exception AND there was an OnError action which captured the error.  We need to continue the
            // turn based on the actions the OnError handler introduced.
            while (true)
            {
                try
                {
                    if (dc.ActiveDialog == null)
                    {
                        // start root dialog
                        turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        // Continue execution
                        // - This will apply any queued up interruptions and execute the current/next step(s).
                        turnResult = await dc.ContinueDialogAsync(cancellationToken : cancellationToken).ConfigureAwait(false);

                        if (turnResult.Status == DialogTurnStatus.Empty)
                        {
                            // restart root dialog
                            turnResult = await dc.BeginDialogAsync(this.rootDialogId, cancellationToken : cancellationToken).ConfigureAwait(false);
                        }
                    }

                    // turn successfully completed, break the loop
                    break;
                }
                catch (Exception err)
                {
                    // fire error event, bubbling from the leaf.
                    var handled = await dc.EmitEventAsync(DialogEvents.Error, err, bubble : true, fromLeaf : true, cancellationToken : cancellationToken).ConfigureAwait(false);

                    if (!handled)
                    {
                        // error was NOT handled, throw the exception and end the turn. (This will trigger the Adapter.OnError handler and end the entire dialog stack)
                        throw;
                    }
                }
            }

            // save all state scopes to their respective botState locations.
            await dc.GetState().SaveAllChangesAsync(cancellationToken).ConfigureAwait(false);

            // save botstate changes
            await botStateSet.SaveAllChangesAsync(dc.Context, false, cancellationToken).ConfigureAwait(false);

            // send trace of memory
            var snapshot      = dc.GetState().GetMemorySnapshot();
            var traceActivity = (Activity)Activity.CreateTraceActivity("BotState", "https://www.botframework.com/schemas/botState", snapshot, "Bot State");
            await dc.Context.SendActivityAsync(traceActivity).ConfigureAwait(false);

            return(new DialogManagerResult()
            {
                TurnResult = turnResult
            });
        }
Exemplo n.º 20
0
 public async Task Handle(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
 {
     await _qnADialog.RunAsync(turnContext,
                               _conversationState.CreateProperty <DialogState>(nameof(DialogState)), cancellationToken);
 }