Iceshrimp.NET/Iceshrimp.Backend/Controllers/Mastodon/Renderers/PollRenderer.cs

76 lines
No EOL
2.6 KiB
C#

using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Extensions;
using Microsoft.EntityFrameworkCore;
namespace Iceshrimp.Backend.Controllers.Mastodon.Renderers;
public class PollRenderer(DatabaseContext db)
{
public async Task<PollEntity> RenderAsync(Poll poll, User? user, PollRendererDto? data = null)
{
var voted = (data?.Voted ?? await GetVoted([poll], user)).Contains(poll.NoteId);
var ownVotes = (data?.OwnVotes ?? await GetOwnVotes([poll], user)).Where(p => p.Key == poll.NoteId)
.Select(p => p.Value)
.DefaultIfEmpty([])
.First();
var res = new PollEntity
{
Id = poll.NoteId,
Expired = poll.ExpiresAt < DateTime.UtcNow,
Multiple = poll.Multiple,
ExpiresAt = poll.ExpiresAt?.ToStringIso8601Like(),
VotesCount = poll.Votes.Sum(),
VotersCount = poll.VotersCount ?? poll.Votes.Sum(),
Voted = voted,
OwnVotes = ownVotes,
Options = poll.Choices
.Select(p => new PollOptionEntity
{
Title = p, VotesCount = poll.Votes[poll.Choices.IndexOf(p)]
})
.ToList()
};
return res;
}
private async Task<List<string>> GetVoted(IEnumerable<Poll> polls, User? user)
{
if (user == null) return [];
return await db.PollVotes.Where(p => polls.Select(i => i.NoteId).Any(i => i == p.NoteId) && p.User == user)
.Select(p => p.NoteId)
.Distinct()
.ToListAsync();
}
private async Task<Dictionary<string, int[]>> GetOwnVotes(IEnumerable<Poll> polls, User? user)
{
if (user == null) return [];
return await db.PollVotes
.Where(p => polls.Select(i => i.NoteId).Any(i => i == p.NoteId) && p.User == user)
.GroupBy(p => p.NoteId)
.ToDictionaryAsync(p => p.Key, p => p.Select(i => i.Choice).ToArray());
}
public async Task<IEnumerable<PollEntity>> RenderManyAsync(IEnumerable<Poll> polls, User? user)
{
var pollList = polls.ToList();
var data = new PollRendererDto
{
OwnVotes = await GetOwnVotes(pollList, user), Voted = await GetVoted(pollList, user)
};
return await pollList.Select(p => RenderAsync(p, user, data)).AwaitAllAsync();
}
public class PollRendererDto
{
public Dictionary<string, int[]>? OwnVotes;
public List<string>? Voted;
}
}