public async Task SendMessage(Guid conferenceId, string message, string to, Guid messageUuid) { var userName = await GetObfuscatedUsernameAsync(Context.User.Identity.Name); _logger.LogTrace($"{userName} is attempting to SendMessages"); // this determines if the message is from admin var isSenderAdmin = IsSenderAdmin(); _logger.LogDebug($"{userName} is sender admin: {isSenderAdmin}"); var isRecipientAdmin = await IsRecipientAdmin(to); _logger.LogDebug($"{userName} is recipient admin: {isSenderAdmin}"); // only admins and participants in the conference can send or receive a message within a conference channel var from = Context.User.Identity.Name.ToLowerInvariant(); var participantUsername = isSenderAdmin ? to : from; var isAllowed = await IsAllowedToSendMessageAsync(conferenceId, isSenderAdmin, isRecipientAdmin, participantUsername); if (!isAllowed) { return; } var dto = new SendMessageDto { Conference = new Conference { Id = conferenceId }, From = from, To = to, Message = message, ParticipantUsername = participantUsername, Timestamp = DateTime.UtcNow, MessageUuid = messageUuid }; _logger.LogDebug($"Message validation passed for message {dto.MessageUuid}"); // send to admin channel await SendToAdmin(dto); // determine participant username dto.Conference = await GetConference(conferenceId); await SendToParticipant(dto); _logger.LogDebug($"Pushing message to Video API history {dto.MessageUuid}"); await _videoApiClient.AddInstantMessageToConferenceAsync(conferenceId, new AddInstantMessageRequest { From = from, To = to, Message_text = message }); if (isSenderAdmin) { _logger.LogDebug($"Admin has responded, notifying admin channel"); await Clients.Group(VhOfficersGroupName).AdminAnsweredChat(conferenceId, to.ToLower()); } }