Reworking paths management

This commit is contained in:
Zoe Roux 2021-03-23 00:16:42 +01:00
parent 57e49b7e83
commit 365fd1e79f
14 changed files with 217 additions and 128 deletions

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.IO; using System.IO;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -6,11 +7,15 @@ namespace Kyoo.Controllers
{ {
public interface IFileManager public interface IFileManager
{ {
public IActionResult FileResult([NotNull] string path, bool rangeSupport = false); public IActionResult FileResult([CanBeNull] string path, bool rangeSupport = false);
public StreamReader GetReader([NotNull] string path); public StreamReader GetReader([NotNull] string path);
public ICollection<string> ListFiles([NotNull] string path);
// TODO implement a List for directorys, a Exist to check existance and all. // TODO implement a List for directorys, a Exist to check existance and all.
// TODO replace every use of System.IO with this to allow custom paths (like uptobox://path) // TODO replace every use of System.IO with this to allow custom paths (like uptobox://path)
// TODO find a way to handle Transmux/Transcode with this system. // TODO find a way to handle Transmux/Transcode with this system.
public string GetExtraDirectory(string showPath);
} }
} }

View File

@ -35,6 +35,7 @@ namespace Kyoo.Controllers
Task<Track> GetTrack(int id); Task<Track> GetTrack(int id);
Task<Studio> GetStudio(int id); Task<Studio> GetStudio(int id);
Task<People> GetPeople(int id); Task<People> GetPeople(int id);
Task<ProviderID> GetProvider(int id);
// Get by slug // Get by slug
Task<Library> GetLibrary(string slug); Task<Library> GetLibrary(string slug);
@ -49,6 +50,7 @@ namespace Kyoo.Controllers
Task<Genre> GetGenre(string slug); Task<Genre> GetGenre(string slug);
Task<Studio> GetStudio(string slug); Task<Studio> GetStudio(string slug);
Task<People> GetPeople(string slug); Task<People> GetPeople(string slug);
Task<ProviderID> GetProvider(string slug);
// Get by predicate // Get by predicate
Task<Library> GetLibrary(Expression<Func<Library, bool>> where); Task<Library> GetLibrary(Expression<Func<Library, bool>> where);

View File

@ -1,6 +1,7 @@
using Kyoo.Models; using Kyoo.Models;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
@ -11,5 +12,13 @@ namespace Kyoo.Controllers
Task<Episode> Validate(Episode episode, bool alwaysDownload = false); Task<Episode> Validate(Episode episode, bool alwaysDownload = false);
Task<People> Validate(People actors, bool alwaysDownload = false); Task<People> Validate(People actors, bool alwaysDownload = false);
Task<ProviderID> Validate(ProviderID actors, bool alwaysDownload = false); Task<ProviderID> Validate(ProviderID actors, bool alwaysDownload = false);
Task<string> GetShowPoster([NotNull] Show show);
Task<string> GetShowLogo([NotNull] Show show);
Task<string> GetShowBackdrop([NotNull] Show show);
Task<string> GetSeasonPoster([NotNull] Season season);
Task<string> GetEpisodeThumb([NotNull] Episode episode);
Task<string> GetPeoplePoster([NotNull] People people);
Task<string> GetProviderLogo([NotNull] ProviderID provider);
} }
} }

View File

