Adding episodes related info & NotFound exceptions

This commit is contained in:
Zoe Roux 2020-07-24 02:47:31 +02:00
parent 00ed7a4863
commit 59e72b6dca
9 changed files with 328 additions and 47 deletions

View File

@ -55,11 +55,61 @@ namespace Kyoo.Controllers
Pagination limit = default
) => GetSeasons(showSlug, where, new Sort<Season>(sort), limit);
Task<ICollection<Episode>> GetEpisodes(int showID, int seasonNumber);
Task<ICollection<Episode>> GetEpisodes(string showSlug, int seasonNumber);
Task<ICollection<Episode>> GetEpisodes(int seasonID);
Task<ICollection<Episode>> GetEpisodes(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(int showID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showSlug, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(seasonID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
int seasonNumber,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showID, seasonNumber, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
int seasonNumber,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showSlug, seasonNumber, where, new Sort<Episode>(sort), limit);
// Helpers
Task AddShowLink(int showID, int? libraryID, int? collectionID);
Task AddShowLink([NotNull] Show show, Library library, Collection collection);

View File

@ -106,6 +106,7 @@ namespace Kyoo.Controllers
public interface ISeasonRepository : IRepository<Season>
{
Task<Season> Get(int showID, int seasonNumber);
Task<Season> Get(string showSlug, int seasonNumber);
Task Delete(string showSlug, int seasonNumber);
@ -128,7 +129,6 @@ namespace Kyoo.Controllers
Expression<Func<Season, object>> sort,
Pagination limit = default
) => GetSeasons(showSlug, where, new Sort<Season>(sort), limit);
}
public interface IEpisodeRepository : IRepository<Episode>
@ -136,9 +136,57 @@ namespace Kyoo.Controllers
Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber);
Task Delete(string showSlug, int seasonNumber, int episodeNumber);
Task<ICollection<Episode>> GetEpisodes(int showID, int seasonNumber);
Task<ICollection<Episode>> GetEpisodes(string showSlug, int seasonNumber);
Task<ICollection<Episode>> GetEpisodes(int seasonID);
Task<ICollection<Episode>> GetEpisodes(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(int showID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showSlug, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(seasonID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
int seasonNumber,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showID, seasonNumber, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
int seasonNumber,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showSlug, seasonNumber, where, new Sort<Episode>(sort), limit);
}
public interface ITrackRepository : IRepository<Track>

View File

@ -213,21 +213,48 @@ namespace Kyoo.Controllers
return SeasonRepository.GetSeasons(showSlug, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodes(int showID, int seasonNumber)
public Task<ICollection<Episode>> GetEpisodes(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodes(showID, seasonNumber);
}
public Task<ICollection<Episode>> GetEpisodes(string showSlug, int seasonNumber)
{
return EpisodeRepository.GetEpisodes(showSlug, seasonNumber);
}
public Task<ICollection<Episode>> GetEpisodes(int seasonID)
{
return EpisodeRepository.GetEpisodes(seasonID);
return EpisodeRepository.GetEpisodes(showID, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodes(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodes(showSlug, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodesFromSeason(seasonID, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodesFromSeason(showID, seasonNumber, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodesFromSeason(showSlug, seasonNumber, where, sort, limit);
}
public Task AddShowLink(int showID, int? libraryID, int? collectionID)
{
return ShowRepository.AddShowLink(showID, libraryID, collectionID);

View File

@ -6,6 +6,8 @@ namespace Kyoo.Models.Exceptions
{
public override string Message { get; }
public ItemNotFound() {}
public ItemNotFound(string message)
{
Message = message;

View File

@ -14,13 +14,21 @@ namespace Kyoo.Controllers
{
private readonly DatabaseContext _database;
private readonly IProviderRepository _providers;
private readonly IShowRepository _shows;
private readonly ISeasonRepository _seasons;
protected override Expression<Func<Episode, object>> DefaultSort => x => x.EpisodeNumber;
public EpisodeRepository(DatabaseContext database, IProviderRepository providers) : base(database)
public EpisodeRepository(DatabaseContext database,
IProviderRepository providers,
IShowRepository shows,
ISeasonRepository seasons)
: base(database)
{
_database = database;
_providers = providers;
_shows = shows;
_seasons = seasons;
}
@ -105,23 +113,80 @@ namespace Kyoo.Controllers
}
}
public async Task<ICollection<Episode>> GetEpisodes(int showID, int seasonNumber)
public async Task<ICollection<Episode>> GetEpisodes(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return await _database.Episodes.Where(x => x.ShowID == showID
&& x.SeasonNumber == seasonNumber).ToListAsync();
}
public async Task<ICollection<Episode>> GetEpisodes(string showSlug, int seasonNumber)
{
return await _database.Episodes.Where(x => x.Show.Slug == showSlug
&& x.SeasonNumber == seasonNumber).ToListAsync();
}
public async Task<ICollection<Episode>> GetEpisodes(int seasonID)
{
return await _database.Episodes.Where(x => x.SeasonID == seasonID).ToListAsync();
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.ShowID == showID),
where,
sort,
limit);
if (!episodes.Any() && await _shows.Get(showID) == null)
throw new ItemNotFound();
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodes(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.Show.Slug == showSlug),
where,
sort,
limit);
if (!episodes.Any() && await _shows.Get(showSlug) == null)
throw new ItemNotFound();
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.SeasonID == seasonID),
where,
sort,
limit);
if (!episodes.Any() && await _seasons.Get(seasonID) == null)
throw new ItemNotFound();
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.ShowID == showID
&& x.SeasonNumber == seasonNumber),
where,
sort,
limit);
if (!episodes.Any() && await _seasons.Get(showID, seasonNumber) == null)
throw new ItemNotFound();
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.Show.Slug == showSlug
&& x.SeasonNumber == seasonNumber),
where,
sort,
limit);
if (!episodes.Any() && await _seasons.Get(showSlug, seasonNumber) == null)
throw new ItemNotFound();
return episodes;
}
public async Task Delete(string showSlug, int seasonNumber, int episodeNumber)
{
Episode obj = await Get(showSlug, seasonNumber, episodeNumber);

View File

@ -15,15 +15,20 @@ namespace Kyoo.Controllers
private readonly DatabaseContext _database;
private readonly IProviderRepository _providers;
private readonly IEpisodeRepository _episodes;
private readonly IShowRepository _shows;
protected override Expression<Func<Season, object>> DefaultSort => x => x.SeasonNumber;
public SeasonRepository(DatabaseContext database, IProviderRepository providers, IEpisodeRepository episodes)
public SeasonRepository(DatabaseContext database,
IProviderRepository providers,
IEpisodeRepository episodes,
IShowRepository shows)
: base(database)
{
_database = database;
_providers = providers;
_episodes = episodes;
_shows = shows;
}
@ -50,6 +55,12 @@ namespace Kyoo.Controllers
return Get(match.Groups["show"].Value, int.Parse(match.Groups["season"].Value));
}
public Task<Season> Get(int showID, int seasonNumber)
{
return _database.Seasons.FirstOrDefaultAsync(x => x.ShowID == showID
&& x.SeasonNumber == seasonNumber);
}
public Task<Season> Get(string showSlug, int seasonNumber)
{
return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
@ -102,26 +113,32 @@ namespace Kyoo.Controllers
}
}
public Task<ICollection<Season>> GetSeasons(int showID,
public async Task<ICollection<Season>> GetSeasons(int showID,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default)
{
return ApplyFilters(_database.Seasons.Where(x => x.ShowID == showID),
ICollection<Season> seasons = await ApplyFilters(_database.Seasons.Where(x => x.ShowID == showID),
where,
sort,
limit);
if (!seasons.Any() && await _shows.Get(showID) == null)
throw new ItemNotFound();
return seasons;
}
public Task<ICollection<Season>> GetSeasons(string showSlug,
public async Task<ICollection<Season>> GetSeasons(string showSlug,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default)
{
return ApplyFilters(_database.Seasons.Where(x => x.Show.Slug == showSlug),
ICollection<Season> seasons = await ApplyFilters(_database.Seasons.Where(x => x.Show.Slug == showSlug),
where,
sort,
limit);
if (!seasons.Any() && await _shows.Get(showSlug) == null)
throw new ItemNotFound();
return seasons;
}
public async Task Delete(string showSlug, int seasonNumber)

View File

@ -171,6 +171,7 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
// TODO fix circular references of Show/Season/Episode Repository.
if (obj.Seasons != null)
await _seasons.DeleteRange(obj.Seasons);

View File

@ -1,4 +1,5 @@
using Kyoo.Models;
using System;
using Kyoo.Models;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
@ -21,14 +22,9 @@ namespace Kyoo.Api
[HttpGet("{showSlug}/season/{seasonNumber}")]
[Authorize(Policy="Read")]
public async Task<ActionResult<IEnumerable<Episode>>> GetEpisodesForSeason(string showSlug, int seasonNumber)
public Task<ActionResult<IEnumerable<Episode>>> GetEpisodesForSeason(string showSlug, int seasonNumber)
{
IEnumerable<Episode> episodes = await _libraryManager.GetEpisodes(showSlug, seasonNumber);
if(episodes == null)
return NotFound();
return episodes.ToList();
throw new NotImplementedException();
}
[HttpGet("{showSlug}/season/{seasonNumber}/episode/{episodeNumber}")]

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Kyoo.CommonApi;
using Kyoo.Controllers;
using Kyoo.Models.Exceptions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
@ -47,6 +48,10 @@ namespace Kyoo.Api
return Page(ressources, limit);
}
catch (ItemNotFound)
{
return NotFound();
}
catch (ArgumentException ex)
{
return BadRequest(new {Error = ex.Message});
@ -76,6 +81,76 @@ namespace Kyoo.Api
return Page(ressources, limit);
}
catch (ItemNotFound)
{
return NotFound();
}
catch (ArgumentException ex)
{
return BadRequest(new {Error = ex.Message});
}
}
[HttpGet("{showID:int}/episode")]
[HttpGet("{showID:int}/episodes")]
[Authorize(Policy = "Read")]
public async Task<ActionResult<Page<Episode>>> GetEpisodes(int showID,
[FromQuery] string sortBy,
[FromQuery] int afterID,
[FromQuery] Dictionary<string, string> where,
[FromQuery] int limit = 50)
{
where.Remove("showID");
where.Remove("sortBy");
where.Remove("limit");
where.Remove("afterID");
try
{
ICollection<Episode> ressources = await _libraryManager.GetEpisodes(showID,
ApiHelper.ParseWhere<Episode>(where),
new Sort<Episode>(sortBy),
new Pagination(limit, afterID));
return Page(ressources, limit);
}
catch (ItemNotFound)
{
return NotFound();
}
catch (ArgumentException ex)
{
return BadRequest(new {Error = ex.Message});
}
}
[HttpGet("{slug}/episode")]
[HttpGet("{slug}/episodes")]
[Authorize(Policy = "Read")]
public async Task<ActionResult<Page<Episode>>> GetEpisodes(string slug,
[FromQuery] string sortBy,
[FromQuery] int afterID,
[FromQuery] Dictionary<string, string> where,
[FromQuery] int limit = 20)
{
where.Remove("slug");
where.Remove("sortBy");
where.Remove("limit");
where.Remove("afterID");
try
{
ICollection<Episode> ressources = await _libraryManager.GetEpisodes(slug,
ApiHelper.ParseWhere<Episode>(where),
new Sort<Episode>(sortBy),
new Pagination(limit, afterID));
return Page(ressources, limit);
}
catch (ItemNotFound)
{
return NotFound();
}
catch (ArgumentException ex)
{
return BadRequest(new {Error = ex.Message});