using MongoDB.Entities; using PrivaPub.Federation.Actors; using PrivaPub.Domain.Statuses; using PrivaPub.Federation.Objects; using PrivaPub.Federation.Outbox; using PrivaPub.Models.Post; using PrivaPub.Models.User; using PrivaPub.StaticServices; using System.Text.Json.Nodes; using static PrivaPub.Federation.Objects.ActivityJson; using PostEntity = PrivaPub.Models.Post.Post; namespace PrivaPub.Federation.Inbox.Handlers { public class UpdateHandler : IActivityHandler { readonly DbEntities _dbEntities; readonly ILocalActorService _localActors; readonly IRemoteActorService _remoteActors; readonly IGroupDistributor _groups; readonly IObjectRecords _records; readonly IQuoteService _quotes; public UpdateHandler(DbEntities dbEntities, ILocalActorService localActors, IRemoteActorService remoteActors, IGroupDistributor groups, IObjectRecords records, IQuoteService quotes) { _quotes = quotes; _records = records; _groups = groups; _dbEntities = dbEntities; _localActors = localActors; _remoteActors = remoteActors; } public string Type => "Update"; public async Task Handle(JsonNode activity, ForeignAvatar actor, CancellationToken token) { var inner = activity["object"]; if (Id(inner) == actor.ActorURI) { await _remoteActors.GetActor(actor.ActorURI, refresh: true, token); Arrival.Accept("actor-refresh"); Arrival.About(actor.AvatarType.ToString()); return; } if (inner is not JsonObject || !Origin.Same(Id(inner), actor.ActorURI)) { Arrival.Drop("cross-origin"); return; } var note = NoteParser.Parse(inner); if (note == default || note.AttributedTo != actor.ActorURI) { Arrival.Drop(note == default ? "unparseable" : "misattributed"); return; } var post = await _dbEntities.Posts.Match(p => p.ObjectURI == note.Id && p.ActorURI == actor.ActorURI).ExecuteFirstAsync(token); if (post == default || post.DeletedAt.HasValue) { Arrival.Drop("unknown-object"); return; } Arrival.About(note.Type, post.Visibility, post.CreationDate); var edited = await RemoteEdits.Apply(post, note, Id(activity), _localActors, _records, _quotes, token); Arrival.Accept(edited ? "edit" : "refresh"); if (edited && !string.IsNullOrEmpty(post.GroupId) && await _localActors.FindById(Models.Federation.LocalActorKind.Group, post.GroupId, token) is { IsCircle: false } community) await _groups.Announce(community, activity.AsObject(), post.ObjectURI, isNewPost: false, token); } } }