private async Task <T> InvokeChannelApiAsync <T>(BotAdapter adapter, IBot bot, ClaimsIdentity claimsIdentity, string method, string conversationId, params object[] args) { // make sure there is a channel api middleware if (!adapter.MiddlewareSet.Any(mw => mw is ChannelApiMiddleware)) { adapter.MiddlewareSet.Use(new ChannelApiMiddleware()); } _logger.LogInformation($"InvokeChannelApiAsync(). Invoking method \"{method}\""); var(callerConversationId, callerServiceUrl) = _conversationIdIdFactory.GetConversationInfo(conversationId); var channelApiInvokeActivity = Activity.CreateInvokeActivity(); channelApiInvokeActivity.Name = InvokeActivityName; channelApiInvokeActivity.ChannelId = "unknown"; channelApiInvokeActivity.ServiceUrl = callerServiceUrl; channelApiInvokeActivity.Conversation = new ConversationAccount(id: callerConversationId); channelApiInvokeActivity.From = new ChannelAccount(id: "unknown"); channelApiInvokeActivity.Recipient = new ChannelAccount(id: "unknown", role: RoleTypes.Bot); var activityPayload = args?.Where(arg => arg is Activity).Cast <Activity>().FirstOrDefault(); if (activityPayload != null) { // fix up activityPayload with original conversation.Id and id activityPayload.Conversation.Id = callerConversationId; activityPayload.ServiceUrl = callerServiceUrl; // use the activityPayload for channel accounts, it will be in From=Bot/Skill Recipient=User, // We want to send it to the bot as From=User, Recipient=Bot so we have correct state context. channelApiInvokeActivity.ChannelId = activityPayload.ChannelId; channelApiInvokeActivity.From = activityPayload.Recipient; channelApiInvokeActivity.Recipient = activityPayload.From; // We want ActivityPayload to also be in User->Bot context, if it is outbound it will go through context.SendActivity which will flip outgoing to Bot->User // regardless this gives us same memory context of User->Bot which is useful for things like EndOfConversation processing being in the correct memory context. activityPayload.From = channelApiInvokeActivity.From; activityPayload.Recipient = channelApiInvokeActivity.Recipient; } var channelApiArgs = new ChannelApiArgs { Method = method, Args = args }; channelApiInvokeActivity.Value = channelApiArgs; // send up to the bot to process it... await adapter.ProcessActivityAsync(claimsIdentity, (Activity)channelApiInvokeActivity, bot.OnTurnAsync, CancellationToken.None).ConfigureAwait(false); if (channelApiArgs.Exception != null) { throw channelApiArgs.Exception; } // Return the result that was captured in the middleware handler. return((T)channelApiArgs.Result); }
private async Task ProcessSkillActivityAsync(ITurnContext turnContext, NextDelegate next, ChannelApiArgs invokeArgs, CancellationToken cancellationToken) { try { // TODO: this cast won't work for custom adapters var adapter = turnContext.Adapter as BotFrameworkAdapter; switch (invokeArgs.Method) { // Send activity(activity) case ChannelApiMethods.SendToConversation: { var activityPayload = (Activity)invokeArgs.Args[0]; if (activityPayload.Type == ActivityTypes.EndOfConversation) { await ProcessEndOfConversationAsync(turnContext, next, activityPayload, cancellationToken).ConfigureAwait(false); invokeArgs.Result = new ResourceResponse(id: Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)); return; } invokeArgs.Result = await turnContext.SendActivityAsync(activityPayload, cancellationToken).ConfigureAwait(false); return; } // Send activity(replyToId, activity) case ChannelApiMethods.ReplyToActivity: { var activityPayload = (Activity)invokeArgs.Args[1]; activityPayload.ReplyToId = (string)invokeArgs.Args[0]; if (activityPayload.Type == ActivityTypes.EndOfConversation) { await ProcessEndOfConversationAsync(turnContext, next, activityPayload, cancellationToken).ConfigureAwait(false); invokeArgs.Result = new ResourceResponse(id: Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)); return; } invokeArgs.Result = await turnContext.SendActivityAsync(activityPayload, cancellationToken).ConfigureAwait(false); return; } // UpdateActivity(activity) case ChannelApiMethods.UpdateActivity: invokeArgs.Result = await turnContext.UpdateActivityAsync((Activity)invokeArgs.Args[0], cancellationToken).ConfigureAwait(false); return; // DeleteActivity(activityId) case ChannelApiMethods.DeleteActivity: await turnContext.DeleteActivityAsync((string)invokeArgs.Args[0], cancellationToken).ConfigureAwait(false); break; // SendConversationHistory(history) case ChannelApiMethods.SendConversationHistory: throw new NotImplementedException($"{ChannelApiMethods.SendConversationHistory} is not supported"); // GetConversationMembers() case ChannelApiMethods.GetConversationMembers: if (adapter != null) { invokeArgs.Result = await adapter.GetConversationMembersAsync(turnContext, cancellationToken).ConfigureAwait(false); } break; // GetConversationPageMembers((int)pageSize, continuationToken) case ChannelApiMethods.GetConversationPagedMembers: throw new NotImplementedException($"{ChannelApiMethods.SendConversationHistory} is not supported"); //if (adapter != null) //{ // invokeArgs.Result = await adapter.OnGetConversationsAsync((int)invokeArgs.Args[0], (string)invokeArgs.Args[1], cancellationToken).ConfigureAwait(false); //} // DeleteConversationMember(memberId) case ChannelApiMethods.DeleteConversationMember: if (adapter != null) { await adapter.DeleteConversationMemberAsync(turnContext, (string)invokeArgs.Args[0], cancellationToken).ConfigureAwait(false); } break; // GetActivityMembers(activityId) case ChannelApiMethods.GetActivityMembers: if (adapter != null) { invokeArgs.Result = await adapter.GetActivityMembersAsync(turnContext, (string)invokeArgs.Args[0], cancellationToken).ConfigureAwait(false); } break; case ChannelApiMethods.UploadAttachment: throw new NotImplementedException($"{ChannelApiMethods.UploadAttachment} is not supported"); } } #pragma warning disable CA1031 // Do not catch general exception types (excluding, we use the general exception to store it in the inokeArgs). catch (Exception ex) { invokeArgs.Exception = ex; } #pragma warning restore CA1031 // Do not catch general exception types }