private async Task SendToSkill(ITurnContext turnContext, BotFrameworkSkill targetSkill, Activity activity = null, CancellationToken cancellationToken = default)
        {
            // NOTE: Always SaveChanges() before calling a skill so that any activity generated by the skill
            // will have access to current accurate state.
            await _conversationState.SaveChangesAsync(turnContext, force : true, cancellationToken : cancellationToken);

            var activityToSend = activity ?? (Activity)turnContext.Activity;

            if (activityToSend.Type == ActivityTypes.Invoke)
            {
                var invokeResponse = await PostActivityToSkill <JObject>(targetSkill, activityToSend, cancellationToken);

                if (invokeResponse != null)
                {
                    await turnContext.SendActivityAsync("Received Invoke Response Body: " + invokeResponse.ToString());
                }
            }
            else
            {
                var expectedReplies = await PostActivityToSkill <ExpectedReplies>(targetSkill, activityToSend, cancellationToken);

                if (expectedReplies != null && activity.DeliveryMode == DeliveryModes.ExpectReplies)
                {
                    // sending messages back requires the turnContext.Activity.DeliveryMode to NOT be ExpectReplies, so change it back
                    turnContext.Activity.DeliveryMode = DeliveryModes.Normal;
                    foreach (var a in expectedReplies.Activities)
                    {
                        a.Text = $"ExpectedReplies: {a.Text}";
                        await turnContext.SendActivityAsync(a);
                    }
                }
            }
        }
Пример #2
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            // Try to get the active skill
            var activeSkill = await _activeSkillProperty.GetAsync(turnContext, () => null, cancellationToken);

            if (activeSkill != null)
            {
                // Send the activity to the skill
                await SendToSkill(turnContext, activeSkill, cancellationToken);

                return;
            }

            if (turnContext.Activity.Text.Contains("skill"))
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("Got it, connecting you to the skill..."), cancellationToken);

                // Save active skill in state
                await _activeSkillProperty.SetAsync(turnContext, _targetSkill, cancellationToken);

                // Send the activity to the skill
                await SendToSkill(turnContext, _targetSkill, cancellationToken);

                return;
            }

            // just respond
            await turnContext.SendActivityAsync(MessageFactory.Text("Me no nothin'. Say \"skill\" and I'll patch you through"), cancellationToken);

            // Save conversation state
            await _conversationState.SaveChangesAsync(turnContext, force : true, cancellationToken : cancellationToken);
        }
Пример #3
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            var text = turnContext.Activity.Text;

            if (!string.IsNullOrEmpty(text))
            {
                BotFrameworkSkill targetSkill = null;
                if (_skillsConfig.Skills.TryGetValue(text, out targetSkill))
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text($"Got it, connecting you to the {text} skill..."), cancellationToken);

                    // Save active skill in state
                    await _activeSkillProperty.SetAsync(turnContext, targetSkill, cancellationToken);

                    // Send the activity to the skill
                    await SendToSkill(turnContext, targetSkill, cancellationToken);

                    return;
                }
            }

            // just respond with choices
            await turnContext.SendActivityAsync(MessageFactory.Attachment(GetOptionsAttachment()), cancellationToken);

            // Save conversation state
            await _conversationState.SaveChangesAsync(turnContext, force : true, cancellationToken : cancellationToken);
        }
        /// <inheritdoc/>
        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
        {
            await base.OnTurnAsync(turnContext, cancellationToken);

            // Save any state changes that might have occurred during the turn.
            await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        }
