mirror of https://github.com/jellyfin/jellyfin.git
#680 - Support new episode file sorting
This commit is contained in:
parent
d4bdd42acf
commit
ccf707e57b
|
@ -224,7 +224,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
public bool EnableAutomaticRestart { get; set; }
|
public bool EnableAutomaticRestart { get; set; }
|
||||||
|
|
||||||
public FileSortingOptions FileSortingOptions { get; set; }
|
public TvFileSortingOptions TvFileSortingOptions { get; set; }
|
||||||
public LiveTvOptions LiveTvOptions { get; set; }
|
public LiveTvOptions LiveTvOptions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -293,7 +293,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
LiveTvOptions = new LiveTvOptions();
|
LiveTvOptions = new LiveTvOptions();
|
||||||
|
|
||||||
FileSortingOptions = new FileSortingOptions();
|
TvFileSortingOptions = new TvFileSortingOptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,12 +316,12 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public int? GuideDays { get; set; }
|
public int? GuideDays { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileSortingOptions
|
public class TvFileSortingOptions
|
||||||
{
|
{
|
||||||
public bool IsEnabled { get; set; }
|
public bool IsEnabled { get; set; }
|
||||||
public int MinFileSizeMb { get; set; }
|
public int MinFileSizeMb { get; set; }
|
||||||
public string[] LeftOverFileExtensionsToDelete { get; set; }
|
public string[] LeftOverFileExtensionsToDelete { get; set; }
|
||||||
public string[] TvWatchLocations { get; set; }
|
public string[] WatchLocations { get; set; }
|
||||||
|
|
||||||
public string SeasonFolderPattern { get; set; }
|
public string SeasonFolderPattern { get; set; }
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableTrialMode { get; set; }
|
public bool EnableTrialMode { get; set; }
|
||||||
|
|
||||||
public FileSortingOptions()
|
public TvFileSortingOptions()
|
||||||
{
|
{
|
||||||
MinFileSizeMb = 50;
|
MinFileSizeMb = 50;
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
".txt"
|
".txt"
|
||||||
};
|
};
|
||||||
|
|
||||||
TvWatchLocations = new string[] { };
|
WatchLocations = new string[] { };
|
||||||
|
|
||||||
SeasonFolderPattern = "Season %s";
|
SeasonFolderPattern = "Season %s";
|
||||||
SeasonZeroFolderName = "Season 0";
|
SeasonZeroFolderName = "Season 0";
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
|
|
||||||
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
return new TvFileSorter(_libraryManager, _logger, _fileSystem, _iFileSortingRepository).Sort(_config.Configuration.FileSortingOptions, cancellationToken, progress);
|
return new TvFileSorter(_libraryManager, _logger, _fileSystem, _iFileSortingRepository).Sort(_config.Configuration.TvFileSortingOptions, cancellationToken, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
|
||||||
|
@ -58,12 +58,12 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
|
|
||||||
public bool IsHidden
|
public bool IsHidden
|
||||||
{
|
{
|
||||||
get { return !_config.Configuration.FileSortingOptions.IsEnabled; }
|
get { return !_config.Configuration.TvFileSortingOptions.IsEnabled; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEnabled
|
public bool IsEnabled
|
||||||
{
|
{
|
||||||
get { return _config.Configuration.FileSortingOptions.IsEnabled; }
|
get { return _config.Configuration.TvFileSortingOptions.IsEnabled; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,13 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
_iFileSortingRepository = iFileSortingRepository;
|
_iFileSortingRepository = iFileSortingRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Sort(FileSortingOptions options, CancellationToken cancellationToken, IProgress<double> progress)
|
public async Task Sort(TvFileSortingOptions options, CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
var minFileBytes = options.MinFileSizeMb * 1024 * 1024;
|
var minFileBytes = options.MinFileSizeMb * 1024 * 1024;
|
||||||
|
|
||||||
var eligibleFiles = options.TvWatchLocations.SelectMany(GetFilesToSort)
|
var watchLocations = options.WatchLocations.ToList();
|
||||||
|
|
||||||
|
var eligibleFiles = watchLocations.SelectMany(GetFilesToSort)
|
||||||
.OrderBy(_fileSystem.GetCreationTimeUtc)
|
.OrderBy(_fileSystem.GetCreationTimeUtc)
|
||||||
.Where(i => EntityResolutionHelper.IsVideoFile(i.FullName) && i.Length >= minFileBytes)
|
.Where(i => EntityResolutionHelper.IsVideoFile(i.FullName) && i.Length >= minFileBytes)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -72,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
|
|
||||||
if (!options.EnableTrialMode)
|
if (!options.EnableTrialMode)
|
||||||
{
|
{
|
||||||
foreach (var path in options.TvWatchLocations)
|
foreach (var path in watchLocations)
|
||||||
{
|
{
|
||||||
if (options.LeftOverFileExtensionsToDelete.Length > 0)
|
if (options.LeftOverFileExtensionsToDelete.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -116,7 +118,7 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="allSeries">All series.</param>
|
/// <param name="allSeries">All series.</param>
|
||||||
private Task SortFile(string path, FileSortingOptions options, IEnumerable<Series> allSeries)
|
private Task SortFile(string path, TvFileSortingOptions options, IEnumerable<Series> allSeries)
|
||||||
{
|
{
|
||||||
_logger.Info("Sorting file {0}", path);
|
_logger.Info("Sorting file {0}", path);
|
||||||
|
|
||||||
|
@ -180,7 +182,7 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="allSeries">All series.</param>
|
/// <param name="allSeries">All series.</param>
|
||||||
/// <param name="result">The result.</param>
|
/// <param name="result">The result.</param>
|
||||||
private void SortFile(string path, string seriesName, int seasonNumber, int episodeNumber, FileSortingOptions options, IEnumerable<Series> allSeries, FileSortingResult result)
|
private void SortFile(string path, string seriesName, int seasonNumber, int episodeNumber, TvFileSortingOptions options, IEnumerable<Series> allSeries, FileSortingResult result)
|
||||||
{
|
{
|
||||||
var series = GetMatchingSeries(seriesName, allSeries);
|
var series = GetMatchingSeries(seriesName, allSeries);
|
||||||
|
|
||||||
|
@ -216,13 +218,14 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.OverwriteExistingEpisodes && File.Exists(result.TargetPath))
|
var targetExists = File.Exists(result.TargetPath);
|
||||||
|
if (!options.OverwriteExistingEpisodes && targetExists)
|
||||||
{
|
{
|
||||||
result.Status = FileSortingStatus.SkippedExisting;
|
result.Status = FileSortingStatus.SkippedExisting;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformFileSorting(options, result);
|
PerformFileSorting(options, result, targetExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -230,8 +233,40 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <param name="result">The result.</param>
|
/// <param name="result">The result.</param>
|
||||||
private void PerformFileSorting(FileSortingOptions options, FileSortingResult result)
|
/// <param name="copy">if set to <c>true</c> [copy].</param>
|
||||||
|
private void PerformFileSorting(TvFileSortingOptions options, FileSortingResult result, bool copy)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (copy)
|
||||||
|
{
|
||||||
|
File.Copy(result.OriginalPath, result.TargetPath, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File.Move(result.OriginalPath, result.TargetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var errorMsg = string.Format("Failed to move file from {0} to {1}", result.OriginalPath, result.TargetPath);
|
||||||
|
result.Status = FileSortingStatus.Failure;
|
||||||
|
result.ErrorMessage = errorMsg;
|
||||||
|
_logger.ErrorException(errorMsg, ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(result.OriginalPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error deleting {0}", ex, result.OriginalPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -252,7 +287,7 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
/// <param name="episodeNumber">The episode number.</param>
|
/// <param name="episodeNumber">The episode number.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
private string GetNewPath(Series series, int seasonNumber, int episodeNumber, FileSortingOptions options)
|
private string GetNewPath(Series series, int seasonNumber, int episodeNumber, TvFileSortingOptions options)
|
||||||
{
|
{
|
||||||
var currentEpisodes = series.RecursiveChildren.OfType<Episode>()
|
var currentEpisodes = series.RecursiveChildren.OfType<Episode>()
|
||||||
.Where(i => i.IndexNumber.HasValue && i.IndexNumber.Value == episodeNumber && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber)
|
.Where(i => i.IndexNumber.HasValue && i.IndexNumber.Value == episodeNumber && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber)
|
||||||
|
@ -295,7 +330,7 @@ namespace MediaBrowser.Server.Implementations.FileSorting
|
||||||
/// <param name="seasonNumber">The season number.</param>
|
/// <param name="seasonNumber">The season number.</param>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
private string GetSeasonFolderPath(Series series, int seasonNumber, FileSortingOptions options)
|
private string GetSeasonFolderPath(Series series, int seasonNumber, TvFileSortingOptions options)
|
||||||
{
|
{
|
||||||
// If there's already a season folder, use that
|
// If there's already a season folder, use that
|
||||||
var season = series
|
var season = series
|
||||||
|
|
Loading…
Reference in New Issue