♻️ Refactor the pub delivery service

This commit is contained in:
2026-01-01 00:27:09 +08:00
parent 42b46243a4
commit 3e59a102af
2 changed files with 61 additions and 34 deletions

View File

@@ -61,15 +61,14 @@ public class ActivityPubDeliveryService(
string targetActorUri string targetActorUri
) )
{ {
var publisher = await db.Publishers.FindAsync(publisherId); var localActor = await GetLocalActorAsync(publisherId);
if (publisher == null) if (localActor == null)
return false; return false;
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}"; var actorUrl = localActor.Uri;
var targetActor = await GetOrFetchActorAsync(targetActorUri); var targetActor = await GetOrFetchActorAsync(targetActorUri);
var localActor = await GetLocalActorAsync(publisher.Id);
if (targetActor?.InboxUri == null || localActor == null) if (targetActor?.InboxUri == null)
{ {
logger.LogWarning("Target actor or inbox not found: {Uri}", targetActorUri); logger.LogWarning("Target actor or inbox not found: {Uri}", targetActorUri);
return false; return false;
@@ -114,15 +113,14 @@ public class ActivityPubDeliveryService(
string targetActorUri string targetActorUri
) )
{ {
var publisher = await db.Publishers.FindAsync(publisherId); var localActor = await GetLocalActorAsync(publisherId);
if (publisher == null) if (localActor == null)
return false; return false;
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}"; var actorUrl = localActor.Uri;
var targetActor = await GetOrFetchActorAsync(targetActorUri); var targetActor = await GetOrFetchActorAsync(targetActorUri);
var localActor = await GetLocalActorAsync(publisher.Id);
if (targetActor?.InboxUri == null || localActor == null) if (targetActor?.InboxUri == null)
{ {
logger.LogWarning("Target actor or inbox not found: {Uri}", targetActorUri); logger.LogWarning("Target actor or inbox not found: {Uri}", targetActorUri);
return false; return false;
@@ -158,11 +156,13 @@ public class ActivityPubDeliveryService(
public async Task<bool> SendCreateActivityAsync(SnPost post) public async Task<bool> SendCreateActivityAsync(SnPost post)
{ {
var publisher = await db.Publishers.FindAsync(post.PublisherId); if (post.PublisherId == null)
if (publisher == null) return false;
var localActor = await GetLocalActorAsync(post.PublisherId.Value);
if (localActor == null)
return false; return false;
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}"; var actorUrl = localActor.Uri;
var postUrl = $"https://{Domain}/posts/{post.Id}"; var postUrl = $"https://{Domain}/posts/{post.Id}";
var activity = new Dictionary<string, object> var activity = new Dictionary<string, object>
@@ -211,11 +211,13 @@ public class ActivityPubDeliveryService(
public async Task<bool> SendUpdateActivityAsync(SnPost post) public async Task<bool> SendUpdateActivityAsync(SnPost post)
{ {
var publisher = await db.Publishers.FindAsync(post.PublisherId); if (post.PublisherId == null)
if (publisher == null) return false;
var localActor = await GetLocalActorAsync(post.PublisherId.Value);
if (localActor == null)
return false; return false;
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}"; var actorUrl = localActor.Uri;
var postUrl = $"https://{Domain}/posts/{post.Id}"; var postUrl = $"https://{Domain}/posts/{post.Id}";
var activity = new Dictionary<string, object> var activity = new Dictionary<string, object>
@@ -265,11 +267,13 @@ public class ActivityPubDeliveryService(
public async Task<bool> SendDeleteActivityAsync(SnPost post) public async Task<bool> SendDeleteActivityAsync(SnPost post)
{ {
var publisher = await db.Publishers.FindAsync(post.PublisherId); if (post.PublisherId == null)
if (publisher == null) return false;
var localActor = await GetLocalActorAsync(post.PublisherId.Value);
if (localActor == null)
return false; return false;
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}"; var actorUrl = localActor.Uri;
var postUrl = $"https://{Domain}/posts/{post.Id}"; var postUrl = $"https://{Domain}/posts/{post.Id}";
var activity = new Dictionary<string, object> var activity = new Dictionary<string, object>

View File

@@ -27,7 +27,7 @@ public partial class PostService(
Publisher.PublisherService ps, Publisher.PublisherService ps,
WebReaderService reader, WebReaderService reader,
AccountService.AccountServiceClient accounts, AccountService.AccountServiceClient accounts,
ActivityPub.ActivityPubDeliveryService activityPubDeliveryService ActivityPubDeliveryService apDelivery
) )
{ {
private const string PostFileUsageIdentifier = "post"; private const string PostFileUsageIdentifier = "post";
@@ -187,7 +187,7 @@ public partial class PostService(
Notification = new PushNotification Notification = new PushNotification
{ {
Topic = "post.replies", Topic = "post.replies",
Title = localizer["PostReplyTitle", sender.Nick], Title = localizer["PostReplyTitle", sender!.Nick],
Body = string.IsNullOrWhiteSpace(post.Title) Body = string.IsNullOrWhiteSpace(post.Title)
? localizer["PostReplyBody", sender.Nick, ChopPostForNotification(post).content] ? localizer["PostReplyBody", sender.Nick, ChopPostForNotification(post).content]
: localizer["PostReplyContentBody", sender.Nick, post.Title, : localizer["PostReplyContentBody", sender.Nick, post.Title,
@@ -329,7 +329,7 @@ public partial class PostService(
[GeneratedRegex(@"https?://(?!.*\.\w{1,6}(?:[#?]|$))[^\s]+", RegexOptions.IgnoreCase)] [GeneratedRegex(@"https?://(?!.*\.\w{1,6}(?:[#?]|$))[^\s]+", RegexOptions.IgnoreCase)]
private static partial Regex GetLinkRegex(); private static partial Regex GetLinkRegex();
public async Task<SnPost> PreviewPostLinkAsync(SnPost item) private async Task<SnPost> PreviewPostLinkAsync(SnPost item)
{ {
if (item.Type != Shared.Models.PostType.Moment || string.IsNullOrEmpty(item.Content)) return item; if (item.Type != Shared.Models.PostType.Moment || string.IsNullOrEmpty(item.Content)) return item;
@@ -586,7 +586,7 @@ public partial class PostService(
// Send ActivityPub Like/Undo activities if post's publisher has actor // Send ActivityPub Like/Undo activities if post's publisher has actor
if (post.PublisherId.HasValue && reaction.AccountId.HasValue) if (post.PublisherId.HasValue && reaction.AccountId.HasValue)
{ {
var publisherActor = await activityPubDeliveryService.GetLocalActorAsync(post.PublisherId.Value); var publisherActor = await apDelivery.GetLocalActorAsync(post.PublisherId.Value);
if (publisherActor != null && reaction.Attitude == Shared.Models.PostReactionAttitude.Positive) if (publisherActor != null && reaction.Attitude == Shared.Models.PostReactionAttitude.Positive)
{ {
@@ -716,7 +716,7 @@ public partial class PostService(
); );
} }
public async Task<Dictionary<Guid, Dictionary<string, bool>>> GetPostReactionMadeMapBatch(List<Guid> postIds, private async Task<Dictionary<Guid, Dictionary<string, bool>>> GetPostReactionMadeMapBatch(List<Guid> postIds,
Guid accountId) Guid accountId)
{ {
var reactions = await db.Set<SnPostReaction>() var reactions = await db.Set<SnPostReaction>()
@@ -769,7 +769,7 @@ public partial class PostService(
}); });
} }
public async Task<List<SnPost>> LoadPublishers(List<SnPost> posts) private async Task<List<SnPost>> LoadPublishersAndActors(List<SnPost> posts)
{ {
var publisherIds = posts var publisherIds = posts
.SelectMany<SnPost, Guid?>(e => .SelectMany<SnPost, Guid?>(e =>
@@ -781,24 +781,49 @@ public partial class PostService(
.Where(e => e != null) .Where(e => e != null)
.Distinct() .Distinct()
.ToList(); .ToList();
if (publisherIds.Count == 0) return posts; var actorIds = posts
.SelectMany<SnPost, Guid?>(e =>
[
e.ActorId,
e.RepliedPost?.ActorId,
e.ForwardedPost?.ActorId
])
.Where(e => e != null)
.Distinct()
.ToList();
if (publisherIds.Count == 0 && actorIds.Count == 0) return posts;
var publishers = await db.Publishers var publishers = await db.Publishers
.Where(e => publisherIds.Contains(e.Id)) .Where(e => publisherIds.Contains(e.Id))
.ToDictionaryAsync(e => e.Id); .ToDictionaryAsync(e => e.Id);
var actors = await db.FediverseActors
.Where(e => actorIds.Contains(e.Id))
.ToDictionaryAsync(e => e.Id);
foreach (var post in posts) foreach (var post in posts)
{ {
if (post.PublisherId.HasValue && publishers.TryGetValue(post.PublisherId.Value, out var publisher)) if (post.PublisherId.HasValue && publishers.TryGetValue(post.PublisherId.Value, out var publisher))
post.Publisher = publisher; post.Publisher = publisher;
if (post.ActorId.HasValue && actors.TryGetValue(post.ActorId.Value, out var actor))
post.Actor = actor;
if (post.RepliedPost?.PublisherId != null && if (post.RepliedPost?.PublisherId != null &&
publishers.TryGetValue(post.RepliedPost.PublisherId.Value, out var repliedPublisher)) publishers.TryGetValue(post.RepliedPost.PublisherId.Value, out var repliedPublisher))
post.RepliedPost.Publisher = repliedPublisher; post.RepliedPost.Publisher = repliedPublisher;
if (post.RepliedPost?.ActorId != null &&
actors.TryGetValue(post.RepliedPost.ActorId.Value, out var repliedActor))
post.RepliedPost.Actor = repliedActor;
if (post.ForwardedPost?.PublisherId != null && if (post.ForwardedPost?.PublisherId != null &&
publishers.TryGetValue(post.ForwardedPost.PublisherId.Value, out var forwardedPublisher)) publishers.TryGetValue(post.ForwardedPost.PublisherId.Value, out var forwardedPublisher))
post.ForwardedPost.Publisher = forwardedPublisher; post.ForwardedPost.Publisher = forwardedPublisher;
if (post.ForwardedPost?.ActorId != null &&
actors.TryGetValue(post.ForwardedPost.ActorId.Value, out var forwardedActor))
post.ForwardedPost.Actor = forwardedActor;
} }
await ps.LoadIndividualPublisherAccounts(publishers.Values); await ps.LoadIndividualPublisherAccounts(publishers.Values);
@@ -806,7 +831,7 @@ public partial class PostService(
return posts; return posts;
} }
public async Task<List<SnPost>> LoadInteractive(List<SnPost> posts, Account? currentUser = null) private async Task<List<SnPost>> LoadInteractive(List<SnPost> posts, Account? currentUser = null)
{ {
if (posts.Count == 0) return posts; if (posts.Count == 0) return posts;
@@ -842,9 +867,7 @@ public partial class PostService(
: []; : [];
// Set reply count // Set reply count
post.RepliesCount = repliesCountMap.TryGetValue(post.Id, out var repliesCount) post.RepliesCount = repliesCountMap.GetValueOrDefault(post.Id, 0);
? repliesCount
: 0;
// Check visibility for replied post // Check visibility for replied post
if (post.RepliedPost != null) if (post.RepliedPost != null)
@@ -929,7 +952,7 @@ public partial class PostService(
{ {
if (posts.Count == 0) return posts; if (posts.Count == 0) return posts;
posts = await LoadPublishers(posts); posts = await LoadPublishersAndActors(posts);
posts = await LoadInteractive(posts, currentUser); posts = await LoadInteractive(posts, currentUser);
if (truncate) if (truncate)
@@ -954,7 +977,7 @@ public partial class PostService(
if (featuredIds is null) if (featuredIds is null)
{ {
// The previous day highest rated posts // The previous day the highest rated posts
var today = SystemClock.Instance.GetCurrentInstant(); var today = SystemClock.Instance.GetCurrentInstant();
var periodStart = today.InUtc().Date.AtStartOfDayInZone(DateTimeZone.Utc).ToInstant() var periodStart = today.InUtc().Date.AtStartOfDayInZone(DateTimeZone.Utc).ToInstant()
.Minus(Duration.FromDays(1)); .Minus(Duration.FromDays(1));
@@ -994,8 +1017,8 @@ public partial class PostService(
{ {
PostId = postId, PostId = postId,
Count = Count =
(reactionScores.TryGetValue(postId, out var rScore) ? rScore : 0) (reactionScores.GetValueOrDefault(postId, 0))
+ (repliesCounts.TryGetValue(postId, out var repCount) ? repCount : 0) + (repliesCounts.GetValueOrDefault(postId, 0))
+ (awardsScores.TryGetValue(postId, out var awardScore) ? (int)(awardScore / 10) : 0) + (awardsScores.TryGetValue(postId, out var awardScore) ? (int)(awardScore / 10) : 0)
}) })
.OrderByDescending(e => e.Count) .OrderByDescending(e => e.Count)