Пример #5
0
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            //connecting to the echobot skill
            if (turnContext.Activity.Text.Contains("echobot skill"))
            {
                //var targetSkillId = "EchoSkillBot";
                //BotFrameworkSkill value;

                //if (!_skillsConfig.Skills.TryGetValue(targetSkillId, out value))
                //{
                //    skills_Ids.TargetSkill = value;
                //    Console.WriteLine("skills_Ids.TargetSkill ---> " + skills_Ids.TargetSkill);
                //    Console.WriteLine("value ---> " + skills_Ids.TargetSkill);
                //    throw new ArgumentException($"Skill with ID \"{targetSkillId}\" not found in configuration");
                //}
                //Console.WriteLine("skills_Ids.TargetSkill ---> " + skills_Ids.TargetSkill);
                //Console.WriteLine("value ---> " + value);

                await turnContext.SendActivityAsync(MessageFactory.Text("Got it, connecting you to the skill..."), cancellationToken);



                // Save active skill in state
                await _activeSkillProperty.SetAsync(turnContext, _targetSkill, cancellationToken);

                // Send the activity to the skill
                await SendToSkill(turnContext, _targetSkill, cancellationToken);

                return;
            }

            ////connecting to the countris QnA skill
            //else if(turnContext.Activity.Text.Contains("countries QnA"))
            //{

            //    var targetSkillId = "EchoSkillBot";
            //    BotFrameworkSkill value;

            //    if (!_skillsConfig.Skills.TryGetValue(targetSkillId, out value))
            //    {
            //        skills_Ids.TargetSkill = value;
            //        throw new ArgumentException($"Skill with ID \"{targetSkillId}\" not found in configuration");
            //    }

            //    await turnContext.SendActivityAsync(MessageFactory.Text("Got it, connecting you to the skill..."), cancellationToken);

            //    // Save active skill in state
            //    await _activeSkillProperty.SetAsync(turnContext, skills_Ids.TargetSkill, cancellationToken);

            //    // Send the activity to the skill
            //    await SendToSkill(turnContext, skills_Ids.TargetSkill, cancellationToken);
            //    return;
            //}

            // just respond
            await turnContext.SendActivityAsync(MessageFactory.Text("Me no nothin'. Say \"echobot skill or countries QnA\" and I'll patch you through"), cancellationToken);

            // Save conversation state
            await _conversationState.SaveChangesAsync(turnContext, force : true, cancellationToken : cancellationToken);
        }
Пример #6
0
        private async Task EndSkillConversationAsync(ITurnContext turnContext)
        {
            if (_skillClient == null || _skillsConfig == null)
            {
                return;
            }

            try
            {
                // Inform the active skill that the conversation is ended so that it has a chance to clean up.
                // Note: the root bot manages the ActiveSkillPropertyName, which has a value while the root bot
                // has an active conversation with a skill.
                var activeSkill = await _conversationState.CreateProperty <BotFrameworkSkill>(MainDialog.ActiveSkillPropertyName).GetAsync(turnContext, () => null);

                if (activeSkill != null)
                {
                    var endOfConversation = Activity.CreateEndOfConversationActivity();
                    endOfConversation.Code = "RootSkillError";
                    endOfConversation.ApplyConversationReference(turnContext.Activity.GetConversationReference(), true);

                    await _conversationState.SaveChangesAsync(turnContext, true);

                    await _skillClient.PostActivityAsync(_settings.MicrosoftAppId, activeSkill, _skillsConfig.SkillHostEndpoint, (Activity)endOfConversation, CancellationToken.None);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught on attempting to send EndOfConversation : {ex}");
            }
        }
Пример #7
0
        protected override async Task OnMembersAddedAsync(IList <ChannelAccount> membersAdded, ITurnContext <IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            var dc = await _dialogSet.CreateContextAsync(turnContext);

            await dc.BeginDialogAsync(nameof(MainDialog));

            // save any state changes made to your state objects.
            await _conversationState.SaveChangesAsync(turnContext);
        }
Пример #8
0
        private async Task SendToSkill(ITurnContext turnContext, BotFrameworkSkill targetSkill, CancellationToken cancellationToken)
        {
            // NOTE: Always SaveChanges() before calling a skill so that any activity generated by the skill
            // will have access to current accurate state.
            await _conversationState.SaveChangesAsync(turnContext, force : true, cancellationToken : cancellationToken);

            // route the activity to the skill
            var response = await _skillClient.PostActivityAsync(_botId, targetSkill, _skillsConfig.SkillHostEndpoint, (Activity)turnContext.Activity, cancellationToken);

            // Check response status
            if (!(response.Status >= 200 && response.Status <= 299))
            {
                throw new HttpRequestException($"Error invoking the skill id: \"{targetSkill.Id}\" at \"{targetSkill.SkillEndpoint}\" (status is {response.Status}). \r\n {response.Body}");
            }
        }
Пример #9
0
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            var state = await _statePropertyAccessor.GetAsync(
                turnContext,
                () => new SampleBotState());

            if (!state.HasIssuedGreeting)
            {
                state.HasIssuedGreeting = true;

                await turnContext.SendActivityAsync("Hello World!");
            }

            var activity = turnContext.Activity;

            if (activity.Type == ActivityTypes.Message)
            {
                if (activity.Text == "self destruct")
                {
                    throw new System.Exception("Self destruct triggered... BOOM!");
                }

                state.EchoCount++;

                await turnContext.SendActivityAsync($"[{state.EchoCount}] You said: {activity.Text}", cancellationToken : cancellationToken);
            }

            await _conversationState.SaveChangesAsync(turnContext);
        }
        public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
        {
            // The skillBegin event signals the start of a skill conversation to a Bot.
            var activity = turnContext.Activity;

            if (activity != null && activity.Type == ActivityTypes.Event)
            {
                if (activity.Name == SkillEvents.SkillBeginEventName && activity.Value != null && !string.IsNullOrWhiteSpace(activity.Value.ToString()))
                {
                    var skillContext = JsonConvert.DeserializeObject <SkillContext>(activity.Value.ToString());
                    if (skillContext != null)
                    {
                        var accessor = _userState.CreateProperty <SkillContext>(nameof(SkillContext));
                        await accessor.SetAsync(turnContext, skillContext);
                    }
                }
                else if (activity.Name == SkillEvents.CancelAllSkillDialogsEventName)
                {
                    // when skill receives a CancelAllSkillDialogsEvent, clear the dialog stack and short-circuit
                    var currentConversation = await _dialogState.GetAsync(turnContext);

                    currentConversation.DialogStack.Clear();
                    await _dialogState.SetAsync(turnContext, currentConversation);

                    await _conversationState.SaveChangesAsync(turnContext, true);

                    return;
                }
            }

            await next(cancellationToken).ConfigureAwait(false);
        }
