using MongoDB.Entities; using PrivaPub.Models.Group; using PrivaPub.Models.Post; using System.Linq.Expressions; using GroupEntity = PrivaPub.Models.Group.Group; namespace PrivaPub.Domain.Privacy { public static class VisibilityPolicy { //neither deleted nor kept back after its remote author deleted their account (owner decision, 2026-10-03) public static readonly Expression> IsShown = p => !p.DeletedAt.HasValue && !p.AuthorGone; public static readonly Expression> IsPublic = p => !p.DeletedAt.HasValue && !p.AuthorGone && (p.Visibility == PostVisibility.Public || p.Visibility == PostVisibility.Unlisted); static readonly Func IsShownCompiled = IsShown.Compile(); static readonly Func IsPublicCompiled = IsPublic.Compile(); public static bool Shown(Post post) => post != default && IsShownCompiled(post); public static async Task CanSee(Post post, string viewerAvatarId, CancellationToken token) { if (!Shown(post)) return false; if (IsPublicCompiled(post)) return true; if (string.IsNullOrEmpty(viewerAvatarId)) return false; if (post.GroupUserId == viewerAvatarId || post.Mentions.Any(m => m.IsLocal && m.AccountId == viewerAvatarId)) return true; return post.Visibility switch { PostVisibility.Direct => !string.IsNullOrEmpty(post.ConversationId) && await DB.Default.Find() .Match(g => g.ID == post.ConversationId && g.Members.Any(m => !m.IsForeign && m.AvatarId == viewerAvatarId)) .ExecuteAnyAsync(token), PostVisibility.Circle => !string.IsNullOrEmpty(post.GroupId) && await DB.Default.Find() .Match(g => g.ID == post.GroupId && g.Members.Any(m => !m.IsForeign && m.AvatarId == viewerAvatarId)) .ExecuteAnyAsync(token), _ => false }; } } }