LANCommander/LANCommander.Server/Hubs/Chat.cs
2025-11-13 18:33:08 -06:00

129 lines
No EOL
4.3 KiB
C#

using LANCommander.SDK.Models;
namespace LANCommander.Server.Hubs;
public partial class RpcHub
{
private string GetThreadParticipantCacheKey(Guid threadId) => $"Chat/Thread/{threadId}/Participants";
private async Task<List<string>> GetThreadParticipants(Guid threadId)
{
logger.LogDebug("Getting thread participants for {ThreadId}", threadId);
var cacheKey = GetThreadParticipantCacheKey(threadId);
var participants = await cache.TryGetAsync<List<string>>(cacheKey);
return participants.GetValueOrDefault([]);
}
public async Task<Guid> Chat_StartThreadAsync(string[] userIdentifiers)
{
logger.LogDebug("Starting new thread with {ParticipantCount} participants", userIdentifiers.Length);
var thread = await chatService.StartThreadAsync();
foreach (var userIdentifier in userIdentifiers)
await Chat_AddParticipantAsync(thread.Id, userIdentifier);
logger.LogDebug("Created new thread with ID {ThreadId}", thread.Id);
return thread.Id;
}
public async Task Chat_AddParticipantAsync(Guid threadId, string participantId)
{
var cacheKey = GetThreadParticipantCacheKey(threadId);
var participants = await cache.TryGetAsync<List<string>>(cacheKey);
if (participants.HasValue && !participants.Value.Contains(participantId))
{
if (Guid.TryParse(participantId, out var userId))
await chatService.AddParticipantAsync(threadId, userId);
participants.Value.Add(participantId);
await cache.SetAsync(cacheKey, participants.Value);
}
}
public async Task<ChatThread> Chat_GetThreadAsync(Guid threadId)
{
var thread = await chatService.GetThreadAsync(threadId);
return mapper.Map<ChatThread>(thread);
}
public async Task<IEnumerable<ChatThread>> Chat_GetThreadsAsync()
{
if (Guid.TryParse(Context.UserIdentifier, out var userId))
{
var threads = await chatService.GetThreadsAsync(userId);
// Populate participant cache
foreach (var thread in threads)
{
var cacheKey = GetThreadParticipantCacheKey(thread.Id);
var participants = await cache.TryGetAsync<List<string>>(cacheKey);
if (!participants.HasValue && thread.Participants != null)
await cache.SetAsync(cacheKey, thread.Participants.Select(p => p.Id).ToList());
}
return mapper.Map<IEnumerable<ChatThread>>(threads);
}
return [];
}
public async Task Chat_SendMessageAsync(Guid threadId, string content)
{
var message = await chatService.SendMessageAsync(threadId, content);
var participants = await GetThreadParticipants(threadId);
await Clients.Users(participants).Chat_ReceiveMessageAsync(threadId, mapper.Map<ChatMessage>(message));
}
public async Task Chat_GetMessagesAsync(Guid threadId)
{
var messages = await chatService.GetMessagesAsync(threadId);
await Clients.Caller.Chat_ReceiveMessagesAsync(threadId, mapper.Map<ChatMessage[]>(messages));
}
public async Task Chat_StartTyping(Guid threadId)
{
var participants = await GetThreadParticipants(threadId);
await Clients.Users(participants).Chat_StartTyping(threadId, Context.UserIdentifier);
}
public async Task Chat_StopTyping(Guid threadId)
{
var participants = await GetThreadParticipants(threadId);
await Clients.Users(participants).Chat_StopTyping(threadId, Context.UserIdentifier);
}
public async Task Chat_UpdateReadStatus(Guid threadId)
{
if (Guid.TryParse(Context.UserIdentifier, out var userId))
await chatService.UpdateReadStatus(threadId, userId);
}
public async Task<int> Chat_GetUnreadMessageCountAsync(Guid threadId)
{
if (Guid.TryParse(Context.UserIdentifier, out var userId))
return await chatService.GetUnreadMessageCountAsync(threadId, userId);
return 0;
}
public async Task<IEnumerable<User>> Chat_GetUsersAsync()
{
var users = await chatService.GetUsersAsync();
return mapper.Map<IEnumerable<User>>(users);
}
}