Пример #11
0
        /// <summary>
        /// Every conversation turn for our Echo Bot will call this method.
        /// There are no dialogs used, since it's "single turn" processing, meaning a single
        /// request and response.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        /// <seealso cref="IMiddleware"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            DialogContext dc = null;

            switch (turnContext.Activity.Type)
            {
            case ActivityTypes.Message:
                await HandleMessageAsync(turnContext, cancellationToken);

                break;

            case ActivityTypes.Event:
            case ActivityTypes.Invoke:
                // This handles the Microsoft Teams Invoke Activity sent when magic code is not used.
                dc = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

                await dc.ContinueDialogAsync(cancellationToken);

                break;

            case ActivityTypes.ConversationUpdate:
                if (turnContext.Activity.MembersAdded != null)
                {
                    await turnContext.SendActivityAsync("ConversationUpdate");

                    await turnContext.SendActivityAsync("Type \"Sign in\" to log in.");
                }
                break;
            }

            await _conversationState.SaveChangesAsync(turnContext);
        }
Пример #12
0
        public BotFrameworkHttpAdapter GetBotAdapter(IStorage storage, BotSettings settings, UserState userState, ConversationState conversationState, IServiceProvider s)
        {
            HostContext.Current.Set <IConfiguration>(Configuration);

            var adapter = new BotFrameworkHttpAdapter(new ConfigurationCredentialProvider(this.Configuration));

            adapter
            .UseStorage(storage)
            .UseState(userState, conversationState);

            // Configure Middlewares
            ConfigureTranscriptLoggerMiddleware(adapter, settings);
            ConfigureInspectionMiddleWare(adapter, settings, s);
            ConfigureShowTypingMiddleWare(adapter, settings);

            adapter.OnTurnError = async(turnContext, exception) =>
            {
                await turnContext.SendActivityAsync(exception.Message).ConfigureAwait(false);

                await conversationState.ClearStateAsync(turnContext).ConfigureAwait(false);

                await conversationState.SaveChangesAsync(turnContext).ConfigureAwait(false);
            };
            return(adapter);
        }
