using Knot.Shared.Kernel; using Knot.Contracts.Conversations.Domain; using Knot.Modules.Conversations.Infrastructure.SignalR; using MediatR; using Microsoft.AspNetCore.SignalR; namespace Knot.Modules.Conversations.Infrastructure.Handlers; /// /// Обработчик доменного события создания чата. /// public sealed class ChatCreatedDomainEventHandler : INotificationHandler, INotificationHandler { private readonly IHubContext _hubContext; private readonly IChatRepository _chatRepository; private readonly IUserDisplayNameProvider _displayNameProvider; public ChatCreatedDomainEventHandler( IHubContext hubContext, IChatRepository chatRepository, IUserDisplayNameProvider displayNameProvider) { _hubContext = hubContext; _chatRepository = chatRepository; _displayNameProvider = displayNameProvider; } public async Task Handle(ChatCreatedDomainEvent notification, CancellationToken cancellationToken) { await NotifyNewChatAsync(notification.Chat, cancellationToken); } public async Task Handle(ChatMemberAddedDomainEvent notification, CancellationToken cancellationToken) { var chat = await _chatRepository.GetByIdAsync(notification.ChatId, cancellationToken); if (chat != null) { // Уведомляем всех участников, что кто-то добавлен (или пользователь сам видит новый чат) await NotifyNewChatAsync(chat, cancellationToken); } } private async Task NotifyNewChatAsync(Chat chat, CancellationToken cancellationToken, string? targetUserId = null) { var members = new List(); foreach (var member in chat.Members) { var userInfo = await _displayNameProvider.GetUserInfoAsync(member.UserId, cancellationToken); members.Add(new { member.Id, member.UserId, member.Role, member.JoinedAt, User = userInfo != null ? new { userInfo.Id, userInfo.Username, userInfo.DisplayName, userInfo.Avatar, isOnline = false } : new { Id = member.UserId, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null, isOnline = false } }); } var payload = new { id = chat.Id, type = chat.Type.ToString().ToLowerInvariant(), name = chat.Type == ChatType.Favorites ? "Избранное" : (chat.Type == ChatType.Personal ? null : chat.Name), avatar = chat.Avatar, createdAt = chat.CreatedAt, members = members, messages = new List(), unreadCount = 0 }; if (targetUserId != null) { // Отправляем конкретному пользователю (по всем его соединениям) // Мы можем использовать метод Hub или просто отправить в группу UserId (если она есть) // В нашем ChatHub мы добавляем пользователя в группы чатов при подключении. // Но для нового чата он еще не в группе. // Поэтому отправляем через User ID (SignalR поддерживает Clients.User(id)) await _hubContext.Clients.User(targetUserId).SendAsync("new_chat", payload, cancellationToken); } else { // Уведомляем всех текущих участников foreach (var member in chat.Members) { await _hubContext.Clients.User(member.UserId.ToString()).SendAsync("new_chat", payload, cancellationToken); } } } }