using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity.Data; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using StackExchange.Redis; using System.Diagnostics; using WebAppServer1.ApplicationDbContext; using WebAppServer1.Authentication; using WebAppServer1.Models; using WebAppServer1.Tool; namespace WebAppServer1.Chat { public class Chat : Hub { private readonly ILogger logger; private readonly IConnectionMultiplexer _redis; private readonly AppDbContext pgSql; private readonly TokenService jwtService; public Chat(ILogger _logger, IConnectionMultiplexer redis, AppDbContext _pgsql,TokenService _jwtService) { logger = _logger; _redis = redis; pgSql = _pgsql; jwtService = _jwtService; } //wss子端点API public override async Task OnConnectedAsync() { var db = _redis.GetDatabase(); await db.SetAddAsync("AllConnections", Context.ConnectionId); await BroadcastOnlineCount(); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception? exception) { var db = _redis.GetDatabase(); await db.SetRemoveAsync("AllConnections", Context.ConnectionId); // 遍历所有群组,移除该连接 var server = _redis.GetServer(_redis.GetEndPoints().First()); foreach (var key in server.Keys(pattern: "Group:*")) { await db.SetRemoveAsync(key, Context.ConnectionId); var groupName = key.ToString().Replace("Group:", ""); await BroadcastGroupCount(groupName); } await BroadcastOnlineCount(); await base.OnDisconnectedAsync(exception); } //简单广播消息 [Authorize] public async Task SendMessage(string user, string message) { logger.LogWarning("广播消息"); //测试发送 var exuser = Context.User?.Identity?.Name ?? "匿名"; await Clients.All.SendAsync("ReceiveMessage", exuser, message); } //群聊分组消息 public async Task JoinGroup(string groupName) { var db = _redis.GetDatabase(); await Groups.AddToGroupAsync(Context.ConnectionId, groupName); await db.SetAddAsync($"Group:{groupName}", Context.ConnectionId); await BroadcastGroupCount(groupName); logger.LogWarning($"用户: {Context.ConnectionId}加入了{groupName}群组!"); await Clients.Group(groupName).SendAsync("ReceiveMessage", groupName, "系统", $"{Context.ConnectionId} 加入了群组"); } public async Task LeaveGroup(string groupName) { var db = _redis.GetDatabase(); await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName); await db.SetRemoveAsync($"Group:{groupName}", Context.ConnectionId); await BroadcastGroupCount(groupName); logger.LogInformation($"用户{Context.ConnectionId}---离开了---{groupName}群组"); await Clients.Group(groupName).SendAsync("ReceiveMessage",groupName, "系统", $"{Context.ConnectionId} 离开了群聊 {groupName}"); } [Authorize] public async Task SendMessageToGroup(string groupName, string user, string message) { logger.LogInformation($"用户{user}发来的的消息:{message}"); await Clients.Group(groupName).SendAsync("ReceiveMessage", groupName, user, message); } //发送已读回执 public async Task SendReadReceipt(int messageId) { var update = await pgSql.Messages.FindAsync(messageId); if (update == null) { return; }; update.IsRead = true; pgSql.Messages.Update(update); await pgSql.SaveChangesAsync(); await Clients.User(update.SenderId.ToString()).SendAsync("SendReadReceipt",messageId); } //发送私聊消息 [Authorize] public async Task SendPrivateMessage(string userid, string message) { var receiver = await pgSql.Users.FindAsync(int.Parse(userid)); if (receiver == null) { await Clients.Caller.SendAsync("SendPrivateMessage", false, "用户不存在", Context.UserIdentifier); return; } var newMesssage = new Message { SenderId = int.Parse(Context.UserIdentifier!), ReceiverId = receiver.Id, Content = message, CreatedAt = DateTime.UtcNow, MessageType = MessageType.Text, IsDeleted = false, IsRead = false }; pgSql.Messages.Add(newMesssage); await pgSql.SaveChangesAsync(); await Clients.User(userid).SendAsync("SendPrivateMessage", true, message,Context.UserIdentifier,newMesssage.Id); await Clients.Caller.SendAsync("SendPrivateMessage", false, message, Context.UserIdentifier,newMesssage.Id); } //搜索好友 public async Task SearchFriends(string username) { User? user = null; if (int.TryParse(username, out int userId)) { user = await pgSql.Users.FindAsync(userId); Console.WriteLine("按 ID 查询: " + userId); } if (user == null) { user = await pgSql.Users.FirstOrDefaultAsync(a => a.Username == username); } return user == null ? new SearchFriendsResultResponse { success = false } : new SearchFriendsResultResponse { success = true, userid = user.Id, username = user.Nickname }; } //获取用户表单测试 public async Task> GetFormData() { var users = await pgSql.Users .Select(u => new { Id = u.Id, Name = u.Username, Password = u.PasswordHash, CreatedDate = u.CreatedAt, LastModifiedDate = u.LastActive }) .ToListAsync(); return users.Cast().ToList(); } //刷新Token // 刷新 Token public async Task RefreshAccessToken(string refreshToken) { var token = await pgSql.Tokens.FirstOrDefaultAsync(t => t.RefreshToken == refreshToken); if (token == null || token.IsRevoked || token.ExpiresAt < DateTime.UtcNow) { await Clients.Caller.SendAsync("RefreshFailed", "Refresh token invalid or expired"); return; } var newAccessToken = jwtService.GenerateAccessToken(token.UserName, token.UserId); var newRefreshToken = await jwtService.GenerateRefreshToken(token.UserId, token.UserName); token.IsRevoked = true; await pgSql.SaveChangesAsync(); await Clients.Caller.SendAsync("ReceiveNewAccessToken", newAccessToken, newRefreshToken); } //登录认证 public async Task LoginAuthentication(string username, string password) { var exists = await pgSql.Users.AnyAsync(a => a.Username == username && a.PasswordHash == password); if (!exists) { await Clients.Client(Context.ConnectionId).SendAsync("LoginResult",false,"用户名或密码错误!"); return; } var user = await pgSql.Users.FirstOrDefaultAsync(a => a.Username == username); if (user == null) { return; } var accessToken = jwtService.GenerateAccessToken(user.Username,user.Id); var refreshToken = await jwtService.GenerateRefreshToken(user.Id, username); await Clients.Client(Context.ConnectionId).SendAsync("LoginResult", true, accessToken, refreshToken); logger.LogInformation($"用户:{username}正在进行登录认证!密码:{password}===accessToken:{accessToken}"); } //新用户注册 public async Task Register() { var newUser = new User { Username = "user_" + Guid.NewGuid().ToString("N").Substring(0, 8), Nickname = GenerateTool.GenerateRandomNickname(), PasswordHash = GenerateTool.GeneratePassword(), CreatedAt = DateTime.UtcNow, LastActive = DateTime.UtcNow }; pgSql.Add(newUser); await pgSql.SaveChangesAsync(); logger.LogInformation($"新用户:{newUser.Username}正在进行登录注册操作!密码:{newUser.Nickname}"); await Clients.Client(Context.ConnectionId).SendAsync("RegisterResult", true,"恭喜注册成功!"); await LoginAuthentication(newUser.Username,newUser.PasswordHash); } //统计在线人数 private async Task BroadcastOnlineCount() { var db = _redis.GetDatabase(); var count = await db.SetLengthAsync("AllConnections"); await Clients.All.SendAsync("OnlineCount", count); } //统计群组在线人数 private async Task BroadcastGroupCount(string groupName) { var db = _redis.GetDatabase(); var count = await db.SetLengthAsync($"Group:{groupName}"); await Clients.Group(groupName).SendAsync("GroupCount", groupName, count); } } }