femto-backend/Femto.Modules.Blog/Domain/Posts/Commands/GetAuthorPosts/GetAuthorPostsQueryHandler.cs
2025-05-03 15:38:57 +02:00

61 lines
1.9 KiB
C#

using Dapper;
using Femto.Modules.Blog.Contracts.Dto;
using Femto.Modules.Blog.Infrastructure.DbConnection;
using MediatR;
using Microsoft.Data.SqlClient;
namespace Femto.Modules.Blog.Domain.Posts.Commands.GetAuthorPosts;
public class GetAuthorPostsQueryHandler(IDbConnectionFactory connectionFactory)
: IRequestHandler<GetAuthorPostsQuery, IList<GetAuthorPostsDto>>
{
public async Task<IList<GetAuthorPostsDto>> Handle(
GetAuthorPostsQuery query,
CancellationToken cancellationToken
)
{
using var conn = connectionFactory.GetConnection();
var sql = $$"""
with post_page as (
select * from blog.post
where blog.post.author_id = @authorId
and (@cursor is null or blog.post.id < @cursor)
order by blog.post.id desc
limit @count
)
select
p.id as PostId,
p.content as Content,
pm.url as MediaUrl
from post_page p
left join blog.post_media pm on pm.post_id = p.id
order by p.id desc
""";
var result = await conn.QueryAsync<QueryResult>(
sql,
new { authorId = query.AuthorId, cursor = query.Cursor, count = query.Count }
);
return result
.GroupBy(row => row.PostId)
.Select(group => new GetAuthorPostsDto(
group.Key,
group.First().Content,
group
.Select(row => row.MediaUrl)
.OfType<string>()
.Select(url => new GetAuthorPostsMediaDto(new Uri(url)))
.ToList()
))
.ToList();
}
internal class QueryResult
{
public Guid PostId { get; set; }
public string Content { get; set; }
public string? MediaUrl { get; set; }
}
}