Files
Govor/Govor.Application/Services/Messages/MessagesLoader.cs
T
2026-02-08 22:30:29 +07:00

142 lines
4.5 KiB
C#

using Govor.Application.Interfaces;
using Govor.Core.Models.Messages;
using Govor.Core.Repositories.Groups;
using Govor.Core.Repositories.PrivateChats;
using Govor.Data;
using Govor.Data.Repositories.Exceptions;
using Microsoft.EntityFrameworkCore;
namespace Govor.Application.Services.Messages;
public class MessagesLoader : IMessagesLoader
{
private IGroupsRepository _groupsRepository;
private IPrivateChatsRepository _privateChatsRepository;
private GovorDbContext _dbContext;
public MessagesLoader(
IGroupsRepository groupsRepository,
IPrivateChatsRepository privateChatsRepository,
GovorDbContext dbContext)
{
_groupsRepository = groupsRepository;
_privateChatsRepository = privateChatsRepository;
_dbContext = dbContext;
}
public async Task<List<Message>> LoadMessagesInUserChat(
Guid privateChatId,
Guid currentUser,
Guid? startMessageId,
int before = 20,
int after = 2)
{
if (privateChatId == Guid.Empty)
throw new ArgumentException("PrivateChatId id cannot be empty");
if (!_privateChatsRepository.Exist(privateChatId))
throw new InvalidOperationException("Private chat not found");
var query = _dbContext.Messages
.AsNoTracking()
.Include(m => m.MediaAttachments)
.ThenInclude(m => m.MediaFile)
.Where(m => m.RecipientType == RecipientType.User &&
m.RecipientId == privateChatId);
if (startMessageId is null)
{
return await query
.OrderByDescending(m => m.SentAt)
.Take(before)
.ToListAsync();
}
var startMessage = await _dbContext.Messages.FindAsync(startMessageId.Value);
if (startMessage == null)
throw new NotFoundException("Start message not found");
var beforeMessages = await query
.Where(m => m.SentAt < startMessage.SentAt)
.OrderByDescending(m => m.SentAt)
.Take(before)
.ToListAsync();
var afterMessages = await query
.Where(m => m.SentAt > startMessage.SentAt)
.OrderBy(m => m.SentAt)
.Take(after)
.ToListAsync();
// older -> start -> newer
var result = beforeMessages
.OrderBy(m => m.SentAt)
.Concat(new[] { startMessage })
.Concat(afterMessages)
.ToList();
return result;
}
public async Task<List<Message>> LoadMessagesInChatGroup(
Guid chatId,
Guid currentUser,
Guid? startMessageId,
int before = 20,
int after = 2)
{
if (chatId == Guid.Empty)
throw new ArgumentException("Chat id cannot be empty");
var isMember = await _groupsRepository.IsUserMemberOfGroupAsync(currentUser, chatId);
if (!isMember)
throw new UnauthorizedAccessException("You are not a member of this group.");
var baseQuery = _dbContext.Messages
.AsNoTracking()
.Include(m => m.MediaAttachments)
.ThenInclude(m => m.MediaFile)
.AsSplitQuery()
.Where(m => m.RecipientType == RecipientType.Group && m.RecipientId == chatId);
if (startMessageId is null)
{
return await baseQuery
.OrderByDescending(m => m.SentAt)
.Take(before)
.OrderBy(m => m.SentAt)
.ToListAsync();
}
var startMessage = await _dbContext.Messages
.AsNoTracking()
.FirstOrDefaultAsync(m => m.Id == startMessageId.Value &&
m.RecipientType == RecipientType.Group &&
m.RecipientId == chatId);
if (startMessage == null)
throw new NotFoundException("Start message not found in this group.");
var beforeMessages = await baseQuery
.Where(m => m.SentAt < startMessage.SentAt)
.OrderByDescending(m => m.SentAt)
.Take(before)
.ToListAsync();
var afterMessages = await baseQuery
.Where(m => m.SentAt > startMessage.SentAt)
.OrderBy(m => m.SentAt)
.Take(after)
.ToListAsync();
var result = beforeMessages
.OrderBy(m => m.SentAt)
.Concat(new[] { startMessage })
.Concat(afterMessages)
.ToList();
return result;
}
}