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 Expression<Func<T, object>> Key { get; }
|
||||||
public bool Descendant { get; }
|
public bool Descendant { get; }
|
||||||
|
|
||||||
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
public Sort(Expression<Func<T, object>> key, bool descendant = false)
|
||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
Descendant = descendant;
|
Descendant = descendant;
|
||||||
|
|
||||||
|
if (!(Key.Body is MemberExpression))
|
||||||
|
throw new ArgumentException("The given sort key is not valid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sort(string sortBy)
|
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)
|
object val = string.IsNullOrEmpty(value) || value.Equals("null", StringComparison.OrdinalIgnoreCase)
|
||||||
? null
|
? null
|
||||||
: Convert.ChangeType(value, propertyType);
|
: Convert.ChangeType(value, propertyType);
|
||||||
ConstantExpression valueExpr = Expression.Constant(val);
|
ConstantExpression valueExpr = Expression.Constant(val, property.PropertyType);
|
||||||
|
|
||||||
Expression condition = operand switch
|
Expression condition = operand switch
|
||||||
{
|
{
|
||||||
@ -297,7 +297,14 @@ namespace Kyoo
|
|||||||
expression = condition;
|
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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
@ -39,20 +40,13 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
public Task<Episode> Get(string slug)
|
public Task<Episode> Get(string slug)
|
||||||
{
|
{
|
||||||
int sIndex = slug.IndexOf("-s", StringComparison.Ordinal);
|
Match match = Regex.Match(slug, @"(<show>.*)-s(<season>\d*)-e(<episode>\d*)");
|
||||||
int eIndex = slug.IndexOf("-e", StringComparison.Ordinal);
|
|
||||||
|
|
||||||
if (sIndex == -1 && eIndex == -1)
|
|
||||||
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == slug);
|
|
||||||
|
|
||||||
if (sIndex == -1 || eIndex == -1 || eIndex < sIndex)
|
if (!match.Success)
|
||||||
throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}");
|
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == slug);
|
||||||
string showSlug = slug.Substring(0, sIndex);
|
return Get(match.Groups["show"].Value,
|
||||||
if (!int.TryParse(slug.Substring(sIndex + 2), out int seasonNumber))
|
int.Parse(match.Groups["season"].Value),
|
||||||
throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}");
|
int.Parse(match.Groups["episode"].Value));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber)
|
public Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber)
|
||||||
|
@ -92,7 +92,7 @@ namespace Kyoo.Controllers
|
|||||||
(ParameterExpression)((MemberExpression)sortKey.Body).Expression
|
(ParameterExpression)((MemberExpression)sortKey.Body).Expression
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
query = query.Take(page.Count <= 0 ? 20 : page.Count);
|
query = query.Take(page.Count);
|
||||||
|
|
||||||
return await query.ToListAsync();
|
return await query.ToListAsync();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Kyoo.Models;
|
using System;
|
||||||
|
using Kyoo.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -6,6 +7,7 @@ using System.Threading.Tasks;
|
|||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Kyoo.Api
|
namespace Kyoo.Api
|
||||||
{
|
{
|
||||||
@ -19,23 +21,26 @@ namespace Kyoo.Api
|
|||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IThumbnailsManager _thumbnailsManager;
|
private readonly IThumbnailsManager _thumbnailsManager;
|
||||||
private readonly ITaskManager _taskManager;
|
private readonly ITaskManager _taskManager;
|
||||||
|
private readonly string _baseURL;
|
||||||
|
|
||||||
public ShowsAPI(ILibraryManager libraryManager,
|
public ShowsAPI(ILibraryManager libraryManager,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
DatabaseContext database,
|
DatabaseContext database,
|
||||||
IThumbnailsManager thumbnailsManager,
|
IThumbnailsManager thumbnailsManager,
|
||||||
ITaskManager taskManager)
|
ITaskManager taskManager,
|
||||||
|
IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
_database = database;
|
_database = database;
|
||||||
_thumbnailsManager = thumbnailsManager;
|
_thumbnailsManager = thumbnailsManager;
|
||||||
_taskManager = taskManager;
|
_taskManager = taskManager;
|
||||||
|
_baseURL = configuration.GetValue<string>("public_url").TrimEnd('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Policy="Read")]
|
[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 limit,
|
||||||
[FromQuery] int afterID,
|
[FromQuery] int afterID,
|
||||||
[FromQuery] Dictionary<string, string> where)
|
[FromQuery] Dictionary<string, string> where)
|
||||||
@ -43,10 +48,26 @@ namespace Kyoo.Api
|
|||||||
where.Remove("sortBy");
|
where.Remove("sortBy");
|
||||||
where.Remove("limit");
|
where.Remove("limit");
|
||||||
where.Remove("afterID");
|
where.Remove("afterID");
|
||||||
|
if (limit <= 0)
|
||||||
return await _libraryManager.GetShows(Utility.ParseWhere<Show>(where),
|
limit = 20;
|
||||||
new Sort<Show>(sortBy),
|
|
||||||
new Pagination(limit, afterID));
|
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}")]
|
[HttpGet("{slug}")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user