@ -131,6 +131,11 @@ namespace Kyoo.Controllers
return PeopleRepository.Get(id); return PeopleRepository.Get(id);
} }
public Task<ProviderID> GetProvider(int id)
{
return ProviderRepository.Get(id);
}
public Task<Library> GetLibrary(string slug) public Task<Library> GetLibrary(string slug)
{ {
return LibraryRepository.Get(slug); return LibraryRepository.Get(slug);
@ -191,6 +196,11 @@ namespace Kyoo.Controllers
return PeopleRepository.Get(slug); return PeopleRepository.Get(slug);
} }
public Task<ProviderID> GetProvider(string slug)
{
return ProviderRepository.Get(slug);
}
public Task<Library> GetLibrary(Expression<Func<Library, bool>> where) public Task<Library> GetLibrary(Expression<Func<Library, bool>> where)
{ {
return LibraryRepository.Get(where); return LibraryRepository.Get(where);

View File

@ -1,11 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public class FileManager : ControllerBase, IFileManager public class FileManager : IFileManager
{ {
private FileExtensionContentTypeProvider _provider; private FileExtensionContentTypeProvider _provider;
@ -19,16 +20,19 @@ namespace Kyoo.Controllers
if (_provider.TryGetContentType(path, out string contentType)) if (_provider.TryGetContentType(path, out string contentType))
return contentType; return contentType;
return "video/mp4"; throw new NotImplementedException($"Can't get the content type of the file at: {path}");
} }
public IActionResult FileResult(string path, bool range) public IActionResult FileResult(string path, bool range)
{ {
if (path == null) if (path == null)
throw new ArgumentNullException(nameof(path)); return new NotFoundResult();
if (!System.IO.File.Exists(path)) if (!File.Exists(path))
return NotFound(); return new NotFoundResult();
return PhysicalFile(path, _GetContentType(path), range); return new PhysicalFileResult(Path.GetFullPath(path), _GetContentType(path))
{
EnableRangeProcessing = range
};
} }
public StreamReader GetReader(string path) public StreamReader GetReader(string path)
@ -37,5 +41,19 @@ namespace Kyoo.Controllers
throw new ArgumentNullException(nameof(path)); throw new ArgumentNullException(nameof(path));
return new StreamReader(path); return new StreamReader(path);
} }
public string GetExtraDirectory(string showPath)
{
string path = Path.Combine(showPath, "Extra");
Directory.CreateDirectory(path);
return path;
}
public ICollection<string> ListFiles(string path)
{
if (path == null)
throw new ArgumentNullException(nameof(path));
return Directory.GetFiles(path);
}
} }
} }

View File

