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);
|
||||
|
||||
/// <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.
|
||||
/// It can be useful if the filesystem is readonly.
|
||||
/// </summary>
|
||||
/// <param name="show">The show to proceed</param>
|
||||
/// <returns>The extra directory of the show</returns>
|
||||
public string GetExtraDirectory([NotNull] Show show);
|
||||
/// <param name="resource">The resource to proceed</param>
|
||||
/// <typeparam name="T">The type of the resource.</typeparam>
|
||||
/// <returns>The extra directory of the resource.</returns>
|
||||
public Task<string> GetExtraDirectory<T>([NotNull] T resource);
|
||||
}
|
||||
}
|
@ -225,42 +225,51 @@ namespace Kyoo.Controllers
|
||||
/// </summary>
|
||||
/// <param name="obj">The source object.</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="T2">The related resource's type</typeparam>
|
||||
/// <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}(T, System.String)"/>
|
||||
/// <seealso cref="Load(IResource, string)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member)
|
||||
/// <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)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member, bool force = false)
|
||||
where T : class, IResource
|
||||
where T2 : class, IResource, new();
|
||||
where T2 : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
/// Load a collection of related resource
|
||||
/// </summary>
|
||||
/// <param name="obj">The source object.</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="T2">The related resource's type</typeparam>
|
||||
/// <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}(T, System.String)"/>
|
||||
/// <seealso cref="Load(IResource, string)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, ICollection<T2>>> member)
|
||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,T2}}, bool)"/>
|
||||
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||
/// <seealso cref="Load(IResource, string, bool)"/>
|
||||
Task<T> Load<T, T2>([NotNull] T obj, Expression<Func<T, ICollection<T2>>> member, bool force = false)
|
||||
where T : class, IResource
|
||||
where T2 : class, new();
|
||||
where T2 : class;
|
||||
|
||||
/// <summary>
|
||||
/// Load a related resource by it's name
|
||||
/// </summary>
|
||||
/// <param name="obj">The source object.</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>
|
||||
/// <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,System.Collections.Generic.ICollection{T2}}})"/>
|
||||
/// <seealso cref="Load(IResource, string)"/>
|
||||
Task<T> Load<T>([NotNull] T 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(IResource, string, bool)"/>
|
||||
Task<T> Load<T>([NotNull] T obj, string memberName, bool force = false)
|
||||
where T : class, IResource;
|
||||
|
||||
/// <summary>
|
||||
@ -268,10 +277,13 @@ namespace Kyoo.Controllers
|
||||
/// </summary>
|
||||
/// <param name="obj">The source object.</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}})"/>
|
||||
/// <seealso cref="Load{T,T2}(T,System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}})"/>
|
||||
/// <seealso cref="Load{T}(T, System.String)"/>
|
||||
Task Load([NotNull] IResource obj, string memberName);
|
||||
/// <param name="force">
|
||||
/// <c>true</c> if you want to load the relation even if it is not null, <c>false</c> otherwise.
|
||||
/// </param>
|
||||
/// <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>
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Set relations between to objects.
|
||||
/// </summary>
|
||||
@ -211,11 +183,46 @@ namespace Kyoo.Controllers
|
||||
}
|
||||
|
||||
/// <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)
|
||||
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
|
||||
{
|
||||
(Library l, nameof(Library.Providers)) => ProviderRepository
|
||||
|
@ -8,7 +8,9 @@ using Autofac.Features.Metadata;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Common.Models.Attributes;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Options;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
@ -23,14 +25,31 @@ namespace Kyoo.Controllers
|
||||
/// </summary>
|
||||
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>
|
||||
/// Create a new <see cref="FileSystemComposite"/> from a list of <see cref="IFileSystem"/> mapped to their
|
||||
/// metadata.
|
||||
/// </summary>
|
||||
/// <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;
|
||||
_libraryManager = libraryManager;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
|
||||
@ -132,12 +151,37 @@ namespace Kyoo.Controllers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetExtraDirectory(Show show)
|
||||
public async Task<string> GetExtraDirectory<T>(T resource)
|
||||
{
|
||||
if (show == null)
|
||||
throw new ArgumentNullException(nameof(show));
|
||||
return _GetFileSystemForPath(show.Path, out string _)
|
||||
.GetExtraDirectory(show);
|
||||
switch (resource)
|
||||
{
|
||||
case Season season:
|
||||
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 />
|
||||
public string GetExtraDirectory(Show show)
|
||||
public Task<string> GetExtraDirectory<T>(T resource)
|
||||
{
|
||||
throw new NotSupportedException("Extras can not be stored inside an http filesystem.");
|
||||
}
|
||||
@ -117,6 +117,11 @@ namespace Kyoo.Controllers
|
||||
public Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
// TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15
|
||||
|
||||
// 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 Kyoo.Common.Models.Attributes;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Options;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
@ -20,6 +22,20 @@ namespace Kyoo.Controllers
|
||||
/// </summary>
|
||||
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>
|
||||
/// Get the content type of a file using it's extension.
|
||||
/// </summary>
|
||||
@ -104,11 +120,18 @@ namespace Kyoo.Controllers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetExtraDirectory(Show show)
|
||||
public Task<string> GetExtraDirectory<T>(T resource)
|
||||
{
|
||||
string path = Path.Combine(show.Path, "Extra");
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
if (!_options.CurrentValue.MetadataInShow)
|
||||
return null;
|
||||
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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Models.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
@ -22,37 +20,17 @@ namespace Kyoo.Controllers
|
||||
/// A logger to report errors.
|
||||
/// </summary>
|
||||
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>
|
||||
/// Create a new <see cref="ThumbnailsManager"/>.
|
||||
/// </summary>
|
||||
/// <param name="files">The file manager to use.</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,
|
||||
ILogger<ThumbnailsManager> logger,
|
||||
IOptionsMonitor<BasicOptions> options,
|
||||
Lazy<ILibraryManager> library)
|
||||
ILogger<ThumbnailsManager> logger)
|
||||
{
|
||||
_files = files;
|
||||
_logger = logger;
|
||||
_options = options;
|
||||
_library = library;
|
||||
|
||||
options.OnChange(x =>
|
||||
{
|
||||
_files.CreateDirectory(x.PeoplePath);
|
||||
_files.CreateDirectory(x.ProviderPath);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -119,35 +97,7 @@ namespace Kyoo.Controllers
|
||||
_ => $"{imageID}.jpg"
|
||||
};
|
||||
|
||||
// TODO implement a generic way, probably need to rework IFileManager.GetExtraDirectory too.
|
||||
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.");
|
||||
}
|
||||
return _files.Combine(await _files.GetExtraDirectory(item), imageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,10 +88,8 @@ namespace Kyoo.Controllers
|
||||
|
||||
public async Task<Track[]> ExtractInfos(Episode episode, bool reextract)
|
||||
{
|
||||
if (episode.Show == null)
|
||||
await _library.Value.Load(episode, x => x.Show);
|
||||
|
||||
string dir = _files.GetExtraDirectory(episode.Show);
|
||||
string dir = await _files.GetExtraDirectory(episode.Show);
|
||||
if (dir == null)
|
||||
throw new ArgumentException("Invalid path.");
|
||||
return await Task.Factory.StartNew(
|
||||
|
@ -25,16 +25,6 @@ namespace Kyoo.Models.Options
|
||||
/// </summary>
|
||||
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>
|
||||
/// The temporary folder to cache transmuxed file.
|
||||
/// </summary>
|
||||
@ -44,5 +34,22 @@ namespace Kyoo.Models.Options
|
||||
/// The temporary folder to cache transcoded file.
|
||||
/// </summary>
|
||||
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
|
||||
{
|
||||
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))
|
||||
.ToDictionary(Path.GetFileNameWithoutExtension,
|
||||
x => $"{BaseURL}api/shows/{slug}/fonts/{Path.GetFileName(x)}");
|
||||
@ -402,7 +402,7 @@ namespace Kyoo.Api
|
||||
try
|
||||
{
|
||||
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);
|
||||
}
|
||||
catch (ItemNotFoundException)
|
||||
|
@ -3,10 +3,10 @@
|
||||
"url": "http://*:5000",
|
||||
"publicUrl": "http://localhost:5000/",
|
||||
"pluginsPath": "plugins/",
|
||||
"peoplePath": "people/",
|
||||
"providerPath": "providers/",
|
||||
"transmuxPath": "cached/transmux",
|
||||
"transcodePath": "cached/transcode"
|
||||
"transcodePath": "cached/transcode",
|
||||
"metadataInShow": true,
|
||||
"metadataPath": "metadata/"
|
||||
},
|
||||
|
||||
"database": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user