using MongoDB.Entities; using PrivaPub.Federation.Objects; 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 { // A moderator's lock of a thread sent as it is, not inside its community's announce (Mbin sends it to the magazine's // subscribers itself): taken only from the post's own server, which speaks for it. Replies are refused until the // Undo{Lock}, as for a lock a community announces. public class LockHandler : IActivityHandler { readonly DbEntities _dbEntities; public LockHandler(DbEntities dbEntities) { _dbEntities = dbEntities; } public string Type => "Lock"; public async Task Handle(JsonNode activity, ForeignAvatar actor, CancellationToken token) { if (await Set(_dbEntities, Id(activity["object"]), actor, locked: true, token)) Arrival.Accept("locked"); else Arrival.Drop("unknown-object"); } // whether the post is ours to lock or unlock for that actor, and was public static async Task Set(DbEntities dbEntities, string objectUri, ForeignAvatar actor, bool locked, CancellationToken token) { if (objectUri == default || !Origin.Same(objectUri, actor.ActorURI)) return false; var post = await dbEntities.Posts.Match(p => p.ObjectURI == objectUri && p.IsFederatedCopy).ExecuteFirstAsync(token); if (post == default) return false; Arrival.About(visibility: post.Visibility, created: post.CreationDate); await DB.Default.Update().MatchID(post.ID).Modify(p => p.LockedAt, locked ? DateTime.UtcNow : null).ExecuteAsync(token); return true; } } }