@ -11,10 +11,16 @@ namespace Kyoo.Controllers
public class ThumbnailsManager : IThumbnailsManager public class ThumbnailsManager : IThumbnailsManager
{ {
private readonly IConfiguration _config; private readonly IConfiguration _config;
private readonly IFileManager _files;
private readonly string _peoplePath;
private readonly string _providerPath;
public ThumbnailsManager(IConfiguration configuration) public ThumbnailsManager(IConfiguration configuration, IFileManager files)
{ {
_config = configuration; _config = configuration;
_files = files;
_peoplePath = Path.GetFullPath(configuration.GetValue<string>("peoplePath"));
_providerPath = Path.GetFullPath(configuration.GetValue<string>("providerPath"));
} }
private static async Task DownloadImage(string url, string localPath, string what) private static async Task DownloadImage(string url, string localPath, string what)
@ -34,22 +40,23 @@ namespace Kyoo.Controllers
{ {
if (show?.Path == null) if (show?.Path == null)
return default; return default;
string basePath = _files.GetExtraDirectory(show.Path);
if (show.Poster != null) if (show.Poster != null)
{ {
string posterPath = Path.Combine(show.Path, "poster.jpg"); string posterPath = Path.Combine(basePath, "poster.jpg");
if (alwaysDownload || !File.Exists(posterPath)) if (alwaysDownload || !File.Exists(posterPath))
await DownloadImage(show.Poster, posterPath, $"The poster of {show.Title}"); await DownloadImage(show.Poster, posterPath, $"The poster of {show.Title}");
} }
if (show.Logo != null) if (show.Logo != null)
{ {
string logoPath = Path.Combine(show.Path, "logo.png"); string logoPath = Path.Combine(basePath, "logo.png");
if (alwaysDownload || !File.Exists(logoPath)) if (alwaysDownload || !File.Exists(logoPath))
await DownloadImage(show.Logo, logoPath, $"The logo of {show.Title}"); await DownloadImage(show.Logo, logoPath, $"The logo of {show.Title}");
} }
if (show.Backdrop != null) if (show.Backdrop != null)
{ {
string backdropPath = Path.Combine(show.Path, "backdrop.jpg"); string backdropPath = Path.Combine(basePath, "backdrop.jpg");
if (alwaysDownload || !File.Exists(backdropPath)) if (alwaysDownload || !File.Exists(backdropPath))
await DownloadImage(show.Backdrop, backdropPath, $"The backdrop of {show.Title}"); await DownloadImage(show.Backdrop, backdropPath, $"The backdrop of {show.Title}");
} }
@ -81,7 +88,8 @@ namespace Kyoo.Controllers
if (season.Poster != null) if (season.Poster != null)
{ {
string localPath = Path.Combine(season.Show.Path, $"season-{season.SeasonNumber}.jpg"); string basePath = _files.GetExtraDirectory(season.Show.Path);
string localPath = Path.Combine(basePath, $"season-{season.SeasonNumber}.jpg");
if (alwaysDownload || !File.Exists(localPath)) if (alwaysDownload || !File.Exists(localPath))
await DownloadImage(season.Poster, localPath, $"The poster of {season.Show.Title}'s season {season.SeasonNumber}"); await DownloadImage(season.Poster, localPath, $"The poster of {season.Show.Title}'s season {season.SeasonNumber}");
} }
@ -95,7 +103,10 @@ namespace Kyoo.Controllers
if (episode.Thumb != null) if (episode.Thumb != null)
{ {
string localPath = Path.ChangeExtension(episode.Path, "jpg"); string localPath = Path.Combine(
_files.GetExtraDirectory(Path.GetDirectoryName(episode.Path)),
"Thumbnails",
$"{Path.GetFileNameWithoutExtension(episode.Path)}.jpg");
if (alwaysDownload || !File.Exists(localPath)) if (alwaysDownload || !File.Exists(localPath))
await DownloadImage(episode.Thumb, localPath, $"The thumbnail of {episode.Slug}"); await DownloadImage(episode.Thumb, localPath, $"The thumbnail of {episode.Slug}");
} }
@ -116,6 +127,66 @@ namespace Kyoo.Controllers
return provider; return provider;
} }
//TODO add get thumbs here public Task<string> GetShowBackdrop(Show show)
{
if (show?.Path == null)
throw new ArgumentNullException(nameof(show));
return Task.FromResult(Path.Combine(_files.GetExtraDirectory(show.Path), "backdrop.jpg"));
}
public Task<string> GetShowLogo(Show show)
{
if (show?.Path == null)
throw new ArgumentNullException(nameof(show));
return Task.FromResult(Path.Combine(_files.GetExtraDirectory(show.Path), "logo.png"));
}
public Task<string> GetShowPoster(Show show)
{
if (show?.Path == null)
throw new ArgumentNullException(nameof(show));
return Task.FromResult(Path.Combine(_files.GetExtraDirectory(show.Path), "poster.jpg"));
}
public Task<string> GetSeasonPoster(Season season)
{
if (season == null)
throw new ArgumentNullException(nameof(season));
// TODO Use a season.Path (for season's folder)
string path = season.Show.Poster;
if (path == null)
return Task.FromResult<string>(null);
string thumb = Path.Combine(_files.GetExtraDirectory(path), $"season-{season.SeasonNumber}.jpg");
return Task.FromResult(File.Exists(thumb) ? Path.GetFullPath(thumb) : null);
}
public Task<string> GetEpisodeThumb(Episode episode)
{
string path = episode.Path;
// TODO use show's path for get extra directory. If seasons folder are used, episodes may not be directly in the show folder.
return Task.FromResult(Path.Combine(
_files.GetExtraDirectory(Path.GetDirectoryName(path)),
"Thumbnails",
$"{Path.GetFileNameWithoutExtension(path)}.jpg"));
}
public Task<string> GetPeoplePoster(People people)
{
if (people == null)
throw new ArgumentNullException(nameof(people));
string thumbPath = Path.GetFullPath(Path.Combine(_peoplePath, $"{people.Slug}.jpg"));
if (!thumbPath.StartsWith(_peoplePath) || File.Exists(thumbPath))
return Task.FromResult<string>(null);
return Task.FromResult(thumbPath);
}
public Task<string> GetProviderLogo(ProviderID provider)
{
if (provider == null)
throw new ArgumentNullException(nameof(provider));
string thumbPath = Path.GetFullPath(Path.Combine(_providerPath, $"{provider.Slug}.jpg"));
return Task.FromResult(thumbPath.StartsWith(_providerPath) ? thumbPath : null);
}
} }
} }

