using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using MimeKit; using MTWorkHR.Application.Filters; using MTWorkHR.Application.Identity; using MTWorkHR.Application.Mapper; using MTWorkHR.Application.Models; using MTWorkHR.Application.Services; using MTWorkHR.Core.Entities; using MTWorkHR.Core.Entities.Base; using MTWorkHR.Core.Global; using MTWorkHR.Core.UnitOfWork; using MTWorkHR.Infrastructure.Entities; using System; using System.ComponentModel.Design; using System.Linq.Dynamic.Core.Tokenizer; using System.Security.Claims; using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace MTWorkHR.API.Chat { [AppAuthorize] public class ChatHub : Hub { private readonly IUnitOfWork _unitOfWork; private readonly GlobalInfo _globalInfo; //private readonly UserService _userService; private readonly ApplicationUserManager _userManager; public ChatHub(IUnitOfWork unitOfWork, GlobalInfo globalInfo, ApplicationUserManager userManager /*, UserService userService*/) { _unitOfWork = unitOfWork; _globalInfo = globalInfo; // _userService = userService; _userManager = userManager; } public async Task GetUsers() { var myCompanyUsers = await GetAllCompanyEmployees(); await Clients.Caller.SendAsync("UpdateUserList", myCompanyUsers); } public async Task> GetAllCompanyEmployees() { List response = null; try { var employees = await _userManager.GetUsersInRoleAsync("Employee"); var CompanyId = GetAuthenticatedCompanyId(); var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var res = employees.Where(e => e.CompanyId == CompanyId && e.Id != userId).ToList(); response = MapperObject.Mapper.Map>(res); var allConnections = await _unitOfWork.HubConnection.GetAllAsync(); var onlineUsers = allConnections.Item1 .Select(c => new { c.UserId, c.SignalrId }).ToList(); foreach (var emp in res) { var online = onlineUsers.FirstOrDefault(u => u.UserId == emp.Id); var profileImg = ""; var lastMessage = await GetLastMessage(emp.Id); var lastMsg = lastMessage.Item1?.Content; var lastMsgDate = lastMessage.Item1?.CreateDate; var unseenCount = lastMessage.Item2; var chatUser = new ChatUserDto(emp.Id, emp.FirstName + " " + emp.LastName, online?.SignalrId, emp.Email, online != null ? true : false, profileImg, unseenCount, lastMsg, lastMsgDate); } }catch(Exception e) { var m = e.Message; Console.WriteLine(e.Message); } return response; } private long GetAuthenticatedCompanyId() { long CompanyIdLong = 0; var identity = Context.User?.Identities.FirstOrDefault(); var CompanyId = identity!=null ? identity.FindFirst("companyId")?.Value : "0"; if(CompanyId != null) { CompanyIdLong = long.Parse(CompanyId); } return CompanyIdLong; } // Send a message from one user to another public async Task sendMsg(string receiverUserId, string msg) { try { var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var userName = Context.User.Identities.FirstOrDefault().FindFirst("name")?.Value; var allConnections = await _unitOfWork.HubConnection.GetAllAsync(); var receiverUser = allConnections.Item1.FirstOrDefault(c => c.UserId == receiverUserId); var receiverconnIdDB = receiverUser != null ? receiverUser.SignalrId : "0"; ChatMessage messag = new ChatMessage { Content = msg, ReceiverId = receiverUserId, ReceiverName = receiverUser.UserName ?? "", SenderId = userId, SenderName = userName, IsSeen = false }; await _unitOfWork.ChatMessage.AddAsync(messag); await _unitOfWork.CompleteAsync(); await Clients.Client(receiverconnIdDB).SendAsync("ReceiveMessage", messag); await Clients.Caller.SendAsync("ReceiveMessage", messag); } catch (Exception e) { } } // Get previous messages between two users public async Task GetPreviousMessages(string contactId) { var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(userId, contactId); // Ensure the query is fully materialized before passing it to SignalR var messagesList = await allmessages.Item1.ToListAsync(); await Clients.Caller.SendAsync("PreviousMessages", messagesList); } public async Task> GetLastMessage(string contactId) { var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var allmessages = await _unitOfWork.ChatMessage.GetAllWithChildrenAsync(userId, contactId); // Ensure the query is fully materialized before passing it to SignalR var lastOne = allmessages.Item1.OrderByDescending(m=> m.Id).FirstOrDefault(); var unseen = allmessages.Item1.Count(m=> m.IsSeen == false); return new Tuple( lastOne?? new ChatMessage(), unseen); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- //---------------------------------------------------------------------- //Simple Test Method public async Task SendMessageAll(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } public async override Task OnDisconnectedAsync(Exception exception) { var email = Context.User?.FindFirst(ClaimTypes.Email)?.Value; var connections = await _unitOfWork.HubConnection.GetAllAsync(Context.ConnectionId); var currUserId = connections.Item1.Select(c => c.UserId).SingleOrDefault(); await _unitOfWork.HubConnection.DeleteRangeAsync(connections.Item1.ToList()); await _unitOfWork.CompleteAsync(); await Clients.Others.SendAsync("userOff", currUserId); await base.OnDisconnectedAsync(exception); } public override async Task OnConnectedAsync() { try { string currSignalrID = Context.ConnectionId; var email = Context.User?.FindFirst(ClaimTypes.Email)?.Value; var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var userName = Context.User.Identities.FirstOrDefault().FindFirst("name")?.Value; if (userId != null) //if credentials are correct { HubConnection currUser = new HubConnection { UserId = userId, UserName = userName, SignalrId = currSignalrID, TimeStamp = DateTime.Now }; var newConnection = await _unitOfWork.HubConnection.AddAsync(currUser); await _unitOfWork.CompleteAsync(); ChatUserDto newUser = new ChatUserDto(userId, userName, currSignalrID); await Clients.Caller.SendAsync("authMeResponseSuccess", newUser);//4Tutorial await Clients.Others.SendAsync("userOn", newUser);//4Tutorial } else //if credentials are incorrect { await Clients.Caller.SendAsync("authMeResponseFail"); } } catch (Exception ex) { } await base.OnConnectedAsync(); } public void logOut(string userId) { var userIdAuth = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var connections = _unitOfWork.HubConnection.GetAllAsync(Context.ConnectionId).Result; // var currUserId = connections.Item1.Select(c => c.UserId).SingleOrDefault(); _unitOfWork.HubConnection.DeleteRangeAsync(connections.Item1.ToList()); _unitOfWork.CompleteAsync(); Clients.Caller.SendAsync("logoutResponse"); Clients.Others.SendAsync("userOff", userIdAuth); } public async Task getOnlineUsers() { var allConnections = await _unitOfWork.HubConnection.GetAllAsync(); var currUserId = allConnections.Item1.Where(c => c.SignalrId == Context.ConnectionId).Select(c => c.UserId).SingleOrDefault(); List onlineUsers = allConnections.Item1 .Where(c => c.UserId != currUserId) .Select(c => new ChatUserDto(c.UserId, c.UserName, c.SignalrId) ).ToList(); await Clients.Caller.SendAsync("getOnlineUsersResponse", onlineUsers); } public async Task authMe(PersonalInfo person) { try { string currSignalrID = Context.ConnectionId; //Person tempPerson = ctx.Person.Where(p => p.Username == personInfo.userName && p.Password == personInfo.password) // .SingleOrDefault(); var companyId = Context.User.Identities.FirstOrDefault().FindFirst("companyId")?.Value; var userId = Context.User.Identities.FirstOrDefault().FindFirst("uid")?.Value; var userName = Context.User.Identities.FirstOrDefault().FindFirst("name")?.Value; if (userId != null) //if credentials are correct { Console.WriteLine("\n" + userName + " logged in" + "\nSignalrID: " + currSignalrID); HubConnection currUser = new HubConnection { UserId = userId, UserName = userName, SignalrId = currSignalrID, TimeStamp = DateTime.Now }; var newConnection = await _unitOfWork.HubConnection.AddAsync(currUser); await _unitOfWork.CompleteAsync(); ChatUserDto newUser = new ChatUserDto(userId, userName, currSignalrID); await Clients.Caller.SendAsync("authMeResponseSuccess", newUser);//4Tutorial await Clients.Others.SendAsync("userOn", newUser);//4Tutorial } else //if credentials are incorrect { await Clients.Caller.SendAsync("authMeResponseFail"); } } catch (Exception e) { await Clients.Caller.SendAsync("authMeResponseFail"); } } //public async Task reauthMe(string userId) //{ // string currSignalrID = Context.ConnectionId; // //ApplicationUser tempPerson = ctx.Person.Where(p => p.Id == personId) // // .SingleOrDefault(); // if (userId == _globalInfo.UserId) //if credentials are correct // { // Console.WriteLine("\n" + _globalInfo.UserName + " logged in" + "\nSignalrID: " + currSignalrID); // HubConnection currUser = new HubConnection // { // UserId = _globalInfo.UserId, // SignalrId = currSignalrID, // TimeStamp = DateTime.Now // }; // var newConnection = await _unitOfWork.HubConnection.AddAsync(currUser); // await _unitOfWork.CompleteAsync(); // ChatUserDto newUser = new ChatUserDto(_globalInfo.UserId, _globalInfo.UserName, currSignalrID); // await Clients.Caller.SendAsync("reauthMeResponse", newUser);//4Tutorial // await Clients.Others.SendAsync("userOn", newUser);//4Tutorial // } //} //end of reauthMe } public class PersonalInfo { public string userName { get; set; } public string password { get; set; } public string userId { get; set; } } }