Convert library items to an interface

This commit is contained in:
Zoe Roux 2023-11-18 23:44:40 +01:00
parent c5a2a05af6
commit ca6a4d8ab5
16 changed files with 86 additions and 238 deletions

View File

@ -31,7 +31,7 @@ namespace Kyoo.Abstractions.Controllers
/// <summary> /// <summary>
/// The repository that handle libraries items (a wrapper around shows and collections). /// The repository that handle libraries items (a wrapper around shows and collections).
/// </summary> /// </summary>
IRepository<LibraryItem> LibraryItems { get; } IRepository<ILibraryItem> LibraryItems { get; }
/// <summary> /// <summary>
/// The repository that handle collections. /// The repository that handle collections.

View File

@ -35,10 +35,10 @@ public interface ISearchManager
/// <param name="pagination">How pagination should be done (where to start and how many to return)</param> /// <param name="pagination">How pagination should be done (where to start and how many to return)</param>
/// <param name="include">The related fields to include.</param> /// <param name="include">The related fields to include.</param>
/// <returns>A list of resources that match every filters</returns> /// <returns>A list of resources that match every filters</returns>
public Task<SearchPage<LibraryItem>.SearchResult> SearchItems(string? query, public Task<SearchPage<ILibraryItem>.SearchResult> SearchItems(string? query,
Sort<LibraryItem> sortBy, Sort<ILibraryItem> sortBy,
SearchPagination pagination, SearchPagination pagination,
Include<LibraryItem>? include = default); Include<ILibraryItem>? include = default);
/// <summary> /// <summary>
/// Search for movies. /// Search for movies.

View File

@ -30,138 +30,20 @@ namespace Kyoo.Abstractions.Models
public enum ItemKind public enum ItemKind
{ {
/// <summary> /// <summary>
/// The <see cref="LibraryItem"/> is a <see cref="Show"/>. /// The <see cref="ILibraryItem"/> is a <see cref="Show"/>.
/// </summary> /// </summary>
Show, Show,
/// <summary> /// <summary>
/// The <see cref="LibraryItem"/> is a Movie. /// The <see cref="ILibraryItem"/> is a Movie.
/// </summary> /// </summary>
Movie, Movie,
/// <summary> /// <summary>
/// The <see cref="LibraryItem"/> is a <see cref="Collection"/>. /// The <see cref="ILibraryItem"/> is a <see cref="Collection"/>.
/// </summary> /// </summary>
Collection Collection
} }
public class LibraryItem : IResource, IThumbnails, IMetadata, IAddedDate public interface ILibraryItem : IResource, IThumbnails, IMetadata, IAddedDate { }
{
/// <inheritdoc />
public int Id { get; set; }
/// <inheritdoc />
[MaxLength(256)]
public string Slug { get; set; }
/// <summary>
/// The title of this show.
/// </summary>
public string Name { get; set; }
/// <summary>
/// A catchphrase for this movie.
/// </summary>
public string? Tagline { get; set; }
/// <summary>
/// The list of alternative titles of this show.
/// </summary>
public string[] Aliases { get; set; } = Array.Empty<string>();
/// <summary>
/// The path of the movie video file.
/// </summary>
public string? Path { get; set; }
/// <summary>
/// The summary of this show.
/// </summary>
public string? Overview { get; set; }
/// <summary>
/// A list of tags that match this movie.
/// </summary>
public string[] Tags { get; set; } = Array.Empty<string>();
/// <summary>
/// The list of genres (themes) this show has.
/// </summary>
public Genre[] Genres { get; set; } = Array.Empty<Genre>();
/// <summary>
/// Is this show airing, not aired yet or finished?
/// </summary>
public Status Status { get; set; }
/// <summary>
/// How well this item is rated? (from 0 to 100).
/// </summary>
public int Rating { get; set; }
/// <summary>
/// How long is this movie? (in minutes)
/// </summary>
public int? Runtime { get; set; }
/// <summary>
/// The date this show started airing. It can be null if this is unknown.
/// </summary>
public DateTime? StartAir { get; set; }
/// <summary>
/// The date this show finished airing.
/// It can also be null if this is unknown.
/// </summary>
public DateTime? EndAir { get; set; }
/// <summary>
/// The date this movie aired.
/// </summary>
public DateTime? AirDate { get; set; }
/// <inheritdoc />
public DateTime AddedDate { get; set; }
/// <inheritdoc />
public Image? Poster { get; set; }
/// <inheritdoc />
public Image? Thumbnail { get; set; }
/// <inheritdoc />
public Image? Logo { get; set; }
/// <summary>
/// A video of a few minutes that tease the content.
/// </summary>
public string? Trailer { get; set; }
/// <summary>
/// Is the item a collection, a movie or a show?
/// </summary>
public ItemKind Kind { get; set; }
/// <inheritdoc />
public Dictionary<string, MetadataId> ExternalId { get; set; } = new();
/// <summary>
/// Links to watch this movie.
/// </summary>
public VideoLinks? Links => Kind == ItemKind.Movie ? new()
{
Direct = $"/video/movie/{Slug}/direct",
Hls = $"/video/movie/{Slug}/master.m3u8",
}
: null;
public LibraryItem() { }
[JsonConstructor]
public LibraryItem(string name)
{
Slug = Utility.ToSlug(name);
Name = name;
}
}
} }

