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