Esempio n. 1
0
        /// <summary>
        /// Checks the given activity for a possible command.
        ///
        /// All messages that start with a specific command keyword or contain a mention of the bot
        /// ("@<bot name>") are checked for possible commands.
        /// </summary>
        /// <param name="activity">An Activity instance containing a possible command.</param>
        /// <returns>True, if a command was detected and handled. False otherwise.</returns>
        public async virtual Task <bool> HandleCommandAsync(Activity activity)
        {
            bool     wasHandled    = false;
            Activity replyActivity = null;

            if ((!string.IsNullOrEmpty(activity.Text) && activity.Text.StartsWith($"{Commands.CommandKeyword} ")) ||
                WasBotAddressedDirectly(activity, false))
            {
                string commandMessage = ExtractCleanCommandMessage(activity);
                Party  senderParty    = MessagingUtils.CreateSenderParty(activity);

                switch (commandMessage.ToLower())
                {
                case string command when(command.StartsWith(Commands.CommandListOptions)):
                    // Present all command options in a card
                    replyActivity = CreateCommandOptionsCard(activity);

                    wasHandled = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandAddAggregationChannel)):
                    // Establish the sender's channel/conversation as an aggreated one if not already exists
                    Party aggregationParty = new Party(activity.ServiceUrl, activity.ChannelId, null, activity.Conversation);

                    if (_messageRouterManager.RoutingDataManager.AddAggregationParty(aggregationParty))
                    {
                        replyActivity = activity.CreateReply("This channel/conversation is now where the requests are aggregated");
                    }
                    else
                    {
                        replyActivity = activity.CreateReply("This channel/conversation is already receiving requests");
                    }

                    wasHandled = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandAcceptRequest) || command.StartsWith(Commands.CommandRejectRequest)):
                    // Accept/reject conversation request
                    bool doAccept = command.StartsWith(Commands.CommandAcceptRequest);

                    if (_messageRouterManager.RoutingDataManager.IsAssociatedWithAggregation(senderParty))
                    {
                        // The party is associated with the aggregation and has the right to accept/reject
                        string errorMessage = await AcceptOrRejectRequestAsync(senderParty, commandMessage, doAccept);

                        if (!string.IsNullOrEmpty(errorMessage))
                        {
                            replyActivity = activity.CreateReply(errorMessage);
                        }
                    }
                    else
                    {
                        replyActivity = activity.CreateReply("Sorry, you are not allowed to accept/reject requests");
                    }

                    wasHandled = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandDisconnect)):
                    // End the 1:1 conversation
                    IList <MessageRouterResult> messageRouterResults = _messageRouterManager.Disconnect(senderParty);

                    foreach (MessageRouterResult messageRouterResult in messageRouterResults)
                    {
                        await _messageRouterResultHandler.HandleResultAsync(messageRouterResult);
                    }

                    wasHandled = true;
                    break;


                    #region Implementation of debugging commands
#if DEBUG
                case string command when(command.StartsWith(Commands.CommandDeleteAllRoutingData)):
                    // DELETE ALL ROUTING DATA
                    await _messageRouterManager.BroadcastMessageToAggregationChannelsAsync(
                        $"Deleting all data as requested by \"{senderParty.ChannelAccount?.Name}\"...");

                    replyActivity = activity.CreateReply("Deleting all data...");
                    _messageRouterManager.RoutingDataManager.DeleteAll();
                    wasHandled = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandListAllParties)):
                    // List user and bot parties
                    IRoutingDataManager routingDataManager = _messageRouterManager.RoutingDataManager;

                    string replyMessage    = string.Empty;
                    string partiesAsString = PartyListToString(routingDataManager.GetUserParties());

                    if (string.IsNullOrEmpty(partiesAsString))
                    {
                        replyMessage = $"No user parties{LineBreak}";
                    }
                    else
                    {
                        replyMessage = $"Users:{LineBreak}{partiesAsString}";
                    }

                    partiesAsString = PartyListToString(routingDataManager.GetBotParties());

                    if (string.IsNullOrEmpty(partiesAsString))
                    {
                        replyMessage += "No bot parties";
                    }
                    else
                    {
                        replyMessage += $"Bot:{LineBreak}{partiesAsString}";
                    }

                    replyActivity = activity.CreateReply(replyMessage);
                    wasHandled    = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandListPendingRequests)):
                    // List all pending requests
                    var attachments = new List <Attachment>();

                    foreach (Party party in _messageRouterManager.RoutingDataManager.GetPendingRequests())
                    {
                        attachments.Add(CreateRequestCard(party, activity.Recipient.Name));
                    }

                    if (attachments.Count > 0)
                    {
                        replyActivity = activity.CreateReply($"{attachments.Count} pending request(s) found:");
                        replyActivity.AttachmentLayout = AttachmentLayoutTypes.Carousel;
                        replyActivity.Attachments      = attachments;
                    }
                    else
                    {
                        replyActivity = activity.CreateReply("No pending requests");
                    }

                    wasHandled = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandListConnections)):
                    // List all connections (conversations)
                    string parties = _messageRouterManager.RoutingDataManager.ConnectionsToString();

                    if (string.IsNullOrEmpty(parties))
                    {
                        replyActivity = activity.CreateReply("No conversations");
                    }
                    else
                    {
                        replyActivity = activity.CreateReply(parties);
                    }

                    wasHandled = true;
                    break;

                case string command when(command.StartsWith(Commands.CommandListLastMessageRouterResults)):
                    // List all logged message router results
                    string resultsAsString = _messageRouterManager.RoutingDataManager.GetLastMessageRouterResults();

                    replyActivity = activity.CreateReply($"{(string.IsNullOrEmpty(resultsAsString) ? "No results" : resultsAsString)}");
                    wasHandled    = true;
                    break;
