Пример #1
0
        public async Task OnTurnAsync(ITurnContext turnContext, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
        {
            Activity activity = turnContext.Activity;

            if (activity.Type is ActivityTypes.Message)
            {
                //Add User Context in the turn context
                ConversationReference selfConversation = activity.GetConversationReference();
                ChatUserContext       userContext      = ChatUserContext.FromConversation(selfConversation);
                if (activity.ChannelId.ToLower() != _config.AdminChannel ||
                    !UserRoleCache.UserRoles.ContainsKey(userContext.Id))
                {
                    userContext.Role = ChatUserRole.Consumer;
                }
                else
                {
                    userContext.Role = UserRoleCache.UserRoles[userContext.Id];
                }
                selfConversation.User.Role = userContext.Role.ToString();
                turnContext.TurnState.Add(typeof(ChatUserContext).FullName, userContext);

                //Add Message router in the turn context
                ConnectorClient connectorClient = turnContext.TurnState.Get <ConnectorClient>(typeof(IConnectorClient).FullName);
                MessageRouter   messageRouter   = new MessageRouter(connectorClient, activity, _logger);
                turnContext.TurnState.Add(typeof(MessageRouter).FullName, messageRouter);

                //Ensure that each user only has one conversation active, and notify the other sessions where a conversation replaced it.
                IEnumerable <ConversationReference> otherConversations = await _routingDataManager.GetConversationsFromUser(selfConversation.User.Id);

                //Remove current conversation
                otherConversations = _routingDataManager.RemoveSelfConversation(otherConversations, selfConversation);
                //Send a notification to all old conversations
                if (otherConversations.Count() > 0)
                {
                    foreach (var otherConversation in otherConversations)
                    {
                        await messageRouter.SendErrorMessageAsync(otherConversation, "You were disconnected from this instance.");
                    }
                }
                //Store the new conversation
                await _routingDataManager.SaveConversationReference(selfConversation);

                //Leave this middleware
                await next(cancellationToken).ConfigureAwait(false);
            }
            if (activity.Type is ActivityTypes.EndOfConversation)
            {
                ConversationReference selfConversation = activity.GetConversationReference();
                _logger.LogInformation($"Conversation Ended: {selfConversation.Conversation.Id}");
            }
        }
        private async Task <IEnumerable <ConversationReference> > GetHandoffConversation(ITurnContext turnContext,
                                                                                         Activity activity, CommandSendMessageProperties properties, ConversationReference selfConversation)
        {
            //Broadcast to many users
            IEnumerable <ConversationReference> conversations = null;

            if (properties.From.Role == ChatUserRole.Consumer)
            {
                conversations = await _routingDataManager.GetAdminConversations();

                //Send event to event processor... if possible
                if (turnContext.TurnState.TryGetValue(typeof(ChatReportModel).FullName, out object result))
                {
                    await PushMessageToEventProcessorSaga(activity.Text, activity.ChannelId, properties, (ChatReportModel)result);
                }
            }
            //To one user only - Admin only
            else if (properties.From.Role == ChatUserRole.Admin)
            {
                if (properties.UserId == "*")
                {
                    conversations = await _routingDataManager.GetConversations();
                }
                else
                {
                    conversations = await _routingDataManager.GetConversationsFromUser(properties.UserId);

                    IEnumerable <ConversationReference> conversations2 = await _routingDataManager.GetAdminConversations();

                    conversations = conversations2.Union(conversations);
                }
            }
            else
            {
                throw new Exception("Message handoff not handled");
            }
            //Do not send to self
            conversations = _routingDataManager.RemoveSelfConversation(conversations, selfConversation);

            return(conversations);
        }
        protected override async Task HandleTurnAsync(ITurnContext turnContext, ChatUserContext userContext,
                                                      MessageRouter messageRouter, NextDelegate next, CancellationToken cancellationToken = default(CancellationToken))
        {
            Activity activity = turnContext.Activity;

            if (activity.TryGetChannelData(out Command command) && command.BaseCommand != Commands.Undefined)
            {
                // Check the activity for commands
                ConversationReference selfConversation = activity.GetConversationReference();
                switch (command.BaseCommand)
                {
                case Commands.GetTranscript:
                    if (userContext.Role == ChatUserRole.Admin)
                    {
                        var conversations = await _reportDataManager.GetActiveChatReports();

                        var readUsersStatus = await _routingDataManager.GetUsersReadStatusPerUser(userContext.Id);

                        await messageRouter.SendTranscriptAsync(activity.Conversation.Id, conversations, readUsersStatus);
                    }
                    else
                    {
                        var conversation = await _reportDataManager.GetActiveChatReportFromUser(activity.From.Id);

                        await messageRouter.SendTranscriptAsync(activity.Conversation.Id, new List <ChatReportModel>() { conversation });
                    }
                    break;

                case Commands.ReadUserMessages:
                    //Update a date that shows the last time a message was read by an admin
                    if (userContext.Role == ChatUserRole.Admin)
                    {
                        if (JsonConvert.DeserializeObject <CommandReadUserMessages>(command.Data.ToString()) is CommandReadUserMessages properties)
                        {
                            var result = await _routingDataManager.UpdateUserReadMessageStatus(activity.From.Id, new ChatUserReadStatusModel()
                            {
                                Date   = properties.Date,
                                UserId = properties.UserId
                            });

                            if (!result)
                            {
                                throw new Exception("Error while executing command ReadUserMessages");
                            }
                        }
                    }
                    break;

                case Commands.EndConversation:
                    //End a conversation by adding an EndDate and delete the user conversation session so broadcast messages aren't sent to them anymore.
                    if (userContext.Role == ChatUserRole.Admin)
                    {
                        if (JsonConvert.DeserializeObject <CommandEndConversation>(command.Data.ToString()) is CommandEndConversation properties)
                        {
                            ChatReportModel userReport = await _reportDataManager.GetActiveChatReportFromUser(properties.UserId);

                            var result = await _reportDataManager.CloseReport(new ChatReportLogCloseModel()
                            {
                                EndDate = DateTime.UtcNow, UserId = properties.UserId
                            });

                            if (result)
                            {
                                var userConversationReference = await _routingDataManager.GetConversationsFromUser(properties.UserId);

                                if (userConversationReference != null && userConversationReference.Count() > 0)
                                {
                                    //Warn the user that the conversation is over
                                    await messageRouter.SendMessageAsync(userConversationReference.ToArray()[0],
                                                                         CommandFactoryHelper.CreateCommandSendMessage(selfConversation.Bot.Id, properties.UserId, selfConversation.User)
                                                                         , "The conversation was ended. If you have an issue, please start a new conversation.");

                                    //Call EndOfConversation on the user
                                    await messageRouter.SendEndConversationAsync(messageRouter.CreateEndOfConversationActivity(userConversationReference.ToArray()[0]));

                                    result = await _routingDataManager.DeleteUserConversation(properties.UserId);

                                    //Tell all admins about end of the conversation
                                    var admins = await _routingDataManager.GetAdminConversations();

                                    admins = _routingDataManager.RemoveSelfConversation(admins, selfConversation);
                                    if (admins != null)
                                    {
                                        foreach (var admin in admins)
                                        {
                                            await messageRouter.SendMessageAsync(admin,
                                                                                 CommandFactoryHelper.CreateCommandEndConversation(selfConversation.Bot.Id, properties.UserId));
                                        }
                                    }

                                    //Send event to event processor... if possible
                                    if (userReport != null)
                                    {
                                        //Sanitize user
                                        string      userId = GetDatabaseUserId(userReport.ChannelId, userReport.User.Id);
                                        DeviceModel device = await _deviceRestService.GetMobileDeviceFromUserId(userId);

                                        //Send close message
                                        await PushClosureMessageToEventProcessorSaga(device.DeviceId);
                                    }
                                }
                            }
                            if (!result)
                            {
                                throw new Exception("Error while executing command EndConversation");
                            }
                        }
                    }
                    break;

                case Commands.SendMessage:
                    if (userContext.Role == ChatUserRole.Admin && !string.IsNullOrWhiteSpace(activity.Text))
                    {
                        if (JsonConvert.DeserializeObject <CommandSendMessageProperties>(command.Data.ToString()) is CommandSendMessageProperties properties)
                        {
                            properties.UserId = properties.UserId;
                            properties.From   = userContext;   //Forcing admin, in case it isn't given by user
                            turnContext.TurnState.Add(typeof(CommandSendMessageProperties).FullName, properties);
                            //We forward to the next middleware
                            await next(cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            throw new Exception("Error while executing command SendMessage");
                        }
                    }
                    break;

                default:
                    if (userContext.Role == ChatUserRole.Admin)
                    {
                        throw new Exception($"Command not recognized: '{command.BaseCommand}'.");
                    }
                    break;
                }
            }