Пример #13
0
        public void SetBotAdapter(BotAdapter adapter, IStorage storage, BotSettings settings, UserState userState, ConversationState conversationState, IServiceProvider s, TelemetryInitializerMiddleware telemetryInitializerMiddleware)
        {
            adapter
            .UseStorage(storage)
            .UseBotState(userState)
            .Use(new RegisterClassMiddleware <ConversationState>(conversationState, typeof(ConversationState).FullName))
            .Use(new RegisterClassMiddleware <IConfiguration>(Configuration))
            .Use(new RegisterClassMiddleware <BotAdapter>(adapter))
            .Use(new RegisterClassMiddleware <TaskManager>(new TaskManager()))
            .Use(new HandleGroupMentionMiddleware())
            .Use(new ReferenceMiddleware())
            .Use(telemetryInitializerMiddleware);

            // Configure Middlewares
            ConfigureTranscriptLoggerMiddleware(adapter, settings);
            ConfigureInspectionMiddleWare(adapter, settings, storage);
            ConfigureShowTypingMiddleWare(adapter, settings);

            adapter.OnTurnError = async(turnContext, exception) =>
            {
                await turnContext.SendActivityAsync(exception.Message).ConfigureAwait(false);

                await conversationState.ClearStateAsync(turnContext).ConfigureAwait(false);

                await conversationState.SaveChangesAsync(turnContext).ConfigureAwait(false);
            };
        }
        /// <summary>
        /// Processes a message activity.
        /// </summary>
        /// <param name="turnContext">Context for the current turn of conversation.</param>
        /// <param name="cancellationToken">CancellationToken propagates notifications that operations should be cancelled.</param>
        /// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
        protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            if (turnContext.Activity.Text.Contains("auth") || turnContext.Activity.Text.Contains("logout") || turnContext.Activity.Text.Contains("Yes") || turnContext.Activity.Text.Contains("No"))
            {
                await _loginDialog.RunAsync(turnContext, _conversationState.CreateProperty <DialogState>(nameof(DialogState)), cancellationToken);

                // Save any state changes that might have occurred during the turn.
                await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            }
            else if (turnContext.Activity.Text.Contains("end") || turnContext.Activity.Text.Contains("stop"))
            {
                // Send End of conversation at the end.
                await turnContext.SendActivityAsync(MessageFactory.Text($"Ending conversation from the skill..."), cancellationToken);

                var endOfConversation = Activity.CreateEndOfConversationActivity();
                endOfConversation.Code = EndOfConversationCodes.CompletedSuccessfully;
                await turnContext.SendActivityAsync(endOfConversation, cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);

                await turnContext.SendActivityAsync(MessageFactory.Text("Say \"end\" or \"stop\" and I'll end the conversation and back to the parent."), cancellationToken);
            }
        }
Пример #15
0
        public async Task DefaultOptions_Positive()
        {
            var storage   = new MemoryStorage();
            var convState = new ConversationState(storage);

            var adapter = new TestAdapter(TestAdapter.CreateConversation("Name"))
                          .Use(new FeedbackMiddleware(convState, new NullBotTelemetryClient()));

            var response = "Response";
            var tag      = "Tag";

            await new TestFlow(adapter, async(context, cancellationToken) =>
            {
                await context.SendActivityAsync(response);
                await FeedbackMiddleware.RequestFeedbackAsync(context, tag);

                // TODO save manualy
                await convState.SaveChangesAsync(context, false, cancellationToken);
            })
            .Send("foo")
            .AssertReply(response)
            .AssertReply((activity) =>
            {
                var card = activity.AsMessageActivity().Attachments[0].Content as HeroCard;
                Assert.AreEqual(card.Buttons.Count, 3);
            })
            .Send(positiveFeedback)
            .AssertReply("Thanks, I appreciate your feedback.")
            .StartTestAsync();
        }
