94 lines
3.0 KiB
C#
94 lines
3.0 KiB
C#
using System.Net.WebSockets;
|
|
using DysonNetwork.Sphere.Chat;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using Microsoft.Extensions.Internal;
|
|
using SystemClock = NodaTime.SystemClock;
|
|
|
|
namespace DysonNetwork.Sphere.Connection.Handlers;
|
|
|
|
public class MessageReadHandler(AppDatabase db, IMemoryCache cache, ChatRoomService crs) : IWebSocketPacketHandler
|
|
{
|
|
public string PacketType => "messages.read";
|
|
|
|
public const string ChatMemberCacheKey = "ChatMember_{0}_{1}";
|
|
|
|
public async Task HandleAsync(
|
|
Account.Account currentUser,
|
|
string deviceId,
|
|
WebSocketPacket packet,
|
|
WebSocket socket,
|
|
WebSocketService srv
|
|
)
|
|
{
|
|
var request = packet.GetData<ChatController.MarkMessageReadRequest>();
|
|
if (request is null)
|
|
{
|
|
await socket.SendAsync(
|
|
new ArraySegment<byte>(new WebSocketPacket
|
|
{
|
|
Type = WebSocketPacketType.Error,
|
|
ErrorMessage = "Mark message as read requires you provide the ChatRoomId and MessageId"
|
|
}.ToBytes()),
|
|
WebSocketMessageType.Binary,
|
|
true,
|
|
CancellationToken.None
|
|
);
|
|
return;
|
|
}
|
|
|
|
ChatMember? sender = null;
|
|
var cacheKey = string.Format(ChatMemberCacheKey, currentUser.Id, request.ChatRoomId);
|
|
if (cache.TryGetValue(cacheKey, out ChatMember? cachedMember))
|
|
sender = cachedMember;
|
|
else
|
|
{
|
|
sender = await db.ChatMembers
|
|
.Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == request.ChatRoomId)
|
|
.FirstOrDefaultAsync();
|
|
|
|
if (sender != null)
|
|
{
|
|
var cacheOptions = new MemoryCacheEntryOptions()
|
|
.SetAbsoluteExpiration(TimeSpan.FromMinutes(5));
|
|
cache.Set(cacheKey, sender, cacheOptions);
|
|
}
|
|
}
|
|
|
|
if (sender is null)
|
|
{
|
|
await socket.SendAsync(
|
|
new ArraySegment<byte>(new WebSocketPacket
|
|
{
|
|
Type = WebSocketPacketType.Error,
|
|
ErrorMessage = "User is not a member of the chat room."
|
|
}.ToBytes()),
|
|
WebSocketMessageType.Binary,
|
|
true,
|
|
CancellationToken.None
|
|
);
|
|
return;
|
|
}
|
|
|
|
db.ChatStatuses.Add(new MessageStatus
|
|
{
|
|
MessageId = request.MessageId,
|
|
SenderId = sender.Id,
|
|
ReadAt = SystemClock.Instance.GetCurrentInstant(),
|
|
});
|
|
|
|
try
|
|
{
|
|
await db.SaveChangesAsync();
|
|
|
|
// Broadcast read statuses
|
|
var otherMembers = (await crs.ListRoomMembers(request.ChatRoomId)).Select(m => m.AccountId).ToList();
|
|
foreach (var member in otherMembers)
|
|
srv.SendPacketToAccount(member, packet);
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
} |