/// <summary>
        /// Tries to send the given message activity to the given party using this bot on the same
        /// channel as the party who the message is sent to.
        /// </summary>
        /// <param name="partyToMessage">The party to send the message to.</param>
        /// <param name="messageActivity">The message activity to send (message content).</param>
        /// <returns>The ResourceResponse instance or null in case of an error.</returns>
        public async Task <ResourceResponse> SendMessageToPartyByBotAsync(Party partyToMessage, IMessageActivity messageActivity)
        {
            Party botParty = null;

            if (partyToMessage != null)
            {
                // We need the channel account of the bot in the SAME CHANNEL as the RECIPIENT.
                // The identity of the bot in the channel of the sender is most likely a different one and
                // thus unusable since it will not be recognized on the recipient's channel.
                botParty = RoutingDataManager.FindBotPartyByChannelAndConversation(
                    partyToMessage.ChannelId, partyToMessage.ConversationAccount);
            }

            if (botParty != null)
            {
                messageActivity.From = botParty.ChannelAccount;

                MessagingUtils.ConnectorClientAndMessageBundle bundle =
                    MessagingUtils.CreateConnectorClientAndMessageActivity(
                        partyToMessage.ServiceUrl, messageActivity);

                return(await bundle.connectorClient.Conversations.SendToConversationAsync(
                           (Activity)bundle.messageActivity));
            }

            return(null);
        }