Пример #16
0
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
        {
            await _mainDialog.RunAsync(turnContext, _conversationState.CreateProperty <DialogState>("DialogState"), cancellationToken);

            // Save any state changes that might have occured during the turn.
            await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        }
        public async Task TestConversationStateBlobStorage()
        {
            // Arrange
            var storageAccount    = CloudStorageAccount.Parse(ConnectionString);
            var storage           = new AzureBlobStorage(storageAccount, ContainerName);
            var conversationState = new ConversationState(storage);
            var propAccessor      = conversationState.CreateProperty <Prop>("prop");
            var adapter           = new TestStorageAdapter();
            var activity          = new Activity
            {
                ChannelId    = "123",
                Conversation = new ConversationAccount {
                    Id = "abc"
                },
            };

            // Act
            var turnContext1 = new TurnContext(adapter, activity);
            var propValue1   = await propAccessor.GetAsync(turnContext1, () => new Prop());

            propValue1.X = "hello";
            propValue1.Y = "world";
            await conversationState.SaveChangesAsync(turnContext1, force : true);

            var turnContext2 = new TurnContext(adapter, activity);
            var propValue2   = await propAccessor.GetAsync(turnContext2);

            // Assert
            Assert.AreEqual("hello", propValue2.X);
            Assert.AreEqual("world", propValue2.Y);
        }
Пример #18
0
        private async Task <DialogTurnResult> SendToSkillAsync(DialogContext dc, Activity activity, CancellationToken cancellationToken)
        {
            // add checking on skill configuration before sending over to skill
            // because we can't perform the check in constructor which will fail startup of the app
            if (string.IsNullOrWhiteSpace(_skill.AppId))
            {
                throw new ArgumentNullException(nameof(_skill.AppId));
            }

            if (string.IsNullOrWhiteSpace(_skill.SkillEndpoint.ToString()))
            {
                throw new ArgumentNullException(nameof(_skill.SkillEndpoint));
            }

            if (string.IsNullOrWhiteSpace(_skillHostEndpoint.ToString()))
            {
                throw new ArgumentNullException(nameof(_skillHostEndpoint));
            }

            if (dc != null)
            {
                // Always save state before forwarding
                // (the dialog stack won't get updated with the skillDialog and things won't work if you don't)
                await _conversationState.SaveChangesAsync(dc.Context, true, cancellationToken).ConfigureAwait(false);
            }

            var response = await _skillClient.PostActivityAsync(_botId, _skill, _skillHostEndpoint, activity, cancellationToken).ConfigureAwait(false);

            if (!(response.Status >= 200 && response.Status <= 299))
            {
                throw new HttpRequestException($"Error invoking the skill id: \"{_skill.Id}\" at \"{_skill.SkillEndpoint}\" (status is {response.Status}). \r\n {response.Body}");
            }

            return(EndOfTurn);
        }
        /// <summary>
        /// Informs to the active skill that the conversation is ended so that it has a chance to clean up.
        /// </summary>
        /// <param name="turnContext">Context for the current turn of conversation.</param>
        /// <param name="cancellationToken">CancellationToken propagates notifications that operations should be cancelled.</param>
        /// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
        private async Task EndSkillConversationAsync(ITurnContext turnContext, CancellationToken cancellationToken)
        {
            if (_conversationState == null || _skillClient == null || _skillsConfig == null)
            {
                return;
            }

            try
            {
                // Note: ActiveSkillPropertyName is set by the HostBot while messages are being
                // forwarded to a Skill.
                var activeSkill = await _conversationState.CreateProperty <BotFrameworkSkill>(HostBot.ActiveSkillPropertyName).GetAsync(turnContext, () => null, cancellationToken);

                if (activeSkill != null)
                {
                    var botId = _configuration.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey)?.Value;

                    var endOfConversation = Activity.CreateEndOfConversationActivity();
                    endOfConversation.Code = "HostSkillError";
                    endOfConversation.ApplyConversationReference(turnContext.Activity.GetConversationReference(), true);

                    await _conversationState.SaveChangesAsync(turnContext, true, cancellationToken);

                    await _skillClient.PostActivityAsync(botId, activeSkill, _skillsConfig.SkillHostEndpoint, (Activity)endOfConversation, cancellationToken);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught on attempting to send EndOfConversation : {ex}");
            }
        }
