Reworking the whole watch api and creating a /count endpoint for crud items

This commit is contained in:
Zoe Roux 2020-10-10 02:33:34 +02:00
parent 423c0cd658
commit cdf5acbbe9
9 changed files with 146 additions and 50 deletions

View File

@ -190,7 +190,18 @@ namespace Kyoo.Controllers
Pagination limit = default
) => GetProviders(where, new Sort<ProviderID>(sort), limit);
// Counts
Task<int> GetLibrariesCount(Expression<Func<Library, bool>> where = null);
Task<int> GetCollectionsCount(Expression<Func<Collection, bool>> where = null);
Task<int> GetShowsCount(Expression<Func<Show, bool>> where = null);
Task<int> GetSeasonsCount(Expression<Func<Season, bool>> where = null);
Task<int> GetEpisodesCount(Expression<Func<Episode, bool>> where = null);
Task<int> GetTracksCount(Expression<Func<Track, bool>> where = null);
Task<int> GetGenresCount(Expression<Func<Genre, bool>> where = null);
Task<int> GetStudiosCount(Expression<Func<Studio, bool>> where = null);
Task<int> GetPeopleCount(Expression<Func<People, bool>> where = null);
// Search
Task<ICollection<Library>> SearchLibraries(string searchQuery);
Task<ICollection<Collection>> SearchCollections(string searchQuery);

View File

@ -90,6 +90,9 @@ namespace Kyoo.Controllers
Expression<Func<T, object>> sort,
Pagination limit = default
) => GetAll(where, new Sort<T>(sort), limit);
Task<int> GetCount(Expression<Func<T, bool>> where = null);
Task<T> Create([NotNull] T obj);
Task<T> CreateIfNotExists([NotNull] T obj);

View File

@ -338,6 +338,51 @@ namespace Kyoo.Controllers
return PeopleRepository.GetFromPeople(slug, where, sort, limit);
}
public Task<int> GetLibrariesCount(Expression<Func<Library, bool>> where = null)
{
return LibraryRepository.GetCount(where);
}
public Task<int> GetCollectionsCount(Expression<Func<Collection, bool>> where = null)
{
return CollectionRepository.GetCount(where);
}
public Task<int> GetShowsCount(Expression<Func<Show, bool>> where = null)
{
return ShowRepository.GetCount(where);
}
public Task<int> GetSeasonsCount(Expression<Func<Season, bool>> where = null)
{
return SeasonRepository.GetCount(where);
}
public Task<int> GetEpisodesCount(Expression<Func<Episode, bool>> where = null)
{
return EpisodeRepository.GetCount(where);
}
public Task<int> GetTracksCount(Expression<Func<Track, bool>> where = null)
{
return TrackRepository.GetCount(where);
}
public Task<int> GetGenresCount(Expression<Func<Genre, bool>> where = null)
{
return GenreRepository.GetCount(where);
}
public Task<int> GetStudiosCount(Expression<Func<Studio, bool>> where = null)
{
return StudioRepository.GetCount(where);
}
public Task<int> GetPeopleCount(Expression<Func<People, bool>> where = null)
{
return PeopleRepository.GetCount(where);
}
public Task AddShowLink(int showID, int? libraryID, int? collectionID)
{
return ShowRepository.AddShowLink(showID, libraryID, collectionID);

View File

@ -1,7 +1,8 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Kyoo.Controllers;
using Kyoo.Models.Watch;
namespace Kyoo.Models
@ -59,53 +60,55 @@ namespace Kyoo.Models
string title,
DateTime? releaseDate,
string path,
Track video,
IEnumerable<Track> audios,
IEnumerable<Track> subtitles,
Track video)
IEnumerable<Track> subtitles)
: this(episodeID, showTitle, showSlug, seasonNumber, episodeNumber, title, releaseDate, path)
{
Video = video;
Audios = audios;
Subtitles = subtitles;
Video = video;
}
public WatchItem(Episode episode)
: this(episode.ID,
episode.Show.Title,
episode.Show.Slug,
episode.SeasonNumber,
episode.EpisodeNumber,
episode.Title,
episode.ReleaseDate,
episode.Path,
episode.Tracks.Where(x => x.Type == StreamType.Audio),
episode.Tracks.Where(x => x.Type == StreamType.Subtitle),
episode.Tracks.FirstOrDefault(x => x.Type == StreamType.Video))
public static async Task<WatchItem> FromEpisode(Episode ep, ILibraryManager library)
{
if (episode.Show.IsMovie)
{
IsMovie = true;
return;
}
Show show = await library.GetShow(ep.ShowID); // TODO load only the title, the slug & the IsMovie with the library manager.
Episode previous = null;
Episode next = null;
if (EpisodeNumber > 1)
PreviousEpisode = episode.Season.Episodes.FirstOrDefault(x => x.EpisodeNumber == EpisodeNumber - 1);
else if (SeasonNumber > 1)
if (!show.IsMovie)
{
Season previousSeason = episode.Show.Seasons
.FirstOrDefault(x => x.SeasonNumber == SeasonNumber - 1);
PreviousEpisode = previousSeason?.Episodes
.FirstOrDefault(x => x.EpisodeNumber == previousSeason.Episodes.Count());
}
if (ep.EpisodeNumber > 1)
previous = await library.GetEpisode(ep.ShowID, ep.SeasonNumber, ep.EpisodeNumber - 1);
else if (ep.SeasonNumber > 1)
{
int count = await library.GetEpisodesCount(x => x.ShowID == ep.ShowID
&& x.SeasonNumber == ep.SeasonNumber - 1);
previous = await library.GetEpisode(ep.ShowID, ep.SeasonNumber - 1, count);
}
if (EpisodeNumber >= episode.Season.Episodes.Count())
{
NextEpisode = episode.Show.Seasons
.FirstOrDefault(x => x.SeasonNumber == SeasonNumber + 1)?.Episodes
.FirstOrDefault(x => x.EpisodeNumber == 1);
if (ep.EpisodeNumber >= await library.GetEpisodesCount(x => x.SeasonID == ep.SeasonID))
next = await library.GetEpisode(ep.ShowID, ep.SeasonNumber + 1, 1);
else
next = await library.GetEpisode(ep.ShowID, ep.SeasonNumber, ep.EpisodeNumber + 1);
}
else
NextEpisode = episode.Season.Episodes.FirstOrDefault(x => x.EpisodeNumber == EpisodeNumber + 1);
return new WatchItem(ep.ID,
show.Title,
show.Slug,
ep.SeasonNumber,
ep.EpisodeNumber,
ep.Title,
ep.ReleaseDate,
ep.Path,
await library.GetTrack(x => x.EpisodeID == ep.ID && x.Type == StreamType.Video),
await library.GetTracks(x => x.EpisodeID == ep.ID && x.Type == StreamType.Audio),
await library.GetTracks(x => x.EpisodeID == ep.ID && x.Type == StreamType.Subtitle))
{
IsMovie = show.IsMovie,
PreviousEpisode = previous,
NextEpisode = next
};
}
}
}

