Home timelines, mention notifications, and threads that fetch their parents
Fanout writes a TimelineEntry for every persona a post should reach: the author, local followers of a local author, local followers of a remote one, the members of a direct conversation or a circle. Mastodon's home rules apply when it is written: a reply shows only to followers of both sides (or to the one replied to), a reblog only where reblogs are wanted. A mention of a local persona becomes a Mention notification. Inbound posts are now also kept when a persona follows their author. RemotePosts holds what CreateHandler and backfill share: building a Post from a note, and fetching a public parent the first time a reply to it arrives, so its author is known (a reply to an unknown or non-public parent stays out of home timelines). Each fetched ancestor queues a FetchAncestors job for the next one, up to ten deep. /clientapi/timeline/home and /clientapi/notifications (with /notifications/read) page by max_id for the persona's own root only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
1 parent
a76cc34557
commit
e99b76dbd7
12 files changed
+609
-52
No files matched your search
@@ -15,6 +15,7 @@ using System.Text.Json.Nodes;
|
||||
|
||||
using PostEntity = PrivaPub.Models.Post.Post;
|
||||
using PrivaPub.Domain.Content;
|
||||
using PrivaPub.Domain.Timelines;
|
||||
using PrivaPub.Federation.Actors;
|
||||
using PrivaPub.Federation.Rendering;
|
||||
using PrivaPub.Federation.Outbox;
|
||||
@@ -41,6 +42,7 @@ namespace PrivaPub.Services
|
||||
readonly IDeliveryService _delivery;
|
||||
readonly IContentRenderer _content;
|
||||
readonly IOutboxPublisher _outbox;
|
||||
readonly IFanout _fanout;
|
||||
readonly IStringLocalizer<GenericRes> _localizer;
|
||||
readonly ILogger<PostsService> _logger;
|
||||
|
||||
@@ -50,6 +52,7 @@ namespace PrivaPub.Services
|
||||
IDeliveryService delivery,
|
||||
IContentRenderer content,
|
||||
IOutboxPublisher outbox,
|
||||
IFanout fanout,
|
||||
IStringLocalizer<GenericRes> localizer,
|
||||
ILogger<PostsService> logger)
|
||||
{
|
||||
@@ -59,6 +62,7 @@ namespace PrivaPub.Services
|
||||
_delivery = delivery;
|
||||
_content = content;
|
||||
_outbox = outbox;
|
||||
_fanout = fanout;
|
||||
_localizer = localizer;
|
||||
_logger = logger;
|
||||
}
|
||||
@@ -113,6 +117,7 @@ namespace PrivaPub.Services
|
||||
if (isLocalOnly)
|
||||
{
|
||||
await DB.Default.SaveAsync(post, token);
|
||||
await _fanout.Distribute(post, token);
|
||||
result.Data = ToView(post);
|
||||
return result;
|
||||
}
|
||||
@@ -126,6 +131,7 @@ namespace PrivaPub.Services
|
||||
if (parent != default)
|
||||
await DB.Default.Update<PostEntity>().MatchID(parent.ID).Modify(b => b.Inc(p => p.RepliesCount, 1)).ExecuteAsync(token);
|
||||
|
||||
await _fanout.Distribute(post, token);
|
||||
await _outbox.Publish(author, post, create, token);
|
||||
if (group is { IsFederated: true } && post.Visibility is PostVisibility.Public or PostVisibility.Unlisted)
|
||||
await _delivery.EnqueueToFollowers(group, ActivityPubRenderer.Announce(group, post.ObjectURI, $"announce-{post.ID}"), token);
|
||||
@@ -367,6 +373,7 @@ namespace PrivaPub.Services
|
||||
dm.Mentions = remote.Select(r => new PostMention { ActorURI = r.Uri, Handle = "@" + r.Handle, IsLocal = r.Uri.StartsWith(author.BaseAddress + "/") }).ToList();
|
||||
await DB.Default.SaveAsync(dm, token);
|
||||
await DB.Default.Update<DmGroup>().MatchID(dmGroup.ID).Modify(g => g.UpdatedAt, DateTime.UtcNow).ExecuteAsync(token);
|
||||
await _fanout.Distribute(dm, token);
|
||||
if (inboxes.Count > 0)
|
||||
await _delivery.Enqueue(author, inboxes, directCreate, token);
|
||||
|
||||
|
||||
Reference in new issue
Block a user