Files
forkmessager/backend/src/Modules/Conversations/Application/Messages/GetSharedMedia/GetSharedMediaQuery.cs
2026-03-22 23:59:33 +03:00

132 lines
5.3 KiB
C#

using Knot.Modules.Messaging.Application.Abstractions;
using Knot.Modules.Messaging.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Knot.Shared.Kernel;
using Knot.Modules.Conversations.Application.DTOs;
using Knot.Modules.Conversations.Domain;
using Knot.Modules.Conversations.Application.Abstractions;
namespace Knot.Modules.Conversations.Application.Messages.GetSharedMedia;
public record GetSharedMediaQuery(Guid UserId, Guid ChatId, string? Type) : IQuery<List<SharedMediaDto>>;
internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQuery, List<SharedMediaDto>>
{
private readonly IMessageRepository _messageRepository;
private readonly IUserDisplayNameProvider _userProvider;
private readonly IChatRepository _chatRepository;
public GetSharedMediaQueryHandler(IMessageRepository messageRepository, IUserDisplayNameProvider userProvider, IChatRepository chatRepository)
{
_messageRepository = messageRepository;
_userProvider = userProvider;
_chatRepository = chatRepository;
}
public async Task<Result<List<SharedMediaDto>>> Handle(GetSharedMediaQuery request, CancellationToken cancellationToken)
{
var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
if (chat == null || !chat.Members.Any(member => member.UserId == request.UserId))
{
return Result.Failure<List<SharedMediaDto>>(ChatErrors.ChatsForbidden);
}
var messages = await _messageRepository.GetChatMessagesAsync(request.ChatId, ChatConstants.MaxSharedMediaQueryLimit, 0, cancellationToken);
messages = messages.Where(message => !message.IsDeletedForUser(request.UserId)).ToList();
var result = new List<SharedMediaDto>();
var filterType = request.Type?.ToLower();
var userIds = messages.Select(message => message.SenderId).Distinct();
var senders = await _userProvider.GetUsersInfoAsync(userIds, cancellationToken);
foreach (var message in messages)
{
if (filterType == "links")
{
var messageContent = message.Content;
var linkRegex = new Regex(@"https?://[^\s]+", RegexOptions.IgnoreCase);
var contentLinks = !string.IsNullOrEmpty(messageContent) ? linkRegex.Matches(messageContent).Select(match => match.Value).ToList() : new List<string>();
var messageMediaColl = message.Media;
var mediaLinks = (messageMediaColl ?? Enumerable.Empty<Media>()).Where(media => media.Type?.ToString().ToLower() == "link").Select(media => media.Url).ToList();
var allLinks = contentLinks.Concat(mediaLinks).Distinct().ToList();
if (allLinks.Any())
{
senders.TryGetValue(message.SenderId, out var sender);
result.Add(new SharedMediaDto(
message.Id,
messageContent,
message.CreatedAt,
allLinks,
sender != null ? new MessageSenderDto(sender.Id, sender.Username, sender.DisplayName, sender.Avatar) : null,
null, null, null, null, null, null, null, null
));
}
continue;
}
var messageMedia = message.Media;
if (messageMedia == null || !messageMedia.Any())
{
continue;
}
var filteredMedia = messageMedia.Where(media =>
{
var mediaType = media.Type?.ToLower() ?? "file";
var isGif = mediaType == "image" && (media.Url.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase) || media.Url.EndsWith(".gif", StringComparison.OrdinalIgnoreCase));
if (filterType == "gifs")
{
return isGif;
}
if (filterType == "files")
{
return mediaType != "image" && mediaType != "video" && mediaType != "link";
}
if (filterType == "media")
{
return mediaType == "image" || mediaType == "video";
}
return true;
}).ToList();
if (filteredMedia.Any())
{
senders.TryGetValue(message.SenderId, out var sender);
result.Add(new SharedMediaDto(
message.Id,
message.Content,
message.CreatedAt,
null,
sender != null ? new MessageSenderDto(sender.Id, sender.Username, sender.DisplayName, sender.Avatar) : null,
message.ReplyToId,
message.Quote,
message.StoryId,
message.StoryMediaUrl,
message.StoryMediaType,
message.IsEdited,
message.Type,
filteredMedia.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size)).ToList()
));
}
}
return Result.Success(result.OrderByDescending(x => x.CreatedAt).ToList());
}
}