View File

@ -28,12 +28,12 @@ namespace Kyoo.Abstractions.Models
public enum NewsKind public enum NewsKind
{ {
/// <summary> /// <summary>
/// The <see cref="LibraryItem"/> is an <see cref="Episode"/>. /// The <see cref="ILibraryItem"/> is an <see cref="Episode"/>.
/// </summary> /// </summary>
Episode, Episode,
/// <summary> /// <summary>
/// The <see cref="LibraryItem"/> is a Movie. /// The <see cref="ILibraryItem"/> is a Movie.
/// </summary> /// </summary>
Movie, Movie,
} }

View File

@ -28,7 +28,7 @@ namespace Kyoo.Abstractions.Models
/// <summary> /// <summary>
/// A class representing collections of <see cref="Show"/>. /// A class representing collections of <see cref="Show"/>.
/// </summary> /// </summary>
public class Collection : IResource, IMetadata, IThumbnails, IAddedDate public class Collection : IResource, IMetadata, IThumbnails, IAddedDate, ILibraryItem
{ {
/// <inheritdoc /> /// <inheritdoc />
public int Id { get; set; } public int Id { get; set; }

View File

@ -28,7 +28,7 @@ namespace Kyoo.Abstractions.Models
/// <summary> /// <summary>
/// A series or a movie. /// A series or a movie.
/// </summary> /// </summary>
public class Movie : IResource, IMetadata, IOnMerge, IThumbnails, IAddedDate public class Movie : IResource, IMetadata, IOnMerge, IThumbnails, IAddedDate, ILibraryItem
{ {
/// <inheritdoc /> /// <inheritdoc />
public int Id { get; set; } public int Id { get; set; }

View File

@ -30,7 +30,7 @@ namespace Kyoo.Abstractions.Models
/// <summary> /// <summary>
/// A series or a movie. /// A series or a movie.
/// </summary> /// </summary>
public class Show : IResource, IMetadata, IOnMerge, IThumbnails, IAddedDate public class Show : IResource, IMetadata, IOnMerge, IThumbnails, IAddedDate, ILibraryItem
{ {
/// <inheritdoc /> /// <inheritdoc />
public int Id { get; set; } public int Id { get; set; }

View File

@ -30,7 +30,7 @@ namespace Kyoo.Core.Controllers
private readonly IBaseRepository[] _repositories; private readonly IBaseRepository[] _repositories;
public LibraryManager( public LibraryManager(
IRepository<LibraryItem> libraryItemRepository, IRepository<ILibraryItem> libraryItemRepository,
IRepository<Collection> collectionRepository, IRepository<Collection> collectionRepository,
IRepository<Movie> movieRepository, IRepository<Movie> movieRepository,
IRepository<Show> showRepository, IRepository<Show> showRepository,
@ -65,7 +65,7 @@ namespace Kyoo.Core.Controllers
} }
/// <inheritdoc /> /// <inheritdoc />
public IRepository<LibraryItem> LibraryItems { get; } public IRepository<ILibraryItem> LibraryItems { get; }
/// <inheritdoc /> /// <inheritdoc />
public IRepository<Collection> Collections { get; } public IRepository<Collection> Collections { get; }

View File

@ -36,13 +36,11 @@ namespace Kyoo.Core.Controllers
/// <summary> /// <summary>
/// A local repository to handle library items. /// A local repository to handle library items.
/// </summary> /// </summary>
public class LibraryItemRepository : IRepository<LibraryItem> public class LibraryItemRepository : IRepository<ILibraryItem>
{ {
private readonly DbConnection _database; private readonly DbConnection _database;
protected Sort<LibraryItem> DefaultSort => new Sort<LibraryItem>.By(x => x.Name); public Type RepositoryType => typeof(ILibraryItem);
public Type RepositoryType => typeof(LibraryItem);
public LibraryItemRepository(DbConnection database) public LibraryItemRepository(DbConnection database)
{ {
@ -50,45 +48,45 @@ namespace Kyoo.Core.Controllers
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual async Task<LibraryItem> Get(int id, Include<LibraryItem>? include = default) public virtual async Task<ILibraryItem> Get(int id, Include<ILibraryItem>? include = default)
{ {
LibraryItem? ret = await GetOrDefault(id, include); ILibraryItem? ret = await GetOrDefault(id, include);
if (ret == null) if (ret == null)
throw new ItemNotFoundException($"No {nameof(LibraryItem)} found with the id {id}"); throw new ItemNotFoundException($"No {nameof(ILibraryItem)} found with the id {id}");
return ret; return ret;
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual async Task<LibraryItem> Get(string slug, Include<LibraryItem>? include = default) public virtual async Task<ILibraryItem> Get(string slug, Include<ILibraryItem>? include = default)
{ {
LibraryItem? ret = await GetOrDefault(slug, include); ILibraryItem? ret = await GetOrDefault(slug, include);
if (ret == null) if (ret == null)
throw new ItemNotFoundException($"No {nameof(LibraryItem)} found with the slug {slug}"); throw new ItemNotFoundException($"No {nameof(ILibraryItem)} found with the slug {slug}");
return ret; return ret;
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual async Task<LibraryItem> Get( public virtual async Task<ILibraryItem> Get(
Expression<Func<LibraryItem, bool>> where, Expression<Func<ILibraryItem, bool>> where,
Include<LibraryItem>? include = default) Include<ILibraryItem>? include = default)
{ {
LibraryItem? ret = await GetOrDefault(where, include: include); ILibraryItem? ret = await GetOrDefault(where, include: include);
if (ret == null) if (ret == null)
throw new ItemNotFoundException($"No {nameof(LibraryItem)} found with the given predicate."); throw new ItemNotFoundException($"No {nameof(ILibraryItem)} found with the given predicate.");
return ret; return ret;
} }
public Task<LibraryItem?> GetOrDefault(int id, Include<LibraryItem>? include = null) public Task<ILibraryItem?> GetOrDefault(int id, Include<ILibraryItem>? include = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<LibraryItem?> GetOrDefault(string slug, Include<LibraryItem>? include = null) public Task<ILibraryItem?> GetOrDefault(string slug, Include<ILibraryItem>? include = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<LibraryItem?> GetOrDefault(Expression<Func<LibraryItem, bool>> where, Include<LibraryItem>? include = null, Sort<LibraryItem>? sortBy = null) public Task<ILibraryItem?> GetOrDefault(Expression<Func<ILibraryItem, bool>> where, Include<ILibraryItem>? include = null, Sort<ILibraryItem>? sortBy = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -106,11 +104,11 @@ namespace Kyoo.Core.Controllers
}; };
} }
public async Task<ICollection<LibraryItem>> GetAll( public async Task<ICollection<ILibraryItem>> GetAll(
Expression<Func<LibraryItem, bool>>? where = null, Expression<Func<ILibraryItem, bool>>? where = null,
Sort<LibraryItem>? sort = null, Sort<ILibraryItem>? sort = null,
Pagination? limit = null, Pagination? limit = null,
Include<LibraryItem>? include = null) Include<ILibraryItem>? include = null)
{ {
// language=PostgreSQL // language=PostgreSQL
IDapperSqlCommand query = _database.SqlBuilder($""" IDapperSqlCommand query = _database.SqlBuilder($"""
@ -136,7 +134,8 @@ namespace Kyoo.Core.Controllers
limit {limit.Limit} limit {limit.Limit}
""").Build(); """).Build();
var data = await query.QueryAsync<IResource>(new[] { typeof(Show), typeof(Movie), typeof(Collection), typeof(Studio) }, items => Type[] types = new[] { typeof(Show), typeof(Movie), typeof(Collection), typeof(Studio) };
IEnumerable<ILibraryItem> data = await query.QueryAsync<ILibraryItem>(types, items =>
{ {
var studio = items[3] as Studio; var studio = items[3] as Studio;
if (items[0] is Show show && show.Id != 0) if (items[0] is Show show && show.Id != 0)
@ -147,44 +146,26 @@ namespace Kyoo.Core.Controllers
return collection; return collection;
throw new InvalidDataException(); throw new InvalidDataException();
}); });
return data.ToList();
// await using DbDataReader reader = await _database.ExecuteReaderAsync(sql);
// int kindOrdinal = reader.GetOrdinal("kind");
// var showParser = reader.GetRowParser<IResource>(typeof(Show));
// var movieParser = reader.GetRowParser<IResource>(typeof(Movie));
// var collectionParser = reader.GetRowParser<IResource>(typeof(Collection));
//
// while (await reader.ReadAsync())
// {
// ItemKind type = await reader.GetFieldValueAsync<ItemKind>(kindOrdinal);
// ret.Add(type switch
// {
// ItemKind.Show => showParser(reader),
// ItemKind.Movie => movieParser(reader),
// ItemKind.Collection => collectionParser(reader),
// _ => throw new InvalidDataException(),
// });
// }
throw new NotImplementedException();
// return ret;
} }
public Task<int> GetCount(Expression<Func<LibraryItem, bool>>? where = null) public Task<int> GetCount(Expression<Func<ILibraryItem, bool>>? where = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<ICollection<LibraryItem>> FromIds(IList<int> ids, Include<LibraryItem>? include = null) public Task<ICollection<ILibraryItem>> FromIds(IList<int> ids, Include<ILibraryItem>? include = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task DeleteAll(Expression<Func<LibraryItem, bool>> where) public Task DeleteAll(Expression<Func<ILibraryItem, bool>> where)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<ICollection<LibraryItem>> Search(string query, Include<LibraryItem>? include = default) public async Task<ICollection<ILibraryItem>> Search(string query, Include<ILibraryItem>? include = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
// return await Sort( // return await Sort(
@ -195,12 +176,12 @@ namespace Kyoo.Core.Controllers
// .ToListAsync(); // .ToListAsync();
} }
public async Task<ICollection<LibraryItem>> GetAllOfCollection( public async Task<ICollection<ILibraryItem>> GetAllOfCollection(
Expression<Func<Collection, bool>> selector, Expression<Func<Collection, bool>> selector,
Expression<Func<LibraryItem, bool>>? where = null, Expression<Func<ILibraryItem, bool>>? where = null,
Sort<LibraryItem>? sort = default, Sort<ILibraryItem>? sort = default,
Pagination? limit = default, Pagination? limit = default,
Include<LibraryItem>? include = default) Include<ILibraryItem>? include = default)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
// return await ApplyFilters( // return await ApplyFilters(
@ -220,19 +201,19 @@ namespace Kyoo.Core.Controllers
} }
/// <inheritdoc /> /// <inheritdoc />
public Task<LibraryItem> Create(LibraryItem obj) public Task<ILibraryItem> Create(ILibraryItem obj)
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />
public Task<LibraryItem> CreateIfNotExists(LibraryItem obj) public Task<ILibraryItem> CreateIfNotExists(ILibraryItem obj)
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />
public Task<LibraryItem> Edit(LibraryItem edited) public Task<ILibraryItem> Edit(ILibraryItem edited)
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />
public Task<LibraryItem> Patch(int id, Func<LibraryItem, Task<bool>> patch) public Task<ILibraryItem> Patch(int id, Func<ILibraryItem, Task<bool>> patch)
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />
@ -244,7 +225,7 @@ namespace Kyoo.Core.Controllers
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
/// <inheritdoc /> /// <inheritdoc />
public Task Delete(LibraryItem obj) public Task Delete(ILibraryItem obj)
=> throw new InvalidOperationException(); => throw new InvalidOperationException();
} }
} }

View File

@ -119,7 +119,6 @@ namespace Kyoo.Core.Controllers
{ {
string directory = item switch string directory = item switch
{ {
LibraryItem litem => Path.Combine("./metadata", litem.Kind.ToString().ToLowerInvariant(), litem.Slug),
IResource res => Path.Combine("./metadata", item.GetType().Name.ToLowerInvariant(), res.Slug), IResource res => Path.Combine("./metadata", item.GetType().Name.ToLowerInvariant(), res.Slug),
_ => Path.Combine("./metadata", typeof(T).Name.ToLowerInvariant()) _ => Path.Combine("./metadata", typeof(T).Name.ToLowerInvariant())
}; };

View File

@ -138,16 +138,16 @@ namespace Kyoo.Core.Api
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<Page<LibraryItem>>> GetItems(Identifier identifier, public async Task<ActionResult<Page<ILibraryItem>>> GetItems(Identifier identifier,
[FromQuery] Sort<LibraryItem> sortBy, [FromQuery] Sort<ILibraryItem> sortBy,
[FromQuery] Dictionary<string, string> where, [FromQuery] Dictionary<string, string> where,
[FromQuery] Pagination pagination, [FromQuery] Pagination pagination,
[FromQuery] Include<LibraryItem>? fields) [FromQuery] Include<ILibraryItem>? fields)
{ {
ICollection<LibraryItem> resources = await _items.GetAllOfCollection( ICollection<ILibraryItem> resources = await _items.GetAllOfCollection(
identifier.IsSame<Collection>(), identifier.IsSame<Collection>(),
ApiHelper.ParseWhere<LibraryItem>(where), ApiHelper.ParseWhere<ILibraryItem>(where),
sortBy == new Sort<LibraryItem>.Default() ? new Sort<LibraryItem>.By(x => x.AirDate) : sortBy, sortBy == new Sort<ILibraryItem>.Default() ? new Sort<ILibraryItem>.By(nameof(Movie.AirDate)) : sortBy,
pagination, pagination,
fields fields
); );

View File

@ -35,12 +35,12 @@ namespace Kyoo.Core.Api
[ResourceView] [ResourceView]
[PartialPermission("LibraryItem")] [PartialPermission("LibraryItem")]
[ApiDefinition("Items", Group = ResourcesGroup)] [ApiDefinition("Items", Group = ResourcesGroup)]
public class LibraryItemApi : CrudThumbsApi<LibraryItem> public class LibraryItemApi : CrudThumbsApi<ILibraryItem>
{ {
/// <summary> /// <summary>
/// The library item repository used to modify or retrieve information in the data store. /// The library item repository used to modify or retrieve information in the data store.
/// </summary> /// </summary>
private readonly IRepository<LibraryItem> _libraryItems; private readonly IRepository<ILibraryItem> _libraryItems;
/// <summary> /// <summary>
/// Create a new <see cref="LibraryItemApi"/>. /// Create a new <see cref="LibraryItemApi"/>.
@ -49,7 +49,7 @@ namespace Kyoo.Core.Api
/// The library item repository used to modify or retrieve information in the data store. /// The library item repository used to modify or retrieve information in the data store.
/// </param> /// </param>
/// <param name="thumbs">Thumbnail manager to retrieve images.</param> /// <param name="thumbs">Thumbnail manager to retrieve images.</param>
public LibraryItemApi(IRepository<LibraryItem> libraryItems, IThumbnailsManager thumbs) public LibraryItemApi(IRepository<ILibraryItem> libraryItems, IThumbnailsManager thumbs)
: base(libraryItems, thumbs) : base(libraryItems, thumbs)
{ {
_libraryItems = libraryItems; _libraryItems = libraryItems;

View File

@ -135,14 +135,14 @@ namespace Kyoo.Core.Api
/// <returns>A list of items found for the specified query.</returns> /// <returns>A list of items found for the specified query.</returns>
[HttpGet("items")] [HttpGet("items")]
[HttpGet("item", Order = AlternativeRoute)] [HttpGet("item", Order = AlternativeRoute)]
[Permission(nameof(LibraryItem), Kind.Read)] [Permission(nameof(ILibraryItem), Kind.Read)]
[ApiDefinition("Item")] [ApiDefinition("Item")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public async Task<SearchPage<LibraryItem>> SearchItems( public async Task<SearchPage<ILibraryItem>> SearchItems(
[FromQuery] string? q, [FromQuery] string? q,
[FromQuery] Sort<LibraryItem> sortBy, [FromQuery] Sort<ILibraryItem> sortBy,
[FromQuery] SearchPagination pagination, [FromQuery] SearchPagination pagination,
[FromQuery] Include<LibraryItem> fields) [FromQuery] Include<ILibraryItem> fields)
{ {
return SearchPage(await _searchManager.SearchItems(q, sortBy, pagination, fields)); return SearchPage(await _searchManager.SearchItems(q, sortBy, pagination, fields));
} }

View File

@ -41,32 +41,32 @@ namespace Kyoo.Meiliseach
{ {
SearchableAttributes = new[] SearchableAttributes = new[]
{ {
CamelCase.ConvertName(nameof(LibraryItem.Name)), CamelCase.ConvertName(nameof(Movie.Name)),
CamelCase.ConvertName(nameof(LibraryItem.Slug)), CamelCase.ConvertName(nameof(Movie.Slug)),
CamelCase.ConvertName(nameof(LibraryItem.Aliases)), CamelCase.ConvertName(nameof(Movie.Aliases)),
CamelCase.ConvertName(nameof(LibraryItem.Path)), CamelCase.ConvertName(nameof(Movie.Path)),
CamelCase.ConvertName(nameof(LibraryItem.Tags)), CamelCase.ConvertName(nameof(Movie.Tags)),
CamelCase.ConvertName(nameof(LibraryItem.Overview)), CamelCase.ConvertName(nameof(Movie.Overview)),
}, },
FilterableAttributes = new[] FilterableAttributes = new[]
{ {
CamelCase.ConvertName(nameof(LibraryItem.Genres)), CamelCase.ConvertName(nameof(Movie.Genres)),
CamelCase.ConvertName(nameof(LibraryItem.Status)), CamelCase.ConvertName(nameof(Movie.Status)),
CamelCase.ConvertName(nameof(LibraryItem.AirDate)), CamelCase.ConvertName(nameof(Movie.AirDate)),
CamelCase.ConvertName(nameof(Movie.StudioId)), CamelCase.ConvertName(nameof(Movie.StudioId)),
CamelCase.ConvertName(nameof(LibraryItem.Kind)), "kind"
}, },
SortableAttributes = new[] SortableAttributes = new[]
{ {
CamelCase.ConvertName(nameof(LibraryItem.AirDate)), CamelCase.ConvertName(nameof(Movie.AirDate)),
CamelCase.ConvertName(nameof(LibraryItem.AddedDate)), CamelCase.ConvertName(nameof(Movie.AddedDate)),
CamelCase.ConvertName(nameof(LibraryItem.Rating)), CamelCase.ConvertName(nameof(Movie.Rating)),
CamelCase.ConvertName(nameof(LibraryItem.Runtime)), CamelCase.ConvertName(nameof(Movie.Runtime)),
}, },
DisplayedAttributes = new[] DisplayedAttributes = new[]
{ {
CamelCase.ConvertName(nameof(LibraryItem.Id)), CamelCase.ConvertName(nameof(Movie.Id)),
CamelCase.ConvertName(nameof(LibraryItem.Kind)), "kind"
}, },
RankingRules = new[] RankingRules = new[]
{ {
@ -76,10 +76,9 @@ namespace Kyoo.Meiliseach
"attribute", "attribute",
"sort", "sort",
"exactness", "exactness",
$"{CamelCase.ConvertName(nameof(LibraryItem.Rating))}:desc", $"{CamelCase.ConvertName(nameof(Movie.Rating))}:desc",
} }
// TODO: Add stopwords // TODO: Add stopwords
// TODO: Extend default ranking to add ratings.
} }
}, },
{ {

View File

@ -73,10 +73,10 @@ public class SearchManager : ISearchManager
}; };
} }
public async Task<SearchPage<LibraryItem>.SearchResult> SearchItems(string? query, public async Task<SearchPage<ILibraryItem>.SearchResult> SearchItems(string? query,
Sort<LibraryItem> sortBy, Sort<ILibraryItem> sortBy,
SearchPagination pagination, SearchPagination pagination,
Include<LibraryItem>? include = default) Include<ILibraryItem>? include = default)
{ {
// TODO: add filters and facets // TODO: add filters and facets
ISearchable<IdResource> res = await _client.Index("items").SearchAsync<IdResource>(query, new SearchQuery() ISearchable<IdResource> res = await _client.Index("items").SearchAsync<IdResource>(query, new SearchQuery()
@ -96,7 +96,7 @@ public class SearchManager : ISearchManager
_ => throw new InvalidOperationException("An unknown item kind was found in meilisearch"), _ => throw new InvalidOperationException("An unknown item kind was found in meilisearch"),
}).ToList(); }).ToList();
return new SearchPage<LibraryItem>.SearchResult return new SearchPage<ILibraryItem>.SearchResult
{ {
Query = query, Query = query,
Items = await _libraryManager.LibraryItems Items = await _libraryManager.LibraryItems

View File

@ -92,14 +92,6 @@ namespace Kyoo.Postgresql
/// </summary> /// </summary>
public DbSet<PeopleRole> PeopleRoles { get; set; } public DbSet<PeopleRole> PeopleRoles { get; set; }
/// <summary>
/// The list of library items (shows and collections that are part of a library - or the global one).
/// </summary>
/// <remarks>
/// This set is ready only, on most database this will be a view.
/// </remarks>
public DbSet<LibraryItem> LibraryItems { get; set; }
/// <summary> /// <summary>
/// The list of new items (episodes and movies). /// The list of new items (episodes and movies).
/// </summary> /// </summary>
@ -291,7 +283,6 @@ namespace Kyoo.Postgresql
.WithMany("Users") .WithMany("Users")
.UsingEntity(x => x.ToTable(LinkName<User, Show>())); .UsingEntity(x => x.ToTable(LinkName<User, Show>()));
_HasMetadata<LibraryItem>(modelBuilder);
_HasMetadata<News>(modelBuilder); _HasMetadata<News>(modelBuilder);
_HasMetadata<Collection>(modelBuilder); _HasMetadata<Collection>(modelBuilder);
_HasMetadata<Movie>(modelBuilder); _HasMetadata<Movie>(modelBuilder);
@ -301,7 +292,6 @@ namespace Kyoo.Postgresql
_HasMetadata<People>(modelBuilder); _HasMetadata<People>(modelBuilder);
_HasMetadata<Studio>(modelBuilder); _HasMetadata<Studio>(modelBuilder);
_HasImages<LibraryItem>(modelBuilder);
_HasImages<News>(modelBuilder); _HasImages<News>(modelBuilder);
_HasImages<Collection>(modelBuilder); _HasImages<Collection>(modelBuilder);
_HasImages<Movie>(modelBuilder); _HasImages<Movie>(modelBuilder);
@ -310,7 +300,6 @@ namespace Kyoo.Postgresql
_HasImages<Episode>(modelBuilder); _HasImages<Episode>(modelBuilder);
_HasImages<People>(modelBuilder); _HasImages<People>(modelBuilder);
_HasAddedDate<LibraryItem>(modelBuilder);
_HasAddedDate<News>(modelBuilder); _HasAddedDate<News>(modelBuilder);
_HasAddedDate<Collection>(modelBuilder); _HasAddedDate<Collection>(modelBuilder);
_HasAddedDate<Movie>(modelBuilder); _HasAddedDate<Movie>(modelBuilder);
@ -357,8 +346,6 @@ namespace Kyoo.Postgresql
modelBuilder.Entity<Movie>() modelBuilder.Entity<Movie>()
.Ignore(x => x.Links); .Ignore(x => x.Links);
modelBuilder.Entity<LibraryItem>()
.Ignore(x => x.Links);
modelBuilder.Entity<News>() modelBuilder.Entity<News>()
.Ignore(x => x.Links); .Ignore(x => x.Links);