#endif
                    #endregion

                default:
                    replyActivity = activity.CreateReply($"Command \"{commandMessage}\" not recognized");
                    break;
                }

                if (replyActivity != null)
                {
                    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                    await connector.Conversations.ReplyToActivityAsync(replyActivity);
                }
            }

            return(wasHandled);
        }
Esempio n. 2
0
        /// <summary>
        /// Handles the received message.
        /// </summary>
        public async Task <HttpResponseMessage> Post([FromBody] Activity activity)
        {
            if (activity.Locale != null)
            {
                ConversationText.Culture = new CultureInfo(activity.Locale);
            }

            if (activity.Type == ActivityTypes.Message)
            {
                MessageRouterManager        messageRouterManager       = WebApiConfig.MessageRouterManager;
                IMessageRouterResultHandler messageRouterResultHandler = WebApiConfig.MessageRouterResultHandler;

                messageRouterManager.MakeSurePartiesAreTracked(activity);

                // First check for commands (both from back channel and the ones directly typed)
                MessageRouterResult messageRouterResult =
                    WebApiConfig.BackChannelMessageHandler.HandleBackChannelMessage(activity);

                if (messageRouterResult.Type != MessageRouterResultType.Connected &&
                    await WebApiConfig.CommandMessageHandler.HandleCommandAsync(activity) == false)
                {
                    // No valid back channel (command) message or typed command detected

                    // Let the message router manager instance handle the activity
                    messageRouterResult = await messageRouterManager.HandleActivityAsync(activity, false);

                    if (messageRouterResult.Type == MessageRouterResultType.NoActionTaken)
                    {
                        // No action was taken by the message router manager. This means that the
                        // user is not connected (in a 1:1 conversation) with a human
                        // (e.g. customer service agent) yet.
                        //
                        // You can, for example, check if the user (customer) needs human
                        // assistance here or forward the activity to a dialog. You could also do
                        // the check in the dialog too...
                        //
                        // Here's an example:
                        if (!string.IsNullOrEmpty(activity.Text) &&
                            activity.Text.ToLower().Contains(CommandRequestConnection))
                        {
                            messageRouterResult = messageRouterManager.RequestConnection(activity);
                        }
                        else
                        {
                            await Conversation.SendAsync(activity, () => new RootDialog());
                        }
                    }
                }

                // Handle the result, if required
                await messageRouterResultHandler.HandleResultAsync(messageRouterResult);
            }
            else
            {
                await HandleSystemMessageAsync(activity);
            }

            var response = Request.CreateResponse(HttpStatusCode.OK);

            return(response);
        }
