diff --git a/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs b/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs index a09fdb70..5c2d5fab 100644 --- a/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs +++ b/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs @@ -10,9 +10,12 @@ using Microsoft.Extensions.Options; namespace Iceshrimp.Backend.Core.Services; +using MentionTuple = (List mentions, + Dictionary<(string usernameLower, string webDomain), string> splitDomainMapping); + public class UserProfileMentionsResolver(ActivityPub.UserResolver userResolver, IOptions config) { - public async Task> ResolveMentions(ASActor actor, string? host) + public async Task ResolveMentions(ASActor actor, string? host) { var fields = actor.Attachments?.OfType() .Where(p => p is { Name: not null, Value: not null }) @@ -44,17 +47,25 @@ public class UserProfileMentionsResolver(ActivityPub.UserResolver userResolver, .Select(async p => await userResolver.ResolveAsyncOrNull(p)) .AwaitAllNoConcurrencyAsync()); - return users.Where(p => p != null) - .Cast() - .DistinctBy(p => p.Id) - .Select(p => new Note.MentionedUser - { - Host = p.Host, - Uri = p.Uri ?? p.GetPublicUri(config.Value), - Url = p.UserProfile?.Url, - Username = p.Username - }) - .ToList(); + var mentions = users.Where(p => p != null) + .Cast() + .DistinctBy(p => p.Id) + .Select(p => new Note.MentionedUser + { + Host = p.Host, + Uri = p.Uri ?? p.GetPublicUri(config.Value), + Url = p.UserProfile?.Url, + Username = p.Username + }) + .ToList(); + + var splitDomainMapping = users.Where(p => p is { Host: not null, Uri: not null }) + .Cast() + .Where(p => new Uri(p.Uri!).Host != p.Host) + .DistinctBy(p => p.Host) + .ToDictionary(p => (p.UsernameLower, new Uri(p.Uri!).Host), p => p.Host!); + + return (mentions, splitDomainMapping); } public async Task> ResolveMentions(UserProfile.Field[]? fields, string? bio, string? host) diff --git a/Iceshrimp.Backend/Core/Services/UserService.cs b/Iceshrimp.Backend/Core/Services/UserService.cs index 958d7937..f0546770 100644 --- a/Iceshrimp.Backend/Core/Services/UserService.cs +++ b/Iceshrimp.Backend/Core/Services/UserService.cs @@ -28,7 +28,8 @@ public class UserService( DriveService driveSvc, FollowupTaskService followupTaskSvc, NotificationService notificationSvc, - EmojiService emojiSvc + EmojiService emojiSvc, + ActivityPub.MentionsResolver mentionsResolver ) { private static readonly AsyncKeyedLocker KeyedLocker = new(o => @@ -642,7 +643,7 @@ public class UserService( if (actor != null) { - var mentions = await bgMentionsResolver.ResolveMentions(actor, bgUser.Host); + var (mentions, splitDomainMapping) = await bgMentionsResolver.ResolveMentions(actor, bgUser.Host); var fields = actor.Attachments != null ? await actor.Attachments .OfType() @@ -655,11 +656,13 @@ public class UserService( .AwaitAllAsync() : null; - bgUser.UserProfile.Mentions = mentions; - bgUser.UserProfile.Fields = fields?.ToArray() ?? []; - bgUser.UserProfile.Description = actor.MkSummary ?? - await MfmConverter.FromHtmlAsync(actor.Summary, - bgUser.UserProfile.Mentions); + var description = actor.MkSummary != null + ? mentionsResolver.ResolveMentions(actor.MkSummary, bgUser.Host, mentions, splitDomainMapping) + : await MfmConverter.FromHtmlAsync(actor.Summary, mentions); + + bgUser.UserProfile.Mentions = mentions; + bgUser.UserProfile.Fields = fields?.ToArray() ?? []; + bgUser.UserProfile.Description = description; } else {