From df726f6f9f618e6c4157d1aca531c5445e1eb18a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Tue, 20 Feb 2024 19:46:06 +0100 Subject: [PATCH] [backend/masto-client] Add notification filtering --- .../Mastodon/NotificationController.cs | 7 +++++-- .../Schemas/Entities/NotificationEntity.cs | 16 +++++++++++++++ .../Mastodon/Schemas/NotificationSchemas.cs | 13 ++++++++++++ .../Core/Extensions/QueryableExtensions.cs | 20 +++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 Iceshrimp.Backend/Controllers/Mastodon/Schemas/NotificationSchemas.cs diff --git a/Iceshrimp.Backend/Controllers/Mastodon/NotificationController.cs b/Iceshrimp.Backend/Controllers/Mastodon/NotificationController.cs index 68072417..9574243d 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/NotificationController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/NotificationController.cs @@ -27,7 +27,9 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not [LinkPagination(40, 80)] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List))] [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))] - public async Task GetNotifications(MastodonPaginationQuery query) + public async Task GetNotifications( + MastodonPaginationQuery query, NotificationSchemas.GetNotificationsRequest request + ) { var user = HttpContext.GetUserOrFail(); var res = await db.Notifications @@ -40,8 +42,9 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not p.Type == NotificationType.Quote || p.Type == NotificationType.Like || p.Type == NotificationType.PollEnded || - p.Type == NotificationType.FollowRequestReceived || + p.Type == NotificationType.FollowRequestReceived || p.Type == NotificationType.Edit) + .FilterByGetNotificationsRequest(request) .EnsureNoteVisibilityFor(p => p.Note, user) .FilterBlocked(p => p.Notifier, user) .FilterBlocked(p => p.Note, user) diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/NotificationEntity.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/NotificationEntity.cs index db41bcbb..cf477aa6 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/NotificationEntity.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/NotificationEntity.cs @@ -32,4 +32,20 @@ public class NotificationEntity : IEntity _ => throw new GracefulException($"Unsupported notification type: {type}") }; } + + public static IEnumerable DecodeType(string type) + { + return type switch + { + "follow" => [NotificationType.Follow], + "mention" => [NotificationType.Mention, NotificationType.Reply], + "renote" => [NotificationType.Renote], + "reblog" => [NotificationType.Quote], + "favourite" => [NotificationType.Like], + "poll" => [NotificationType.PollEnded], + "follow_request" => [NotificationType.FollowRequestReceived], + "update" => [NotificationType.Edit], + _ => [] + }; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/NotificationSchemas.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/NotificationSchemas.cs new file mode 100644 index 00000000..23db70c3 --- /dev/null +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/NotificationSchemas.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas; + +public abstract class NotificationSchemas +{ + public class GetNotificationsRequest + { + [FromQuery(Name = "types")] public List? Types { get; set; } + [FromQuery(Name = "exclude_types")] public List? ExcludeTypes { get; set; } + [FromQuery(Name = "account_id")] public string? AccountId { get; set; } + } +} \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs b/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs index 8e59c3c2..75be58e1 100644 --- a/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs @@ -292,6 +292,26 @@ public static class QueryableExtensions return query; } + + public static IQueryable FilterByGetNotificationsRequest( + this IQueryable query, + NotificationSchemas.GetNotificationsRequest request + ) + { + if (request.AccountId != null) + query = query.Where(p => p.NotifierId == request.AccountId); + if (request.Types != null) + query = query.Where(p => request.Types.SelectMany(NotificationEntity.DecodeType) + .Distinct() + .Contains(p.Type)); + if (request.ExcludeTypes != null) + query = query.Where(p => !request.ExcludeTypes.SelectMany(NotificationEntity.DecodeType) + .Distinct() + .Contains(p.Type)); + + return query; + } + #pragma warning disable CS8602 // Dereference of a possibly null reference. // Justification: in the context of nullable EF navigation properties, null values are ignored and therefore irrelevant. // Source: https://learn.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types#navigating-and-including-nullable-relationships