public async Task OnTurnAsync(ITurnContext context, NextDelegate next, CancellationToken ct) { Activity activity = context.Activity; if (activity.Type is ActivityTypes.Message) { bool.TryParse( Configuration[KeyRejectConnectionRequestIfNoAggregationChannel], out bool rejectConnectionRequestIfNoAggregationChannel); // Store the conversation references (identities of the sender and the recipient [bot]) // in the activity MessageRouter.StoreConversationReferences(activity); AbstractMessageRouterResult messageRouterResult = null; // Check the activity for commands if (await CommandHandler.HandleCommandAsync(context) == false) { // No command detected/handled // Let the message router route the activity, if the sender is connected with // another user/bot messageRouterResult = await MessageRouter.RouteReachMessageIfSenderIsConnectedAsync(activity); if (messageRouterResult is MessageRoutingResult && (messageRouterResult as MessageRoutingResult).Type == MessageRoutingResultType.NoActionTaken) { // No action was taken by the message router. This means that the user // is not connected (in a 1:1 conversation) with a human // (e.g. customer service agent) yet. // Check for cry for help (agent assistance) if (!string.IsNullOrWhiteSpace(activity.Text) && activity.Text.ToLower().Contains("human")) { // Create a connection request on behalf of the sender // Note that the returned result must be handled messageRouterResult = MessageRouter.CreateConnectionRequest( MessageRouter.CreateSenderConversationReference(activity), rejectConnectionRequestIfNoAggregationChannel); } else { // No action taken - this middleware did not consume the activity so let it propagate await next(ct).ConfigureAwait(false); } } } // Uncomment to see the result in a reply (may be useful for debugging) //if (messageRouterResult != null) //{ // await MessageRouter.ReplyToActivityAsync(activity, messageRouterResult.ToString()); //} // Handle the result, if necessary await MessageRouterResultHandler.HandleResultAsync(messageRouterResult); } }
/// <summary> /// Handles the given message router result. /// </summary> /// <param name="messageRouterResult">The result to handle.</param> /// <returns>True, if the result was handled. False, if no action was taken.</returns> public virtual async Task <bool> HandleResultAsync(AbstractMessageRouterResult messageRouterResult) { if (messageRouterResult != null) { if (messageRouterResult is ConnectionRequestResult) { return(await HandleConnectionRequestResultAsync(messageRouterResult as ConnectionRequestResult)); } if (messageRouterResult is ConnectionResult) { return(await HandleConnectionResultAsync(messageRouterResult as ConnectionResult)); } if (messageRouterResult is MessageRoutingResult) { return(await HandleMessageRoutingResultAsync(messageRouterResult as MessageRoutingResult)); } } return(false); }
/// <summary> /// Checks the given activity for a possible command. /// </summary> /// <param name="activity">The context containing the activity, which in turn may contain a possible command.</param> /// <returns>True, if a command was detected and handled. False otherwise.</returns> public async virtual Task <bool> HandleCommandAsync(ITurnContext context) { Activity activity = context.Activity; Command command = Command.FromMessageActivity(activity); if (command == null) { // Check for back channel command command = Command.FromChannelData(activity); } if (command == null) { return(false); } bool wasHandled = false; Activity replyActivity = null; ConversationReference sender = MessageRouter.CreateSenderConversationReference(activity); switch (command.BaseCommand) { case Commands.ShowOptions: // Present all command options in a card replyActivity = CommandCardFactory.AddCardToActivity( activity.CreateReply(), CommandCardFactory.CreateCommandOptionsCard(activity.Recipient?.Name)); wasHandled = true; break; case Commands.Watch: // Add the sender's channel/conversation into the list of aggregation channels bool isPermittedAggregationChannel = false; if (_permittedAggregationChannels != null && _permittedAggregationChannels.Count > 0) { foreach (string permittedAggregationChannel in _permittedAggregationChannels) { if (!string.IsNullOrWhiteSpace(activity.ChannelId) && activity.ChannelId.ToLower().Equals(permittedAggregationChannel.ToLower())) { isPermittedAggregationChannel = true; break; } } } else { isPermittedAggregationChannel = true; } if (isPermittedAggregationChannel) { ConversationReference aggregationChannelToAdd = new ConversationReference( null, null, null, activity.Conversation, activity.ChannelId, activity.ServiceUrl); ModifyRoutingDataResult modifyRoutingDataResult = _messageRouter.RoutingDataManager.AddAggregationChannel(aggregationChannelToAdd); if (modifyRoutingDataResult.Type == ModifyRoutingDataResultType.Added) { replyActivity = activity.CreateReply(Strings.AggregationChannelSet); } else if (modifyRoutingDataResult.Type == ModifyRoutingDataResultType.AlreadyExists) { replyActivity = activity.CreateReply(Strings.AggregationChannelAlreadySet); } else if (modifyRoutingDataResult.Type == ModifyRoutingDataResultType.Error) { replyActivity = activity.CreateReply( string.Format(Strings.FailedToSetAggregationChannel, modifyRoutingDataResult.ErrorMessage)); } } else { replyActivity = activity.CreateReply( string.Format(Strings.NotPermittedAggregationChannel, activity.ChannelId)); } wasHandled = true; break; case Commands.Unwatch: // Remove the sender's channel/conversation from the list of aggregation channels if (_messageRouter.RoutingDataManager.IsAssociatedWithAggregation(sender)) { ConversationReference aggregationChannelToRemove = new ConversationReference( null, null, null, activity.Conversation, activity.ChannelId, activity.ServiceUrl); if (_messageRouter.RoutingDataManager.RemoveAggregationChannel(aggregationChannelToRemove)) { replyActivity = activity.CreateReply(Strings.AggregationChannelRemoved); } else { replyActivity = activity.CreateReply(Strings.FailedToRemoveAggregationChannel); } wasHandled = true; } break; case Commands.GetRequests: IList <ConnectionRequest> connectionRequests = _messageRouter.RoutingDataManager.GetConnectionRequests(); replyActivity = activity.CreateReply(); if (connectionRequests.Count == 0) { replyActivity.Text = Strings.NoPendingRequests; } else { replyActivity.Attachments = CommandCardFactory.CreateMultipleConnectionRequestCards( connectionRequests, activity.Recipient?.Name); } replyActivity.ChannelData = JsonConvert.SerializeObject(connectionRequests); wasHandled = true; break; case Commands.AcceptRequest: case Commands.RejectRequest: // Accept/reject connection request bool doAccept = (command.BaseCommand == Commands.AcceptRequest); if (_messageRouter.RoutingDataManager.IsAssociatedWithAggregation(sender)) { // The sender is associated with the aggregation and has the right to accept/reject if (command.Parameters.Count == 0) { replyActivity = activity.CreateReply(); connectionRequests = _messageRouter.RoutingDataManager.GetConnectionRequests(); if (connectionRequests.Count == 0) { replyActivity.Text = Strings.NoPendingRequests; } else { replyActivity = CommandCardFactory.AddCardToActivity( replyActivity, CommandCardFactory.CreateMultiConnectionRequestCard( connectionRequests, doAccept, activity.Recipient?.Name)); } } else if (!doAccept && command.Parameters[0].Equals(Command.CommandParameterAll)) { // Reject all pending connection requests if (!await _connectionRequestHandler.RejectAllPendingRequestsAsync( _messageRouter, _messageRouterResultHandler)) { replyActivity = activity.CreateReply(); replyActivity.Text = Strings.FailedToRejectPendingRequests; } } else if (command.Parameters.Count > 1) { // Try to accept/reject the specified connection request ChannelAccount requestorChannelAccount = new ChannelAccount(command.Parameters[0]); ConversationAccount requestorConversationAccount = new ConversationAccount(null, null, command.Parameters[1]); AbstractMessageRouterResult messageRouterResult = await _connectionRequestHandler.AcceptOrRejectRequestAsync( _messageRouter, _messageRouterResultHandler, sender, doAccept, requestorChannelAccount, requestorConversationAccount); await _messageRouterResultHandler.HandleResultAsync(messageRouterResult); } else { replyActivity = activity.CreateReply(Strings.InvalidOrMissingCommandParameter); } } #if DEBUG // We shouldn't respond to command attempts by regular users, but I guess // it's okay when debugging else { replyActivity = activity.CreateReply(Strings.ConnectionRequestResponseNotAllowed); } #endif wasHandled = true; break; case Commands.Disconnect: // End the 1:1 conversation(s) IList <ConnectionResult> disconnectResults = _messageRouter.Disconnect(sender); if (disconnectResults != null && disconnectResults.Count > 0) { foreach (ConnectionResult disconnectResult in disconnectResults) { await _messageRouterResultHandler.HandleResultAsync(disconnectResult); } wasHandled = true; } break; default: replyActivity = activity.CreateReply(string.Format(Strings.CommandNotRecognized, command.BaseCommand)); break; } if (replyActivity != null) { await context.SendActivity(replyActivity); } return(wasHandled); }
public async Task OnTurnAsync(ITurnContext context, NextDelegate next, CancellationToken ct) { Activity activity = context.Activity; var conversationStateAccessors = _conversationState.CreateProperty <Conversacion>(nameof(Conversacion)); var conversationData = await conversationStateAccessors.GetAsync(context, () => new Conversacion()); var userStateAccessors = _userState.CreateProperty <Conversacion>(nameof(Conversacion)); var conversacion = await userStateAccessors.GetAsync(context, () => new Conversacion()); if (activity.Type is ActivityTypes.Message) { bool.TryParse( Configuration[KeyRejectConnectionRequestIfNoAggregationChannel], out bool rejectConnectionRequestIfNoAggregationChannel); // Store the conversation references (identities of the sender and the recipient [bot]) // in the activity MessageRouter.StoreConversationReferences(activity); AbstractMessageRouterResult messageRouterResult = null; // Check the activity for commands if (await CommandHandler.HandleCommandAsync(context) == false) { // No command detected/handled // Let the message router route the activity, if the sender is connected with // another user/bot messageRouterResult = await MessageRouter.RouteMessageIfSenderIsConnectedAsync(activity); if (messageRouterResult is MessageRoutingResult && (messageRouterResult as MessageRoutingResult).Type == MessageRoutingResultType.NoActionTaken) { // No action was taken by the message router. This means that the user // is not connected (in a 1:1 conversation) with a human // (e.g. customer service agent) yet. // Check for cry for help (agent assistance) if (!string.IsNullOrWhiteSpace(activity.Text) && activity.Text.ToLower().Contains("agente")) { conversacion.Eleccion = activity.Text.ToLower(); await _conversationState.SaveChangesAsync(context, false, ct); await _userState.SaveChangesAsync(context, false, ct); // Create a connection request on behalf of the sender // Note that the returned result must be handled await context.SendActivityAsync($"{context.Activity.From.Name}, te voy a comunicar con un agente"); await context.SendActivityAsync("Por favor esperame unos segundos a que uno de nuestros agentes esté disponible para atenderte..."); messageRouterResult = MessageRouter.CreateConnectionRequest( MessageRouter.CreateSenderConversationReference(activity), rejectConnectionRequestIfNoAggregationChannel); } else { // No action taken - this middleware did not consume the activity so let it propagate await next(ct).ConfigureAwait(false); } } } // Uncomment to see the result in a reply (may be useful for debugging) //if (messageRouterResult != null) //{ // await MessageRouter.ReplyToActivityAsync(activity, messageRouterResult.ToString()); //} // Handle the result, if necessary await MessageRouterResultHandler.HandleResultAsync(messageRouterResult); } else { // No action taken - this middleware did not consume the activity so let it propagate await next(ct).ConfigureAwait(false); } }