2026-10-03 11:04:42 +02:00
|
|
|
using PrivaPub.Federation.Actors;
|
|
|
|
|
using PrivaPub.Infrastructure.Statistics;
|
|
|
|
|
using PrivaPub.Models.Federation;
|
|
|
|
|
using PrivaPub.Models.Post;
|
|
|
|
|
|
2026-10-01 17:49:22 +02:00
|
|
|
namespace PrivaPub.Federation.Inbox
|
|
|
|
|
{
|
|
|
|
|
public sealed record Arrival(string ActivityId, string ActivityType, string ActorURI, string Inbox, string KeyId, string Algorithm,
|
|
|
|
|
IReadOnlyList<string> SignedHeaders, DateTime ReceivedAt, string Context = default)
|
|
|
|
|
{
|
|
|
|
|
static readonly AsyncLocal<Arrival> current = new();
|
|
|
|
|
|
|
|
|
|
public static Arrival Current
|
|
|
|
|
{
|
|
|
|
|
get => current.Value;
|
|
|
|
|
set => current.Value = value;
|
|
|
|
|
}
|
2026-10-03 11:04:42 +02:00
|
|
|
|
|
|
|
|
public ArrivalVerdict Verdict { get; } = new();
|
|
|
|
|
|
|
|
|
|
public static void Drop(string reason) => Current?.Verdict.Drop(reason);
|
|
|
|
|
|
|
|
|
|
public static void Reject(string reason) => Current?.Verdict.Reject(reason);
|
|
|
|
|
|
|
|
|
|
public static void Accept(string reason) => Current?.Verdict.Accept(reason);
|
|
|
|
|
|
|
|
|
|
public static void About(string objectType = default, PostVisibility? visibility = default, DateTime? created = default, LocalActor local = default) =>
|
|
|
|
|
Current?.Verdict.About(objectType, visibility, created, local);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed class ArrivalVerdict
|
|
|
|
|
{
|
|
|
|
|
public string Outcome { get; private set; }
|
|
|
|
|
public string Reason { get; private set; }
|
|
|
|
|
public string ObjectType { get; private set; }
|
|
|
|
|
public string Audience { get; private set; }
|
|
|
|
|
public string LocalKind { get; private set; }
|
|
|
|
|
public long? AgeSeconds { get; private set; }
|
|
|
|
|
|
|
|
|
|
public void Drop(string reason) => Decide(Interactions.Dropped, reason);
|
|
|
|
|
|
|
|
|
|
public void Reject(string reason) => Decide(Interactions.Rejected, reason);
|
|
|
|
|
|
|
|
|
|
public void Accept(string reason) => Decide(Interactions.Accepted, reason);
|
|
|
|
|
|
|
|
|
|
void Decide(string outcome, string reason)
|
|
|
|
|
{
|
|
|
|
|
if (Outcome != default)
|
|
|
|
|
return;
|
|
|
|
|
Outcome = outcome;
|
|
|
|
|
Reason = reason;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void About(string objectType, PostVisibility? visibility, DateTime? created, LocalActor local)
|
|
|
|
|
{
|
|
|
|
|
ObjectType = objectType ?? ObjectType;
|
|
|
|
|
if (visibility is { } known)
|
|
|
|
|
Audience = AudienceOf(known);
|
|
|
|
|
if (created is { } at)
|
|
|
|
|
AgeSeconds = Math.Max(0, (long)(DateTime.UtcNow - at).TotalSeconds);
|
|
|
|
|
if (local != default)
|
|
|
|
|
LocalKind = local.Kind switch
|
|
|
|
|
{
|
|
|
|
|
LocalActorKind.Person => "person",
|
|
|
|
|
LocalActorKind.Group when !local.IsCircle => "group",
|
|
|
|
|
LocalActorKind.Application => "application",
|
|
|
|
|
_ => default
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string AudienceOf(PostVisibility visibility) => visibility switch
|
|
|
|
|
{
|
|
|
|
|
PostVisibility.Public => Interactions.Public,
|
|
|
|
|
PostVisibility.Unlisted => Interactions.Unlisted,
|
|
|
|
|
_ => Interactions.Private
|
|
|
|
|
};
|
2026-10-01 17:49:22 +02:00
|
|
|
}
|
|
|
|
|
}
|