Relays: PrivaPub reads from the relays its configuration names
Federation:Relays names relays by their actor (or inbox) address; the instance actor follows Public at each, as Mastodon subscribes, a minute after start and every six hours (asked again a day after no answer or a refusal, undone when a relay is no longer named). What an accepted relay passes on comes to the federated timeline and nobody's home: a public post it forwards (Activity-Relay), read again from its origin like any forwarded post, and a post it announces (aode-relay), kept as its author's and never as the relay's boost. Nothing of a persona's is sent to a relay; sending public posts there waits for the owner. The pasture gains both relays (peers/relay.sh, peers/aoderelay.sh) and scenarios/relay.sh, 13 checks. The village backlog is clean: 2574 checks pass, one known gap (Misskey's). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
1c7d1ece9c
commit
f6fc0c535c
22 files changed
+542
-24
No files matched your search
@@ -19,10 +19,12 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
readonly IQuoteService _quotes;
|
||||
readonly IInteractionApprovals _approvals;
|
||||
readonly IParticipations _participations;
|
||||
readonly Relays.IRelays _relays;
|
||||
|
||||
public AcceptHandler(DbEntities dbEntities, ILocalActorService localActors, IQuoteService quotes, IInteractionApprovals approvals = default,
|
||||
IParticipations participations = default)
|
||||
IParticipations participations = default, Relays.IRelays relays = default)
|
||||
{
|
||||
_relays = relays;
|
||||
_participations = participations;
|
||||
_dbEntities = dbEntities;
|
||||
_localActors = localActors;
|
||||
@@ -49,6 +51,11 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
Arrival.Accept("participation-answer");
|
||||
return;
|
||||
}
|
||||
if (_relays != default && await _relays.Answered(activity, actor, accepted: Type == "Accept", token))
|
||||
{
|
||||
Arrival.Accept("relay-answer");
|
||||
return;
|
||||
}
|
||||
var following = await FindFollowing(activity["object"], actor, _dbEntities, _localActors, token);
|
||||
if (following == default)
|
||||
{
|
||||
@@ -88,8 +95,8 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
public class RejectHandler : AcceptHandler
|
||||
{
|
||||
public RejectHandler(DbEntities dbEntities, ILocalActorService localActors, IQuoteService quotes, IInteractionApprovals approvals = default,
|
||||
IParticipations participations = default)
|
||||
: base(dbEntities, localActors, quotes, approvals, participations)
|
||||
IParticipations participations = default, Relays.IRelays relays = default)
|
||||
: base(dbEntities, localActors, quotes, approvals, participations, relays)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,12 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
// handler is one of them; tests set it
|
||||
public IEnumerable<IActivityHandler> Relays { get; set; }
|
||||
|
||||
readonly PrivaPub.Federation.Relays.IRelays _relayService;
|
||||
|
||||
public AnnounceHandler(DbEntities dbEntities, ILocalActorService localActors, IRemotePosts remotePosts, IFanout fanout, IRemoteActorService remoteActors,
|
||||
IObjectRecords records, IQuoteService quotes, IServiceProvider services = default)
|
||||
IObjectRecords records, IQuoteService quotes, IServiceProvider services = default, PrivaPub.Federation.Relays.IRelays relays = default)
|
||||
{
|
||||
_relayService = relays;
|
||||
_services = services;
|
||||
_records = records;
|
||||
_quotes = quotes;
|
||||
@@ -74,6 +77,11 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
return;
|
||||
}
|
||||
|
||||
if (_relayService != default && await _relayService.Passes(actor.ActorURI, token))
|
||||
{
|
||||
await FromRelay(objectUri, token);
|
||||
return;
|
||||
}
|
||||
var isLocal = objectUri.StartsWith(_localActors.BaseAddress + "/", StringComparison.OrdinalIgnoreCase);
|
||||
var original = await _dbEntities.Posts.Match(p => p.ObjectURI == objectUri && !p.DeletedAt.HasValue && p.ReblogOfPostId == null).ExecuteFirstAsync(token);
|
||||
var followed = await _dbEntities.Followings.Match(f => f.TargetActorURI == actor.ActorURI && f.State == FollowState.Accepted).ExecuteAnyAsync(token);
|
||||
@@ -139,6 +147,27 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
await _fanout.Distribute(reblog, token);
|
||||
}
|
||||
|
||||
// a post a relay we subscribe to announces: kept as its author's, for the federated timeline, never as the relay's
|
||||
// boost (Mastodon unwraps them the same way)
|
||||
async Task FromRelay(string objectUri, CancellationToken token)
|
||||
{
|
||||
var held = await _dbEntities.Posts.Match(p => p.ObjectURI == objectUri).ExecuteFirstAsync(token);
|
||||
var post = held ?? await _remotePosts.StoreContext(objectUri, 0, token);
|
||||
if (post == default)
|
||||
{
|
||||
Arrival.Drop("fetch-failed");
|
||||
return;
|
||||
}
|
||||
Arrival.About(post.ObjectType ?? "Note", post.Visibility, post.CreationDate);
|
||||
if (held != default)
|
||||
{
|
||||
Arrival.Drop("duplicate");
|
||||
return;
|
||||
}
|
||||
Arrival.Accept("relayed");
|
||||
await _fanout.Distribute(post, token);
|
||||
}
|
||||
|
||||
async Task GroupActivity(JsonNode inner, ForeignAvatar group, CancellationToken token)
|
||||
{
|
||||
Arrival.About(Value(inner, "type"));
|
||||
|
||||
@@ -41,11 +41,13 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
readonly ILinkPreviews _previews;
|
||||
readonly IQuoteService _quotes;
|
||||
readonly IInteractionApprovals _approvals;
|
||||
readonly Relays.IRelays _relays;
|
||||
|
||||
public CreateHandler(DbEntities dbEntities, ILocalActorService localActors, IRemoteActorService remoteActors, IDeliveryService delivery,
|
||||
IDomainBlocks domainBlocks, IFanout fanout, IRemotePosts remotePosts, IGroupDistributor groups, IObjectRecords records, IPollService polls, ILinkPreviews previews, IQuoteService quotes,
|
||||
IInteractionApprovals approvals = default)
|
||||
IInteractionApprovals approvals = default, Relays.IRelays relays = default)
|
||||
{
|
||||
_relays = relays;
|
||||
_approvals = approvals;
|
||||
_quotes = quotes;
|
||||
_previews = previews;
|
||||
@@ -183,8 +185,12 @@ namespace PrivaPub.Federation.Inbox.Handlers
|
||||
var inFollowedGroup = !followed && visibility is PostVisibility.Public or PostVisibility.Unlisted && note.Audience != default
|
||||
&& Origin.Same(note.Audience, author.ActorURI) && Origin.Same(note.Id, note.Audience)
|
||||
&& await _dbEntities.Followings.Match(f => f.TargetActorURI == note.Audience && f.State == FollowState.Accepted).ExecuteAnyAsync(token);
|
||||
// a public post a relay we subscribe to passes on, for the federated timeline (read again from its origin, as any
|
||||
// forwarded post)
|
||||
var relayed = !followed && visibility == PostVisibility.Public && _relays != default
|
||||
&& await _relays.Passes(Arrival.Current?.ForwardedBy, token);
|
||||
if (visibility == PostVisibility.Direct ? persons.Count == 0
|
||||
: group == default && persons.Count == 0 && !repliesToLocal && !followed && !repliesToFollowed && !inFollowedGroup)
|
||||
: group == default && persons.Count == 0 && !repliesToLocal && !followed && !repliesToFollowed && !inFollowedGroup && !relayed)
|
||||
{
|
||||
Arrival.Drop("not-addressed");
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user