| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- using Application.Abstractions.Cache;
- using Application.Abstractions.Chat;
- using Application.Abstractions.Hub;
- using Microsoft.AspNetCore.SignalR;
- using Microsoft.Extensions.Logging;
- using StackExchange.Redis;
- namespace Infrastructure.Hubs;
- /// <summary>
- /// 공통 Hub — 모든 페이지에서 사용
- /// 접속자 추적 + 채팅 + 알림 + 쪽지 + 크루 초대/동의/toast + YouTube 채팅 통합
- /// </summary>
- public sealed class AppHub(
- IConnectionMultiplexer redis,
- ILogger<AppHub> logger
- ) : Hub<IAppHubClient>
- {
- // ── 연결 관리 ────────────────────────────────────────────────
- public override async Task OnConnectedAsync()
- {
- var memberID = GetMemberID();
- if (memberID > 0)
- {
- var db = redis.GetDatabase();
- await db.HashSetAsync(CacheKeys.ChatConnections, Context.ConnectionId, memberID);
- // 개인 그룹 (알림/쪽지용)
- await Groups.AddToGroupAsync(Context.ConnectionId, $"member:{memberID}");
- }
- await base.OnConnectedAsync();
- }
- public override async Task OnDisconnectedAsync(Exception? exception)
- {
- var db = redis.GetDatabase();
- await db.HashDeleteAsync(CacheKeys.ChatConnections, Context.ConnectionId);
- await base.OnDisconnectedAsync(exception);
- }
- // ── 채팅 그룹 참가/퇴장 ──────────────────────────────────────
- public async Task JoinChat(string room)
- {
- await Groups.AddToGroupAsync(Context.ConnectionId, $"chat:{room}");
- }
- public async Task LeaveChat(string room)
- {
- await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"chat:{room}");
- }
- // ── 채팅 메시지 전송 ─────────────────────────────────────────
- public async Task SendMessage(string room, ChatMessage message)
- {
- await Clients.Group($"chat:{room}").ReceiveMessage(message);
- }
- // ── 채널 그룹 (크루 초대/동의 실시간 등) ─────────────────────
- public async Task JoinChannel(string channelSID)
- {
- await Groups.AddToGroupAsync(Context.ConnectionId, $"channel:{channelSID}");
- }
- public async Task LeaveChannel(string channelSID)
- {
- await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"channel:{channelSID}");
- }
- // ── Private ──────────────────────────────────────────────────
- private int GetMemberID()
- {
- var claim = Context.User?.FindFirst("memberID")?.Value;
- return int.TryParse(claim, out var id) ? id : 0;
- }
- }
|