Esempio n. 3
0
        /// <summary>
        /// Handles the received message.
        /// </summary>
        public async Task <HttpResponseMessage> Post([FromBody] Activity activity)
        {
            //await Repository.UtilityRepo.LogMsgAsync("activity id" + activity.From.Id);
            //await Repository.UtilityRepo.LogMsgAsync("activity from" + activity.From.Name);
            //await Repository.UtilityRepo.LogMsgAsync("activity channel" + activity.ChannelId);
            // var t = System.Web.HttpContext.Current.Request.UserHostAddress;
            //var CallerIp = System.Web.HttpContext.Current.Request.UserHostAddress;
            var CallerAgent = System.Web.HttpContext.Current.Request.UserAgent;
            //var CalledUrl = System.Web.HttpContext.Current.Request.Url.OriginalString;
            var current = System.Web.HttpContext.Current;
            var ip      = GetUserIP(current);

            await Repository.UtilityRepo.UpdatedUserAttendedByAsync(activity);

            if (activity.Locale != null)
            {
                ConversationText.Culture = new CultureInfo(activity.Locale);
            }

            if (activity.Type == ActivityTypes.Message)
            {
                MessageRouterManager        messageRouterManager       = WebApiConfig.MessageRouterManager;
                IMessageRouterResultHandler messageRouterResultHandler = WebApiConfig.MessageRouterResultHandler;

                messageRouterManager.MakeSurePartiesAreTracked(activity);

                // First check for commands (both from back channel and the ones directly typed)
                MessageRouterResult messageRouterResult =
                    WebApiConfig.BackChannelMessageHandler.HandleBackChannelMessage(activity);

                if (messageRouterResult.Type != MessageRouterResultType.Connected &&
                    await WebApiConfig.CommandMessageHandler.HandleCommandAsync(activity) == false)
                {
                    // No valid back channel (command) message or typed command detected

                    // Let the message router manager instance handle the activity
                    messageRouterResult = await messageRouterManager.HandleActivityAsync(activity, false);

                    if (messageRouterResult.Type == MessageRouterResultType.NoActionTaken)
                    {
                        // No action was taken by the message router manager. This means that the
                        // user is not connected (in a 1:1 conversation) with a human
                        // (e.g. customer service agent) yet.
                        //
                        // You can, for example, check if the user (customer) needs human
                        // assistance here or forward the activity to a dialog. You could also do
                        // the check in the dialog too...
                        //
                        // Here's an example:
                        if (!string.IsNullOrEmpty(activity.Text) &&
                            activity.Text.ToLower().Contains(CommandRequestConnection))    //&& System.Web.HttpContext.Current.Session["UserID"] != null)
                        {
                            messageRouterResult = messageRouterManager.RequestConnection(activity);
                            // log all the request and thier sources
                            try
                            {
                                await Repository.UtilityRepo.LogPendingRequestAsync(activity, ip, CallerAgent);
                            }
                            catch (System.Data.Entity.Validation.DbEntityValidationException e)
                            {
                                foreach (var eve in e.EntityValidationErrors)
                                {
                                    await Repository.UtilityRepo.LogMsgAsync(string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                                                                                           eve.Entry.Entity.GetType().Name, eve.Entry.State));

                                    foreach (var ve in eve.ValidationErrors)
                                    {
                                        await Repository.UtilityRepo.LogMsgAsync(string.Format("- Property: \"{0}\", Error: \"{1}\"",
                                                                                               ve.PropertyName, ve.ErrorMessage));
                                    }
                                }
                                //throw;
                            }
                            catch (Exception ex)
                            {
                                await Repository.UtilityRepo.LogMsgAsync("Eror on human request : " + ex.Message);
                            }
                        }
                        else
                        {
                            try
                            {
                                await Repository.UtilityRepo.LogRequestMessageAsync(activity);

                                // Call
                                await Conversation.SendAsync(activity, () => new RootDialog());
                            }
                            catch (FormCanceledException fcEx) when(fcEx.InnerException is TooManyAttemptsException)
                            {
                                ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));

                                Activity reply = activity.CreateReply(
                                    $"Too Many Attempts at {fcEx.Last}. " +
                                    $"Completed Steps: {string.Join(", ", fcEx.Completed)}");

                                await Repository.UtilityRepo.LogMsgAsync("reply : " + reply.Text);

                                await connector.Conversations.ReplyToActivityAsync(reply);
                            }
                            catch (FormCanceledException fcEx)
                            {
                                ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));

                                Activity reply = activity.CreateReply(
                                    $"Form cancelled at {fcEx.Last}. " +
                                    $"Completed Steps: {string.Join(", ", fcEx.Completed)}");


                                await Repository.UtilityRepo.LogMsgAsync("reply : " + reply.Text);

                                await connector.Conversations.ReplyToActivityAsync(reply);
                            }

                            catch (Exception ex)
                            {
                                await Repository.UtilityRepo.LogErrorAsync(ex);
                            }
                        }
                    }
                }

                if (messageRouterResult != null && messageRouterResult.Type == MessageRouterResultType.OK && string.IsNullOrEmpty(messageRouterResult.ErrorMessage))
                {
                    await Repository.UtilityRepo.CustomerAgentChatHistoryLogAsync(messageRouterResult);
                }
                // Handle the result, if required
                await messageRouterResultHandler.HandleResultAsync(messageRouterResult);
            }
            else
            {
                await HandleSystemMessageAsync(activity);
            }

            var response = Request.CreateResponse(HttpStatusCode.OK);

            return(response);
        }