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