예제 #1
0
        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);
        }