Files
SocialPub/PrivaPub/Federation/Inbox/ConversationContainers.cs
T

45 lines
1.9 KiB
C#
Raw Normal View History

using PrivaPub.Federation.Objects;
using PrivaPub.Infrastructure.Jobs;
using PrivaPub.Models.Jobs;
using PrivaPub.Models.User;
using System.Text.Json;
using System.Text.Json.Nodes;
using static PrivaPub.Federation.Objects.ActivityJson;
namespace PrivaPub.Federation.Inbox
{
// FEP-171b conversation containers (Hubzilla, Streams, Forte): a thread's owner adds each activity in it to the
// thread's context, a collection of its own, and tells the thread's audience with Add{activity}. The activity it adds
// is another's, so it is taken as forwarded by the owner: a Create, Update or Delete of the actor's own object,
// believed on its FEP-8b32 proof or as its origin has it (Forwarded). Hubzilla also passes the activity on by itself;
// the two are one job.
public static class ConversationContainers
{
public static async Task<bool> Unwrap(JsonNode add, ForeignAvatar owner, IJobQueue queue, CancellationToken token)
{
if (add["object"] is not JsonObject inner || Value(inner, "type") is not ("Create" or "Update" or "Delete") || Id(inner) is not { } innerId)
return false;
var target = add["target"];
var context = Id(target);
if (context == default || !Origin.Same(context, owner.ActorURI)
|| target is JsonObject collection && Id(collection["attributedTo"]) is { } attributedTo && attributedTo != owner.ActorURI)
return false;
var actorUri = Id(inner["actor"]);
if (actorUri == default || !Forwarded.Takeable(Value(inner, "type"), inner, actorUri))
{
Arrival.Drop("container-unusable");
return true;
}
var payload = new InboxPayload(actorUri, inner.ToJsonString(), "shared", ReceivedAt: DateTime.UtcNow, ForwardedBy: owner.ActorURI);
var queued = await queue.Enqueue(JobKind.ProcessInbox, JsonSerializer.Serialize(payload), new Uri(actorUri).Host.ToLowerInvariant(),
"inbox|forwarded|" + innerId, token);
if (queued)
Arrival.Accept("unwrapped");
else
Arrival.Drop("duplicate");
return true;
}
}
}