using Diligent.WebAPI.Data.Entities; using Diligent.WebAPI.Host.DTOs.Notification; using Diligent.WebAPI.Host.DTOs.Chat; using Diligent.WebAPI.Host.Mediator.Chat.Commands; using Diligent.WebAPI.Host.Mediator.Messages.Commands; using Diligent.WebAPI.Host.Mediator.Notifications.Commands; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; using Diligent.WebAPI.Host.Middlewares; namespace Diligent.WebAPI.Host.Hubs { public class ChatHub : Hub { private readonly IDictionary _connections; private readonly IMediator _mediator; public ChatHub(IDictionary connections,IMediator mediator) { _connections = connections; _mediator = mediator; } //public override Task OnDisconnectedAsync(Exception? exception) //{ // if (_connections.TryGetValue(Context.ConnectionId, out UserConnection room)) // { // _connections.Remove(Context.ConnectionId); // Clients.Group(room.RoomId).ReceiveMessage(new ChatMessage { User = room.UserId, Message = $"{room.UserId} has left room" }); // } // return base.OnDisconnectedAsync(exception); //} [HubMethodName("SendMessageToGroup")] [AuthorizationHubFilter(Roles = "Customer,Support")] public async Task SendMessageToGroup(ChatMessage message) { // Find user's room and send message to everyone // All other users will receive notification if (_connections.TryGetValue(message.ConnId, out UserConnection room)) { await Clients.Group(room.RoomId).ReceiveMessage(new ChatMessage { User = room.UserId, Message = message.Message }); await Clients.OthersInGroup(room.RoomId).ReceiveNotifications(room.UserId, room.RoomId); await _mediator.Send(new AddMessageCommand(room.RoomId, new Message { Content = message.Message, SenderId = message.UserId, Username = room.Username })); // Find other users in room and save notification in database foreach (KeyValuePair conn in _connections) { if (conn.Value.RoomId == room.RoomId && conn.Key != message.ConnId) { await _mediator.Send(new AddNotificationCommand(new NotificationSaveDTO { RoomId = room.RoomId, ReceiverId = conn.Value.UserId })); } } } } [HubMethodName("JoinRoom")] [AuthorizationHubFilter(Roles = "Customer,Support")] public async Task JoinRoom(UserConnection userConnection) { // Check is user in requested room var result = _connections.Where(x => x.Value.UserId == userConnection.UserId && x.Value.RoomId == userConnection.RoomId).FirstOrDefault(); // If user is not in room, add him // Return message "User has joined room" to all users in room if (result.Value == null) { await Groups.AddToGroupAsync(Context.ConnectionId, userConnection.RoomId); _connections[Context.ConnectionId] = userConnection; await Clients.Group(userConnection.RoomId).ReceiveMessage(new ChatMessage { User = userConnection.UserId, Message = $"{userConnection.Username} has joined room", ConnId = Context.ConnectionId }); } else { await _mediator.Send(new DeleteNotificationCommand(new NotificationDeleteDTO { UserId = userConnection.UserId, RoomId = userConnection.RoomId })); } } [HubMethodName("LeaveRoom")] [AuthorizationHubFilter(Roles = "Customer,Support")] public async Task LeaveRoom(LeaveChatRoomDTO connection) { if (_connections.TryGetValue(connection.ConnId, out UserConnection room)) { _connections.Remove(Context.ConnectionId); await Clients.OthersInGroup(room.RoomId).ReceiveMessage(new ChatMessage { User = room.UserId, Message = $"{room.Username} has left room" }); await _mediator.Send(new RemoveUserFromGroupCommand(room.RoomId, room.UserId)); } } [HubMethodName("SeeWhoIsTyping")] public async Task SeeWhoIsTyping(TypingInvokeMessage message) { // Find user's room and send message to everyone //if (_connections.TryGetValue(Context.ConnectionId, out UserConnection room)) if (_connections.TryGetValue(message.ConnId, out UserConnection room)) { // send the typing info to all in group except the caller // viewtyping(username + "is typing") // message, roomId //await Clients.GroupExcept(message.RoomId, Context.ConnectionId).ViewTyping(new TypingMessage { RoomId = room.RoomId, Message = message.Message }); await Clients.GroupExcept(message.RoomId, message.ConnId).ViewTyping(new TypingMessage { RoomId = room.RoomId, Message = message.Message }); } } } }