Пример #20
0
        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
        {
            // Close down and save state at the end of the turn
            await base.OnTurnAsync(turnContext, cancellationToken);

            await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        }
Пример #21
0
        public async Task ReplaceDialogBranchAsync()
        {
            var conversationState   = new ConversationState(new MemoryStorage());
            var dialogStateAccessor = conversationState.CreateProperty <DialogState>("dialogState");

            var adapter = new TestAdapter();
            var dialog  = new FirstDialog();

            await new TestFlow(adapter, async(turnContext, cancellationToken) =>
            {
                await dialog.RunAsync(turnContext, dialogStateAccessor, cancellationToken);
                await conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            })
            .Send("hello")
            .AssertReply("prompt one")
            .Send("hello")
            .AssertReply("prompt two")
            .Send("replace")
            .AssertReply("*** WaterfallDialog End ***")
            .AssertReply("prompt four")
            .Send("hello")
            .AssertReply("prompt five")
            .Send("hello")
            .StartTestAsync();
        }
Пример #22
0
        public void SetCurrent(string botDir)
        {
            IStorage storage           = new MemoryStorage();
            var      userState         = new UserState(storage);
            var      conversationState = new ConversationState(storage);
            var      inspectionState   = new InspectionState(storage);

            // manage all bot resources
            var resourceExplorer = new ResourceExplorer().AddFolder(botDir);

            var adapter = new BotFrameworkHttpAdapter(new ConfigurationCredentialProvider(Config));

            var credentials = new MicrosoftAppCredentials(Config["MicrosoftAppId"], Config["MicrosoftAppPassword"]);

            adapter
            .UseStorage(storage)
            .UseState(userState, conversationState)
            .UseAdaptiveDialogs()
            .UseResourceExplorer(resourceExplorer)
            .UseLanguageGeneration(resourceExplorer, "common.lg")
            .Use(new RegisterClassMiddleware <IConfiguration>(Config))
            .Use(new InspectionMiddleware(inspectionState, userState, conversationState, credentials));

            adapter.OnTurnError = async(turnContext, exception) =>
            {
                await turnContext.SendActivityAsync(exception.Message).ConfigureAwait(false);

                await conversationState.ClearStateAsync(turnContext).ConfigureAwait(false);

                await conversationState.SaveChangesAsync(turnContext).ConfigureAwait(false);
            };
            CurrentAdapter = adapter;

            CurrentBot = new ComposerBot("Main.dialog", conversationState, userState, resourceExplorer, DebugSupport.SourceMap);
        }
Пример #23
0
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellation)
        {
            var activity = turnContext.Activity;
            var context  = await Dialogs.CreateContextAsync(turnContext);

            if (activity.Type == ActivityTypes.Message)
            {
                var dialogResult = await context.ContinueDialogAsync();

                if (!context.Context.Responded)
                {
                    if (dialogResult != null && dialogResult.Status == DialogTurnStatus.Empty)
                    {
                        await Start(context, activity);
                    }
                    else if (dialogResult != null)
                    {
                        await Complete(dialogResult, context);
                    }
                }
            }
            else if (IsConversationUpdate(activity))
            {
                foreach (var member in activity.MembersAdded)
                {
                    await SendWelcomeCard(member, activity, context);
                }
            }

            await _conversationState.SaveChangesAsync(turnContext);

            await _userState.SaveChangesAsync(turnContext);
        }
