Reworking images

This commit is contained in:
Zoe Roux 2021-07-27 00:11:06 +02:00
parent 2812c9cacf
commit 9777551b78
22 changed files with 326 additions and 310 deletions

View File

@ -23,37 +23,18 @@ namespace Kyoo.Controllers
/// <typeparam name="T">The type of the item</typeparam> /// <typeparam name="T">The type of the item</typeparam>
/// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns> /// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns>
Task<bool> DownloadImages<T>([NotNull] T item, bool alwaysDownload = false) Task<bool> DownloadImages<T>([NotNull] T item, bool alwaysDownload = false)
where T : IResource; where T : IThumbnails;
/// <summary> /// <summary>
/// Retrieve the local path of the poster of the given item. /// Retrieve the local path of the poster of the given item.
/// </summary> /// </summary>
/// <param name="item">The item to retrieve the poster from.</param> /// <param name="item">The item to retrieve the poster from.</param>
/// <param name="imageID">The ID of the image. See <see cref="Thumbnails"/> for values.</param>
/// <typeparam name="T">The type of the item</typeparam> /// <typeparam name="T">The type of the item</typeparam>
/// <exception cref="NotSupportedException">If the type does not have a poster</exception> /// <exception cref="NotSupportedException">If the type does not have a poster</exception>
/// <returns>The path of the poster for the given resource (it might or might not exists).</returns> /// <returns>The path of the poster for the given resource (it might or might not exists).</returns>
Task<string> GetPoster<T>([NotNull] T item) Task<string> GetImagePath<T>([NotNull] T item, int imageID)
where T : IResource; where T : IThumbnails;
/// <summary>
/// Retrieve the local path of the logo of the given item.
/// </summary>
/// <param name="item">The item to retrieve the logo from.</param>
/// <typeparam name="T">The type of the item</typeparam>
/// <exception cref="NotSupportedException">If the type does not have a logo</exception>
/// <returns>The path of the logo for the given resource (it might or might not exists).</returns>
Task<string> GetLogo<T>([NotNull] T item)
where T : IResource;
/// <summary>
/// Retrieve the local path of the thumbnail of the given item.
/// </summary>
/// <param name="item">The item to retrieve the thumbnail from.</param>
/// <typeparam name="T">The type of the item</typeparam>
/// <exception cref="NotSupportedException">If the type does not have a thumbnail</exception>
/// <returns>The path of the thumbnail for the given resource (it might or might not exists).</returns>
Task<string> GetThumbnail<T>([NotNull] T item)
where T : IResource;
} }
} }

View File

