[parsing] Allow searching for notes by visibility

This commit is contained in:
notfire 2025-02-25 09:19:58 -05:00
parent a8e3597811
commit 4db0c528bf
Signed by: notfire
GPG key ID: 3AFDACAAB4E56B16
3 changed files with 66 additions and 0 deletions

View file

@ -35,6 +35,7 @@ public static class QueryableFtsExtensions
InstanceFilter instanceFilter => current.ApplyInstanceFilter(instanceFilter, config), InstanceFilter instanceFilter => current.ApplyInstanceFilter(instanceFilter, config),
MentionFilter mentionFilter => current.ApplyMentionFilter(mentionFilter, config, db), MentionFilter mentionFilter => current.ApplyMentionFilter(mentionFilter, config, db),
MiscFilter miscFilter => current.ApplyMiscFilter(miscFilter, user), MiscFilter miscFilter => current.ApplyMiscFilter(miscFilter, user),
VisibilityFilter visibilityFilter => current.ApplyVisibilityFilter(visibilityFilter),
ReplyFilter replyFilter => current.ApplyReplyFilter(replyFilter, config, db), ReplyFilter replyFilter => current.ApplyReplyFilter(replyFilter, config, db),
CwFilter cwFilter => current.ApplyCwFilter(cwFilter, caseSensitivity, matchType), CwFilter cwFilter => current.ApplyCwFilter(cwFilter, caseSensitivity, matchType),
WordFilter wordFilter => current.ApplyWordFilter(wordFilter, caseSensitivity, matchType), WordFilter wordFilter => current.ApplyWordFilter(wordFilter, caseSensitivity, matchType),
@ -163,6 +164,19 @@ public static class QueryableFtsExtensions
}; };
} }
private static IQueryable<Note> ApplyVisibilityFilter(this IQueryable<Note> query, VisibilityFilter filter)
{
return filter.Value switch
{
VisibilityFilterType.Public => query.ApplyPublicFilter(filter.Negated),
VisibilityFilterType.Home => query.ApplyHomeFilter(filter.Negated),
VisibilityFilterType.Followers => query.ApplyFollowersOnlyFilter(filter.Negated),
VisibilityFilterType.Specified => query.ApplySpecifiedFilter(filter.Negated),
VisibilityFilterType.Local => query.ApplyLocalFilter(filter.Negated),
_ => throw new ArgumentOutOfRangeException(nameof(filter))
};
}
[SuppressMessage("ReSharper", "EntityFramework.UnsupportedServerSideFunctionCall", Justification = "Projectables")] [SuppressMessage("ReSharper", "EntityFramework.UnsupportedServerSideFunctionCall", Justification = "Projectables")]
private static IQueryable<Note> ApplyFollowersFilter(this IQueryable<Note> query, User user, bool negated) private static IQueryable<Note> ApplyFollowersFilter(this IQueryable<Note> query, User user, bool negated)
=> query.Where(p => negated ? !p.User.IsFollowing(user) : p.User.IsFollowing(user)); => query.Where(p => negated ? !p.User.IsFollowing(user) : p.User.IsFollowing(user));
@ -177,6 +191,21 @@ public static class QueryableFtsExtensions
private static IQueryable<Note> ApplyBoostsFilter(this IQueryable<Note> query, bool negated) private static IQueryable<Note> ApplyBoostsFilter(this IQueryable<Note> query, bool negated)
=> query.Where(p => negated ? !p.IsPureRenote : p.IsPureRenote); => query.Where(p => negated ? !p.IsPureRenote : p.IsPureRenote);
private static IQueryable<Note> ApplyPublicFilter(this IQueryable<Note> query, bool negated)
=> query.Where(p => negated ? p.Visibility != Note.NoteVisibility.Public : p.Visibility == Note.NoteVisibility.Public);
private static IQueryable<Note> ApplyHomeFilter(this IQueryable<Note> query, bool negated)
=> query.Where(p => negated ? p.Visibility != Note.NoteVisibility.Home : p.Visibility == Note.NoteVisibility.Home);
private static IQueryable<Note> ApplyFollowersOnlyFilter(this IQueryable<Note> query, bool negated)
=> query.Where(p => negated ? p.Visibility != Note.NoteVisibility.Followers : p.Visibility == Note.NoteVisibility.Followers);
private static IQueryable<Note> ApplySpecifiedFilter(this IQueryable<Note> query, bool negated)
=> query.Where(p => negated ? p.Visibility != Note.NoteVisibility.Specified : p.Visibility == Note.NoteVisibility.Specified);
private static IQueryable<Note> ApplyLocalFilter(this IQueryable<Note> query, bool negated)
=> query.Where(p => negated ? !p.LocalOnly : p.LocalOnly);
private static IQueryable<Note> ApplyAttachmentFilter(this IQueryable<Note> query, AttachmentFilter filter) private static IQueryable<Note> ApplyAttachmentFilter(this IQueryable<Note> query, AttachmentFilter filter)
=> filter.Negated ? query.ApplyNegatedAttachmentFilter(filter) : query.ApplyRegularAttachmentFilter(filter); => filter.Negated ? query.ApplyNegatedAttachmentFilter(filter) : query.ApplyRegularAttachmentFilter(filter);

View file

@ -54,6 +54,42 @@ public record MiscFilter(bool Negated, MiscFilterType Value) : ISearchQueryFilte
} }
} }
public enum VisibilityFilterType
{
Public,
Home,
Followers,
Specified,
Local
}
public record VisibilityFilter(bool Negated, VisibilityFilterType Value) : ISearchQueryFilter
{
public static bool TryParse(bool negated, ReadOnlySpan<char> value, [NotNullWhen(true)] out VisibilityFilter? result)
{
VisibilityFilterType? type = value switch
{
"public" => VisibilityFilterType.Public,
"home" => VisibilityFilterType.Home,
"unlisted" => VisibilityFilterType.Home,
"followers" => VisibilityFilterType.Followers,
"direct" => VisibilityFilterType.Specified,
"specified" => VisibilityFilterType.Specified,
"local" => VisibilityFilterType.Local,
_ => null
};
if (!type.HasValue)
{
result = null;
return false;
}
result = new VisibilityFilter(negated, type.Value);
return true;
}
}
public enum InFilterType public enum InFilterType
{ {
Bookmarks, Bookmarks,

View file

@ -83,6 +83,7 @@ public static class SearchQueryParser
"instance" or "domain" or "host" => new InstanceFilter(negated, value.ToString()), "instance" or "domain" or "host" => new InstanceFilter(negated, value.ToString()),
"filter" when MiscFilter.TryParse(negated, value, out var parsed) => parsed, "filter" when MiscFilter.TryParse(negated, value, out var parsed) => parsed,
"visibility" when VisibilityFilter.TryParse(negated, value, out var parsed) => parsed,
"in" when InFilter.TryParse(negated, value, out var parsed) => parsed, "in" when InFilter.TryParse(negated, value, out var parsed) => parsed,
"has" or "attachment" or "attached" when AttachmentFilter.TryParse(negated, value, out var parsed) "has" or "attachment" or "attached" when AttachmentFilter.TryParse(negated, value, out var parsed)
=> parsed, => parsed,