diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs index e10972de..40e3b653 100644 --- a/Kyoo.Common/Utility.cs +++ b/Kyoo.Common/Utility.cs @@ -237,6 +237,18 @@ namespace Kyoo return member.Member.Name; } + public static Expression StringCompatibleExpression(Func operand, + Expression left, + Expression right) + { + if (left is MemberExpression member && ((PropertyInfo)member.Member).PropertyType == typeof(string)) + { + MethodCallExpression call = Expression.Call(typeof(string), "Compare", null, left, right); + return operand(call, Expression.Constant(0)); + } + return operand(left, right); + } + public static Expression> ParseWhere(Dictionary where) { if (where == null || where.Count == 0) @@ -259,16 +271,21 @@ namespace Kyoo if (property == null) throw new ArgumentException($"No filterable parameter with the name {key}."); MemberExpression propertyExpr = Expression.Property(param, property); - ConstantExpression valueExpr = Expression.Constant(Convert.ChangeType(value, property.PropertyType)); + + Type propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; + object val = string.IsNullOrEmpty(value) || value.Equals("null", StringComparison.OrdinalIgnoreCase) + ? null + : Convert.ChangeType(value, propertyType); + ConstantExpression valueExpr = Expression.Constant(val); Expression condition = operand switch { "eq" => Expression.Equal(propertyExpr, valueExpr), "not" => Expression.NotEqual(propertyExpr, valueExpr), - "lt" => Expression.LessThan(propertyExpr, valueExpr), - "lte" => Expression.LessThanOrEqual(propertyExpr, valueExpr), - "gt" => Expression.GreaterThan(propertyExpr, valueExpr), - "gte" => Expression.GreaterThanOrEqual(propertyExpr, valueExpr), + "lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr), + "lte" => StringCompatibleExpression(Expression.LessThanOrEqual, propertyExpr, valueExpr), + "gt" => StringCompatibleExpression(Expression.GreaterThan, propertyExpr, valueExpr), + "gte" => StringCompatibleExpression(Expression.GreaterThanOrEqual, propertyExpr, valueExpr), // TODO Implement the Like expression "like" => throw new NotImplementedException("Like not implemented yet"), _ => throw new ArgumentException($"Invalid operand: {operand}") diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index 4ac185fa..cd67da1e 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -88,7 +88,8 @@ namespace Kyoo.Controllers Show after = await Get(page.AfterID); object afterObj = sortKey.Compile()(after); query = query.Where(Expression.Lambda>( - Expression.GreaterThan(sortKey, Expression.Constant(afterObj)) + Utility.StringCompatibleExpression(Expression.GreaterThan, sortKey.Body, Expression.Constant(afterObj)), + (ParameterExpression)((MemberExpression)sortKey.Body).Expression )); } query = query.Take(page.Count <= 0 ? 20 : page.Count); diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 3e45db4b..c406472c 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -39,7 +39,7 @@ namespace Kyoo { configuration.RootPath = "wwwroot"; }); - + services.AddControllers().AddNewtonsoftJson(); services.AddHttpClient(); diff --git a/Kyoo/Views/API/ShowsAPI.cs b/Kyoo/Views/API/ShowsAPI.cs index 0ce7fa33..7426f08a 100644 --- a/Kyoo/Views/API/ShowsAPI.cs +++ b/Kyoo/Views/API/ShowsAPI.cs @@ -1,11 +1,8 @@ -using System; -using Kyoo.Models; +using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; using System.Threading.Tasks; -using Castle.DynamicProxy.Generators.Emitters.SimpleAST; using Kyoo.Controllers; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; @@ -43,6 +40,10 @@ namespace Kyoo.Api [FromQuery] int afterID, [FromQuery] Dictionary where) { + where.Remove("sortBy"); + where.Remove("limit"); + where.Remove("afterID"); + return await _libraryManager.GetShows(Utility.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID));