using MongoDB.Entities; using PrivaPub.Federation.Actors; 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 { public static class Communities { // the remote community a post was made in: its own audience, or the first one its thread names on the way up (a // comment fetched for its thread, or delivered to a persona, may name none) public static async Task Of(PostEntity post, DbEntities dbEntities, CancellationToken token) { for (var depth = 0; post != default && depth < RemotePosts.MaxDepth; depth++) { if (!string.IsNullOrEmpty(post.AudienceURI)) return post.AudienceURI; post = string.IsNullOrEmpty(post.AnsweringToPostId) ? default : await dbEntities.Posts.MatchID(post.AnsweringToPostId).ExecuteFirstAsync(token); } return default; } // whether an account may act for a community's moderators: anyone on the community's own server (its admins and // moderators, as Lemmy's verify_mod_or_admin_action allows), or an account its moderators collection lists public static async Task Moderates(ForeignAvatar community, string actorUri, IRemoteActorService remoteActors, CancellationToken token) { if (actorUri == default || community == default) return false; if (Origin.Same(actorUri, community.ActorURI)) return true; if (string.IsNullOrEmpty(community.ModeratorsURL)) return false; using var fetched = await remoteActors.FetchObject(community.ModeratorsURL, token); if (fetched == default) return false; var collection = JsonNode.Parse(fetched.Root.GetRawText()); var items = collection?["orderedItems"] ?? collection?["items"] ?? collection?["first"]?["orderedItems"] ?? collection?["first"]?["items"]; return items is JsonArray listed && listed.Any(item => Id(item) == actorUri); } } }