View File

@ -71,11 +71,13 @@ namespace Kyoo.Controllers
} }
} }
private readonly IFileManager _files;
private readonly string _transmuxPath; private readonly string _transmuxPath;
private readonly string _transcodePath; private readonly string _transcodePath;
public Transcoder(IConfiguration config) public Transcoder(IConfiguration config, IFileManager files)
{ {
_files = files;
_transmuxPath = Path.GetFullPath(config.GetValue<string>("transmuxTempPath")); _transmuxPath = Path.GetFullPath(config.GetValue<string>("transmuxTempPath"));
_transcodePath = Path.GetFullPath(config.GetValue<string>("transcodeTempPath")); _transcodePath = Path.GetFullPath(config.GetValue<string>("transcodeTempPath"));
@ -85,9 +87,10 @@ namespace Kyoo.Controllers
public Task<Track[]> ExtractInfos(string path, bool reextract) public Task<Track[]> ExtractInfos(string path, bool reextract)
{ {
string dir = Path.GetDirectoryName(path); string dir = _files.GetExtraDirectory(path);
if (dir == null) if (dir == null)
throw new ArgumentException("Invalid path."); throw new ArgumentException("Invalid path.");
// TODO invalid path here.
dir = Path.Combine(dir, "Extra"); dir = Path.Combine(dir, "Extra");
return Task.Factory.StartNew( return Task.Factory.StartNew(
() => TranscoderAPI.ExtractInfos(path, dir, reextract), () => TranscoderAPI.ExtractInfos(path, dir, reextract),

View File

@ -158,7 +158,7 @@ namespace Kyoo
services.AddScoped<DbContext, DatabaseContext>(); services.AddScoped<DbContext, DatabaseContext>();
services.AddScoped<ILibraryManager, LibraryManager>(); services.AddScoped<ILibraryManager, LibraryManager>();
services.AddScoped<IFileManager, FileManager>(); services.AddSingleton<IFileManager, FileManager>();
services.AddSingleton<ITranscoder, Transcoder>(); services.AddSingleton<ITranscoder, Transcoder>();
services.AddSingleton<IThumbnailsManager, ThumbnailsManager>(); services.AddSingleton<IThumbnailsManager, ThumbnailsManager>();
services.AddSingleton<IProviderManager, ProviderManager>(); services.AddSingleton<IProviderManager, ProviderManager>();

View File

@ -2,7 +2,6 @@
using Kyoo.Models; using Kyoo.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.CommonApi; using Kyoo.CommonApi;
@ -18,11 +17,18 @@ namespace Kyoo.Api
public class EpisodeApi : CrudApi<Episode> public class EpisodeApi : CrudApi<Episode>
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IThumbnailsManager _thumbnails;
private readonly IFileManager _files;
public EpisodeApi(ILibraryManager libraryManager, IConfiguration configuration) public EpisodeApi(ILibraryManager libraryManager,
IConfiguration configuration,
IFileManager files,
IThumbnailsManager thumbnails)
: base(libraryManager.EpisodeRepository, configuration) : base(libraryManager.EpisodeRepository, configuration)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_files = files;
_thumbnails = thumbnails;
} }
[HttpGet("{episodeID:int}/show")] [HttpGet("{episodeID:int}/show")]
@ -156,30 +162,20 @@ namespace Kyoo.Api
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetThumb(int id) public async Task<IActionResult> GetThumb(int id)
{ {
string path = (await _libraryManager.GetEpisode(id))?.Path; Episode episode = await _libraryManager.GetEpisode(id);
if (path == null) if (episode == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbnails.GetEpisodeThumb(episode));
string thumb = Path.ChangeExtension(path, "jpg");
if (System.IO.File.Exists(thumb))
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
return NotFound();
} }
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/thumb")] [HttpGet("{slug}/thumb")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetThumb(string showSlug, int seasonNumber, int episodeNumber) public async Task<IActionResult> GetThumb(string slug)
{ {
string path = (await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber))?.Path; Episode episode = await _libraryManager.GetEpisode(slug);
if (path == null) if (episode == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbnails.GetEpisodeThumb(episode));
string thumb = Path.ChangeExtension(path, "jpg");
if (System.IO.File.Exists(thumb))
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
return NotFound();
} }
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.CommonApi; using Kyoo.CommonApi;
using Kyoo.Controllers; using Kyoo.Controllers;
@ -17,13 +16,18 @@ namespace Kyoo.Api
public class PeopleApi : CrudApi<People> public class PeopleApi : CrudApi<People>
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly string _peoplePath; private readonly IFileManager _files;
private readonly IThumbnailsManager _thumbs;
public PeopleApi(ILibraryManager libraryManager, IConfiguration configuration) public PeopleApi(ILibraryManager libraryManager,
IConfiguration configuration,
IFileManager files,
IThumbnailsManager thumbs)
: base(libraryManager.PeopleRepository, configuration) : base(libraryManager.PeopleRepository, configuration)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_peoplePath = Path.GetFullPath(configuration.GetValue<string>("peoplePath")); _files = files;
_thumbs = thumbs;
} }
[HttpGet("{id:int}/role")] [HttpGet("{id:int}/role")]
@ -86,19 +90,16 @@ namespace Kyoo.Api
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetPeopleIcon(int id) public async Task<IActionResult> GetPeopleIcon(int id)
{ {
string slug = (await _libraryManager.GetPeople(id)).Slug; People people = await _libraryManager.GetPeople(id);
return GetPeopleIcon(slug); return _files.FileResult(await _thumbs.GetPeoplePoster(people));
} }
[HttpGet("{slug}/poster")] [HttpGet("{slug}/poster")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public IActionResult GetPeopleIcon(string slug) public async Task<IActionResult> GetPeopleIcon(string slug)
{ {
string thumbPath = Path.GetFullPath(Path.Combine(_peoplePath, slug + ".jpg")); People people = await _libraryManager.GetPeople(slug);
if (!thumbPath.StartsWith(_peoplePath) || !System.IO.File.Exists(thumbPath)) return _files.FileResult(await _thumbs.GetPeoplePoster(people));
return NotFound();
return new PhysicalFileResult(Path.GetFullPath(thumbPath), "image/jpg");
} }
} }
} }

