133 lines
5.8 KiB
C#
133 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Knot.Contracts.Messaging.Application.Abstractions;
|
|
using Knot.Contracts.Messaging.Domain;
|
|
using Knot.Contracts.Conversations.Application.Abstractions;
|
|
using Knot.Modules.Conversations.Application.DTOs;
|
|
using Knot.Contracts.Conversations.Domain;
|
|
using Knot.Shared.Kernel;
|
|
using MediatR;
|
|
|
|
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)
|
|
{
|
|
var mediaMessage = message as MediaMessage;
|
|
var textMessage = message as TextMessage;
|
|
var storyMessage = message as StoryMessage;
|
|
|
|
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 mediaLinks = (mediaMessage?.Media ?? Enumerable.Empty<Media>())
|
|
.Where(media => media.Type?.ToString().ToLower() == "link" && !string.IsNullOrEmpty(media.Url))
|
|
.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 = mediaMessage?.Media;
|
|
if (messageMedia == null || !messageMedia.Any())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var filteredMedia = messageMedia.Where(media =>
|
|
{
|
|
var mType = media.Type?.ToLower() ?? "file";
|
|
var filename = media.Filename?.ToLower() ?? "";
|
|
var url = media.Url?.ToLower() ?? "";
|
|
|
|
var isGif = mType == "gif" ||
|
|
(mType == "image" && (filename.EndsWith(".mp4") || filename.EndsWith(".gif") || url.EndsWith(".gif") || filename.Contains("gif"))) ||
|
|
(mType == "video" && (filename.Contains("animation") || filename.Contains("gif")));
|
|
|
|
if (filterType == "gifs") return isGif;
|
|
if (filterType == "media") return (mType == "image" || mType == "video") && !isGif;
|
|
if (filterType == "files") return (mType == "file" || mType == "audio") && !isGif && mType != "image" && mType != "video";
|
|
if (filterType == "links") return mType == "link";
|
|
|
|
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,
|
|
textMessage?.Quote,
|
|
storyMessage?.StoryId,
|
|
storyMessage?.StoryMediaUrl,
|
|
storyMessage?.StoryMediaType,
|
|
message.IsEdited,
|
|
message.Type,
|
|
filteredMedia.Select(media => new MediaDto(media.Id, media.Type, media.Url, media.Filename, media.Size, media.Duration)).ToList()
|
|
));
|
|
}
|
|
}
|
|
|
|
return Result.Success(result.OrderByDescending(x => x.CreatedAt).ToList());
|
|
}
|
|
}
|
|
|
|
|
|
|