mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Making where & pagination works
This commit is contained in:
parent
4e9096ae76
commit
6bdd363b7b
@ -25,11 +25,14 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
public Expression<Func<T, object>> Key { get; }
|
||||
public bool Descendant { get; }
|
||||
|
||||
|
||||
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
||||
{
|
||||
Key = key;
|
||||
Descendant = descendant;
|
||||
|
||||
if (!(Key.Body is MemberExpression))
|
||||
throw new ArgumentException("The given sort key is not valid.");
|
||||
}
|
||||
|
||||
public Sort(string sortBy)
|
||||
|
50
Kyoo.Common/Models/Page.cs
Normal file
50
Kyoo.Common/Models/Page.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class Page<T>
|
||||
{
|
||||
public string This { get; set; }
|
||||
public string First { get; set; }
|
||||
public string Next { get; set; }
|
||||
|
||||
public int Count => Items.Count;
|
||||
public ICollection<T> Items { get; set; }
|
||||
|
||||
public Page() { }
|
||||
|
||||
public Page(ICollection<T> items)
|
||||
{
|
||||
Items = items;
|
||||
}
|
||||
|
||||
public Page(ICollection<T> items, string @this, string next, string first)
|
||||
{
|
||||
Items = items;
|
||||
This = @this;
|
||||
Next = next;
|
||||
First = first;
|
||||
}
|
||||
|
||||
public Page(ICollection<T> items,
|
||||
Func<T, string> getID,
|
||||
string url,
|
||||
Dictionary<string, string> query,
|
||||
int limit)
|
||||
{
|
||||
Items = items;
|
||||
This = url + query.ToQueryString();
|
||||
|
||||
if (items.Count == limit)
|
||||
{
|
||||
query["afterID"] = getID(items.Last());
|
||||
Next = url + query.ToQueryString();
|
||||
}
|
||||
|
||||
query.Remove("afterID");
|
||||
First = url + query.ToQueryString();
|
||||
}
|
||||
}
|
||||
}
|
@ -276,7 +276,7 @@ namespace Kyoo
|
||||
object val = string.IsNullOrEmpty(value) || value.Equals("null", StringComparison.OrdinalIgnoreCase)
|
||||
? null
|
||||
: Convert.ChangeType(value, propertyType);
|
||||
ConstantExpression valueExpr = Expression.Constant(val);
|
||||
ConstantExpression valueExpr = Expression.Constant(val, property.PropertyType);
|
||||
|
||||
Expression condition = operand switch
|
||||
{
|
||||
@ -297,7 +297,14 @@ namespace Kyoo
|
||||
expression = condition;
|
||||
}
|
||||
|
||||
return Expression.Lambda<Func<T, bool>>(expression!);
|
||||
return Expression.Lambda<Func<T, bool>>(expression!, param);
|
||||
}
|
||||
|
||||
public static string ToQueryString(this Dictionary<string, string> query)
|
||||
{
|
||||
if (!query.Any())
|
||||
return string.Empty;
|
||||
return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}"));
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
@ -39,20 +40,13 @@ namespace Kyoo.Controllers
|
||||
|
||||
public Task<Episode> Get(string slug)
|
||||
{
|
||||
int sIndex = slug.IndexOf("-s", StringComparison.Ordinal);
|
||||
int eIndex = slug.IndexOf("-e", StringComparison.Ordinal);
|
||||
|
||||
if (sIndex == -1 && eIndex == -1)
|
||||
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == slug);
|
||||
Match match = Regex.Match(slug, @"(<show>.*)-s(<season>\d*)-e(<episode>\d*)");
|
||||
|
||||
if (sIndex == -1 || eIndex == -1 || eIndex < sIndex)
|
||||
throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}");
|
||||
string showSlug = slug.Substring(0, sIndex);
|
||||
if (!int.TryParse(slug.Substring(sIndex + 2), out int seasonNumber))
|
||||
throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}");
|
||||
if (!int.TryParse(slug.Substring(eIndex + 2), out int episodeNumber))
|
||||
throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}");
|
||||
return Get(showSlug, seasonNumber, episodeNumber);
|
||||
if (!match.Success)
|
||||
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == slug);
|
||||
return Get(match.Groups["show"].Value,
|
||||
int.Parse(match.Groups["season"].Value),
|
||||
int.Parse(match.Groups["episode"].Value));
|
||||
}
|
||||
|
||||
public Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber)
|
||||
|
@ -92,7 +92,7 @@ namespace Kyoo.Controllers
|
||||
(ParameterExpression)((MemberExpression)sortKey.Body).Expression
|
||||
));
|
||||
}
|
||||
query = query.Take(page.Count <= 0 ? 20 : page.Count);
|
||||
query = query.Take(page.Count);
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Kyoo.Models;
|
||||
using System;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -6,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using Kyoo.Controllers;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Kyoo.Api
|
||||
{
|
||||
@ -19,23 +21,26 @@ namespace Kyoo.Api
|
||||
private readonly DatabaseContext _database;
|
||||
private readonly IThumbnailsManager _thumbnailsManager;
|
||||
private readonly ITaskManager _taskManager;
|
||||
private readonly string _baseURL;
|
||||
|
||||
public ShowsAPI(ILibraryManager libraryManager,
|
||||
IProviderManager providerManager,
|
||||
DatabaseContext database,
|
||||
IThumbnailsManager thumbnailsManager,
|
||||
ITaskManager taskManager)
|
||||
ITaskManager taskManager,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_providerManager = providerManager;
|
||||
_database = database;
|
||||
_thumbnailsManager = thumbnailsManager;
|
||||
_taskManager = taskManager;
|
||||
_baseURL = configuration.GetValue<string>("public_url").TrimEnd('/');
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize(Policy="Read")]
|
||||
public async Task<IEnumerable<Show>> GetShows([FromQuery] string sortBy,
|
||||
public async Task<ActionResult<Page<Show>>> GetShows([FromQuery] string sortBy,
|
||||
[FromQuery] int limit,
|
||||
[FromQuery] int afterID,
|
||||
[FromQuery] Dictionary<string, string> where)
|
||||
@ -43,10 +48,26 @@ namespace Kyoo.Api
|
||||
where.Remove("sortBy");
|
||||
where.Remove("limit");
|
||||
where.Remove("afterID");
|
||||
|
||||
return await _libraryManager.GetShows(Utility.ParseWhere<Show>(where),
|
||||
new Sort<Show>(sortBy),
|
||||
new Pagination(limit, afterID));
|
||||
if (limit <= 0)
|
||||
limit = 20;
|
||||
|
||||
ICollection<Show> shows;
|
||||
try
|
||||
{
|
||||
shows = await _libraryManager.GetShows(Utility.ParseWhere<Show>(where),
|
||||
new Sort<Show>(sortBy),
|
||||
new Pagination(limit, afterID));
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
return BadRequest(new { Error = ex.Message });
|
||||
}
|
||||
|
||||
return new Page<Show>(shows,
|
||||
x => $"{x.ID}",
|
||||
_baseURL + Request.Path,
|
||||
Request.Query.ToDictionary(x => x.Key, x => x.Value.ToString(), StringComparer.InvariantCultureIgnoreCase),
|
||||
limit);
|
||||
}
|
||||
|
||||
[HttpGet("{slug}")]
|
||||
|
Loading…
x
Reference in New Issue
Block a user