Пример #24
0
        /// <summary>
        /// Handles a single turn of the chatbot.
        /// </summary>
        /// <param name="turnContext">Context information for the turn.</param>
        /// <param name="cancellationToken">Cancellation token used to stop processing.</param>
        /// <returns>Returns an awaitable task.</returns>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            var activity      = turnContext.Activity;
            var dialogContext = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

            if (activity.Type == ActivityTypes.ConversationUpdate)
            {
                // Start the root dialog when the user joins the conversation.
                if (turnContext.Activity.MembersAdded.Any(x => x.Id == activity.Recipient.Id))
                {
                    await dialogContext.BeginDialogAsync(DialogNames.RootDialog, null, cancellationToken);
                }
            }
            else if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                var redirectedToManager = await HandleEscalationProtocol(turnContext, dialogContext, cancellationToken);

                if (!redirectedToManager)
                {
                    var handledWithKnowledgeBase = await HandleWithKnowledgeBase(turnContext, cancellationToken);

                    if (!handledWithKnowledgeBase)
                    {
                        await HandleWithDialog(turnContext, dialogContext, cancellationToken);
                    }
                }
            }

            await _conversationState.SaveChangesAsync(turnContext, cancellationToken : cancellationToken);
        }
Пример #25
0
        private async Task EndSkillConversationAsync(ITurnContext turnContext)
        {
            if (_skillsConfig == null)
            {
                return;
            }

            try
            {
                // Inform the active skill that the conversation is ended so that it has
                // a chance to clean up.
                // Note: ActiveSkillPropertyName is set by the RooBot while messages are being
                // forwarded to a Skill.
                var activeSkill = await _conversationState.CreateProperty <BotFrameworkSkill>(RootBot.ActiveSkillPropertyName).GetAsync(turnContext, () => null);

                if (activeSkill != null)
                {
                    var botId = _configuration.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey)?.Value;

                    var endOfConversation = Activity.CreateEndOfConversationActivity();
                    endOfConversation.Code = "RootSkillError";
                    endOfConversation.ApplyConversationReference(turnContext.Activity.GetConversationReference(), true);

                    await _conversationState.SaveChangesAsync(turnContext, true);

                    using var client = _auth.CreateBotFrameworkClient();

                    await client.PostActivityAsync(botId, activeSkill.AppId, activeSkill.SkillEndpoint, _skillsConfig.SkillHostEndpoint, endOfConversation.Conversation.Id, (Activity)endOfConversation, CancellationToken.None);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Exception caught on attempting to send EndOfConversation : {ex}");
            }
        }
Пример #26
0
        private async Task TestConversationStateBlobStorage_Method(IStorage blobs)
        {
            if (StorageEmulatorHelper.CheckEmulator())
            {
                // Arrange
                var conversationState = new ConversationState(blobs);
                var propAccessor      = conversationState.CreateProperty <Prop>("prop");
                var adapter           = new TestStorageAdapter();
                var activity          = new Activity
                {
                    ChannelId    = "123",
                    Conversation = new ConversationAccount {
                        Id = "abc"
                    },
                };

                // Act
                var turnContext1 = new TurnContext(adapter, activity);
                var propValue1   = await propAccessor.GetAsync(turnContext1, () => new Prop());

                propValue1.X = "hello";
                propValue1.Y = "world";
                await conversationState.SaveChangesAsync(turnContext1, force : true);

                var turnContext2 = new TurnContext(adapter, activity);
                var propValue2   = await propAccessor.GetAsync(turnContext2);

                // Assert
                Assert.Equal("hello", propValue2.X);
                Assert.Equal("world", propValue2.Y);
            }
        }
Пример #27
0
        public BotFrameworkHttpAdapter GetBotAdapter(IStorage storage, BotSettings settings, UserState userState, ConversationState conversationState, IServiceProvider s)
        {
            var adapter = IsSkill(settings)
                ? new BotFrameworkHttpAdapter(new ConfigurationCredentialProvider(this.Configuration), s.GetService <AuthenticationConfiguration>())
                : new BotFrameworkHttpAdapter(new ConfigurationCredentialProvider(this.Configuration));

            adapter
            .UseStorage(storage)
            .UseBotState(userState, conversationState)
            .Use(new RegisterClassMiddleware <IConfiguration>(Configuration))
            .Use(s.GetService <TelemetryInitializerMiddleware>());

            // Configure Middlewares
            ConfigureTranscriptLoggerMiddleware(adapter, settings);
            ConfigureInspectionMiddleWare(adapter, settings, storage);
            ConfigureShowTypingMiddleWare(adapter, settings);

            adapter.OnTurnError = async(turnContext, exception) =>
            {
                await turnContext.SendActivityAsync(exception.Message).ConfigureAwait(false);

                await conversationState.ClearStateAsync(turnContext).ConfigureAwait(false);

                await conversationState.SaveChangesAsync(turnContext).ConfigureAwait(false);
            };
            return(adapter);
        }