View File

@ -1,5 +1,3 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.CommonApi; using Kyoo.CommonApi;
using Kyoo.Controllers; using Kyoo.Controllers;
@ -15,33 +13,35 @@ namespace Kyoo.Api
[ApiController] [ApiController]
public class ProviderAPI : CrudApi<ProviderID> public class ProviderAPI : CrudApi<ProviderID>
{ {
private readonly IThumbnailsManager _thumbnails;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly string _providerPath; private readonly IFileManager _files;
public ProviderAPI(ILibraryManager libraryManager, IConfiguration config) public ProviderAPI(ILibraryManager libraryManager,
IConfiguration config,
IFileManager files,
IThumbnailsManager thumbnails)
: base(libraryManager.ProviderRepository, config) : base(libraryManager.ProviderRepository, config)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_providerPath = Path.GetFullPath(config.GetValue<string>("providerPath")); _files = files;
_thumbnails = thumbnails;
} }
[HttpGet("{id:int}/logo")] [HttpGet("{id:int}/logo")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetLogo(int id) public async Task<IActionResult> GetLogo(int id)
{ {
string slug = (await _libraryManager.GetPeople(id)).Slug; ProviderID provider = await _libraryManager.GetProvider(id);
return GetLogo(slug); return _files.FileResult(await _thumbnails.GetProviderLogo(provider));
} }
[HttpGet("{slug}/logo")] [HttpGet("{slug}/logo")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public IActionResult GetLogo(string slug) public async Task<IActionResult> GetLogo(string slug)
{ {
string thumbPath = Path.GetFullPath(Path.Combine(_providerPath, slug + ".jpg")); ProviderID provider = await _libraryManager.GetProvider(slug);
if (!thumbPath.StartsWith(_providerPath) || !System.IO.File.Exists(thumbPath)) return _files.FileResult(await _thumbnails.GetProviderLogo(provider));
return NotFound();
return new PhysicalFileResult(Path.GetFullPath(thumbPath), "image/jpg");
} }
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.CommonApi; using Kyoo.CommonApi;
using Kyoo.Controllers; using Kyoo.Controllers;
@ -18,11 +17,18 @@ namespace Kyoo.Api
public class SeasonApi : CrudApi<Season> public class SeasonApi : CrudApi<Season>
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IThumbnailsManager _thumbs;
private readonly IFileManager _files;
public SeasonApi(ILibraryManager libraryManager, IConfiguration configuration) public SeasonApi(ILibraryManager libraryManager,
IConfiguration configuration,
IThumbnailsManager thumbs,
IFileManager files)
: base(libraryManager.SeasonRepository, configuration) : base(libraryManager.SeasonRepository, configuration)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_thumbs = thumbs;
_files = files;
} }
[HttpGet("{seasonID:int}/episode")] [HttpGet("{seasonID:int}/episode")]
@ -131,31 +137,18 @@ namespace Kyoo.Api
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetThumb(int id) public async Task<IActionResult> GetThumb(int id)
{ {
// TODO remove the next lambda and use a Season.Path (should exit for seasons in a different folder) Season season = await _libraryManager.GetSeason(id);
string path = (await _libraryManager.GetShow(x => x.Seasons.Any(y => y.ID == id)))?.Path; await _libraryManager.Load(season, x => x.Show);
int seasonNumber = (await _libraryManager.GetSeason(id)).SeasonNumber; return _files.FileResult(await _thumbs.GetSeasonPoster(season));
if (path == null)
return NotFound();
string thumb = Path.Combine(path, $"season-{seasonNumber}.jpg");
if (System.IO.File.Exists(thumb))
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
return NotFound();
} }
[HttpGet("{showSlug}-s{seasonNumber:int}/thumb")] [HttpGet("{slug}/thumb")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetThumb(string showSlug, int seasonNumber) public async Task<IActionResult> GetThumb(string slug)
{ {
// TODO use a season.Path Season season = await _libraryManager.GetSeason(slug);
string path = (await _libraryManager.GetShow(showSlug))?.Path; await _libraryManager.Load(season, x => x.Show);
if (path == null) return _files.FileResult(await _thumbs.GetSeasonPoster(season));
return NotFound();
string thumb = Path.Combine(path, $"season-{seasonNumber}.jpg");
if (System.IO.File.Exists(thumb))
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
return NotFound();
} }
} }
} }

