mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 15:30:34 -04:00
Creating a registerr subtitle task
This commit is contained in:
parent
f71ae0385c
commit
e66e59cf32
@ -1,5 +1,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
@ -12,10 +13,21 @@ namespace Kyoo.Controllers
|
||||
/// Identify a path and return the parsed metadata.
|
||||
/// </summary>
|
||||
/// <param name="path">The path of the episode file to parse.</param>
|
||||
/// <exception cref="IdentificationFailed">The identifier could not work for the given path.</exception>
|
||||
/// <returns>
|
||||
/// A tuple of models representing parsed metadata.
|
||||
/// If no metadata could be parsed for a type, null can be returned.
|
||||
/// </returns>
|
||||
Task<(Collection, Show, Season, Episode)> Identify(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Identify an external subtitle or track file from it's path and return the parsed metadata.
|
||||
/// </summary>
|
||||
/// <param name="path">The path of the external track file to parse.</param>
|
||||
/// <exception cref="IdentificationFailed">The identifier could not work for the given path.</exception>
|
||||
/// <returns>
|
||||
/// The metadata of the track identified.
|
||||
/// </returns>
|
||||
Task<Track> IdentifyTrack(string path);
|
||||
}
|
||||
}
|
37
Kyoo.Common/Models/Exceptions/IdentificationFailed.cs
Normal file
37
Kyoo.Common/Models/Exceptions/IdentificationFailed.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Kyoo.Controllers;
|
||||
|
||||
namespace Kyoo.Models.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception raised when an <see cref="IIdentifier"/> failed.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class IdentificationFailed : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new <see cref="IdentificationFailed"/> with a default message.
|
||||
/// </summary>
|
||||
public IdentificationFailed()
|
||||
: base("An identification failed.")
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="IdentificationFailed"/> with a custom message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to use.</param>
|
||||
public IdentificationFailed(string message)
|
||||
: base(message)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// The serialization constructor
|
||||
/// </summary>
|
||||
/// <param name="info">Serialization infos</param>
|
||||
/// <param name="context">The serialization context</param>
|
||||
protected IdentificationFailed(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
@ -3,8 +3,9 @@ using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Kyoo.Models.Options;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Kyoo.Models.Watch;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
@ -18,23 +19,16 @@ namespace Kyoo.Controllers
|
||||
/// The configuration of kyoo to retrieve the identifier regex.
|
||||
/// </summary>
|
||||
private readonly IOptions<MediaOptions> _configuration;
|
||||
/// <summary>
|
||||
/// A logger to print errors.
|
||||
/// </summary>
|
||||
private readonly ILogger<RegexIdentifier> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="RegexIdentifier"/>.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The regex patterns to use.</param>
|
||||
/// <param name="logger">The logger to use.</param>
|
||||
public RegexIdentifier(IOptions<MediaOptions> configuration, ILogger<RegexIdentifier> logger)
|
||||
public RegexIdentifier(IOptions<MediaOptions> configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<(Collection, Show, Season, Episode)> Identify(string path)
|
||||
{
|
||||
@ -42,10 +36,7 @@ namespace Kyoo.Controllers
|
||||
Match match = regex.Match(path);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
_logger.LogError("The episode at {Path} does not match the episode's regex", path);
|
||||
return Task.FromResult<(Collection, Show, Season, Episode)>(default);
|
||||
}
|
||||
throw new IdentificationFailed($"The episode at {path} does not match the episode's regex.");
|
||||
|
||||
(Collection collection, Show show, Season season, Episode episode) ret = new();
|
||||
|
||||
@ -81,5 +72,31 @@ namespace Kyoo.Controllers
|
||||
|
||||
return Task.FromResult(ret);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Track> IdentifyTrack(string path)
|
||||
{
|
||||
Regex regex = new(_configuration.Value.SubtitleRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
Match match = regex.Match(path);
|
||||
|
||||
if (!match.Success)
|
||||
throw new IdentificationFailed($"The subtitle at {path} does not match the subtitle's regex.");
|
||||
|
||||
string episodePath = match.Groups["Episode"].Value;
|
||||
return Task.FromResult(new Track
|
||||
{
|
||||
Type = StreamType.Subtitle,
|
||||
Language = match.Groups["Language"].Value,
|
||||
IsDefault = match.Groups["Default"].Value.Length > 0,
|
||||
IsForced = match.Groups["Forced"].Value.Length > 0,
|
||||
Codec = FileExtensions.SubtitleExtensions[Path.GetExtension(path)],
|
||||
IsExternal = true,
|
||||
Path = path,
|
||||
Episode = new Episode
|
||||
{
|
||||
Path = episodePath
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
53
Kyoo/Models/FileExtensions.cs
Normal file
53
Kyoo/Models/FileExtensions.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Kyoo.Models.Watch
|
||||
{
|
||||
public static class FileExtensions
|
||||
{
|
||||
public static readonly string[] VideoExtensions =
|
||||
{
|
||||
".webm",
|
||||
".mkv",
|
||||
".flv",
|
||||
".vob",
|
||||
".ogg",
|
||||
".ogv",
|
||||
".avi",
|
||||
".mts",
|
||||
".m2ts",
|
||||
".ts",
|
||||
".mov",
|
||||
".qt",
|
||||
".asf",
|
||||
".mp4",
|
||||
".m4p",
|
||||
".m4v",
|
||||
".mpg",
|
||||
".mp2",
|
||||
".mpeg",
|
||||
".mpe",
|
||||
".mpv",
|
||||
".m2v",
|
||||
".3gp",
|
||||
".3g2"
|
||||
};
|
||||
|
||||
public static bool IsVideo(string filePath)
|
||||
{
|
||||
return VideoExtensions.Contains(Path.GetExtension(filePath));
|
||||
}
|
||||
|
||||
public static readonly Dictionary<string, string> SubtitleExtensions = new()
|
||||
{
|
||||
{".ass", "ass"},
|
||||
{".str", "subrip"}
|
||||
};
|
||||
|
||||
public static bool IsSubtitle(string filePath)
|
||||
{
|
||||
return SubtitleExtensions.ContainsKey(Path.GetExtension(filePath));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class LazyDi<T> : Lazy<T>
|
||||
{
|
||||
public LazyDi(IServiceProvider provider)
|
||||
: base(provider.GetRequiredService<T>)
|
||||
{ }
|
||||
}
|
||||
}
|
@ -3,13 +3,11 @@ using Kyoo.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Controllers;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Kyoo.Models.Watch;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Kyoo.Tasks
|
||||
@ -86,6 +84,7 @@ namespace Kyoo.Tasks
|
||||
float percent = 0;
|
||||
|
||||
ICollection<Episode> episodes = await LibraryManager.GetAll<Episode>();
|
||||
ICollection<Track> tracks = await LibraryManager.GetAll<Track>();
|
||||
foreach (Library library in libraries)
|
||||
{
|
||||
IProgress<float> reporter = new Progress<float>(x =>
|
||||
@ -93,7 +92,7 @@ namespace Kyoo.Tasks
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
progress.Report(percent + x / libraries.Count);
|
||||
});
|
||||
await Scan(library, episodes, reporter, cancellationToken);
|
||||
await Scan(library, episodes, tracks, reporter, cancellationToken);
|
||||
percent += 100f / libraries.Count;
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
@ -105,6 +104,7 @@ namespace Kyoo.Tasks
|
||||
|
||||
private async Task Scan(Library library,
|
||||
IEnumerable<Episode> episodes,
|
||||
IEnumerable<Track> tracks,
|
||||
IProgress<float> progress,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@ -120,19 +120,20 @@ namespace Kyoo.Tasks
|
||||
// This speeds up the scan process because further episodes of a show are registered when all metadata
|
||||
// of the show has already been fetched.
|
||||
List<IGrouping<string, string>> shows = files
|
||||
.Where(IsVideo)
|
||||
.Where(FileExtensions.IsVideo)
|
||||
.Where(x => episodes.All(y => y.Path != x))
|
||||
.GroupBy(Path.GetDirectoryName)
|
||||
.ToList();
|
||||
|
||||
|
||||
string[] paths = shows.Select(x => x.First())
|
||||
.Concat(shows.SelectMany(x => x.Skip(1)))
|
||||
.ToArray();
|
||||
|
||||
float percent = 0;
|
||||
IProgress<float> reporter = new Progress<float>(x =>
|
||||
{
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
progress.Report((percent + x / paths.Length) / library.Paths.Length);
|
||||
progress.Report((percent + x / paths.Length - 10) / library.Paths.Length);
|
||||
});
|
||||
|
||||
foreach (string episodePath in paths)
|
||||
@ -145,53 +146,27 @@ namespace Kyoo.Tasks
|
||||
percent += 100f / paths.Length;
|
||||
}
|
||||
|
||||
// await Task.WhenAll(files.Where(x => IsSubtitle(x) && tracks.All(y => y.Path != x))
|
||||
// .Select(x => RegisterExternalSubtitle(x, cancellationToken)));
|
||||
|
||||
string[] subtitles = files
|
||||
.Where(FileExtensions.IsSubtitle)
|
||||
.Where(x => tracks.All(y => y.Path != x))
|
||||
.ToArray();
|
||||
percent = 0;
|
||||
reporter = new Progress<float>(x =>
|
||||
{
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
progress.Report((90 + (percent + x / subtitles.Length)) / library.Paths.Length);
|
||||
});
|
||||
|
||||
foreach (string trackPath in subtitles)
|
||||
{
|
||||
TaskManager.StartTask<RegisterSubtitle>(reporter, new Dictionary<string, object>
|
||||
{
|
||||
["path"] = trackPath
|
||||
}, cancellationToken);
|
||||
percent += 100f / subtitles.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly string[] VideoExtensions =
|
||||
{
|
||||
".webm",
|
||||
".mkv",
|
||||
".flv",
|
||||
".vob",
|
||||
".ogg",
|
||||
".ogv",
|
||||
".avi",
|
||||
".mts",
|
||||
".m2ts",
|
||||
".ts",
|
||||
".mov",
|
||||
".qt",
|
||||
".asf",
|
||||
".mp4",
|
||||
".m4p",
|
||||
".m4v",
|
||||
".mpg",
|
||||
".mp2",
|
||||
".mpeg",
|
||||
".mpe",
|
||||
".mpv",
|
||||
".m2v",
|
||||
".3gp",
|
||||
".3g2"
|
||||
};
|
||||
|
||||
private static bool IsVideo(string filePath)
|
||||
{
|
||||
return VideoExtensions.Contains(Path.GetExtension(filePath));
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> SubtitleExtensions = new()
|
||||
{
|
||||
{".ass", "ass"},
|
||||
{".str", "subrip"}
|
||||
};
|
||||
|
||||
private static bool IsSubtitle(string filePath)
|
||||
{
|
||||
return SubtitleExtensions.ContainsKey(Path.GetExtension(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using Kyoo.Controllers;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Kyoo.Models.Exceptions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Kyoo.Tasks
|
||||
{
|
||||
@ -56,11 +55,7 @@ namespace Kyoo.Tasks
|
||||
/// The transcoder used to extract subtitles and metadata.
|
||||
/// </summary>
|
||||
[Injected] public ITranscoder Transcoder { private get; set; }
|
||||
/// <summary>
|
||||
/// The logger used to inform the current status to the console.
|
||||
/// </summary>
|
||||
[Injected] public ILogger<RegisterEpisode> Logger { private get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public TaskParameters GetParameters()
|
||||
{
|
||||
@ -76,58 +71,67 @@ namespace Kyoo.Tasks
|
||||
{
|
||||
string path = arguments["path"].As<string>();
|
||||
Library library = arguments["library"].As<Library>();
|
||||
progress.Report(0);
|
||||
|
||||
try
|
||||
if (library.Providers == null)
|
||||
await LibraryManager.Load(library, x => x.Providers);
|
||||
MetadataProvider.UseProviders(library.Providers);
|
||||
(Collection collection, Show show, Season season, Episode episode) = await Identifier.Identify(path);
|
||||
progress.Report(15);
|
||||
|
||||
collection = await _RegisterAndFill(collection);
|
||||
progress.Report(20);
|
||||
|
||||
Show registeredShow = await _RegisterAndFill(show);
|
||||
if (registeredShow.Path != show.Path)
|
||||
{
|
||||
if (library != null)
|
||||
if (show.StartAir.HasValue)
|
||||
{
|
||||
if (library.Providers == null)
|
||||
await LibraryManager.Load(library, x => x.Providers);
|
||||
MetadataProvider.UseProviders(library.Providers);
|
||||
}
|
||||
|
||||
(Collection collection, Show show, Season season, Episode episode) = await Identifier.Identify(path);
|
||||
|
||||
collection = await _RegisterAndFill(collection);
|
||||
|
||||
Show registeredShow = await _RegisterAndFill(show);
|
||||
if (registeredShow.Path != show.Path)
|
||||
{
|
||||
if (show.StartAir.HasValue)
|
||||
{
|
||||
show.Slug += $"-{show.StartAir.Value.Year}";
|
||||
show = await LibraryManager.Create(show);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("Duplicated show found ({Slug}) at {Path1} and {Path2}",
|
||||
show.Slug, registeredShow.Path, show.Path);
|
||||
return;
|
||||
}
|
||||
show.Slug += $"-{show.StartAir.Value.Year}";
|
||||
show = await LibraryManager.Create(show);
|
||||
}
|
||||
else
|
||||
show = registeredShow;
|
||||
|
||||
if (season != null)
|
||||
season.Show = show;
|
||||
season = await _RegisterAndFill(season);
|
||||
|
||||
episode = await MetadataProvider.Get(episode);
|
||||
episode.Season = season;
|
||||
episode.Tracks = (await Transcoder.ExtractInfos(episode, false))
|
||||
.Where(x => x.Type != StreamType.Attachment)
|
||||
.ToArray();
|
||||
await ThumbnailsManager.DownloadImages(episode);
|
||||
|
||||
await LibraryManager.Create(episode);
|
||||
await LibraryManager.AddShowLink(show, library, collection);
|
||||
}
|
||||
catch (DuplicatedItemException ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Duplicated found at {Path}", path);
|
||||
{
|
||||
throw new DuplicatedItemException($"Duplicated show found ({show.Slug}) " +
|
||||
$"at {registeredShow.Path} and {show.Path}");
|
||||
}
|
||||
}
|
||||
else
|
||||
show = registeredShow;
|
||||
// If they are not already loaded, load external ids to allow metadata providers to use them.
|
||||
if (show.ExternalIDs == null)
|
||||
await LibraryManager.Load(show, x => x.ExternalIDs);
|
||||
progress.Report(50);
|
||||
|
||||
if (season != null)
|
||||
season.Show = show;
|
||||
season = await _RegisterAndFill(season);
|
||||
progress.Report(60);
|
||||
|
||||
episode = await MetadataProvider.Get(episode);
|
||||
progress.Report(70);
|
||||
episode.Show = show;
|
||||
episode.Season = season;
|
||||
episode.Tracks = (await Transcoder.ExtractInfos(episode, false))
|
||||
.Where(x => x.Type != StreamType.Attachment)
|
||||
.ToArray();
|
||||
await ThumbnailsManager.DownloadImages(episode);
|
||||
progress.Report(90);
|
||||
|
||||
await LibraryManager.Create(episode);
|
||||
progress.Report(95);
|
||||
await LibraryManager.AddShowLink(show, library, collection);
|
||||
progress.Report(100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the equivalent item if it already exists in the database,
|
||||
/// if it does not, fill metadata using the metadata provider, download images and register the item to the
|
||||
/// database.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to retrieve or fill and register</param>
|
||||
/// <typeparam name="T">The type of the item</typeparam>
|
||||
/// <returns>The existing or filled item.</returns>
|
||||
private async Task<T> _RegisterAndFill<T>(T item)
|
||||
where T : class, IResource
|
||||
{
|
||||
@ -141,54 +145,5 @@ namespace Kyoo.Tasks
|
||||
await ThumbnailsManager.DownloadImages(item);
|
||||
return await LibraryManager.CreateIfNotExists(item);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
private async Task RegisterExternalSubtitle(string path, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (token.IsCancellationRequested || path.Split(Path.DirectorySeparatorChar).Contains("Subtitles"))
|
||||
return;
|
||||
using IServiceScope serviceScope = ServiceProvider.CreateScope();
|
||||
ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
|
||||
|
||||
string patern = Config.GetValue<string>("subtitleRegex");
|
||||
Regex regex = new(patern, RegexOptions.IgnoreCase);
|
||||
Match match = regex.Match(path);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
await Console.Error.WriteLineAsync($"The subtitle at {path} does not match the subtitle's regex.");
|
||||
return;
|
||||
}
|
||||
|
||||
string episodePath = match.Groups["Episode"].Value;
|
||||
Episode episode = await libraryManager!.Get<Episode>(x => x.Path.StartsWith(episodePath));
|
||||
Track track = new()
|
||||
{
|
||||
Type = StreamType.Subtitle,
|
||||
Language = match.Groups["Language"].Value,
|
||||
IsDefault = match.Groups["Default"].Value.Length > 0,
|
||||
IsForced = match.Groups["Forced"].Value.Length > 0,
|
||||
Codec = SubtitleExtensions[Path.GetExtension(path)],
|
||||
IsExternal = true,
|
||||
Path = path,
|
||||
Episode = episode
|
||||
};
|
||||
|
||||
await libraryManager.Create(track);
|
||||
Console.WriteLine($"Registering subtitle at: {path}.");
|
||||
}
|
||||
catch (ItemNotFoundException)
|
||||
{
|
||||
await Console.Error.WriteLineAsync($"No episode found for subtitle at: ${path}.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Console.Error.WriteLineAsync($"Unknown error while registering subtitle: {ex.Message}");
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
85
Kyoo/Tasks/RegisterSubtitle.cs
Normal file
85
Kyoo/Tasks/RegisterSubtitle.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Controllers;
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Kyoo.Models.Exceptions;
|
||||
|
||||
namespace Kyoo.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// A task to register a new episode
|
||||
/// </summary>
|
||||
public class RegisterSubtitle : ITask
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Slug => "register-sub";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Register subtitle";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Register a new subtitle";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string HelpMessage => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool RunOnStartup => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority => 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <summary>
|
||||
/// An identifier to extract metadata from paths.
|
||||
/// </summary>
|
||||
[Injected] public IIdentifier Identifier { private get; set; }
|
||||
/// <summary>
|
||||
/// The library manager used to register the episode
|
||||
/// </summary>
|
||||
[Injected] public ILibraryManager LibraryManager { private get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public TaskParameters GetParameters()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
TaskParameter.CreateRequired<string>("path", "The path of the episode file"),
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
string path = arguments["path"].As<string>();
|
||||
|
||||
progress.Report(0);
|
||||
Track track = await Identifier.IdentifyTrack(path);
|
||||
progress.Report(25);
|
||||
|
||||
if (track.Episode == null)
|
||||
throw new IdentificationFailed($"No episode identified for the track at {path}");
|
||||
if (track.Episode.ID == 0)
|
||||
{
|
||||
if (track.Episode.Slug != null)
|
||||
track.Episode = await LibraryManager.Get<Episode>(track.Episode.Slug);
|
||||
else if (track.Episode.Path != null)
|
||||
{
|
||||
track.Episode = await LibraryManager.GetOrDefault<Episode>(x => x.Path == track.Episode.Path);
|
||||
if (track.Episode == null)
|
||||
throw new ItemNotFoundException($"No episode found for subtitle at: ${path}.");
|
||||
}
|
||||
else
|
||||
throw new IdentificationFailed($"No episode identified for the track at {path}");
|
||||
}
|
||||
|
||||
progress.Report(50);
|
||||
await LibraryManager.Create(track);
|
||||
progress.Report(100);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user