[backend/mastodon] Add filter support to GetUserStatusees (ISH-13)
This commit is contained in:
parent
46820efbea
commit
48b78de6a3
4 changed files with 49 additions and 10 deletions
|
@ -1,3 +1,4 @@
|
|||
using EntityFrameworkCore.Projectables;
|
||||
using Iceshrimp.Backend.Controllers.Attributes;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Attributes;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Schemas;
|
||||
|
@ -186,7 +187,7 @@ public class AccountController(
|
|||
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("relationships")]
|
||||
[Authorize("read:follows")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Relationship[]))]
|
||||
|
@ -231,12 +232,15 @@ public class AccountController(
|
|||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<Status>))]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(MastodonErrorResponse))]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(MastodonErrorResponse))]
|
||||
public async Task<IActionResult> GetHomeTimeline(string id, PaginationQuery query) {
|
||||
//TODO: there's a lot more query params to implement here
|
||||
var user = HttpContext.GetUserOrFail();
|
||||
public async Task<IActionResult> GetUserStatuses(string id, AccountSchemas.AccountStatusesRequest request,
|
||||
PaginationQuery query) {
|
||||
var user = HttpContext.GetUserOrFail();
|
||||
var account = await db.Users.FirstOrDefaultAsync(p => p.Id == id) ?? throw GracefulException.RecordNotFound();
|
||||
|
||||
var res = await db.Notes
|
||||
.IncludeCommonProperties()
|
||||
.FilterByUser(id)
|
||||
.FilterByUser(account)
|
||||
.FilterByAccountStatusesRequest(request, account)
|
||||
.EnsureVisibleFor(user)
|
||||
.Paginate(query, ControllerContext)
|
||||
.PrecomputeVisibilities(user)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas;
|
||||
|
||||
public abstract class AccountSchemas {
|
||||
public class AccountStatusesRequest {
|
||||
[FromQuery(Name = "only_media")] public bool OnlyMedia { get; set; } = false;
|
||||
[FromQuery(Name = "exclude_replies")] public bool ExcludeReplies { get; set; } = false;
|
||||
[FromQuery(Name = "exclude_reblogs")] public bool ExcludeRenotes { get; set; } = false;
|
||||
[FromQuery(Name = "pinned")] public bool Pinned { get; set; } = false;
|
||||
[FromQuery(Name = "tagged")] public string? Tagged { get; set; }
|
||||
}
|
||||
}
|
|
@ -445,6 +445,8 @@ public class User : IEntity {
|
|||
[InverseProperty(nameof(UserNotePin.User))]
|
||||
public virtual ICollection<UserNotePin> UserNotePins { get; set; } = new List<UserNotePin>();
|
||||
|
||||
[Projectable] public virtual IEnumerable<Note> PinnedNotes => UserNotePins.Select(p => p.Note);
|
||||
|
||||
[InverseProperty(nameof(Tables.UserProfile.User))]
|
||||
public virtual UserProfile? UserProfile { get; set; }
|
||||
|
||||
|
@ -477,7 +479,7 @@ public class User : IEntity {
|
|||
[Projectable]
|
||||
public bool DisplayNameContainsCaseInsensitive(string str) =>
|
||||
DisplayName != null && EF.Functions.ILike(DisplayName, "%" + EfHelpers.EscapeLikeQuery(str) + "%", @"\");
|
||||
|
||||
|
||||
[Projectable]
|
||||
public bool UsernameContainsCaseInsensitive(string str) =>
|
||||
DisplayName != null && EF.Functions.ILike(DisplayName, "%" + EfHelpers.EscapeLikeQuery(str) + "%", @"\");
|
||||
|
@ -506,6 +508,9 @@ public class User : IEntity {
|
|||
[Projectable]
|
||||
public bool IsMuting(User user) => Muting.Contains(user);
|
||||
|
||||
[Projectable]
|
||||
public bool HasPinned(Note note) => PinnedNotes.Contains(note);
|
||||
|
||||
public User WithPrecomputedBlockStatus(bool blocking, bool blockedBy) {
|
||||
PrecomputedIsBlocking = blocking;
|
||||
PrecomputedIsBlockedBy = blockedBy;
|
||||
|
|
|
@ -75,11 +75,11 @@ public static class NoteQueryableExtensions {
|
|||
public static IQueryable<Note> FilterByFollowingAndOwn(this IQueryable<Note> query, User user) {
|
||||
return query.Where(note => note.User == user || note.User.IsFollowedBy(user));
|
||||
}
|
||||
|
||||
|
||||
public static IQueryable<Note> FilterByUser(this IQueryable<Note> query, User user) {
|
||||
return query.Where(note => note.User == user);
|
||||
}
|
||||
|
||||
|
||||
public static IQueryable<Note> FilterByUser(this IQueryable<Note> query, string userId) {
|
||||
return query.Where(note => note.UserId == userId);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public static class NoteQueryableExtensions {
|
|||
return query.Where(note => !note.User.UserListMembers.Any(p => p.UserList.User == user &&
|
||||
p.UserList.HideFromHomeTl));
|
||||
}
|
||||
|
||||
|
||||
public static Note EnforceRenoteReplyVisibility(this Note note) {
|
||||
if (!note.PrecomputedIsReplyVisible ?? false)
|
||||
note.Reply = null;
|
||||
|
@ -145,10 +145,27 @@ public static class NoteQueryableExtensions {
|
|||
.EnforceRenoteReplyVisibility();
|
||||
return (await renderer.RenderManyAsync(list)).ToList();
|
||||
}
|
||||
|
||||
|
||||
public static async Task<List<Account>> RenderAllForMastodonAsync(
|
||||
this IQueryable<User> users, UserRenderer renderer) {
|
||||
var list = await users.ToListAsync();
|
||||
return (await renderer.RenderManyAsync(list)).ToList();
|
||||
}
|
||||
|
||||
public static IQueryable<Note> FilterByAccountStatusesRequest(this IQueryable<Note> query,
|
||||
AccountSchemas.AccountStatusesRequest request,
|
||||
User account) {
|
||||
if (request.ExcludeReplies)
|
||||
query = query.Where(p => p.Reply == null);
|
||||
if (request.ExcludeRenotes)
|
||||
query = query.Where(p => p.Renote == null);
|
||||
if (request.Tagged != null)
|
||||
query = query.Where(p => p.Tags.Contains(request.Tagged.ToLowerInvariant()));
|
||||
if (request.OnlyMedia)
|
||||
query = query.Where(p => p.FileIds.Count != 0);
|
||||
if (request.Pinned)
|
||||
query = query.Where(note => account.HasPinned(note));
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue