/// <summary> /// Uses the SkillConversationIdFactory to create or retrieve a Skill Conversation Id, and sends the activity. /// </summary> /// <typeparam name="T">The type of body in the InvokeResponse.</typeparam> /// <param name="originatingAudience">The oauth audience scope, used during token retrieval. (Either https://api.botframework.com or bot app id.)</param> /// <param name="fromBotId">The MicrosoftAppId of the bot sending the activity.</param> /// <param name="toSkill">The skill to create the conversation Id for.</param> /// <param name="callbackUrl">The callback Url for the skill host.</param> /// <param name="activity">The activity to send.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <returns>Async task with invokeResponse.</returns> public async Task <InvokeResponse <T> > PostActivityAsync <T>(string originatingAudience, string fromBotId, BotFrameworkSkill toSkill, Uri callbackUrl, Activity activity, CancellationToken cancellationToken) { string skillConversationId; try { var options = new SkillConversationIdFactoryOptions { FromBotOAuthScope = originatingAudience, FromBotId = fromBotId, Activity = activity, BotFrameworkSkill = toSkill }; skillConversationId = await _conversationIdFactory.CreateSkillConversationIdAsync(options, cancellationToken).ConfigureAwait(false); } catch (NotImplementedException) { // Attempt to create the ID using deprecated method. #pragma warning disable 618 // Keeping this for backward compat, this catch should be removed when the deprecated method is removed. skillConversationId = await _conversationIdFactory.CreateSkillConversationIdAsync(activity.GetConversationReference(), cancellationToken).ConfigureAwait(false); #pragma warning restore 618 } return(await PostActivityAsync <T>(fromBotId, toSkill.AppId, toSkill.SkillEndpoint, callbackUrl, skillConversationId, activity, cancellationToken).ConfigureAwait(false)); }
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); // Create a conversationId to interact with the skill and send the activity var options = new SkillConversationIdFactoryOptions { FromBotOAuthScope = turnContext.TurnState.Get <string>(BotAdapter.OAuthScopeKey), FromBotId = _botId, Activity = turnContext.Activity, BotFrameworkSkill = targetSkill }; var skillConversationId = await _conversationIdFactory.CreateSkillConversationIdAsync(options, cancellationToken); using var client = _auth.CreateBotFrameworkClient(); // route the activity to the skill var response = await client.PostActivityAsync(_botId, targetSkill.AppId, targetSkill.SkillEndpoint, _skillsConfig.SkillHostEndpoint, skillConversationId, 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}"); } }
public async Task PostAsync() { var inboundActivity = await HttpHelper.ReadRequestAsync <Activity>(Request); var nextConversationId = await _factory.CreateSkillConversationIdAsync(inboundActivity.GetConversationReference(), CancellationToken.None); await _client.PostActivityAsync(null, null, _toUri, _serviceUrl, nextConversationId, inboundActivity); // ALTERNATIVE API IDEA... //var inboundConversationReference = inboundActivity.GetConversationReference(); //var outboundActivity = MessageFactory.CreateActivity(inboundActivity); //outboundActivity.ApplyConversationReference(inboundConversationReference, _serviceUrl, nextConversationId); //await _client.PostActivityAsync(_toUri, outboundActivity, null, null); }
public async Task <InvokeResponse> PostActivityAsync(string fromBotId, BotFrameworkSkill toSkill, Uri callbackUrl, Activity activity, CancellationToken cancellationToken) { var skillConversationId = await _conversationIdFactory.CreateSkillConversationIdAsync(activity.GetConversationReference(), cancellationToken).ConfigureAwait(false); return(await PostActivityAsync(fromBotId, toSkill.AppId, toSkill.SkillEndpoint, callbackUrl, skillConversationId, activity, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Sends an activity to the skill bot. /// </summary> /// <param name="turnContext">Context for the current turn of conversation.</param> /// <param name="deliveryMode">The delivery mode to use when communicating to the skill.</param> /// <param name="targetSkill">The skill that will receive the activity.</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 SendToSkillAsync(ITurnContext turnContext, string deliveryMode, 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. using var client = _auth.CreateBotFrameworkClient(); // Create a conversationId to interact with the skill and send the activity var options = new SkillConversationIdFactoryOptions { FromBotOAuthScope = turnContext.TurnState.Get <string>(BotAdapter.OAuthScopeKey), FromBotId = _botId, Activity = turnContext.Activity, BotFrameworkSkill = targetSkill }; var skillConversationId = await _conversationIdFactory.CreateSkillConversationIdAsync(options, cancellationToken); if (deliveryMode == DeliveryModes.ExpectReplies) { // Clone activity and update its delivery mode. var activity = JsonConvert.DeserializeObject <Activity>(JsonConvert.SerializeObject(turnContext.Activity)); activity.DeliveryMode = deliveryMode; // route the activity to the skill var expectRepliesResponse = await client.PostActivityAsync(_botId, targetSkill.AppId, targetSkill.SkillEndpoint, _skillsConfig.SkillHostEndpoint, skillConversationId, activity, cancellationToken); // Check response status. if (!expectRepliesResponse.IsSuccessStatusCode()) { throw new HttpRequestException($"Error invoking the skill id: \"{targetSkill.Id}\" at \"{targetSkill.SkillEndpoint}\" (status is {expectRepliesResponse.Status}). \r\n {expectRepliesResponse.Body}"); } // Route response activities back to the channel. var response = expectRepliesResponse.Body as JObject; var activities = response["activities"]; var responseActivities = activities.ToObject <IList <Activity> >(); foreach (var responseActivity in responseActivities) { if (responseActivity.Type == ActivityTypes.EndOfConversation) { await EndConversation(responseActivity, turnContext, cancellationToken); } else { await turnContext.SendActivityAsync(responseActivity, cancellationToken); } } } else { // Route the activity to the skill. var response = await client.PostActivityAsync(_botId, targetSkill.AppId, targetSkill.SkillEndpoint, _skillsConfig.SkillHostEndpoint, skillConversationId, turnContext.Activity, cancellationToken); // Check response status if (!response.IsSuccessStatusCode()) { throw new HttpRequestException($"Error invoking the skill id: \"{targetSkill.Id}\" at \"{targetSkill.SkillEndpoint}\" (status is {response.Status}). \r\n {response.Body}"); } } }