@ -8,7 +8,7 @@ namespace Kyoo.Models
/// A class representing collections of <see cref="Show"/>. /// A class representing collections of <see cref="Show"/>.
/// A collection can also be stored in a <see cref="Library"/>. /// A collection can also be stored in a <see cref="Library"/>.
/// </summary> /// </summary>
public class Collection : IResource, IMetadata public class Collection : IResource, IMetadata, IThumbnails
{ {
/// <inheritdoc /> /// <inheritdoc />
public int ID { get; set; } public int ID { get; set; }
@ -20,14 +20,18 @@ namespace Kyoo.Models
/// The name of this collection. /// The name of this collection.
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <inheritdoc />
public Dictionary<int, string> Images { get; set; }
/// <summary> /// <summary>
/// The path of this poster. /// The path of this poster.
/// By default, the http path for this poster is returned from the public API. /// By default, the http path for this poster is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/collection/{Slug}/poster")] public string Poster { get; set; } [SerializeAs("{HOST}/api/collection/{Slug}/poster")]
public string Poster => Images[Thumbnails.Poster];
/// <summary> /// <summary>
/// The description of this collection. /// The description of this collection.
/// </summary> /// </summary>
@ -44,7 +48,7 @@ namespace Kyoo.Models
[LoadableRelation] public ICollection<Library> Libraries { get; set; } [LoadableRelation] public ICollection<Library> Libraries { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
#if ENABLE_INTERNAL_LINKS #if ENABLE_INTERNAL_LINKS

View File

@ -10,7 +10,7 @@ namespace Kyoo.Models
/// <summary> /// <summary>
/// A class to represent a single show's episode. /// A class to represent a single show's episode.
/// </summary> /// </summary>
public class Episode : IResource, IMetadata public class Episode : IResource, IMetadata, IThumbnails
{ {
/// <inheritdoc /> /// <inheritdoc />
public int ID { get; set; } public int ID { get; set; }
@ -98,13 +98,17 @@ namespace Kyoo.Models
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed. /// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
/// </summary> /// </summary>
[SerializeIgnore] public string Path { get; set; } [SerializeIgnore] public string Path { get; set; }
/// <inheritdoc />
public Dictionary<int, string> Images { get; set; }
/// <summary> /// <summary>
/// The path of this episode's thumbnail. /// The path of this episode's thumbnail.
/// By default, the http path for the thumbnail is returned from the public API. /// By default, the http path for the thumbnail is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/episodes/{Slug}/thumb")] public string Thumb { get; set; } [SerializeAs("{HOST}/api/episodes/{Slug}/thumb")]
public string Thumb => Images[Thumbnails.Thumbnail];
/// <summary> /// <summary>
/// The title of this episode. /// The title of this episode.
@ -122,7 +126,7 @@ namespace Kyoo.Models
public DateTime? ReleaseDate { get; set; } public DateTime? ReleaseDate { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The list of tracks this episode has. This lists video, audio and subtitles available. /// The list of tracks this episode has. This lists video, audio and subtitles available.

View File

@ -11,6 +11,7 @@ namespace Kyoo.Models
/// <summary> /// <summary>
/// The link to metadata providers that this show has. See <see cref="MetadataID"/> for more information. /// The link to metadata providers that this show has. See <see cref="MetadataID"/> for more information.
/// </summary> /// </summary>
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation]
public ICollection<MetadataID> ExternalIDs { get; set; }
} }
} }

View File

@ -0,0 +1,49 @@
using System.Collections.Generic;
using Kyoo.Controllers;
namespace Kyoo.Models
{
/// <summary>
/// An interface representing items that contains images (like posters, thumbnails, logo, banners...)
/// </summary>
public interface IThumbnails
{
/// <summary>
/// The list of images mapped to a certain index.
/// The string value should be a path supported by the <see cref="IFileSystem"/>.
/// </summary>
/// <remarks>
/// An arbitrary index should not be used, instead use indexes from <see cref="Thumbnails"/>
/// </remarks>
public Dictionary<int, string> Images { get; set; }
// TODO remove Posters properties add them via the json serializer for every IThumbnails
}
/// <summary>
/// A class containing constant values for images. To be used as index of a <see cref="IThumbnails.Images"/>.
/// </summary>
public static class Thumbnails
{
/// <summary>
/// A poster is a 9/16 format image with the cover of the resource.
/// </summary>
public const int Poster = 0;
/// <summary>
/// A thumbnail is a 16/9 format image, it could ether be used as a background or as a preview but it usually
/// is not an official image.
/// </summary>
public const int Thumbnail = 1;
/// <summary>
/// A logo is a small image representing the resource.
/// </summary>
public const int Logo = 2;
/// <summary>
/// A video of a few minutes that tease the content.
/// </summary>
public const int Trailer = 3;
}
}

View File

@ -6,7 +6,7 @@ namespace Kyoo.Models
/// <summary> /// <summary>
/// An actor, voice actor, writer, animator, somebody who worked on a <see cref="Show"/>. /// An actor, voice actor, writer, animator, somebody who worked on a <see cref="Show"/>.
/// </summary> /// </summary>
public class People : IResource, IMetadata public class People : IResource, IMetadata, IThumbnails
{ {
/// <inheritdoc /> /// <inheritdoc />
public int ID { get; set; } public int ID { get; set; }
@ -19,15 +19,19 @@ namespace Kyoo.Models
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <inheritdoc />
public Dictionary<int, string> Images { get; set; }
/// <summary> /// <summary>
/// The path of this poster. /// The path of this poster.
/// By default, the http path for this poster is returned from the public API. /// By default, the http path for this poster is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/people/{Slug}/poster")] public string Poster { get; set; } [SerializeAs("{HOST}/api/people/{Slug}/poster")]
public string Poster => Images[Thumbnails.Poster];
/// <inheritdoc /> /// <inheritdoc />
public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information. /// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information.

View File

@ -9,7 +9,7 @@ namespace Kyoo.Models
/// This class contains metadata about <see cref="IMetadataProvider"/>. /// This class contains metadata about <see cref="IMetadataProvider"/>.
/// You can have providers even if you don't have the corresponding <see cref="IMetadataProvider"/>. /// You can have providers even if you don't have the corresponding <see cref="IMetadataProvider"/>.
/// </summary> /// </summary>
public class Provider : IResource public class Provider : IResource, IThumbnails
{ {
/// <inheritdoc /> /// <inheritdoc />
public int ID { get; set; } public int ID { get; set; }
@ -22,12 +22,16 @@ namespace Kyoo.Models
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <inheritdoc />
public Dictionary<int, string> Images { get; set; }
/// <summary> /// <summary>
/// The path of this provider's logo. /// The path of this provider's logo.
/// By default, the http path for this logo is returned from the public API. /// By default, the http path for this logo is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/providers/{Slug}/logo")] public string Logo { get; set; } [SerializeAs("{HOST}/api/providers/{Slug}/logo")]
public string Logo => Images[Thumbnails.Logo];
/// <summary> /// <summary>
/// The extension of the logo. This is used for http responses. /// The extension of the logo. This is used for http responses.
@ -61,7 +65,7 @@ namespace Kyoo.Models
{ {
Slug = Utility.ToSlug(name); Slug = Utility.ToSlug(name);
Name = name; Name = name;
Logo = logo; Images[Thumbnails.Logo] = logo;
} }
} }
} }

View File

@ -10,7 +10,7 @@ namespace Kyoo.Models
/// <summary> /// <summary>
/// A season of a <see cref="Show"/>. /// A season of a <see cref="Show"/>.
/// </summary> /// </summary>
public class Season : IResource, IMetadata public class Season : IResource, IMetadata, IThumbnails
{ {
/// <inheritdoc /> /// <inheritdoc />
public int ID { get; set; } public int ID { get; set; }
@ -74,15 +74,19 @@ namespace Kyoo.Models
/// </summary> /// </summary>
public DateTime? EndDate { get; set; } public DateTime? EndDate { get; set; }
/// <inheritdoc />
public Dictionary<int, string> Images { get; set; }
/// <summary> /// <summary>
/// The path of this poster. /// The path of this poster.
/// By default, the http path for this poster is returned from the public API. /// By default, the http path for this poster is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")] public string Poster { get; set; } [SerializeAs("{HOST}/api/seasons/{Slug}/thumb")]
public string Poster => Images[Thumbnails.Poster];
/// <inheritdoc /> /// <inheritdoc />
public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The list of episodes that this season contains. /// The list of episodes that this season contains.

View File

@ -11,7 +11,7 @@ namespace Kyoo.Models
/// <summary> /// <summary>
/// A series or a movie. /// A series or a movie.
/// </summary> /// </summary>
public class Show : IResource, IMetadata, IOnMerge public class Show : IResource, IMetadata, IOnMerge, IThumbnails
{ {
/// <inheritdoc /> /// <inheritdoc />
public int ID { get; set; } public int ID { get; set; }
@ -44,12 +44,12 @@ namespace Kyoo.Models
/// Is this show airing, not aired yet or finished? /// Is this show airing, not aired yet or finished?
/// </summary> /// </summary>
public Status Status { get; set; } public Status Status { get; set; }
/// <summary> /// <summary>
/// An URL to a trailer. This could be any path supported by the <see cref="IFileSystem"/>. /// An URL to a trailer. This could be any path supported by the <see cref="IFileSystem"/>.
/// </summary> /// </summary>
/// TODO for now, this is set to a youtube url. It should be cached and converted to a local file. /// TODO for now, this is set to a youtube url. It should be cached and converted to a local file.
public string TrailerUrl { get; set; } public string TrailerUrl => Images[Thumbnails.Trailer];
/// <summary> /// <summary>
/// The date this show started airing. It can be null if this is unknown. /// The date this show started airing. It can be null if this is unknown.
@ -63,26 +63,32 @@ namespace Kyoo.Models
/// </summary> /// </summary>
public DateTime? EndAir { get; set; } public DateTime? EndAir { get; set; }
/// <inheritdoc />
public Dictionary<int, string> Images { get; set; }
/// <summary> /// <summary>
/// The path of this show's poster. /// The path of this show's poster.
/// By default, the http path for this poster is returned from the public API. /// By default, the http path for this poster is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/shows/{Slug}/poster")] public string Poster { get; set; } [SerializeAs("{HOST}/api/shows/{Slug}/poster")]
public string Poster => Images[Thumbnails.Poster];
/// <summary> /// <summary>
/// The path of this show's logo. /// The path of this show's logo.
/// By default, the http path for this logo is returned from the public API. /// By default, the http path for this logo is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/shows/{Slug}/logo")] public string Logo { get; set; } [SerializeAs("{HOST}/api/shows/{Slug}/logo")]
public string Logo => Images[Thumbnails.Logo];
/// <summary> /// <summary>
/// The path of this show's backdrop. /// The path of this show's backdrop.
/// By default, the http path for this backdrop is returned from the public API. /// By default, the http path for this backdrop is returned from the public API.
/// This can be disabled using the internal query flag. /// This can be disabled using the internal query flag.
/// </summary> /// </summary>
[SerializeAs("{HOST}/api/shows/{Slug}/backdrop")] public string Backdrop { get; set; } [SerializeAs("{HOST}/api/shows/{Slug}/backdrop")]
public string Backdrop => Images[Thumbnails.Thumbnail];
/// <summary> /// <summary>
/// True if this show represent a movie, false otherwise. /// True if this show represent a movie, false otherwise.
@ -90,7 +96,7 @@ namespace Kyoo.Models
public bool IsMovie { get; set; } public bool IsMovie { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The ID of the Studio that made this show. /// The ID of the Studio that made this show.

View File

@ -25,7 +25,7 @@ namespace Kyoo.Models
[LoadableRelation] public ICollection<Show> Shows { get; set; } [LoadableRelation] public ICollection<Show> Shows { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// Create a new, empty, <see cref="Studio"/>. /// Create a new, empty, <see cref="Studio"/>.

View File

@ -41,7 +41,10 @@ namespace Kyoo.Tests
Slug = "collection", Slug = "collection",
Name = "Collection", Name = "Collection",
Overview = "A nice collection for tests", Overview = "A nice collection for tests",
Poster = "Poster" Images =
{
[Thumbnails.Poster] = "Poster"
}
} }
}, },
{ {
@ -61,12 +64,14 @@ namespace Kyoo.Tests
"In time, however, these childhood friends drifted apart, and when they became high " + "In time, however, these childhood friends drifted apart, and when they became high " +
"school students, they had long ceased to think of each other as friends.", "school students, they had long ceased to think of each other as friends.",
Status = Status.Finished, Status = Status.Finished,
TrailerUrl = null,
StartAir = new DateTime(2011, 1, 1), StartAir = new DateTime(2011, 1, 1),
EndAir = new DateTime(2011, 1, 1), EndAir = new DateTime(2011, 1, 1),
Poster = "poster", Images =
Logo = "logo", {
Backdrop = "backdrop", [Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "Logo",
[Thumbnails.Thumbnail] = "Thumbnail"
},
IsMovie = false, IsMovie = false,
Studio = null Studio = null
} }
@ -83,7 +88,12 @@ namespace Kyoo.Tests
Overview = "The first season", Overview = "The first season",
StartDate = new DateTime(2020, 06, 05), StartDate = new DateTime(2020, 06, 05),
EndDate = new DateTime(2020, 07, 05), EndDate = new DateTime(2020, 07, 05),
Poster = "poster" Images =
{
[Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "Logo",
[Thumbnails.Thumbnail] = "Thumbnail"
},
} }
}, },
{ {
@ -98,7 +108,12 @@ namespace Kyoo.Tests
EpisodeNumber = 1, EpisodeNumber = 1,
AbsoluteNumber = 1, AbsoluteNumber = 1,
Path = "/home/kyoo/anohana-s1e1", Path = "/home/kyoo/anohana-s1e1",
Thumb = "thumbnail", Images =
{
[Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "Logo",
[Thumbnails.Thumbnail] = "Thumbnail"
},
Title = "Episode 1", Title = "Episode 1",
Overview = "Summary of the first episode", Overview = "Summary of the first episode",
ReleaseDate = new DateTime(2020, 06, 05) ReleaseDate = new DateTime(2020, 06, 05)
@ -129,7 +144,12 @@ namespace Kyoo.Tests
ID = 1, ID = 1,
Slug = "the-actor", Slug = "the-actor",
Name = "The Actor", Name = "The Actor",
Poster = "NicePoster" Images =
{
[Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "Logo",
[Thumbnails.Thumbnail] = "Thumbnail"
},
} }
}, },
{ {
@ -138,7 +158,7 @@ namespace Kyoo.Tests
{ {
ID = 1, ID = 1,
Slug = "hyper-studio", Slug = "hyper-studio",
Name = "Hyper studio" Name = "Hyper studio",
} }
}, },
{ {
@ -157,7 +177,12 @@ namespace Kyoo.Tests
ID = 1, ID = 1,
Slug = "tvdb", Slug = "tvdb",
Name = "The TVDB", Name = "The TVDB",
Logo = "path/tvdb.svg", Images =
{
[Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "path/tvdb.svg",
[Thumbnails.Thumbnail] = "Thumbnail"
},
LogoExtension = "svg" LogoExtension = "svg"
} }
}, },
@ -257,7 +282,12 @@ namespace Kyoo.Tests
EpisodeNumber = null, EpisodeNumber = null,
AbsoluteNumber = 3, AbsoluteNumber = 3,
Path = "/home/kyoo/anohana-3", Path = "/home/kyoo/anohana-3",
Thumb = "thumbnail", Images =
{
[Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "Logo",
[Thumbnails.Thumbnail] = "Thumbnail"
},
Title = "Episode 3", Title = "Episode 3",
Overview = "Summary of the third absolute episode", Overview = "Summary of the third absolute episode",
ReleaseDate = new DateTime(2020, 06, 05) ReleaseDate = new DateTime(2020, 06, 05)
@ -272,7 +302,12 @@ namespace Kyoo.Tests
ShowSlug = "anohana", ShowSlug = "anohana",
ShowID = 1, ShowID = 1,
Path = "/home/kyoo/john-wick", Path = "/home/kyoo/john-wick",
Thumb = "thumb", Images =
{
[Thumbnails.Poster] = "Poster",
[Thumbnails.Logo] = "Logo",
[Thumbnails.Thumbnail] = "Thumbnail"
},
Title = "John wick", Title = "John wick",
Overview = "A movie episode test", Overview = "A movie episode test",
ReleaseDate = new DateTime(1595, 05, 12) ReleaseDate = new DateTime(1595, 05, 12)

View File

@ -26,17 +26,21 @@ namespace Kyoo.TheMovieDb
Title = movie.Title, Title = movie.Title,
Aliases = movie.AlternativeTitles.Titles.Select(x => x.Title).ToArray(), Aliases = movie.AlternativeTitles.Titles.Select(x => x.Title).ToArray(),
Overview = movie.Overview, Overview = movie.Overview,
TrailerUrl = movie.Videos?.Results.Where(x => x.Type is "Trailer" or "Teaser" && x.Site == "YouTube")
.Select(x => "https://www.youtube.com/watch?v=" + x.Key).FirstOrDefault(),
Status = movie.Status == "Released" ? Status.Finished : Status.Planned, Status = movie.Status == "Released" ? Status.Finished : Status.Planned,
StartAir = movie.ReleaseDate, StartAir = movie.ReleaseDate,
EndAir = movie.ReleaseDate, EndAir = movie.ReleaseDate,
Poster = movie.PosterPath != null Images =
? $"https://image.tmdb.org/t/p/original{movie.PosterPath}" {
: null, [Thumbnails.Poster] = movie.PosterPath != null
Backdrop = movie.BackdropPath != null ? $"https://image.tmdb.org/t/p/original{movie.PosterPath}"
? $"https://image.tmdb.org/t/p/original{movie.BackdropPath}" : null,
: null, [Thumbnails.Thumbnail] = movie.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{movie.BackdropPath}"
: null,
[Thumbnails.Trailer] = movie.Videos?.Results
.Where(x => x.Type is "Trailer" or "Teaser" && x.Site == "YouTube")
.Select(x => "https://www.youtube.com/watch?v=" + x.Key).FirstOrDefault(),
},
Genres = movie.Genres.Select(x => new Genre(x.Name)).ToArray(), Genres = movie.Genres.Select(x => new Genre(x.Name)).ToArray(),
Studio = !string.IsNullOrEmpty(movie.ProductionCompanies.FirstOrDefault()?.Name) Studio = !string.IsNullOrEmpty(movie.ProductionCompanies.FirstOrDefault()?.Name)
? new Studio(movie.ProductionCompanies.First().Name) ? new Studio(movie.ProductionCompanies.First().Name)
@ -72,17 +76,21 @@ namespace Kyoo.TheMovieDb
Title = tv.Name, Title = tv.Name,
Aliases = tv.AlternativeTitles.Results.Select(x => x.Title).ToArray(), Aliases = tv.AlternativeTitles.Results.Select(x => x.Title).ToArray(),
Overview = tv.Overview, Overview = tv.Overview,
TrailerUrl = tv.Videos?.Results.Where(x => x.Type is "Trailer" or "Teaser" && x.Site == "YouTube")
.Select(x => "https://www.youtube.com/watch?v=" + x.Key).FirstOrDefault(),
Status = tv.Status == "Ended" ? Status.Finished : Status.Planned, Status = tv.Status == "Ended" ? Status.Finished : Status.Planned,
StartAir = tv.FirstAirDate, StartAir = tv.FirstAirDate,
EndAir = tv.LastAirDate, EndAir = tv.LastAirDate,
Poster = tv.PosterPath != null Images =
? $"https://image.tmdb.org/t/p/original{tv.PosterPath}" {
: null, [Thumbnails.Poster] = tv.PosterPath != null
Backdrop = tv.BackdropPath != null ? $"https://image.tmdb.org/t/p/original{tv.PosterPath}"
? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}" : null,
: null, [Thumbnails.Thumbnail] = tv.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}"
: null,
[Thumbnails.Trailer] = tv.Videos?.Results
.Where(x => x.Type is "Trailer" or "Teaser" && x.Site == "YouTube")
.Select(x => "https://www.youtube.com/watch?v=" + x.Key).FirstOrDefault()
},
Genres = tv.Genres.Select(x => new Genre(x.Name)).ToArray(), Genres = tv.Genres.Select(x => new Genre(x.Name)).ToArray(),
Studio = !string.IsNullOrEmpty(tv.ProductionCompanies.FirstOrDefault()?.Name) Studio = !string.IsNullOrEmpty(tv.ProductionCompanies.FirstOrDefault()?.Name)
? new Studio(tv.ProductionCompanies.First().Name) ? new Studio(tv.ProductionCompanies.First().Name)
@ -117,7 +125,15 @@ namespace Kyoo.TheMovieDb
{ {
Slug = Utility.ToSlug(collection.Name), Slug = Utility.ToSlug(collection.Name),
Name = collection.Name, Name = collection.Name,
Poster = $"https://image.tmdb.org/t/p/original{collection.PosterPath}" Images =
{
[Thumbnails.Poster] = collection.PosterPath != null
? $"https://image.tmdb.org/t/p/original{collection.PosterPath}"
: null,
[Thumbnails.Thumbnail] = collection.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{collection.BackdropPath}"
: null
}
}; };
} }
@ -136,12 +152,15 @@ namespace Kyoo.TheMovieDb
Overview = movie.Overview, Overview = movie.Overview,
StartAir = movie.ReleaseDate, StartAir = movie.ReleaseDate,
EndAir = movie.ReleaseDate, EndAir = movie.ReleaseDate,
Poster = movie.PosterPath != null Images =
? $"https://image.tmdb.org/t/p/original{movie.PosterPath}" {
: null, [Thumbnails.Poster] = movie.PosterPath != null
Backdrop = movie.BackdropPath != null ? $"https://image.tmdb.org/t/p/original{movie.PosterPath}"
? $"https://image.tmdb.org/t/p/original{movie.BackdropPath}" : null,
: null, [Thumbnails.Thumbnail] = movie.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{movie.BackdropPath}"
: null,
},
IsMovie = true, IsMovie = true,
ExternalIDs = new [] ExternalIDs = new []
{ {
@ -169,12 +188,15 @@ namespace Kyoo.TheMovieDb
Title = tv.Name, Title = tv.Name,
Overview = tv.Overview, Overview = tv.Overview,
StartAir = tv.FirstAirDate, StartAir = tv.FirstAirDate,
Poster = tv.PosterPath != null Images =
? $"https://image.tmdb.org/t/p/original{tv.PosterPath}" {
: null, [Thumbnails.Poster] = tv.PosterPath != null
Backdrop = tv.BackdropPath != null ? $"https://image.tmdb.org/t/p/original{tv.PosterPath}"
? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}" : null,
: null, [Thumbnails.Thumbnail] = tv.BackdropPath != null
? $"https://image.tmdb.org/t/p/original{tv.BackdropPath}"
: null,
},
IsMovie = true, IsMovie = true,
ExternalIDs = new [] ExternalIDs = new []
{ {
@ -202,7 +224,12 @@ namespace Kyoo.TheMovieDb
{ {
Slug = Utility.ToSlug(cast.Name), Slug = Utility.ToSlug(cast.Name),
Name = cast.Name, Name = cast.Name,
Poster = cast.ProfilePath != null ? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}" : null, Images =
{
[Thumbnails.Poster] = cast.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}"
: null
},
ExternalIDs = new[] ExternalIDs = new[]
{ {
new MetadataID new MetadataID
@ -232,7 +259,12 @@ namespace Kyoo.TheMovieDb
{ {
Slug = Utility.ToSlug(cast.Name), Slug = Utility.ToSlug(cast.Name),
Name = cast.Name, Name = cast.Name,
Poster = cast.ProfilePath != null ? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}" : null, Images =
{
[Thumbnails.Poster] = cast.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{cast.ProfilePath}"
: null
},
ExternalIDs = new[] ExternalIDs = new[]
{ {
new MetadataID new MetadataID
@ -262,7 +294,12 @@ namespace Kyoo.TheMovieDb
{ {
Slug = Utility.ToSlug(crew.Name), Slug = Utility.ToSlug(crew.Name),
Name = crew.Name, Name = crew.Name,
Poster = crew.ProfilePath != null ? $"https://image.tmdb.org/t/p/original{crew.ProfilePath}" : null, Images =
{
[Thumbnails.Poster] = crew.ProfilePath != null
? $"https://image.tmdb.org/t/p/original{crew.ProfilePath}"
: null
},
ExternalIDs = new[] ExternalIDs = new[]
{ {
new MetadataID new MetadataID

View File

@ -29,7 +29,11 @@ namespace Kyoo.TheMovieDb
Slug = "the-moviedb", Slug = "the-moviedb",
Name = "TheMovieDB", Name = "TheMovieDB",
LogoExtension = "svg", LogoExtension = "svg",
Logo = "https://www.themoviedb.org/assets/2/v4/logos/v2/blue_short-8e7b30f73a4020692ccca9c88bafe5dcb6f8a62a4c6bc55cd9ba82bb2cd95f6c.svg" Images =
{
[Thumbnails.Logo] = "https://www.themoviedb.org/assets/2/v4/logos/v2/" +
"blue_short-8e7b30f73a4020692ccca9c88bafe5dcb6f8a62a4c6bc55cd9ba82bb2cd95f6c.svg"
}
}; };
/// <summary> /// <summary>

View File

@ -55,7 +55,12 @@ namespace Kyoo.TheTvdb
Overview = result.Overview, Overview = result.Overview,
Status = _GetStatus(result.Status), Status = _GetStatus(result.Status),
StartAir = _ParseDate(result.FirstAired), StartAir = _ParseDate(result.FirstAired),
Poster = result.Poster != null ? $"https://www.thetvdb.com{result.Poster}" : null, Images =
{
[Thumbnails.Poster] = result.Poster != null
? $"https://www.thetvdb.com{result.Poster}"
: null,
},
ExternalIDs = new[] ExternalIDs = new[]
{ {
new MetadataID new MetadataID
@ -84,8 +89,15 @@ namespace Kyoo.TheTvdb
Overview = series.Overview, Overview = series.Overview,
Status = _GetStatus(series.Status), Status = _GetStatus(series.Status),
StartAir = _ParseDate(series.FirstAired), StartAir = _ParseDate(series.FirstAired),
Poster = series.Poster != null ? $"https://www.thetvdb.com/banners/{series.Poster}" : null, Images=
Backdrop = series.FanArt != null ? $"https://www.thetvdb.com/banners/{series.FanArt}" : null, {
[Thumbnails.Poster] = series.Poster != null
? $"https://www.thetvdb.com/banners/{series.Poster}"
: null,
[Thumbnails.Thumbnail] = series.FanArt != null
? $"https://www.thetvdb.com/banners/{series.FanArt}"
: null
},
Genres = series.Genre.Select(y => new Genre(y)).ToList(), Genres = series.Genre.Select(y => new Genre(y)).ToList(),
ExternalIDs = new[] ExternalIDs = new[]
{ {
@ -113,7 +125,12 @@ namespace Kyoo.TheTvdb
{ {
Slug = Utility.ToSlug(actor.Name), Slug = Utility.ToSlug(actor.Name),
Name = actor.Name, Name = actor.Name,
Poster = actor.Image != null ? $"https://www.thetvdb.com/banners/{actor.Image}" : null, Images =
{
[Thumbnails.Poster] = actor.Image != null
? $"https://www.thetvdb.com/banners/{actor.Image}"
: null
},
ExternalIDs = new [] ExternalIDs = new []
{ {
new MetadataID new MetadataID
@ -144,7 +161,12 @@ namespace Kyoo.TheTvdb
AbsoluteNumber = episode.AbsoluteNumber, AbsoluteNumber = episode.AbsoluteNumber,
Title = episode.EpisodeName, Title = episode.EpisodeName,
Overview = episode.Overview, Overview = episode.Overview,
Thumb = episode.Filename != null ? $"https://www.thetvdb.com/banners/{episode.Filename}" : null, Images =
{
[Thumbnails.Thumbnail] = episode.Filename != null
? $"https://www.thetvdb.com/banners/{episode.Filename}"
: null
},
ExternalIDs = new[] ExternalIDs = new[]
{ {
new MetadataID new MetadataID

View File

@ -33,7 +33,10 @@ namespace Kyoo.TheTvdb
Slug = "the-tvdb", Slug = "the-tvdb",
Name = "TheTVDB", Name = "TheTVDB",
LogoExtension = "png", LogoExtension = "png",
Logo = "https://www.thetvdb.com/images/logo.png" Images =
{
[Thumbnails.Logo] = "https://www.thetvdb.com/images/logo.png"
}
}; };

View File

@ -2,7 +2,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Kyoo.Models.Options; using Kyoo.Models.Options;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -55,23 +54,6 @@ namespace Kyoo.Controllers
}); });
} }
/// <inheritdoc />
public Task<bool> DownloadImages<T>(T item, bool alwaysDownload = false)
where T : IResource
{
if (item == null)
throw new ArgumentNullException(nameof(item));
return item switch
{
Show show => _Validate(show, alwaysDownload),
Season season => _Validate(season, alwaysDownload),
Episode episode => _Validate(episode, alwaysDownload),
People people => _Validate(people, alwaysDownload),
Provider provider => _Validate(provider, alwaysDownload),
_ => Task.FromResult(false)
};
}
/// <summary> /// <summary>
/// An helper function to download an image using a <see cref="LocalFileSystem"/>. /// An helper function to download an image using a <see cref="LocalFileSystem"/>.
/// </summary> /// </summary>
@ -97,196 +79,72 @@ namespace Kyoo.Controllers
return false; return false;
} }
} }
/// <summary> /// <inheritdoc />
/// Download images of a specified show. public async Task<bool> DownloadImages<T>(T item, bool alwaysDownload = false)
/// </summary> where T : IThumbnails
/// <param name="show">
/// The item to cache images.
/// </param>
/// <param name="alwaysDownload">
/// <c>true</c> if images should be downloaded even if they already exists locally, <c>false</c> otherwise.
/// </param>
/// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns>
private async Task<bool> _Validate([NotNull] Show show, bool alwaysDownload)
{ {
bool ret = false; if (item == null)
throw new ArgumentNullException(nameof(item));
if (show.Poster != null)
{
string posterPath = await GetPoster(show);
if (alwaysDownload || !await _files.Exists(posterPath))
ret |= await _DownloadImage(show.Poster, posterPath, $"The poster of {show.Title}");
}
if (show.Logo != null)
{
string logoPath = await GetLogo(show);
if (alwaysDownload || !await _files.Exists(logoPath))
ret |= await _DownloadImage(show.Logo, logoPath, $"The logo of {show.Title}");
}
if (show.Backdrop != null)
{
string backdropPath = await GetThumbnail(show);
if (alwaysDownload || !await _files.Exists(backdropPath))
ret |= await _DownloadImage(show.Backdrop, backdropPath, $"The backdrop of {show.Title}");
}
string name = item is IResource res ? res.Slug : "???";
bool ret = false;
foreach ((int id, string image) in item.Images)
{
string localPath = await GetImagePath(item, id);
if (alwaysDownload || !await _files.Exists(localPath))
ret |= await _DownloadImage(image, localPath, $"The image n°{id} of {name}");
}
return ret; return ret;
} }
/// <summary>
/// Download images of a specified person.
/// </summary>
/// <param name="people">
/// The item to cache images.
/// </param>
/// <param name="alwaysDownload">
/// <c>true</c> if images should be downloaded even if they already exists locally, <c>false</c> otherwise.
/// </param>
/// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns>
private async Task<bool> _Validate([NotNull] People people, bool alwaysDownload)
{
if (people == null)
throw new ArgumentNullException(nameof(people));
if (people.Poster == null)
return false;
string localPath = await GetPoster(people);
if (alwaysDownload || !await _files.Exists(localPath))
return await _DownloadImage(people.Poster, localPath, $"The profile picture of {people.Name}");
return false;
}
/// <summary>
/// Download images of a specified season.
/// </summary>
/// <param name="season">
/// The item to cache images.
/// </param>
/// <param name="alwaysDownload">
/// <c>true</c> if images should be downloaded even if they already exists locally, <c>false</c> otherwise.
/// </param>
/// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns>
private async Task<bool> _Validate([NotNull] Season season, bool alwaysDownload)
{
if (season.Poster == null)
return false;
string localPath = await GetPoster(season);
if (alwaysDownload || !await _files.Exists(localPath))
return await _DownloadImage(season.Poster, localPath, $"The poster of {season.Slug}");
return false;
}
/// <summary>
/// Download images of a specified episode.
/// </summary>
/// <param name="episode">
/// The item to cache images.
/// </param>
/// <param name="alwaysDownload">
/// <c>true</c> if images should be downloaded even if they already exists locally, <c>false</c> otherwise.
/// </param>
/// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns>
private async Task<bool> _Validate([NotNull] Episode episode, bool alwaysDownload)
{
if (episode.Thumb == null)
return false;
string localPath = await _GetEpisodeThumb(episode);
if (alwaysDownload || !await _files.Exists(localPath))
return await _DownloadImage(episode.Thumb, localPath, $"The thumbnail of {episode.Slug}");
return false;
}
/// <summary>
/// Download images of a specified provider.
/// </summary>
/// <param name="provider">
/// The item to cache images.
/// </param>
/// <param name="alwaysDownload">
/// <c>true</c> if images should be downloaded even if they already exists locally, <c>false</c> otherwise.
/// </param>
/// <returns><c>true</c> if an image has been downloaded, <c>false</c> otherwise.</returns>
private async Task<bool> _Validate([NotNull] Provider provider, bool alwaysDownload)
{
if (provider.Logo == null)
return false;
string localPath = await GetLogo(provider);
if (alwaysDownload || !await _files.Exists(localPath))
return await _DownloadImage(provider.Logo, localPath, $"The logo of {provider.Slug}");
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public Task<string> GetPoster<T>(T item) public async Task<string> GetImagePath<T>(T item, int imageID)
where T : IResource where T : IThumbnails
{ {
if (item == null) if (item == null)
throw new ArgumentNullException(nameof(item)); throw new ArgumentNullException(nameof(item));
return item switch string imageName = imageID switch
{ {
Show show => Task.FromResult(_files.Combine(_files.GetExtraDirectory(show), "poster.jpg")), Thumbnails.Poster => "poster.jpg",
Season season => _GetSeasonPoster(season), Thumbnails.Logo => "logo.jpg",
People actor => Task.FromResult(_files.Combine(_options.CurrentValue.PeoplePath, $"{actor.Slug}.jpg")), Thumbnails.Thumbnail => "thumbnail.jpg",
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a poster.") _ => $"{imageID}.jpg"
}; };
}
// TODO implement a generic way, probably need to rework IFileManager.GetExtraDirectory too.
/// <summary> switch (item)
/// Retrieve the path of a season's poster.
/// </summary>
/// <param name="season">The season to retrieve the poster from.</param>
/// <returns>The path of the season's poster.</returns>
private async Task<string> _GetSeasonPoster(Season season)
{
if (season.Show == null)
await _library.Value.Load(season, x => x.Show);
return _files.Combine(_files.GetExtraDirectory(season.Show), $"season-{season.SeasonNumber}.jpg");
}
/// <inheritdoc />
public Task<string> GetThumbnail<T>(T item)
where T : IResource
{
if (item == null)
throw new ArgumentNullException(nameof(item));
return item switch
{ {
Show show => Task.FromResult(_files.Combine(_files.GetExtraDirectory(show), "backdrop.jpg")), case Show show:
Episode episode => _GetEpisodeThumb(episode), return _files.Combine(_files.GetExtraDirectory(show), imageName);
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a thumbnail.")
}; case Season season:
} if (season.Show == null)
await _library.Value.Load(season, x => x.Show);
/// <summary> return _files.Combine(
/// Get the path for an episode's thumbnail. _files.GetExtraDirectory(season.Show!),
/// </summary> $"season-{season.SeasonNumber}-{imageName}");
/// <param name="episode">The episode to retrieve the thumbnail from</param>
/// <returns>The path of the given episode's thumbnail.</returns> case Episode episode:
private async Task<string> _GetEpisodeThumb(Episode episode) if (episode.Show == null)
{ await _library.Value.Load(episode, x => x.Show);
if (episode.Show == null) string dir = _files.Combine(_files.GetExtraDirectory(episode.Show!), "Thumbnails");
await _library.Value.Load(episode, x => x.Show); await _files.CreateDirectory(dir);
string dir = _files.Combine(_files.GetExtraDirectory(episode.Show), "Thumbnails"); return _files.Combine(dir, $"{Path.GetFileNameWithoutExtension(episode.Path)}-{imageName}");
await _files.CreateDirectory(dir);
return _files.Combine(dir, $"{Path.GetFileNameWithoutExtension(episode.Path)}.jpg"); case People actor:
} return _files.Combine(_options.CurrentValue.PeoplePath, $"{actor.Slug}-{imageName}");
/// <inheritdoc /> case Provider provider:
public Task<string> GetLogo<T>(T item) return _files.Combine(
where T : IResource _options.CurrentValue.ProviderPath,
{ $"{provider.Slug}-{imageName[..^4]}{provider.LogoExtension}");
if (item == null)
throw new ArgumentNullException(nameof(item)); default:
return Task.FromResult(item switch throw new NotSupportedException($"The type {typeof(T).Name} is not supported.");
{ }
Show show => _files.Combine(_files.GetExtraDirectory(show), "logo.png"),
Provider provider => _files.Combine(_options.CurrentValue.ProviderPath,
$"{provider.Slug}.{provider.LogoExtension}"),
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a thumbnail.")
});
} }
} }
} }

View File

@ -163,7 +163,7 @@ namespace Kyoo.Tasks
/// <typeparam name="T">The type of the item</typeparam> /// <typeparam name="T">The type of the item</typeparam>
/// <returns>The existing or filled item.</returns> /// <returns>The existing or filled item.</returns>
private async Task<T> _RegisterAndFill<T>(T item) private async Task<T> _RegisterAndFill<T>(T item)
where T : class, IResource where T : class, IResource, IThumbnails
{ {
if (item == null || string.IsNullOrEmpty(item.Slug)) if (item == null || string.IsNullOrEmpty(item.Slug))
return null; return null;

View File

@ -195,7 +195,7 @@ namespace Kyoo.Api
try try
{ {
Episode episode = await _libraryManager.Get<Episode>(id); Episode episode = await _libraryManager.Get<Episode>(id);
return _files.FileResult(await _thumbnails.GetThumbnail(episode)); return _files.FileResult(await _thumbnails.GetImagePath(episode, Thumbnails.Thumbnail));
} }
catch (ItemNotFoundException) catch (ItemNotFoundException)
{ {
@ -210,7 +210,7 @@ namespace Kyoo.Api
try try
{ {
Episode episode = await _libraryManager.Get<Episode>(slug); Episode episode = await _libraryManager.Get<Episode>(slug);
return _files.FileResult(await _thumbnails.GetThumbnail(episode)); return _files.FileResult(await _thumbnails.GetImagePath(episode, Thumbnails.Thumbnail));
} }
catch (ItemNotFoundException) catch (ItemNotFoundException)
{ {

View File

@ -94,7 +94,7 @@ namespace Kyoo.Api
People people = await _libraryManager.GetOrDefault<People>(id); People people = await _libraryManager.GetOrDefault<People>(id);
if (people == null) if (people == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbs.GetPoster(people)); return _files.FileResult(await _thumbs.GetImagePath(people, Thumbnails.Poster));
} }
[HttpGet("{slug}/poster")] [HttpGet("{slug}/poster")]
@ -103,7 +103,7 @@ namespace Kyoo.Api
People people = await _libraryManager.GetOrDefault<People>(slug); People people = await _libraryManager.GetOrDefault<People>(slug);
if (people == null) if (people == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbs.GetPoster(people)); return _files.FileResult(await _thumbs.GetImagePath(people, Thumbnails.Poster));
} }
} }
} }

View File

@ -36,7 +36,7 @@ namespace Kyoo.Api
Provider provider = await _libraryManager.GetOrDefault<Provider>(id); Provider provider = await _libraryManager.GetOrDefault<Provider>(id);
if (provider == null) if (provider == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbnails.GetLogo(provider)); return _files.FileResult(await _thumbnails.GetImagePath(provider, Thumbnails.Logo));
} }
[HttpGet("{slug}/logo")] [HttpGet("{slug}/logo")]
@ -45,7 +45,7 @@ namespace Kyoo.Api
Provider provider = await _libraryManager.GetOrDefault<Provider>(slug); Provider provider = await _libraryManager.GetOrDefault<Provider>(slug);
if (provider == null) if (provider == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbnails.GetLogo(provider)); return _files.FileResult(await _thumbnails.GetImagePath(provider, Thumbnails.Logo));
} }
} }
} }

