From bfa69933c5bdc7ea191734b038a96f48adb4fddc Mon Sep 17 00:00:00 2001 From: Kopper Date: Sun, 1 Sep 2024 09:53:27 +0300 Subject: [PATCH] [backend/akko-client] Fix reaction notifications for custom emoji --- .../Renderers/NotificationRenderer.cs | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs index 0e0ebec6..025d8207 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NotificationRenderer.cs @@ -12,7 +12,7 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer, { public async Task RenderAsync( Notification notification, User user, bool isPleroma, List? accounts = null, - IEnumerable? statuses = null + IEnumerable? statuses = null, Dictionary? emojiUrls = null ) { var dbNotifier = notification.Notifier ?? throw new GracefulException("Notification has no notifier"); @@ -29,9 +29,17 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer, await userRenderer.RenderAsync(dbNotifier); string? emojiUrl = null; - if (notification.Reaction != null && EmojiService.IsCustomEmoji(notification.Reaction)) { - var parts = notification.Reaction.Trim(':').Split('@'); - emojiUrl = await db.Emojis.Where(e => e.Name == parts[0] && e.Host == (parts.Length > 1 ? parts[1] : null)).Select(e => e.PublicUrl).FirstOrDefaultAsync(); + if (notification.Reaction != null) { + // explicitly check to skip another database call if url is actually null + if (emojiUrls != null) + { + emojiUrl = emojiUrls.GetValueOrDefault(notification.Reaction); + } + else if (emojiUrl == null && EmojiService.IsCustomEmoji(notification.Reaction)) + { + var parts = notification.Reaction.Trim(':').Split('@'); + emojiUrl = await db.Emojis.Where(e => e.Name == parts[0] && e.Host == (parts.Length > 1 ? parts[1] : null)).Select(e => e.PublicUrl).FirstOrDefaultAsync(); + } } var res = new NotificationEntity @@ -81,8 +89,23 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer, .DistinctBy(p => p.Id), user, Filter.FilterContext.Notifications, accounts); + var parts = notifications.Where(p => p.Reaction != null && EmojiService.IsCustomEmoji(p.Reaction)).Select(p => { + var parts = p.Reaction!.Trim(':').Split('@'); + return new { Name = parts[0], Host = parts.Length > 1 ? parts[1] : null }; + }); + + // https://github.com/dotnet/efcore/issues/31492 + IQueryable urlQ = db.Emojis; + foreach (var part in parts) + urlQ = urlQ.Concat(db.Emojis.Where(e => e.Name == part.Name && e.Host == part.Host)); + var emojiUrls = (await urlQ + .Select(e => new { Name = $":{e.Name}{(e.Host != null ? "@" + e.Host : "")}:", Url = e.PublicUrl }) + .ToArrayAsync()) + .DistinctBy(e => e.Name) + .ToDictionary(e => e.Name, e => e.Url); + return await notificationList - .Select(p => RenderAsync(p, user, isPleroma, accounts, notes)) + .Select(p => RenderAsync(p, user, isPleroma, accounts, notes, emojiUrls)) .AwaitAllAsync(); } } \ No newline at end of file