AppHub.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using Application.Abstractions.Cache;
  2. using Application.Abstractions.Chat;
  3. using Application.Abstractions.Hub;
  4. using Microsoft.AspNetCore.SignalR;
  5. using Microsoft.Extensions.Logging;
  6. using StackExchange.Redis;
  7. namespace Infrastructure.Hubs;
  8. /// <summary>
  9. /// 공통 Hub — 모든 페이지에서 사용
  10. /// 접속자 추적 + 채팅 + 알림 + 쪽지 + 크루 초대/동의/toast + YouTube 채팅 통합
  11. /// </summary>
  12. public sealed class AppHub(
  13. IConnectionMultiplexer redis,
  14. ILogger<AppHub> logger
  15. ) : Hub<IAppHubClient>
  16. {
  17. // ── 연결 관리 ────────────────────────────────────────────────
  18. public override async Task OnConnectedAsync()
  19. {
  20. var memberID = GetMemberID();
  21. if (memberID > 0)
  22. {
  23. var db = redis.GetDatabase();
  24. await db.HashSetAsync(CacheKeys.ChatConnections, Context.ConnectionId, memberID);
  25. // 개인 그룹 (알림/쪽지용)
  26. await Groups.AddToGroupAsync(Context.ConnectionId, $"member:{memberID}");
  27. }
  28. await base.OnConnectedAsync();
  29. }
  30. public override async Task OnDisconnectedAsync(Exception? exception)
  31. {
  32. var db = redis.GetDatabase();
  33. await db.HashDeleteAsync(CacheKeys.ChatConnections, Context.ConnectionId);
  34. await base.OnDisconnectedAsync(exception);
  35. }
  36. // ── 채팅 그룹 참가/퇴장 ──────────────────────────────────────
  37. public async Task JoinChat(string room)
  38. {
  39. await Groups.AddToGroupAsync(Context.ConnectionId, $"chat:{room}");
  40. }
  41. public async Task LeaveChat(string room)
  42. {
  43. await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"chat:{room}");
  44. }
  45. // ── 채팅 메시지 전송 ─────────────────────────────────────────
  46. public async Task SendMessage(string room, ChatMessage message)
  47. {
  48. await Clients.Group($"chat:{room}").ReceiveMessage(message);
  49. }
  50. // ── 채널 그룹 (크루 초대/동의 실시간 등) ─────────────────────
  51. public async Task JoinChannel(string channelSID)
  52. {
  53. await Groups.AddToGroupAsync(Context.ConnectionId, $"channel:{channelSID}");
  54. }
  55. public async Task LeaveChannel(string channelSID)
  56. {
  57. await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"channel:{channelSID}");
  58. }
  59. // ── Private ──────────────────────────────────────────────────
  60. private int GetMemberID()
  61. {
  62. var claim = Context.User?.FindFirst("memberID")?.Value;
  63. return int.TryParse(claim, out var id) ? id : 0;
  64. }
  65. }