View File

@ -151,7 +151,7 @@ namespace Kyoo.Api
if (season == null) if (season == null)
return NotFound(); return NotFound();
await _libraryManager.Load(season, x => x.Show); await _libraryManager.Load(season, x => x.Show);
return _files.FileResult(await _thumbs.GetPoster(season)); return _files.FileResult(await _thumbs.GetImagePath(season, Thumbnails.Poster));
} }
[HttpGet("{slug}/poster")] [HttpGet("{slug}/poster")]
@ -161,7 +161,7 @@ namespace Kyoo.Api
if (season == null) if (season == null)
return NotFound(); return NotFound();
await _libraryManager.Load(season, x => x.Show); await _libraryManager.Load(season, x => x.Show);
return _files.FileResult(await _thumbs.GetPoster(season)); return _files.FileResult(await _thumbs.GetImagePath(season, Thumbnails.Poster));
} }
} }
} }

View File

@ -417,7 +417,7 @@ namespace Kyoo.Api
try try
{ {
Show show = await _libraryManager.Get<Show>(slug); Show show = await _libraryManager.Get<Show>(slug);
return _files.FileResult(await _thumbs.GetPoster(show)); return _files.FileResult(await _thumbs.GetImagePath(show, Thumbnails.Poster));
} }
catch (ItemNotFoundException) catch (ItemNotFoundException)
{ {
@ -431,7 +431,7 @@ namespace Kyoo.Api
try try
{ {
Show show = await _libraryManager.Get<Show>(slug); Show show = await _libraryManager.Get<Show>(slug);
return _files.FileResult(await _thumbs.GetLogo(show)); return _files.FileResult(await _thumbs.GetImagePath(show, Thumbnails.Logo));
} }
catch (ItemNotFoundException) catch (ItemNotFoundException)
{ {
@ -446,7 +446,7 @@ namespace Kyoo.Api
try try
{ {
Show show = await _libraryManager.Get<Show>(slug); Show show = await _libraryManager.Get<Show>(slug);
return _files.FileResult(await _thumbs.GetThumbnail(show)); return _files.FileResult(await _thumbs.GetImagePath(show, Thumbnails.Thumbnail));
} }
catch (ItemNotFoundException) catch (ItemNotFoundException)
{ {