Пример #28
0
        public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
        {
            var activity = turnContext.Activity;

            if (activity != null && activity.Type == ActivityTypes.Event)
            {
                if (activity.Name == SkillEvents.CancelAllSkillDialogsEventName)
                {
                    // when skill receives a CancelAllSkillDialogsEvent, clear the dialog stack and short-circuit
                    var currentConversation = await _dialogState.GetAsync(turnContext, () => new DialogState());

                    if (currentConversation.DialogStack != null)
                    {
                        currentConversation.DialogStack.Clear();
                        await _dialogState.SetAsync(turnContext, currentConversation);

                        await _conversationState.SaveChangesAsync(turnContext, true);
                    }

                    return;
                }
            }

            await next(cancellationToken).ConfigureAwait(false);
        }
Пример #29
0
        // Note: in production scenarios, this controller should be secured.
        public async Task <IActionResult> Get(string user)
        {
            _continuationParametersStore.TryGetValue(user, out var continuationParameters);

            if (continuationParameters == null)
            {
                // Let the caller know a proactive messages have been sent
                return(new ContentResult
                {
                    Content = $"<html><body><h1>No messages sent</h1> <br/>There are no conversations registered to receive proactive messages for {user}.</body></html>",
                    ContentType = "text/html",
                    StatusCode = (int)HttpStatusCode.OK,
                });
            }

            Exception exception = null;

            try
            {
                async Task ContinuationBotCallback(ITurnContext context, CancellationToken cancellationToken)
                {
                    await context.SendActivityAsync($"Got proactive message for user: {user}", cancellationToken : cancellationToken);

                    // If we didn't have dialogs we could remove the code below, but we want to continue the dialog to clear the
                    // dialog stack.
                    // Run the main dialog to continue WaitForProactiveDialog and send an EndOfConversation when that one is done.
                    // ContinueDialogAsync in WaitForProactiveDialog will get a ContinueConversation event when this is called.
                    await _mainDialog.RunAsync(context, _conversationState.CreateProperty <DialogState>("DialogState"), cancellationToken);

                    // Save any state changes so the dialog stack is persisted.
                    await _conversationState.SaveChangesAsync(context, false, cancellationToken);
                }

                // Continue the conversation with the proactive message
                await((CloudAdapter)_adapter).ContinueConversationAsync((ClaimsIdentity)continuationParameters.ClaimsIdentity, continuationParameters.ConversationReference, continuationParameters.OAuthScope, ContinuationBotCallback, default);
Пример #30
0
        /// <summary>
        /// Every conversation turn for our Echo Bot will call this method.
        /// There are no dialogs used, since it's "single turn" processing, meaning a single
        /// request and response.
        /// </summary>
        /// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
        /// for processing this conversation turn. </param>
        /// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
        /// <seealso cref="BotStateSet"/>
        /// <seealso cref="ConversationState"/>
        /// <seealso cref="IMiddleware"/>
        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Handle Message activity type, which is the main activity type for shown within a conversational interface
            // Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
            // see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // Get the conversation state from the turn context.
                var state = await _counterStateAccessor.GetAsync(turnContext, () => new CounterState());

                // Bump the turn count for this conversation.
                state.TurnCount++;

                // Set the property using the accessor.
                await _counterStateAccessor.SetAsync(turnContext, state);

                // Save the new turn count into the conversation state.
                await _conversationState.SaveChangesAsync(turnContext);

                // Echo back to the user whatever they typed.
                var responseMessage = $"Turn {state.TurnCount}: You sent '{turnContext.Activity.Text}'\n";
                await turnContext.SendActivityAsync(responseMessage);
            }
            else
            {
                await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected");
            }
        }