using PrivaPub.Federation.Actors; using PrivaPub.Federation.Outbox; using PrivaPub.Federation.Rendering; using PrivaPub.Models.Federation; using PrivaPub.Models.User; using PrivaPub.StaticServices; using System.Text.Json.Nodes; using static PrivaPub.Federation.Objects.ActivityJson; namespace PrivaPub.Federation.Inbox.Handlers { public class JoinHandler : IActivityHandler { readonly DbEntities _dbEntities; readonly ILocalActorService _localActors; readonly IDeliveryService _delivery; public JoinHandler(DbEntities dbEntities, ILocalActorService localActors, IDeliveryService delivery) { _dbEntities = dbEntities; _localActors = localActors; _delivery = delivery; } public string Type => "Join"; public async Task Handle(JsonNode activity, ForeignAvatar actor, CancellationToken token) { var objectUri = Id(activity["object"]); if (objectUri == default || !objectUri.StartsWith(_localActors.BaseAddress + "/", StringComparison.OrdinalIgnoreCase)) { Arrival.Drop("unknown-object"); return; } var post = await _dbEntities.Posts.Match(p => p.ObjectURI == objectUri && !p.IsFederatedCopy && !p.DeletedAt.HasValue).ExecuteFirstAsync(token); var owner = post == default ? default : await _localActors.FindById(LocalActorKind.Person, post.GroupUserId, token); if (owner == default || string.IsNullOrEmpty(actor.InboxURL)) { Arrival.Drop("unknown-object"); return; } Arrival.About(post.ObjectType ?? "Note", post.Visibility, post.CreationDate); Arrival.Reject("ignored"); await _delivery.Enqueue(owner, new[] { actor.InboxURL }, new JsonObject { ["@context"] = ActivityPubRenderer.ActivityStreams, ["id"] = owner.ActivityUri($"ignore-{Guid.NewGuid():N}"), ["type"] = "Ignore", ["actor"] = owner.Uri, ["object"] = activity.DeepClone() }, token); } } }