View File

@ -9,7 +9,6 @@ using Kyoo.CommonApi;
using Kyoo.Controllers; using Kyoo.Controllers;
using Kyoo.Models.Exceptions; using Kyoo.Models.Exceptions;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
namespace Kyoo.Api namespace Kyoo.Api
@ -20,12 +19,18 @@ namespace Kyoo.Api
public class ShowApi : CrudApi<Show> public class ShowApi : CrudApi<Show>
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private FileExtensionContentTypeProvider _provider; private readonly IFileManager _files;
private readonly IThumbnailsManager _thumbs;
public ShowApi(ILibraryManager libraryManager, IConfiguration configuration) public ShowApi(ILibraryManager libraryManager,
IFileManager files,
IThumbnailsManager thumbs,
IConfiguration configuration)
: base(libraryManager.ShowRepository, configuration) : base(libraryManager.ShowRepository, configuration)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_files = files;
_thumbs = thumbs;
} }
[HttpGet("{showID:int}/season")] [HttpGet("{showID:int}/season")]
@ -374,10 +379,8 @@ namespace Kyoo.Api
string path = (await _libraryManager.GetShow(slug))?.Path; string path = (await _libraryManager.GetShow(slug))?.Path;
if (path == null) if (path == null)
return NotFound(); return NotFound();
path = Path.Combine(path, "Subtitles", "fonts"); path = Path.Combine(_files.GetExtraDirectory(path), "Attachment");
if (!Directory.Exists(path)) return _files.ListFiles(path)
return new Dictionary<string, string>();
return Directory.GetFiles(path)
.ToDictionary(Path.GetFileNameWithoutExtension, .ToDictionary(Path.GetFileNameWithoutExtension,
x => $"{BaseURL}/api/shows/{slug}/fonts/{Path.GetFileName(x)}"); x => $"{BaseURL}/api/shows/{slug}/fonts/{Path.GetFileName(x)}");
} }
@ -385,64 +388,43 @@ namespace Kyoo.Api
[HttpGet("{showSlug}/font/{slug}")] [HttpGet("{showSlug}/font/{slug}")]
[HttpGet("{showSlug}/fonts/{slug}")] [HttpGet("{showSlug}/fonts/{slug}")]
[Authorize(Policy = "Read")] [Authorize(Policy = "Read")]
public async Task<ActionResult> GetFont(string showSlug, string slug) public async Task<IActionResult> GetFont(string showSlug, string slug)
{ {
string path = (await _libraryManager.GetShow(showSlug))?.Path; string path = (await _libraryManager.GetShow(showSlug))?.Path;
if (path == null) if (path == null)
return NotFound(); return NotFound();
string fontPath = Path.Combine(path, "Subtitles", "fonts", slug); path = Path.Combine(_files.GetExtraDirectory(path), "Attachment", slug);
if (!System.IO.File.Exists(fontPath)) return _files.FileResult(path);
return NotFound();
if (_provider == null)
_provider = new FileExtensionContentTypeProvider();
_provider.TryGetContentType(path, out string contentType);
return PhysicalFile(fontPath, contentType ?? "application/x-font-ttf");
} }
[HttpGet("{slug}/poster")] [HttpGet("{slug}/poster")]
[Authorize(Policy = "Read")] [Authorize(Policy = "Read")]
public async Task<ActionResult> GetPoster(string slug) public async Task<IActionResult> GetPoster(string slug)
{ {
string path = (await _libraryManager.GetShow(slug))?.Path; Show show = await _libraryManager.GetShow(slug);
if (path == null) if (show == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbs.GetShowPoster(show));
string poster = Path.Combine(path, "poster.jpg");
if (System.IO.File.Exists(poster))
return new PhysicalFileResult(Path.GetFullPath(poster), "image/jpg");
return NotFound();
} }
[HttpGet("{slug}/logo")] [HttpGet("{slug}/logo")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetLogo(string slug) public async Task<IActionResult> GetLogo(string slug)
{ {
string path = (await _libraryManager.GetShow(slug))?.Path; Show show = await _libraryManager.GetShow(slug);
if (path == null) if (show == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbs.GetShowLogo(show));
string logo = Path.Combine(path, "logo.png");
if (System.IO.File.Exists(logo))
return new PhysicalFileResult(Path.GetFullPath(logo), "image/png");
return NotFound();
} }
[HttpGet("{slug}/backdrop")] [HttpGet("{slug}/backdrop")]
[Authorize(Policy="Read")] [Authorize(Policy="Read")]
public async Task<IActionResult> GetBackdrop(string slug) public async Task<IActionResult> GetBackdrop(string slug)
{ {
string path = (await _libraryManager.GetShow(slug))?.Path; Show show = await _libraryManager.GetShow(slug);
if (path == null) if (show == null)
return NotFound(); return NotFound();
return _files.FileResult(await _thumbs.GetShowBackdrop(show));
string thumb = Path.Combine(path, "backdrop.jpg");
if (System.IO.File.Exists(thumb))
return new PhysicalFileResult(Path.GetFullPath(thumb), "image/jpg");
return NotFound();
} }
} }
} }

View File

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