View File

@ -47,6 +47,20 @@ namespace Kyoo.CommonApi
return resource;
}
[HttpGet("count")]
[Authorize(Policy = "Read")]
public virtual async Task<ActionResult<int>> GetCount([FromQuery] Dictionary<string, string> where)
{
try
{
return await _repository.GetCount(ApiHelper.ParseWhere<T>(where));
}
catch (ArgumentException ex)
{
return BadRequest(new {Error = ex.Message});
}
}
[HttpGet]
[Authorize(Policy = "Read")]
public virtual async Task<ActionResult<Page<T>>> GetAll([FromQuery] string sortBy,

View File

@ -101,6 +101,14 @@ namespace Kyoo.Controllers
return await query.ToListAsync();
}
public virtual Task<int> GetCount(Expression<Func<T, bool>> where = null)
{
IQueryable<T> query = Database.Set<T>();
if (where != null)
query = query.Where(where);
return query.CountAsync();
}
public virtual async Task<T> Create([NotNull] T obj)
{
if (obj == null)
@ -258,6 +266,14 @@ namespace Kyoo.Controllers
return items.ToList<T>();
}
public virtual Task<int> GetCount(Expression<Func<T, bool>> where = null)
{
IQueryable<TInternal> query = Database.Set<TInternal>();
if (where != null)
query = query.Where(where.Convert<Func<TInternal, bool>>());
return query.CountAsync();
}
Task<T> IRepository<T>.Create(T item)
{

View File

@ -83,6 +83,14 @@ namespace Kyoo.Controllers
return ApplyFilters(ItemsQuery, where, sort, limit);
}
public override Task<int> GetCount(Expression<Func<LibraryItem, bool>> where = null)
{
IQueryable<LibraryItem> query = ItemsQuery;
if (where != null)
query = query.Where(where);
return query.CountAsync();
}
public async Task<ICollection<LibraryItem>> Search(string query)
{
return await ItemsQuery

View File

@ -6,7 +6,6 @@ using Kyoo.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Kyoo.CommonApi;
using Kyoo.Models.Exceptions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;

View File

@ -6,38 +6,35 @@ using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Api
{
[Route("api/[controller]")]
[Route("api/watch")]
[ApiController]
public class WatchController : ControllerBase
public class WatchApi : ControllerBase
{
private readonly ILibraryManager _libraryManager;
public WatchController(ILibraryManager libraryManager)
public WatchApi(ILibraryManager libraryManager)
{
_libraryManager = libraryManager;
}
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
[Authorize(Policy="Read")]
public async Task<ActionResult<WatchItem>> Index(string showSlug, int seasonNumber, int episodeNumber)
public async Task<ActionResult<WatchItem>> GetWatchItem(string showSlug, int seasonNumber, int episodeNumber)
{
Episode item = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
if(item == null)
if (item == null)
return NotFound();
return new WatchItem(item);
return await WatchItem.FromEpisode(item, _libraryManager);
}
[HttpGet("{movieSlug}")]
[Authorize(Policy="Read")]
public async Task<ActionResult<WatchItem>> Index(string movieSlug)
public async Task<ActionResult<WatchItem>> GetWatchItem(string movieSlug)
{
Episode item = await _libraryManager.GetMovieEpisode(movieSlug);
if(item == null)
if (item == null)
return NotFound();
return new WatchItem(item);
return await WatchItem.FromEpisode(item, _libraryManager);
}
}
}