mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
FileSystem: Reworking the extra directory
This commit is contained in:
parent
924d03291c
commit
87e1b5aca1
@ -81,12 +81,13 @@ namespace Kyoo.Controllers
|
|||||||
public Task<bool> Exists([NotNull] string path);
|
public Task<bool> Exists([NotNull] string path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the extra directory of a show.
|
/// Get the extra directory of a resource <typeparamref name="T"/>.
|
||||||
/// This method is in this system to allow a filesystem to use a different metadata policy for one.
|
/// This method is in this system to allow a filesystem to use a different metadata policy for one.
|
||||||
/// It can be useful if the filesystem is readonly.
|
/// It can be useful if the filesystem is readonly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="show">The show to proceed</param>
|
/// <param name="resource">The resource to proceed</param>
|
||||||
/// <returns>The extra directory of the show</returns>
|
/// <typeparam name="T">The type of the resource.</typeparam>
|
||||||
public string GetExtraDirectory([NotNull] Show show);
|
/// <returns>The extra directory of the resource.</returns>
|
||||||
|
public Task<string> GetExtraDirectory<T>([NotNull] T resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -225,42 +225,51 @@ namespace Kyoo.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The source object.</param>
|
/// <param name="obj">The source object.</param>
|
||||||
/// <param name="member">A getter function for the member to load</param>
|
/// <param name="member">A getter function for the member to load</param>
|
||||||
|
/// <param name="force">
|
||||||
|
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||||
|
/// </param>
|
||||||
/// <typeparam name="T">The type of the source object</typeparam>
|
/// <typeparam name="T">The type of the source object</typeparam>
|
||||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||||
/// <returns>The param <see cref="obj"/></returns>
|
/// <returns>The param <see cref="obj"/></returns>
|
||||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}})"/>
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||||
/// <seealso cref="Load{T}(T, System.String)"/>
|
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||||
/// <seealso cref="Load(IResource, string)"/>
|
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member)
|
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member, bool force = false)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
where T2 : class, IResource, new();
|
where T2 : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load a collection of related resource
|
/// Load a collection of related resource
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The source object.</param>
|
/// <param name="obj">The source object.</param>
|
||||||
/// <param name="member">A getter function for the member to load</param>
|
/// <param name="member">A getter function for the member to load</param>
|
||||||
|
/// <param name="force">
|
||||||
|
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||||
|
/// </param>
|
||||||
/// <typeparam name="T">The type of the source object</typeparam>
|
/// <typeparam name="T">The type of the source object</typeparam>
|
||||||
/// <typeparam name="T2">The related resource's type</typeparam>
|
/// <typeparam name="T2">The related resource's type</typeparam>
|
||||||
/// <returns>The param <see cref="obj"/></returns>
|
/// <returns>The param <see cref="obj"/></returns>
|
||||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,T2}})"/>
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||||
/// <seealso cref="Load{T}(T, System.String)"/>
|
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||||
/// <seealso cref="Load(IResource, string)"/>
|
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, ICollection<T2>>> member)
|
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, ICollection<T2>>> member, bool force = false)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
where T2 : class, new();
|
where T2 : class;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load a related resource by it's name
|
/// Load a related resource by it's name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The source object.</param>
|
/// <param name="obj">The source object.</param>
|
||||||
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
|
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
|
||||||
|
/// <param name="force">
|
||||||
|
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||||
|
/// </param>
|
||||||
/// <typeparam name="T">The type of the source object</typeparam>
|
/// <typeparam name="T">The type of the source object</typeparam>
|
||||||
/// <returns>The param <see cref="obj"/></returns>
|
/// <returns>The param <see cref="obj"/></returns>
|
||||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,T2}})"/>
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}})"/>
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||||
/// <seealso cref="Load(IResource, string)"/>
|
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||||
Task<T> Load<T>([NotNull] T obj, string memberName)
|
Task<T> Load<T>([NotNull] T obj, string memberName, bool force = false)
|
||||||
where T : class, IResource;
|
where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -268,10 +277,13 @@ namespace Kyoo.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The source object.</param>
|
/// <param name="obj">The source object.</param>
|
||||||
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
|
/// <param name="memberName">The name of the resource to load (case sensitive)</param>
|
||||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,T2}})"/>
|
/// <param name="force">
|
||||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}})"/>
|
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||||
/// <seealso cref="Load{T}(T, System.String)"/>
|
/// </param>
|
||||||
Task Load([NotNull] IResource obj, string memberName);
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||||
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||||
|
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||||
|
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get items (A wrapper arround shows or collections) from a library.
|
/// Get items (A wrapper arround shows or collections) from a library.
|
||||||
|
@ -162,34 +162,6 @@ namespace Kyoo.Controllers
|
|||||||
return await EpisodeRepository.GetOrDefault(showSlug, seasonNumber, episodeNumber);
|
return await EpisodeRepository.GetOrDefault(showSlug, seasonNumber, episodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<T> Load<T, T2>(T obj, Expression<Func<T, T2>> member)
|
|
||||||
where T : class, IResource
|
|
||||||
where T2 : class, IResource, new()
|
|
||||||
{
|
|
||||||
if (member == null)
|
|
||||||
throw new ArgumentNullException(nameof(member));
|
|
||||||
return Load(obj, Utility.GetPropertyName(member));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<T> Load<T, T2>(T obj, Expression<Func<T, ICollection<T2>>> member)
|
|
||||||
where T : class, IResource
|
|
||||||
where T2 : class, new()
|
|
||||||
{
|
|
||||||
if (member == null)
|
|
||||||
throw new ArgumentNullException(nameof(member));
|
|
||||||
return Load(obj, Utility.GetPropertyName(member));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public async Task<T> Load<T>(T obj, string memberName)
|
|
||||||
where T : class, IResource
|
|
||||||
{
|
|
||||||
await Load(obj as IResource, memberName);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set relations between to objects.
|
/// Set relations between to objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -211,11 +183,46 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task Load(IResource obj, string memberName)
|
public Task<T> Load<T, T2>(T obj, Expression<Func<T, T2>> member, bool force = false)
|
||||||
|
where T : class, IResource
|
||||||
|
where T2 : class, IResource
|
||||||
|
{
|
||||||
|
if (member == null)
|
||||||
|
throw new ArgumentNullException(nameof(member));
|
||||||
|
return Load(obj, Utility.GetPropertyName(member), force);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<T> Load<T, T2>(T obj, Expression<Func<T, ICollection<T2>>> member, bool force = false)
|
||||||
|
where T : class, IResource
|
||||||
|
where T2 : class
|
||||||
|
{
|
||||||
|
if (member == null)
|
||||||
|
throw new ArgumentNullException(nameof(member));
|
||||||
|
return Load(obj, Utility.GetPropertyName(member), force);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<T> Load<T>(T obj, string memberName, bool force = false)
|
||||||
|
where T : class, IResource
|
||||||
|
{
|
||||||
|
await Load(obj as IResource, memberName, force);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task Load(IResource obj, string memberName, bool force = false)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
|
object existingValue = obj.GetType()
|
||||||
|
.GetProperties()
|
||||||
|
.FirstOrDefault(x => string.Equals(x.Name, memberName, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
?.GetValue(obj);
|
||||||
|
if (existingValue != null && !force)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
return (obj, member: memberName) switch
|
return (obj, member: memberName) switch
|
||||||
{
|
{
|
||||||
(Library l, nameof(Library.Providers)) => ProviderRepository
|
(Library l, nameof(Library.Providers)) => ProviderRepository
|
||||||
|
@ -8,7 +8,9 @@ using Autofac.Features.Metadata;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Common.Models.Attributes;
|
using Kyoo.Common.Models.Attributes;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
@ -23,14 +25,31 @@ namespace Kyoo.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> _fileSystems;
|
private readonly ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> _fileSystems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The library manager used to load shows to retrieve their path
|
||||||
|
/// (only if the option is set to metadata in show)
|
||||||
|
/// </summary>
|
||||||
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Options to check if the metadata should be kept in the show directory or in a kyoo's directory.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IOptionsMonitor<BasicOptions> _options;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="FileSystemComposite"/> from a list of <see cref="IFileSystem"/> mapped to their
|
/// Create a new <see cref="FileSystemComposite"/> from a list of <see cref="IFileSystem"/> mapped to their
|
||||||
/// metadata.
|
/// metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fileSystems">The list of filesystem mapped to their metadata.</param>
|
/// <param name="fileSystems">The list of filesystem mapped to their metadata.</param>
|
||||||
public FileSystemComposite(ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> fileSystems)
|
/// <param name="libraryManager">The library manager used to load shows to retrieve their path.</param>
|
||||||
|
/// <param name="options">The options to use.</param>
|
||||||
|
public FileSystemComposite(ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> fileSystems,
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
IOptionsMonitor<BasicOptions> options)
|
||||||
{
|
{
|
||||||
_fileSystems = fileSystems;
|
_fileSystems = fileSystems;
|
||||||
|
_libraryManager = libraryManager;
|
||||||
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,12 +151,37 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetExtraDirectory(Show show)
|
public async Task<string> GetExtraDirectory<T>(T resource)
|
||||||
{
|
{
|
||||||
if (show == null)
|
switch (resource)
|
||||||
throw new ArgumentNullException(nameof(show));
|
{
|
||||||
return _GetFileSystemForPath(show.Path, out string _)
|
case Season season:
|
||||||
.GetExtraDirectory(show);
|
await _libraryManager.Load(season, x => x.Show);
|
||||||
|
break;
|
||||||
|
case Episode episode:
|
||||||
|
await _libraryManager.Load(episode, x => x.Show);
|
||||||
|
break;
|
||||||
|
case Track track:
|
||||||
|
await _libraryManager.Load(track, x => x.Episode);
|
||||||
|
await _libraryManager.Load(track.Episode, x => x.Show);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFileSystem fs = resource switch
|
||||||
|
{
|
||||||
|
Show show => _GetFileSystemForPath(show.Path, out string _),
|
||||||
|
Season season => _GetFileSystemForPath(season.Show.Path, out string _),
|
||||||
|
Episode episode => _GetFileSystemForPath(episode.Show.Path, out string _),
|
||||||
|
Track track => _GetFileSystemForPath(track.Episode.Show.Path, out string _),
|
||||||
|
_ => _GetFileSystemForPath(_options.CurrentValue.MetadataPath, out string _)
|
||||||
|
};
|
||||||
|
string path = await fs.GetExtraDirectory(resource);
|
||||||
|
if (resource is IResource res)
|
||||||
|
path ??= Combine(_options.CurrentValue.MetadataPath, res.Slug, typeof(T).Name);
|
||||||
|
else
|
||||||
|
path ??= Combine(_options.CurrentValue.MetadataPath, typeof(T).Name);
|
||||||
|
await CreateDirectory(path);
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,7 +76,7 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetExtraDirectory(Show show)
|
public Task<string> GetExtraDirectory<T>(T resource)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("Extras can not be stored inside an http filesystem.");
|
throw new NotSupportedException("Extras can not be stored inside an http filesystem.");
|
||||||
}
|
}
|
||||||
@ -117,7 +117,12 @@ namespace Kyoo.Controllers
|
|||||||
public Task ExecuteResultAsync(ActionContext context)
|
public Task ExecuteResultAsync(ActionContext context)
|
||||||
{
|
{
|
||||||
// TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15
|
// TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15
|
||||||
throw new NotImplementedException();
|
|
||||||
|
// Silence unused warnings
|
||||||
|
if (_path != null || _rangeSupport || _type == null)
|
||||||
|
throw new NotImplementedException();
|
||||||
|
else
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,8 +4,10 @@ using System.IO;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Common.Models.Attributes;
|
using Kyoo.Common.Models.Attributes;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
|
using Kyoo.Models.Options;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
@ -20,6 +22,20 @@ namespace Kyoo.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private FileExtensionContentTypeProvider _provider;
|
private FileExtensionContentTypeProvider _provider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Options to check if the metadata should be kept in the show directory or in a kyoo's directory.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IOptionsMonitor<BasicOptions> _options;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="LocalFileSystem"/> with the specified options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">The options to use.</param>
|
||||||
|
public LocalFileSystem(IOptionsMonitor<BasicOptions> options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the content type of a file using it's extension.
|
/// Get the content type of a file using it's extension.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -104,11 +120,18 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetExtraDirectory(Show show)
|
public Task<string> GetExtraDirectory<T>(T resource)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(show.Path, "Extra");
|
if (!_options.CurrentValue.MetadataInShow)
|
||||||
Directory.CreateDirectory(path);
|
return null;
|
||||||
return path;
|
return Task.FromResult(resource switch
|
||||||
|
{
|
||||||
|
Show show => Combine(show.Path, "Extra"),
|
||||||
|
Season season => Combine(season.Show.Path, "Extra", "Season"),
|
||||||
|
Episode episode => Combine(episode.Show.Path, "Extra", "Episode"),
|
||||||
|
Track track => Combine(track.Episode.Show.Path, "Track"),
|
||||||
|
_ => null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,9 +3,7 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kyoo.Models.Options;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
@ -22,37 +20,17 @@ namespace Kyoo.Controllers
|
|||||||
/// A logger to report errors.
|
/// A logger to report errors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger<ThumbnailsManager> _logger;
|
private readonly ILogger<ThumbnailsManager> _logger;
|
||||||
/// <summary>
|
|
||||||
/// The options containing the base path of people images and provider logos.
|
|
||||||
/// </summary>
|
|
||||||
private readonly IOptionsMonitor<BasicOptions> _options;
|
|
||||||
/// <summary>
|
|
||||||
/// A library manager used to load episode and seasons shows if they are not loaded.
|
|
||||||
/// </summary>
|
|
||||||
private readonly Lazy<ILibraryManager> _library;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="ThumbnailsManager"/>.
|
/// Create a new <see cref="ThumbnailsManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="files">The file manager to use.</param>
|
/// <param name="files">The file manager to use.</param>
|
||||||
/// <param name="logger">A logger to report errors</param>
|
/// <param name="logger">A logger to report errors</param>
|
||||||
/// <param name="options">The options to use.</param>
|
|
||||||
/// <param name="library">A library manager used to load shows if they are not loaded.</param>
|
|
||||||
public ThumbnailsManager(IFileSystem files,
|
public ThumbnailsManager(IFileSystem files,
|
||||||
ILogger<ThumbnailsManager> logger,
|
ILogger<ThumbnailsManager> logger)
|
||||||
IOptionsMonitor<BasicOptions> options,
|
|
||||||
Lazy<ILibraryManager> library)
|
|
||||||
{
|
{
|
||||||
_files = files;
|
_files = files;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_options = options;
|
|
||||||
_library = library;
|
|
||||||
|
|
||||||
options.OnChange(x =>
|
|
||||||
{
|
|
||||||
_files.CreateDirectory(x.PeoplePath);
|
|
||||||
_files.CreateDirectory(x.ProviderPath);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -119,35 +97,7 @@ namespace Kyoo.Controllers
|
|||||||
_ => $"{imageID}.jpg"
|
_ => $"{imageID}.jpg"
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO implement a generic way, probably need to rework IFileManager.GetExtraDirectory too.
|
return _files.Combine(await _files.GetExtraDirectory(item), imageName);
|
||||||
switch (item)
|
|
||||||
{
|
|
||||||
case Show show:
|
|
||||||
return _files.Combine(_files.GetExtraDirectory(show), imageName);
|
|
||||||
|
|
||||||
case Season season:
|
|
||||||
if (season.Show == null)
|
|
||||||
await _library.Value.Load(season, x => x.Show);
|
|
||||||
return _files.Combine(
|
|
||||||
_files.GetExtraDirectory(season.Show!),
|
|
||||||
$"season-{season.SeasonNumber}-{imageName}");
|
|
||||||
|
|
||||||
case Episode episode:
|
|
||||||
if (episode.Show == null)
|
|
||||||
await _library.Value.Load(episode, x => x.Show);
|
|
||||||
string dir = _files.Combine(_files.GetExtraDirectory(episode.Show!), "Thumbnails");
|
|
||||||
await _files.CreateDirectory(dir);
|
|
||||||
return _files.Combine(dir, $"{Path.GetFileNameWithoutExtension(episode.Path)}-{imageName}");
|
|
||||||
|
|
||||||
case People actor:
|
|
||||||
return _files.Combine(_options.CurrentValue.PeoplePath, $"{actor.Slug}-{imageName}");
|
|
||||||
|
|
||||||
case Provider provider:
|
|
||||||
return _files.Combine(_options.CurrentValue.ProviderPath, $"{provider.Slug}-{imageName}");
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException($"The type {typeof(T).Name} is not supported.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,10 +88,8 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
public async Task<Track[]> ExtractInfos(Episode episode, bool reextract)
|
public async Task<Track[]> ExtractInfos(Episode episode, bool reextract)
|
||||||
{
|
{
|
||||||
if (episode.Show == null)
|
await _library.Value.Load(episode, x => x.Show);
|
||||||
await _library.Value.Load(episode, x => x.Show);
|
string dir = await _files.GetExtraDirectory(episode.Show);
|
||||||
|
|
||||||
string dir = _files.GetExtraDirectory(episode.Show);
|
|
||||||
if (dir == null)
|
if (dir == null)
|
||||||
throw new ArgumentException("Invalid path.");
|
throw new ArgumentException("Invalid path.");
|
||||||
return await Task.Factory.StartNew(
|
return await Task.Factory.StartNew(
|
||||||
|
@ -25,16 +25,6 @@ namespace Kyoo.Models.Options
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string PluginPath { get; set; } = "plugins/";
|
public string PluginPath { get; set; } = "plugins/";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The path of the people pictures.
|
|
||||||
/// </summary>
|
|
||||||
public string PeoplePath { get; set; } = "people/";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The path of providers icons.
|
|
||||||
/// </summary>
|
|
||||||
public string ProviderPath { get; set; } = "providers/";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The temporary folder to cache transmuxed file.
|
/// The temporary folder to cache transmuxed file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,5 +34,22 @@ namespace Kyoo.Models.Options
|
|||||||
/// The temporary folder to cache transcoded file.
|
/// The temporary folder to cache transcoded file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TranscodePath { get; set; } = "cached/transcode";
|
public string TranscodePath { get; set; } = "cached/transcode";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <c>true</c> if the metadata of a show/season/episode should be stored in the same directory as video files,
|
||||||
|
/// <c>false</c> to save them in a kyoo specific directory.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Some file systems might discard this option to store them somewhere else.
|
||||||
|
/// For example, readonly file systems will probably store them in a kyoo specific directory.
|
||||||
|
/// </remarks>
|
||||||
|
public bool MetadataInShow { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path for metadata if they are not stored near show (see <see cref="MetadataInShow"/>).
|
||||||
|
/// Some resources can't be stored near a show and they are stored in this directory
|
||||||
|
/// (like <see cref="Provider"/>).
|
||||||
|
/// </summary>
|
||||||
|
public string MetadataPath { get; set; } = "metadata/";
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -383,7 +383,7 @@ namespace Kyoo.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Show show = await _libraryManager.Get<Show>(slug);
|
Show show = await _libraryManager.Get<Show>(slug);
|
||||||
string path = Path.Combine(_files.GetExtraDirectory(show), "Attachments");
|
string path = _files.Combine(await _files.GetExtraDirectory(show), "Attachments");
|
||||||
return (await _files.ListFiles(path))
|
return (await _files.ListFiles(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)}");
|
||||||
@ -402,7 +402,7 @@ namespace Kyoo.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Show show = await _libraryManager.Get<Show>(showSlug);
|
Show show = await _libraryManager.Get<Show>(showSlug);
|
||||||
string path = Path.Combine(_files.GetExtraDirectory(show), "Attachments", slug);
|
string path = _files.Combine(await _files.GetExtraDirectory(show), "Attachments", slug);
|
||||||
return _files.FileResult(path);
|
return _files.FileResult(path);
|
||||||
}
|
}
|
||||||
catch (ItemNotFoundException)
|
catch (ItemNotFoundException)
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
"url": "http://*:5000",
|
"url": "http://*:5000",
|
||||||
"publicUrl": "http://localhost:5000/",
|
"publicUrl": "http://localhost:5000/",
|
||||||
"pluginsPath": "plugins/",
|
"pluginsPath": "plugins/",
|
||||||
"peoplePath": "people/",
|
|
||||||
"providerPath": "providers/",
|
|
||||||
"transmuxPath": "cached/transmux",
|
"transmuxPath": "cached/transmux",
|
||||||
"transcodePath": "cached/transcode"
|
"transcodePath": "cached/transcode",
|
||||||
|
"metadataInShow": true,
|
||||||
|
"metadataPath": "metadata/"
|
||||||
},
|
},
|
||||||
|
|
||||||
"database": {
|
"database": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user