mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Creating a file system composite
This commit is contained in:
parent
7875c72dd9
commit
bd596638a7
@ -36,7 +36,7 @@ namespace Kyoo.Authentication.Views
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A file manager to send profile pictures
|
/// A file manager to send profile pictures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options about authentication. Those options are monitored and reloads are supported.
|
/// Options about authentication. Those options are monitored and reloads are supported.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -50,7 +50,7 @@ namespace Kyoo.Authentication.Views
|
|||||||
/// <param name="files">A file manager to send profile pictures</param>
|
/// <param name="files">A file manager to send profile pictures</param>
|
||||||
/// <param name="options">Authentication options (this may be hot reloaded)</param>
|
/// <param name="options">Authentication options (this may be hot reloaded)</param>
|
||||||
public AccountApi(IUserRepository users,
|
public AccountApi(IUserRepository users,
|
||||||
IFileManager files,
|
IFileSystem files,
|
||||||
IOptions<AuthenticationOption> options)
|
IOptions<AuthenticationOption> options)
|
||||||
{
|
{
|
||||||
_users = users;
|
_users = users;
|
||||||
@ -205,8 +205,8 @@ namespace Kyoo.Authentication.Views
|
|||||||
user.Username = data.Username;
|
user.Username = data.Username;
|
||||||
if (data.Picture?.Length > 0)
|
if (data.Picture?.Length > 0)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(_options.Value.ProfilePicturePath, user.ID.ToString());
|
string path = _files.Combine(_options.Value.ProfilePicturePath, user.ID.ToString());
|
||||||
await using Stream file = _files.NewFile(path);
|
await using Stream file = await _files.NewFile(path);
|
||||||
await data.Picture.CopyToAsync(file);
|
await data.Picture.CopyToAsync(file);
|
||||||
}
|
}
|
||||||
return await _users.Edit(user, false);
|
return await _users.Edit(user, false);
|
||||||
|
@ -10,7 +10,7 @@ namespace Kyoo.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A service to abstract the file system to allow custom file systems (like distant file systems or external providers)
|
/// A service to abstract the file system to allow custom file systems (like distant file systems or external providers)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IFileManager
|
public interface IFileSystem
|
||||||
{
|
{
|
||||||
// TODO find a way to handle Transmux/Transcode with this system.
|
// TODO find a way to handle Transmux/Transcode with this system.
|
||||||
|
|
||||||
@ -41,14 +41,14 @@ namespace Kyoo.Controllers
|
|||||||
/// <param name="path">The path of the file</param>
|
/// <param name="path">The path of the file</param>
|
||||||
/// <exception cref="FileNotFoundException">If the file could not be found.</exception>
|
/// <exception cref="FileNotFoundException">If the file could not be found.</exception>
|
||||||
/// <returns>A reader to read the file.</returns>
|
/// <returns>A reader to read the file.</returns>
|
||||||
public Stream GetReader([NotNull] string path);
|
public Task<Stream> GetReader([NotNull] string path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new file at <paramref name="path"></paramref>.
|
/// Create a new file at <paramref name="path"></paramref>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path of the new file.</param>
|
/// <param name="path">The path of the new file.</param>
|
||||||
/// <returns>A writer to write to the new file.</returns>
|
/// <returns>A writer to write to the new file.</returns>
|
||||||
public Stream NewFile([NotNull] string path);
|
public Task<Stream> NewFile([NotNull] string path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new directory at the given path
|
/// Create a new directory at the given path
|
||||||
@ -87,24 +87,6 @@ namespace Kyoo.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="show">The show to proceed</param>
|
/// <param name="show">The show to proceed</param>
|
||||||
/// <returns>The extra directory of the show</returns>
|
/// <returns>The extra directory of the show</returns>
|
||||||
public string GetExtraDirectory(Show show);
|
public string GetExtraDirectory([NotNull] Show show);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the extra directory of a season.
|
|
||||||
/// 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="season">The season to proceed</param>
|
|
||||||
/// <returns>The extra directory of the season</returns>
|
|
||||||
public string GetExtraDirectory(Season season);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the extra directory of an episode.
|
|
||||||
/// 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="episode">The episode to proceed</param>
|
|
||||||
/// <returns>The extra directory of the episode</returns>
|
|
||||||
public string GetExtraDirectory(Episode episode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Models.Attributes;
|
using Kyoo.Models.Attributes;
|
||||||
|
using Kyoo.Models.Exceptions;
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
@ -210,6 +211,12 @@ namespace Kyoo.Controllers
|
|||||||
/// they will be set to an available service from the service container before calling this method.
|
/// they will be set to an available service from the service container before calling this method.
|
||||||
/// They also will be removed after this method return (or throw) to prevent dangling services.
|
/// They also will be removed after this method return (or throw) to prevent dangling services.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <exception cref="TaskFailedException">
|
||||||
|
/// An exception meaning that the task has failed for handled reasons like invalid arguments,
|
||||||
|
/// invalid environment, missing plugins or failures not related to a default in the code.
|
||||||
|
/// This exception allow the task to display a failure message to the end user while others exceptions
|
||||||
|
/// will be displayed as unhandled exceptions and display a stack trace.
|
||||||
|
/// </exception>
|
||||||
public Task Run([NotNull] TaskParameters arguments,
|
public Task Run([NotNull] TaskParameters arguments,
|
||||||
[NotNull] IProgress<float> progress,
|
[NotNull] IProgress<float> progress,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0-beta-20204-02" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0-beta-20204-02" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="System.ComponentModel.Composition" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
35
Kyoo.Common/Models/Attributes/FileSystemMetadataAttribute.cs
Normal file
35
Kyoo.Common/Models/Attributes/FileSystemMetadataAttribute.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
|
using Kyoo.Controllers;
|
||||||
|
|
||||||
|
namespace Kyoo.Common.Models.Attributes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An attribute to inform how a <see cref="IFileSystem"/> works.
|
||||||
|
/// </summary>
|
||||||
|
[MetadataAttribute]
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class FileSystemMetadataAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The scheme(s) used to identify this path.
|
||||||
|
/// It can be something like http, https, ftp, file and so on.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If multiples files with the same schemes exists, an exception will be thrown.
|
||||||
|
/// </remarks>
|
||||||
|
public string[] Scheme { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <c>true</c> if the scheme should be removed from the path before calling
|
||||||
|
/// methods of this <see cref="IFileSystem"/>, <c>false</c> otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public bool StripScheme { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public FileSystemMetadataAttribute(string[] schemes)
|
||||||
|
{
|
||||||
|
Scheme = schemes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -95,7 +95,7 @@ namespace Kyoo.Models
|
|||||||
public int? AbsoluteNumber { get; set; }
|
public int? AbsoluteNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the video file for this episode. Any format supported by a <see cref="IFileManager"/> 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; }
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace Kyoo.Models
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the root directory of this show.
|
/// The path of the root directory of this show.
|
||||||
/// This can be any kind of path supported by <see cref="IFileManager"/>
|
/// This can be any kind of path supported by <see cref="IFileSystem"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string Path { get; set; }
|
[SerializeIgnore] public string Path { get; set; }
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ namespace Kyoo.Models
|
|||||||
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="IFileManager"/>.
|
/// 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 { get; set; }
|
||||||
|
@ -62,7 +62,7 @@ namespace Kyoo.Models
|
|||||||
public DateTime? ReleaseDate { get; set; }
|
public DateTime? ReleaseDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the video file for this episode. Any format supported by a <see cref="IFileManager"/> 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; }
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ namespace Kyoo
|
|||||||
/// <example>
|
/// <example>
|
||||||
/// To run <see cref="Merger.MergeLists{T}"/> for a List where you don't know the type at compile type,
|
/// To run <see cref="Merger.MergeLists{T}"/> for a List where you don't know the type at compile type,
|
||||||
/// you could do:
|
/// you could do:
|
||||||
/// <code>
|
/// <code lang="C#">
|
||||||
/// Utility.RunGenericMethod<object>(
|
/// Utility.RunGenericMethod<object>(
|
||||||
/// typeof(Utility),
|
/// typeof(Utility),
|
||||||
/// nameof(MergeLists),
|
/// nameof(MergeLists),
|
||||||
|
143
Kyoo/Controllers/FileSystems/FileSystemComposite.cs
Normal file
143
Kyoo/Controllers/FileSystems/FileSystemComposite.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Autofac.Features.Metadata;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Kyoo.Common.Models.Attributes;
|
||||||
|
using Kyoo.Models;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Kyoo.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A composite that merge every <see cref="IFileSystem"/> available
|
||||||
|
/// using <see cref="FileSystemMetadataAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class FileSystemComposite : IFileSystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The list of <see cref="IFileSystem"/> mapped to their metadata.
|
||||||
|
/// </summary>
|
||||||
|
private readonly ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> _fileSystems;
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
_fileSystems = fileSystems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve the file system that should be used for a given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// The path that was requested.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="usablePath">
|
||||||
|
/// The path that the returned file system wants
|
||||||
|
/// (respecting <see cref="FileSystemMetadataAttribute.StripScheme"/>).
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentException">No file system was registered for the given path.</exception>
|
||||||
|
/// <returns>The file system that should be used for a given path</returns>
|
||||||
|
[NotNull]
|
||||||
|
private IFileSystem _GetFileSystemForPath([NotNull] string path, [NotNull] out string usablePath)
|
||||||
|
{
|
||||||
|
Regex schemeMatcher = new(@"(.+)://(.*)", RegexOptions.Compiled);
|
||||||
|
Match match = schemeMatcher.Match(path);
|
||||||
|
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
usablePath = path;
|
||||||
|
Meta<Func<IFileSystem>, FileSystemMetadataAttribute> defaultFs = _fileSystems
|
||||||
|
.SingleOrDefault(x => x.Metadata.Scheme.Contains(""));
|
||||||
|
if (defaultFs == null)
|
||||||
|
throw new ArgumentException($"No file system registered for the default scheme.");
|
||||||
|
return defaultFs.Value.Invoke();
|
||||||
|
}
|
||||||
|
string scheme = match.Groups[1].Value;
|
||||||
|
Meta<Func<IFileSystem>, FileSystemMetadataAttribute> ret = _fileSystems
|
||||||
|
.SingleOrDefault(x => x.Metadata.Scheme.Contains(scheme));
|
||||||
|
if (ret == null)
|
||||||
|
throw new ArgumentException($"No file system registered for the scheme: {scheme}.");
|
||||||
|
usablePath = ret.Metadata.StripScheme ? match.Groups[2].Value : path;
|
||||||
|
return ret.Value.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
return new NotFoundResult();
|
||||||
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
|
.FileResult(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<Stream> GetReader(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
|
.GetReader(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<Stream> NewFile(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
|
.NewFile(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<string> CreateDirectory(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
|
.CreateDirectory(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Combine(params string[] paths)
|
||||||
|
{
|
||||||
|
return _GetFileSystemForPath(paths[0], out string relativePath)
|
||||||
|
.Combine(paths[1..].Prepend(relativePath).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<ICollection<string>> ListFiles(string path, SearchOption options = SearchOption.TopDirectoryOnly)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
|
.ListFiles(relativePath, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<bool> Exists(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException(nameof(path));
|
||||||
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
|
.Exists(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string GetExtraDirectory(Show show)
|
||||||
|
{
|
||||||
|
if (show == null)
|
||||||
|
throw new ArgumentNullException(nameof(show));
|
||||||
|
return _GetFileSystemForPath(show.Path, out string _)
|
||||||
|
.GetExtraDirectory(show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
Kyoo/Controllers/FileSystems/HttpFileSystem.cs
Normal file
123
Kyoo/Controllers/FileSystems/HttpFileSystem.cs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.Common.Models.Attributes;
|
||||||
|
using Kyoo.Models;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Kyoo.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="IFileSystem"/> for http/https links.
|
||||||
|
/// </summary>
|
||||||
|
[FileSystemMetadata(new [] {"http", "https"})]
|
||||||
|
public class HttpFileSystem : IFileSystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The http client factory used to create clients.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IHttpClientFactory _clientFactory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a <see cref="HttpFileSystem"/> using the given client factory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="factory">The http client factory used to create clients.</param>
|
||||||
|
public HttpFileSystem(IHttpClientFactory factory)
|
||||||
|
{
|
||||||
|
_clientFactory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
return new NotFoundResult();
|
||||||
|
return new HttpForwardResult(new Uri(path), rangeSupport, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<Stream> GetReader(string path)
|
||||||
|
{
|
||||||
|
HttpClient client = _clientFactory.CreateClient();
|
||||||
|
return client.GetStreamAsync(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<Stream> NewFile(string path)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("An http filesystem is readonly, a new file can't be created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<string> CreateDirectory(string path)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("An http filesystem is readonly, a directory can't be created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Combine(params string[] paths)
|
||||||
|
{
|
||||||
|
return Path.Combine(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<ICollection<string>> ListFiles(string path, SearchOption options = SearchOption.TopDirectoryOnly)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Listing files is not supported on an http filesystem.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task<bool> Exists(string path)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Checking if a file exists is not supported on an http filesystem.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string GetExtraDirectory(Show show)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Extras can not be stored inside an http filesystem.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IActionResult"/> to proxy an http request.
|
||||||
|
/// </summary>
|
||||||
|
public class HttpForwardResult : IActionResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path of the request to forward.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Uri _path;
|
||||||
|
/// <summary>
|
||||||
|
/// Should the proxied result support ranges requests?
|
||||||
|
/// </summary>
|
||||||
|
private readonly bool _rangeSupport;
|
||||||
|
/// <summary>
|
||||||
|
/// If not null, override the content type of the resulting request.
|
||||||
|
/// </summary>
|
||||||
|
private readonly string _type;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="HttpForwardResult"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path of the request to forward.</param>
|
||||||
|
/// <param name="rangeSupport">Should the proxied result support ranges requests?</param>
|
||||||
|
/// <param name="type">If not null, override the content type of the resulting request.</param>
|
||||||
|
public HttpForwardResult(Uri path, bool rangeSupport, string type = null)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
_rangeSupport = rangeSupport;
|
||||||
|
_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task ExecuteResultAsync(ActionContext context)
|
||||||
|
{
|
||||||
|
// TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.Common.Models.Attributes;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
@ -9,9 +10,10 @@ using Microsoft.AspNetCore.StaticFiles;
|
|||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="IFileManager"/> for the local filesystem (using System.IO).
|
/// A <see cref="IFileSystem"/> for the local filesystem (using System.IO).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FileManager : IFileManager
|
[FileSystemMetadata(new [] {"", "file"}, StripScheme = true)]
|
||||||
|
public class LocalFileSystem : IFileSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An extension provider to get content types from files extensions.
|
/// An extension provider to get content types from files extensions.
|
||||||
@ -54,19 +56,19 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Stream GetReader(string path)
|
public Task<Stream> GetReader(string path)
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
throw new ArgumentNullException(nameof(path));
|
throw new ArgumentNullException(nameof(path));
|
||||||
return File.OpenRead(path);
|
return Task.FromResult<Stream>(File.OpenRead(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Stream NewFile(string path)
|
public Task<Stream> NewFile(string path)
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
throw new ArgumentNullException(nameof(path));
|
throw new ArgumentNullException(nameof(path));
|
||||||
return File.Create(path);
|
return Task.FromResult<Stream>(File.Create(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -108,24 +110,5 @@ namespace Kyoo.Controllers
|
|||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string GetExtraDirectory(Season season)
|
|
||||||
{
|
|
||||||
if (season.Show == null)
|
|
||||||
throw new NotImplementedException("Can't get season's extra directory when season.Show == null.");
|
|
||||||
// TODO use a season.Path here.
|
|
||||||
string path = Path.Combine(season.Show.Path, "Extra");
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string GetExtraDirectory(Episode episode)
|
|
||||||
{
|
|
||||||
string path = Path.Combine(Path.GetDirectoryName(episode.Path)!, "Extra");
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ namespace Kyoo.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file manager used to download the image if the file is distant
|
/// The file manager used to download the image if the file is distant
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A logger to report errors.
|
/// A logger to report errors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -26,6 +26,10 @@ namespace Kyoo.Controllers
|
|||||||
/// The options containing the base path of people images and provider logos.
|
/// The options containing the base path of people images and provider logos.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IOptionsMonitor<BasicOptions> _options;
|
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"/>.
|
||||||
@ -33,13 +37,16 @@ namespace Kyoo.Controllers
|
|||||||
/// <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="options">The options to use.</param>
|
||||||
public ThumbnailsManager(IFileManager files,
|
/// <param name="library">A library manager used to load shows if they are not loaded.</param>
|
||||||
|
public ThumbnailsManager(IFileSystem files,
|
||||||
ILogger<ThumbnailsManager> logger,
|
ILogger<ThumbnailsManager> logger,
|
||||||
IOptionsMonitor<BasicOptions> options)
|
IOptionsMonitor<BasicOptions> options,
|
||||||
|
Lazy<ILibraryManager> library)
|
||||||
{
|
{
|
||||||
_files = files;
|
_files = files;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_options = options;
|
_options = options;
|
||||||
|
_library = library;
|
||||||
|
|
||||||
options.OnChange(x =>
|
options.OnChange(x =>
|
||||||
{
|
{
|
||||||
@ -66,7 +73,7 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An helper function to download an image using a <see cref="FileManager"/>.
|
/// An helper function to download an image using a <see cref="LocalFileSystem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">The distant url of the image</param>
|
/// <param name="url">The distant url of the image</param>
|
||||||
/// <param name="localPath">The local path of the image</param>
|
/// <param name="localPath">The local path of the image</param>
|
||||||
@ -79,8 +86,8 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await using Stream reader = _files.GetReader(url);
|
await using Stream reader = await _files.GetReader(url);
|
||||||
await using Stream local = _files.NewFile(localPath);
|
await using Stream local = await _files.NewFile(localPath);
|
||||||
await reader.CopyToAsync(local);
|
await reader.CopyToAsync(local);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -185,7 +192,7 @@ namespace Kyoo.Controllers
|
|||||||
if (episode.Thumb == null)
|
if (episode.Thumb == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
string localPath = await GetEpisodeThumb(episode);
|
string localPath = await _GetEpisodeThumb(episode);
|
||||||
if (alwaysDownload || !await _files.Exists(localPath))
|
if (alwaysDownload || !await _files.Exists(localPath))
|
||||||
return await _DownloadImage(episode.Thumb, localPath, $"The thumbnail of {episode.Slug}");
|
return await _DownloadImage(episode.Thumb, localPath, $"The thumbnail of {episode.Slug}");
|
||||||
return false;
|
return false;
|
||||||
@ -218,13 +225,25 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(item));
|
throw new ArgumentNullException(nameof(item));
|
||||||
return Task.FromResult(item switch
|
return item switch
|
||||||
{
|
{
|
||||||
Show show => _files.Combine(_files.GetExtraDirectory(show), "poster.jpg"),
|
Show show => Task.FromResult(_files.Combine(_files.GetExtraDirectory(show), "poster.jpg")),
|
||||||
Season season => _files.Combine(_files.GetExtraDirectory(season), $"season-{season.SeasonNumber}.jpg"),
|
Season season => _GetSeasonPoster(season),
|
||||||
People people => _files.Combine(_options.CurrentValue.PeoplePath, $"{people.Slug}.jpg"),
|
People actor => Task.FromResult(_files.Combine(_options.CurrentValue.PeoplePath, $"{actor.Slug}.jpg")),
|
||||||
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a poster.")
|
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a poster.")
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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 />
|
/// <inheritdoc />
|
||||||
@ -236,14 +255,21 @@ namespace Kyoo.Controllers
|
|||||||
return item switch
|
return item switch
|
||||||
{
|
{
|
||||||
Show show => Task.FromResult(_files.Combine(_files.GetExtraDirectory(show), "backdrop.jpg")),
|
Show show => Task.FromResult(_files.Combine(_files.GetExtraDirectory(show), "backdrop.jpg")),
|
||||||
Episode episode => GetEpisodeThumb(episode),
|
Episode episode => _GetEpisodeThumb(episode),
|
||||||
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a thumbnail.")
|
_ => throw new NotSupportedException($"The type {typeof(T).Name} does not have a thumbnail.")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> GetEpisodeThumb(Episode episode)
|
/// <summary>
|
||||||
|
/// Get the path for an episode's thumbnail.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="episode">The episode to retrieve the thumbnail from</param>
|
||||||
|
/// <returns>The path of the given episode's thumbnail.</returns>
|
||||||
|
private async Task<string> _GetEpisodeThumb(Episode episode)
|
||||||
{
|
{
|
||||||
string dir = _files.Combine(_files.GetExtraDirectory(episode), "Thumbnails");
|
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);
|
await _files.CreateDirectory(dir);
|
||||||
return _files.Combine(dir, $"{Path.GetFileNameWithoutExtension(episode.Path)}.jpg");
|
return _files.Combine(dir, $"{Path.GetFileNameWithoutExtension(episode.Path)}.jpg");
|
||||||
}
|
}
|
||||||
|
@ -72,24 +72,29 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
private readonly IOptions<BasicOptions> _options;
|
private readonly IOptions<BasicOptions> _options;
|
||||||
|
private readonly Lazy<ILibraryManager> _library;
|
||||||
|
|
||||||
public Transcoder(IFileManager files, IOptions<BasicOptions> options)
|
public Transcoder(IFileSystem files, IOptions<BasicOptions> options, Lazy<ILibraryManager> library)
|
||||||
{
|
{
|
||||||
_files = files;
|
_files = files;
|
||||||
_options = options;
|
_options = options;
|
||||||
|
_library = library;
|
||||||
|
|
||||||
if (TranscoderAPI.init() != Marshal.SizeOf<Stream>())
|
if (TranscoderAPI.init() != Marshal.SizeOf<Stream>())
|
||||||
throw new BadTranscoderException();
|
throw new BadTranscoderException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Track[]> ExtractInfos(Episode episode, bool reextract)
|
public async Task<Track[]> ExtractInfos(Episode episode, bool reextract)
|
||||||
{
|
{
|
||||||
string dir = _files.GetExtraDirectory(episode);
|
if (episode.Show == null)
|
||||||
|
await _library.Value.Load(episode, x => x.Show);
|
||||||
|
|
||||||
|
string dir = _files.GetExtraDirectory(episode.Show);
|
||||||
if (dir == null)
|
if (dir == null)
|
||||||
throw new ArgumentException("Invalid path.");
|
throw new ArgumentException("Invalid path.");
|
||||||
return Task.Factory.StartNew(
|
return await Task.Factory.StartNew(
|
||||||
() => TranscoderAPI.ExtractInfos(episode.Path, dir, reextract),
|
() => TranscoderAPI.ExtractInfos(episode.Path, dir, reextract),
|
||||||
TaskCreationOptions.LongRunning);
|
TaskCreationOptions.LongRunning);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace Kyoo
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ICollection<Type> Provides => new[]
|
public ICollection<Type> Provides => new[]
|
||||||
{
|
{
|
||||||
typeof(IFileManager),
|
typeof(IFileSystem),
|
||||||
typeof(ITranscoder),
|
typeof(ITranscoder),
|
||||||
typeof(IThumbnailsManager),
|
typeof(IThumbnailsManager),
|
||||||
typeof(IMetadataProvider),
|
typeof(IMetadataProvider),
|
||||||
@ -101,13 +101,17 @@ namespace Kyoo
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Configure(ContainerBuilder builder)
|
public void Configure(ContainerBuilder builder)
|
||||||
{
|
{
|
||||||
|
builder.RegisterComposite<FileSystemComposite, IFileSystem>();
|
||||||
|
builder.RegisterType<LocalFileSystem>().As<IFileSystem>().SingleInstance();
|
||||||
|
builder.RegisterType<HttpFileSystem>().As<IFileSystem>().SingleInstance();
|
||||||
|
|
||||||
builder.RegisterType<ConfigurationManager>().As<IConfigurationManager>().SingleInstance();
|
builder.RegisterType<ConfigurationManager>().As<IConfigurationManager>().SingleInstance();
|
||||||
builder.RegisterType<FileManager>().As<IFileManager>().SingleInstance();
|
|
||||||
builder.RegisterType<Transcoder>().As<ITranscoder>().SingleInstance();
|
builder.RegisterType<Transcoder>().As<ITranscoder>().SingleInstance();
|
||||||
builder.RegisterType<ThumbnailsManager>().As<IThumbnailsManager>().SingleInstance();
|
builder.RegisterType<ThumbnailsManager>().As<IThumbnailsManager>().SingleInstance();
|
||||||
builder.RegisterType<TaskManager>().As<ITaskManager>().SingleInstance();
|
builder.RegisterType<TaskManager>().As<ITaskManager>().SingleInstance();
|
||||||
builder.RegisterType<LibraryManager>().As<ILibraryManager>().InstancePerLifetimeScope();
|
builder.RegisterType<LibraryManager>().As<ILibraryManager>().InstancePerLifetimeScope();
|
||||||
builder.RegisterType<RegexIdentifier>().As<IIdentifier>().SingleInstance();
|
builder.RegisterType<RegexIdentifier>().As<IIdentifier>().SingleInstance();
|
||||||
|
|
||||||
builder.RegisterComposite<ProviderComposite, IMetadataProvider>();
|
builder.RegisterComposite<ProviderComposite, IMetadataProvider>();
|
||||||
builder.Register(x => (AProviderComposite)x.Resolve<IMetadataProvider>());
|
builder.Register(x => (AProviderComposite)x.Resolve<IMetadataProvider>());
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
<ProjectReference Include="../Kyoo.CommonAPI/Kyoo.CommonAPI.csproj" />
|
<ProjectReference Include="../Kyoo.CommonAPI/Kyoo.CommonAPI.csproj" />
|
||||||
<PackageReference Include="Autofac" Version="6.2.0" />
|
<PackageReference Include="Autofac" Version="6.2.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
|
||||||
|
<PackageReference Include="Autofac.Extras.AttributeMetadata" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.8" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.17" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.17" />
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
|
using Autofac.Extras.AttributeMetadata;
|
||||||
using Kyoo.Authentication;
|
using Kyoo.Authentication;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
using Kyoo.Models.Options;
|
using Kyoo.Models.Options;
|
||||||
@ -76,6 +77,7 @@ namespace Kyoo
|
|||||||
|
|
||||||
public void ConfigureContainer(ContainerBuilder builder)
|
public void ConfigureContainer(ContainerBuilder builder)
|
||||||
{
|
{
|
||||||
|
builder.RegisterModule<AttributedMetadataModule>();
|
||||||
builder.RegisterInstance(_plugins).As<IPluginManager>().ExternallyOwned();
|
builder.RegisterInstance(_plugins).As<IPluginManager>().ExternallyOwned();
|
||||||
builder.RegisterTask<PluginInitializer>();
|
builder.RegisterTask<PluginInitializer>();
|
||||||
_plugins.ConfigureContainer(builder);
|
_plugins.ConfigureContainer(builder);
|
||||||
|
@ -46,7 +46,7 @@ namespace Kyoo.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file manager used walk inside directories and check they existences.
|
/// The file manager used walk inside directories and check they existences.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Injected] public IFileManager FileManager { private get; set; }
|
[Injected] public IFileSystem FileSystem { private get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A task manager used to create sub tasks for each episode to add to the database.
|
/// A task manager used to create sub tasks for each episode to add to the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -111,7 +111,7 @@ namespace Kyoo.Tasks
|
|||||||
Logger.LogInformation("Scanning library {Library} at {Paths}", library.Name, library.Paths);
|
Logger.LogInformation("Scanning library {Library} at {Paths}", library.Name, library.Paths);
|
||||||
foreach (string path in library.Paths)
|
foreach (string path in library.Paths)
|
||||||
{
|
{
|
||||||
ICollection<string> files = await FileManager.ListFiles(path, SearchOption.AllDirectories);
|
ICollection<string> files = await FileSystem.ListFiles(path, SearchOption.AllDirectories);
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
@ -39,7 +39,7 @@ namespace Kyoo.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The file manager used walk inside directories and check they existences.
|
/// The file manager used walk inside directories and check they existences.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Injected] public IFileManager FileManager { private get; set; }
|
[Injected] public IFileSystem FileSystem { private get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger used to inform the user that episodes has been removed.
|
/// The logger used to inform the user that episodes has been removed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -58,7 +58,7 @@ namespace Kyoo.Tasks
|
|||||||
progress.Report(count / delCount * 100);
|
progress.Report(count / delCount * 100);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (await FileManager.Exists(show.Path))
|
if (await FileSystem.Exists(show.Path))
|
||||||
continue;
|
continue;
|
||||||
Logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo",
|
Logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo",
|
||||||
show.Title, show.Path);
|
show.Title, show.Path);
|
||||||
@ -70,7 +70,7 @@ namespace Kyoo.Tasks
|
|||||||
progress.Report(count / delCount * 100);
|
progress.Report(count / delCount * 100);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (await FileManager.Exists(episode.Path))
|
if (await FileSystem.Exists(episode.Path))
|
||||||
continue;
|
continue;
|
||||||
Logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo",
|
Logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo",
|
||||||
episode.Slug, episode.Path);
|
episode.Slug, episode.Path);
|
||||||
|
@ -21,11 +21,11 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IThumbnailsManager _thumbnails;
|
private readonly IThumbnailsManager _thumbnails;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
|
|
||||||
public EpisodeApi(ILibraryManager libraryManager,
|
public EpisodeApi(ILibraryManager libraryManager,
|
||||||
IOptions<BasicOptions> options,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files,
|
IFileSystem files,
|
||||||
IThumbnailsManager thumbnails)
|
IThumbnailsManager thumbnails)
|
||||||
: base(libraryManager.EpisodeRepository, options.Value.PublicUrl)
|
: base(libraryManager.EpisodeRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
|
@ -18,12 +18,12 @@ namespace Kyoo.Api
|
|||||||
public class PeopleApi : CrudApi<People>
|
public class PeopleApi : CrudApi<People>
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
private readonly IThumbnailsManager _thumbs;
|
private readonly IThumbnailsManager _thumbs;
|
||||||
|
|
||||||
public PeopleApi(ILibraryManager libraryManager,
|
public PeopleApi(ILibraryManager libraryManager,
|
||||||
IOptions<BasicOptions> options,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files,
|
IFileSystem files,
|
||||||
IThumbnailsManager thumbs)
|
IThumbnailsManager thumbs)
|
||||||
: base(libraryManager.PeopleRepository, options.Value.PublicUrl)
|
: base(libraryManager.PeopleRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
|
@ -17,11 +17,11 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly IThumbnailsManager _thumbnails;
|
private readonly IThumbnailsManager _thumbnails;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
|
|
||||||
public ProviderApi(ILibraryManager libraryManager,
|
public ProviderApi(ILibraryManager libraryManager,
|
||||||
IOptions<BasicOptions> options,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files,
|
IFileSystem files,
|
||||||
IThumbnailsManager thumbnails)
|
IThumbnailsManager thumbnails)
|
||||||
: base(libraryManager.ProviderRepository, options.Value.PublicUrl)
|
: base(libraryManager.ProviderRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
|
@ -20,12 +20,12 @@ namespace Kyoo.Api
|
|||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IThumbnailsManager _thumbs;
|
private readonly IThumbnailsManager _thumbs;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
|
|
||||||
public SeasonApi(ILibraryManager libraryManager,
|
public SeasonApi(ILibraryManager libraryManager,
|
||||||
IOptions<BasicOptions> options,
|
IOptions<BasicOptions> options,
|
||||||
IThumbnailsManager thumbs,
|
IThumbnailsManager thumbs,
|
||||||
IFileManager files)
|
IFileSystem files)
|
||||||
: base(libraryManager.SeasonRepository, options.Value.PublicUrl)
|
: base(libraryManager.SeasonRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
@ -23,11 +23,11 @@ namespace Kyoo.Api
|
|||||||
public class ShowApi : CrudApi<Show>
|
public class ShowApi : CrudApi<Show>
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
private readonly IThumbnailsManager _thumbs;
|
private readonly IThumbnailsManager _thumbs;
|
||||||
|
|
||||||
public ShowApi(ILibraryManager libraryManager,
|
public ShowApi(ILibraryManager libraryManager,
|
||||||
IFileManager files,
|
IFileSystem files,
|
||||||
IThumbnailsManager thumbs,
|
IThumbnailsManager thumbs,
|
||||||
IOptions<BasicOptions> options)
|
IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.ShowRepository, options.Value.PublicUrl)
|
: base(libraryManager.ShowRepository, options.Value.PublicUrl)
|
||||||
|
@ -14,9 +14,9 @@ namespace Kyoo.Api
|
|||||||
public class SubtitleApi : ControllerBase
|
public class SubtitleApi : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
|
|
||||||
public SubtitleApi(ILibraryManager libraryManager, IFileManager files)
|
public SubtitleApi(ILibraryManager libraryManager, IFileSystem files)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_files = files;
|
_files = files;
|
||||||
@ -71,9 +71,9 @@ namespace Kyoo.Api
|
|||||||
public class ConvertSubripToVtt : IActionResult
|
public class ConvertSubripToVtt : IActionResult
|
||||||
{
|
{
|
||||||
private readonly string _path;
|
private readonly string _path;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
|
|
||||||
public ConvertSubripToVtt(string subtitlePath, IFileManager files)
|
public ConvertSubripToVtt(string subtitlePath, IFileSystem files)
|
||||||
{
|
{
|
||||||
_path = subtitlePath;
|
_path = subtitlePath;
|
||||||
_files = files;
|
_files = files;
|
||||||
@ -92,7 +92,7 @@ namespace Kyoo.Api
|
|||||||
await writer.WriteLineAsync("");
|
await writer.WriteLineAsync("");
|
||||||
await writer.WriteLineAsync("");
|
await writer.WriteLineAsync("");
|
||||||
|
|
||||||
using StreamReader reader = new(_files.GetReader(_path));
|
using StreamReader reader = new(await _files.GetReader(_path));
|
||||||
string line;
|
string line;
|
||||||
while ((line = await reader.ReadLineAsync()) != null)
|
while ((line = await reader.ReadLineAsync()) != null)
|
||||||
{
|
{
|
||||||
|
@ -18,12 +18,12 @@ namespace Kyoo.Api
|
|||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ITranscoder _transcoder;
|
private readonly ITranscoder _transcoder;
|
||||||
private readonly IOptions<BasicOptions> _options;
|
private readonly IOptions<BasicOptions> _options;
|
||||||
private readonly IFileManager _files;
|
private readonly IFileSystem _files;
|
||||||
|
|
||||||
public VideoApi(ILibraryManager libraryManager,
|
public VideoApi(ILibraryManager libraryManager,
|
||||||
ITranscoder transcoder,
|
ITranscoder transcoder,
|
||||||
IOptions<BasicOptions> options,
|
IOptions<BasicOptions> options,
|
||||||
IFileManager files)
|
IFileSystem files)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_transcoder = transcoder;
|
_transcoder = transcoder;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user