93 lines
4.0 KiB
C#
93 lines
4.0 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// Обработчик доменного события создания чата.
|
|
/// </summary>
|
|
public sealed class ChatCreatedDomainEventHandler : INotificationHandler<ChatCreatedDomainEvent>, INotificationHandler<ChatMemberAddedDomainEvent>
|
|
{
|
|
private readonly IHubContext<ChatHub> _hubContext;
|
|
private readonly IChatRepository _chatRepository;
|
|
private readonly IUserDisplayNameProvider _displayNameProvider;
|
|
|
|
public ChatCreatedDomainEventHandler(
|
|
IHubContext<ChatHub> 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<object>();
|
|
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<object>(),
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|