using Iceshrimp.Backend.Components.PublicPreview.Schemas; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; namespace Iceshrimp.Backend.Components.PublicPreview.Renderers; public class UserRenderer( DatabaseContext db, MfmRenderer mfm, IOptions instance, IOptionsSnapshot security ) : IScopedService { public async Task RenderOne(User? user) { if (user == null) return null; var emoji = await GetEmojiAsync([user]); return Render(user, emoji); } private PreviewUser Render(User user, Dictionary> emoji) { var mentions = user.UserProfile?.Mentions ?? []; // @formatter:off var res = new PreviewUser { Id = user.Id, Username = user.Username, Host = user.Host ?? instance.Value.AccountDomain, Uri = user.GetUriOrPublicUri(instance.Value), Url = user.UserProfile?.Url ?? user.Uri ?? user.PublicUrlPath, AvatarUrl = user.GetAvatarUrl(instance.Value), BannerUrl = user.GetBannerUrl(instance.Value), RawDisplayName = user.DisplayName, DisplayName = mfm.RenderSimple(user.DisplayName, user.Host, mentions, emoji[user.Id], "span"), Bio = mfm.RenderSimple(user.UserProfile?.Description, user.Host, mentions, emoji[user.Id], "span"), MovedToUri = user.MovedToUri }; // @formatter:on if (security.Value.PublicPreview is Enums.PublicPreview.RestrictedNoMedia) { res.AvatarUrl = user.IdenticonUrlPath; res.BannerUrl = null; } return res; } private async Task>> GetEmojiAsync(List users) { var ids = users.SelectMany(n => n.Emojis).Distinct().ToList(); if (ids.Count == 0) return users.ToDictionary>(p => p.Id, _ => []); var emoji = await db.Emojis.Where(p => ids.Contains(p.Id)).ToListAsync(); return users.ToDictionary(p => p.Id, p => emoji.Where(e => p.Emojis.Contains(e.Id)).ToList()); } public async Task> RenderManyAsync(List users) { var emoji = await GetEmojiAsync(users); return users.Select(p => Render(p, emoji)).ToList(); } }