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