Esempio n. 2
0
        /// <summary>
        /// Tries to establish 1:1 chat between the two given parties.
        /// Note that the conversation owner will have a new separate party in the created engagement.
        /// </summary>
        /// <param name="conversationOwnerParty">The party who owns the conversation (e.g. customer service agent).</param>
        /// <param name="conversationClientParty">The other party in the conversation.</param>
        /// <returns>The result of the operation.</returns>
        public async Task <MessageRouterResult> AddEngagementAsync(
            Party conversationOwnerParty, Party conversationClientParty)
        {
            if (conversationOwnerParty == null || conversationClientParty == null)
            {
                throw new ArgumentNullException(
                          $"Neither of the arguments ({nameof(conversationOwnerParty)}, {nameof(conversationClientParty)}) can be null");
            }

            MessageRouterResult result = new MessageRouterResult()
            {
                ConversationOwnerParty  = conversationOwnerParty,
                ConversationClientParty = conversationClientParty
            };

            Party botParty = RoutingDataManager.FindBotPartyByChannelAndConversation(
                conversationOwnerParty.ChannelId, conversationOwnerParty.ConversationAccount);

            if (botParty != null)
            {
                ConnectorClient connectorClient = new ConnectorClient(new Uri(conversationOwnerParty.ServiceUrl));

                ConversationResourceResponse response =
                    await connectorClient.Conversations.CreateDirectConversationAsync(
                        botParty.ChannelAccount, conversationOwnerParty.ChannelAccount);

                if (response != null && !string.IsNullOrEmpty(response.Id))
                {
                    // The conversation account of the conversation owner for this 1:1 chat is different -
                    // thus, we need to create a new party instance
                    ConversationAccount directConversationAccount = new ConversationAccount(id: response.Id);

                    Party acceptorPartyEngaged = new Party(
                        conversationOwnerParty.ServiceUrl, conversationOwnerParty.ChannelId,
                        conversationOwnerParty.ChannelAccount, directConversationAccount);

                    RoutingDataManager.AddParty(acceptorPartyEngaged);
                    RoutingDataManager.AddParty(
                        new Party(botParty.ServiceUrl, botParty.ChannelId, botParty.ChannelAccount, directConversationAccount), false);

                    result = RoutingDataManager.AddEngagementAndClearPendingRequest(acceptorPartyEngaged, conversationClientParty);
                    result.ConversationResourceResponse = response;
                }
                else
                {
                    result.Type         = MessageRouterResultType.Error;
                    result.ErrorMessage = "Failed to create a direct conversation";
                }
            }
            else
            {
                result.Type         = MessageRouterResultType.Error;
                result.ErrorMessage = "Failed to find the bot instance";
            }

            await HandleAndLogMessageRouterResultAsync(result);

            return(result);
        }
        /// <summary>
        /// Tries to send the given message to the given party using this bot on the same channel
        /// as the party who the message is sent to.
        /// </summary>
        /// <param name="partyToMessage">The party to send the message to.</param>
        /// <param name="messageText">The message content.</param>
        /// <returns>The ResourceResponse instance or null in case of an error.</returns>
        public async Task <ResourceResponse> SendMessageToPartyByBotAsync(Party partyToMessage, string messageText)
        {
            Party botParty = null;

            if (partyToMessage != null)
            {
                botParty = RoutingDataManager.FindBotPartyByChannelAndConversation(
                    partyToMessage.ChannelId, partyToMessage.ConversationAccount);
            }

            if (botParty != null)
            {
                MessagingUtils.ConnectorClientAndMessageBundle bundle =
                    MessagingUtils.CreateConnectorClientAndMessageActivity(
                        partyToMessage, messageText, botParty?.ChannelAccount);

                return(await bundle.connectorClient.Conversations.SendToConversationAsync(
                           (Activity)bundle.messageActivity));
            }

            return(null);
        }
        /// <summary>
        /// Tries to establish 1:1 chat between the two given parties.
        /// Note that the conversation owner will have a new separate party in the created engagement.
        /// </summary>
        /// <param name="conversationOwnerParty">The party who owns the conversation (e.g. customer service agent).</param>
        /// <param name="conversationClientParty">The other party in the conversation.</param>
        /// <returns>The result of the operation.</returns>
        public async Task <MessageRouterResult> AddEngagementAsync(
            Party conversationOwnerParty, Party conversationClientParty)
        {
            if (conversationOwnerParty == null || conversationClientParty == null)
            {
                throw new ArgumentNullException(
                          $"Neither of the arguments ({nameof(conversationOwnerParty)}, {nameof(conversationClientParty)}) can be null");
            }

            MessageRouterResult result = new MessageRouterResult()
            {
                ConversationOwnerParty  = conversationOwnerParty,
                ConversationClientParty = conversationClientParty
            };

            Party botParty = RoutingDataManager.FindBotPartyByChannelAndConversation(
                conversationOwnerParty.ChannelId, conversationOwnerParty.ConversationAccount);

            if (botParty != null)
            {
                ConnectorClient connectorClient = new ConnectorClient(new Uri(conversationOwnerParty.ServiceUrl));

                try
                {
                    ConversationResourceResponse response =
                        await connectorClient.Conversations.CreateDirectConversationAsync(
                            botParty.ChannelAccount, conversationOwnerParty.ChannelAccount);

                    // ResponseId and conversationOwnerParty.ConversationAccount.Id are not consistent
                    // with each other across channels. Here we need the ConversationAccountId to route
                    // messages correctly across channels, e.g.:
                    // * In Slack they are the same:
                    //      * response.Id: B6JJQ7939: T6HKNHCP7: D6H04L58R
                    //      * conversationOwnerParty.ConversationAccount.Id: B6JJQ7939: T6HKNHCP7: D6H04L58R
                    // * In Skype they are not:
                    //      * response.Id: 8:daltskin
                    //      * conversationOwnerParty.ConversationAccount.Id: 29:11MZyI5R2Eak3t7bFjDwXmjQYnSl7aTBEB8zaSMDIEpA
                    if (response != null && !string.IsNullOrEmpty(conversationOwnerParty.ConversationAccount.Id))
                    {
                        // The conversation account of the conversation owner for this 1:1 chat is different -
                        // thus, we need to create a new party instance
                        ConversationAccount directConversationAccount =
                            new ConversationAccount(id: conversationOwnerParty.ConversationAccount.Id);

                        Party acceptorPartyEngaged = new EngageableParty(
                            conversationOwnerParty.ServiceUrl, conversationOwnerParty.ChannelId,
                            conversationOwnerParty.ChannelAccount, directConversationAccount);

                        RoutingDataManager.AddParty(acceptorPartyEngaged);
                        RoutingDataManager.AddParty(
                            new EngageableParty(botParty.ServiceUrl, botParty.ChannelId, botParty.ChannelAccount, directConversationAccount), false);

                        result = RoutingDataManager.AddEngagementAndClearPendingRequest(acceptorPartyEngaged, conversationClientParty);
                        result.ConversationResourceResponse = response;
                    }
                    else
                    {
                        result.Type         = MessageRouterResultType.Error;
                        result.ErrorMessage = "Failed to create a direct conversation";
                    }
                }
                catch (Exception e)
                {
                    result.Type         = MessageRouterResultType.Error;
                    result.ErrorMessage = $"Failed to create a direct conversation: {e.Message}";
                }
            }
            else
            {
                result.Type         = MessageRouterResultType.Error;
                result.ErrorMessage = "Failed to find the bot instance";
            }

            return(result);
        }