From 4b958a3c3167fb9a1f49263e04aa813c920b1a75 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Fri, 22 Aug 2025 17:07:22 +0800 Subject: [PATCH] :wastebasket: Remove the old search API --- .../DysonNetwork.Sphere.csproj | 1 + DysonNetwork.Sphere/Post/PostController.cs | 95 ++++++++----------- 2 files changed, 40 insertions(+), 56 deletions(-) diff --git a/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj b/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj index fa1604d..315f491 100644 --- a/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj +++ b/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj @@ -60,6 +60,7 @@ + diff --git a/DysonNetwork.Sphere/Post/PostController.cs b/DysonNetwork.Sphere/Post/PostController.cs index c6ea9eb..d7a3af4 100644 --- a/DysonNetwork.Sphere/Post/PostController.cs +++ b/DysonNetwork.Sphere/Post/PostController.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using NodaTime; +using Swashbuckle.AspNetCore.Annotations; using PublisherService = DysonNetwork.Sphere.Publisher.PublisherService; namespace DysonNetwork.Sphere.Post; @@ -37,8 +38,39 @@ public class PostController( return Ok(posts); } + /// + /// Retrieves a paginated list of posts with optional filtering and sorting. + /// + /// Whether to include reply posts in the results. If false, only root posts are returned. + /// The number of posts to skip for pagination. + /// The maximum number of posts to return (default: 20). + /// Filter posts by publisher name. + /// Filter posts by realm slug. + /// Filter posts by post type (as integer). + /// Filter posts by category slugs. + /// Filter posts by tag slugs. + /// Search term to filter posts by title, description, or content. + /// If true, uses vector search with the query term. If false, performs a simple ILIKE search. + /// If true, only returns posts that have attachments. + /// If true, returns posts in random order. If false, orders by published/created date (newest first). + /// + /// Returns an ActionResult containing a list of Post objects that match the specified criteria. + /// Includes an X-Total header with the total count of matching posts before pagination. + /// + /// Returns the list of posts matching the criteria. [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List))] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [SwaggerOperation( + Summary = "Retrieves a paginated list of posts", + Description = "Gets posts with various filtering and sorting options. Supports pagination and advanced search capabilities.", + OperationId = "ListPosts", + Tags = ["Posts"] + )] + [SwaggerResponse(StatusCodes.Status200OK, "Successfully retrieved the list of posts", typeof(List))] + [SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid request parameters")] public async Task>> ListPosts( + [FromQuery(Name = "replies")] bool? includeReplies, [FromQuery] int offset = 0, [FromQuery] int take = 20, [FromQuery(Name = "pub")] string? pubName = null, @@ -48,7 +80,6 @@ public class PostController( [FromQuery(Name = "tags")] List? tags = null, [FromQuery(Name = "query")] string? queryTerm = null, [FromQuery(Name = "vector")] bool queryVector = false, - [FromQuery(Name = "replies")] bool includeReplies = false, [FromQuery(Name = "media")] bool onlyMedia = false, [FromQuery(Name = "shuffle")] bool shuffle = false ) @@ -83,10 +114,15 @@ public class PostController( query = query.Where(p => p.Categories.Any(c => categories.Contains(c.Slug))); if (tags is { Count: > 0 }) query = query.Where(p => p.Tags.Any(c => tags.Contains(c.Slug))); - if (!includeReplies) - query = query.Where(e => e.RepliedPostId == null); if (onlyMedia) query = query.Where(e => e.Attachments.Count > 0); + + query = includeReplies switch + { + false => query.Where(e => e.RepliedPostId == null), + true => query.Where(e => e.RepliedPostId != null), + _ => query + }; if (!string.IsNullOrWhiteSpace(queryTerm)) { @@ -192,59 +228,6 @@ public class PostController( return Ok(post); } - [HttpGet("search")] - [Obsolete("Use the new ListPost API")] - public async Task>> SearchPosts( - [FromQuery] string query, - [FromQuery] int offset = 0, - [FromQuery] int take = 20, - [FromQuery] bool useVector = true - ) - { - if (string.IsNullOrWhiteSpace(query)) - return BadRequest("Search query cannot be empty"); - - HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue); - var currentUser = currentUserValue as Account; - List userFriends = []; - if (currentUser != null) - { - var friendsResponse = await accounts.ListFriendsAsync(new ListRelationshipSimpleRequest - { AccountId = currentUser.Id }); - userFriends = friendsResponse.AccountsId.Select(Guid.Parse).ToList(); - } - - var userPublishers = currentUser is null ? [] : await pub.GetUserPublishers(Guid.Parse(currentUser.Id)); - - var queryable = db.Posts - .FilterWithVisibility(currentUser, userFriends, userPublishers, isListing: true) - .AsQueryable(); - if (useVector) - queryable = queryable.Where(p => p.SearchVector.Matches(EF.Functions.ToTsQuery(query))); - else - queryable = queryable.Where(p => - (p.Title != null && EF.Functions.ILike(p.Title, $"%{query}%")) || - (p.Description != null && EF.Functions.ILike(p.Description, $"%{query}%")) || - (p.Content != null && EF.Functions.ILike(p.Content, $"%{query}%")) - ); - - var totalCount = await queryable.CountAsync(); - - var posts = await queryable - .Include(e => e.RepliedPost) - .Include(e => e.ForwardedPost) - .Include(e => e.Categories) - .Include(e => e.Tags) - .OrderByDescending(e => e.PublishedAt ?? e.CreatedAt) - .Skip(offset) - .Take(take) - .ToListAsync(); - posts = await ps.LoadPostInfo(posts, currentUser, true); - - Response.Headers["X-Total"] = totalCount.ToString(); - return Ok(posts); - } - [HttpGet("{id:guid}/reactions")] public async Task>> GetReactions( Guid id,