Exemplo n.º 1
0
        private async Task <DialogTurnResult> ForwardActivity(DialogContext dc, Activity activity)
        {
            if (!skillInitialized)
            {
                InititializeSkill(dc);
            }

            // Process the activity (pass through middleware) and then perform Skill processing
            inProcAdapter.ProcessActivity(activity, async(skillContext, cancellationToken) =>
            {
                await activatedSkill.OnTurnAsync(skillContext);
            }).Wait();

            // Incurs a lock each time but given we need to inspect each one for EOC and filter them out this saves another collection of activities. Swings and roundabouts
            var filteredActivities = new List <Activity>();
            var endOfConversation  = false;

            var replyActivity = inProcAdapter.GetNextReply();

            while (replyActivity != null)
            {
                if (replyActivity.Type == ActivityTypes.EndOfConversation)
                {
                    endOfConversation = true;
                }
                else if (replyActivity.Type == ActivityTypes.Event && replyActivity.Name == TokenRequestEventName)
                {
                    // Send trace to emulator
                    await dc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"<--Received a Token Request from a skill"));

                    var skill = dc.ActiveDialog.State[ActiveSkillStateKey] as SkillRegistration;

                    // If you want to force signin interactively and not cached uncomment this
                    // var a = dialogContext.Context.Adapter as BotFrameworkAdapter;
                    // await a.SignOutUserAsync(dialogContext.Context, skill.AuthConnectionName, default(CancellationToken));

                    // Skills could support multiple token types, only allow one through config for now.
                    var prompt = new OAuthPrompt(
                        "SkillAuth",
                        new OAuthPromptSettings()
                    {
                        ConnectionName = skill.AuthConnectionName,
                        Text           = $"Please signin to provide an authentication token for the {skill.Name} skill",
                        Title          = "Skill Authentication",
                        Timeout        = 300000, // User has 5 minutes to login
                    },
                        AuthPromptValidator);

                    var tokenResponse = await prompt.GetUserTokenAsync(dc.Context);

                    if (tokenResponse != null)
                    {
                        var response = replyActivity.CreateReply();
                        response.Type  = ActivityTypes.Event;
                        response.Name  = TokenResponseEventName;
                        response.Value = tokenResponse;

                        var result = await ForwardActivity(dc, response);

                        if (result.Status == DialogTurnStatus.Complete)
                        {
                            endOfConversation = true;
                        }
                    }
                    else
                    {
                        var dtr = await prompt.BeginDialogAsync(dc);
                    }
                }
                else
                {
                    filteredActivities.Add(replyActivity);
                }

                replyActivity = inProcAdapter.GetNextReply();
            }

            if (filteredActivities.Count > 0)
            {
                await dc.Context.SendActivitiesAsync(filteredActivities.ToArray());
            }

            // If we got an End of Conversation then close this skill dialog down
            if (endOfConversation)
            {
                var state = dc.Context.TurnState;
                state[ActiveSkillStateKey] = null;
                skillInitialized           = false;

                // Send trace to emulator
                await dc.Context.SendActivityAsync(new Activity(type : ActivityTypes.Trace, text : $"<--Ending the skill conversation"));

                return(await dc.EndDialogAsync());
            }

            return(EndOfTurn);
        }
Exemplo n.º 2
0
        public async Task <DialogTurnResult> ForwardToSkill(DialogContext dc, Activity activity)
        {
            if (!skillInitialized)
            {
                InitializeSkill(dc);
            }

            _inProcAdapter.ProcessActivity(activity, async(skillContext, ct) =>
            {
                await _activatedSkill.OnTurnAsync(skillContext);
            }).Wait();

            var queue             = new List <Activity>();
            var endOfConversation = false;
            var skillResponse     = _inProcAdapter.GetNextReply();

            while (skillResponse != null)
            {
                if (skillResponse.Type == ActivityTypes.EndOfConversation)
                {
                    endOfConversation = true;
                }
                else if (skillResponse?.Name == TokenRequestEventName)
                {
                    // Send trace to emulator
                    await dc.Context.SendActivityAsync(
                        new Activity(
                            type : ActivityTypes.Trace,
                            text : $"<--Received a Token Request from a skill"
                            ));

                    // Uncomment this line to prompt user for login every time the skill requests a token
                    // var a = dc.Context.Adapter as BotFrameworkAdapter;
                    // await a.SignOutUserAsync(dc.Context, _skill.AuthConnectionName, dc.Context.Activity.From.Id, default(CancellationToken));

                    var authResult = await _authPrompt.BeginDialogAsync(dc);

                    if (authResult.Result?.GetType() == typeof(TokenResponse))
                    {
                        var tokenEvent = skillResponse.CreateReply();
                        tokenEvent.Type  = ActivityTypes.Event;
                        tokenEvent.Name  = TokenResponseEventName;
                        tokenEvent.Value = authResult.Result;

                        return(await ForwardToSkill(dc, tokenEvent));
                    }
                    else
                    {
                        return(authResult);
                    }
                }
                else
                {
                    queue.Add(skillResponse);
                }

                skillResponse = _inProcAdapter.GetNextReply();
            }

            // send skill queue to User
            if (queue.Count > 0)
            {
                await dc.Context.SendActivitiesAsync(queue.ToArray());
            }

            // handle ending the skill conversation
            if (endOfConversation)
            {
                return(await dc.EndDialogAsync());
            }
            else
            {
                return(EndOfTurn);
            }
        }