#680 - file organization

This commit is contained in:
Luke Pulverenti 2014-01-20 13:46:08 -05:00
parent c798529cac
commit 69fed2c376
9 changed files with 102 additions and 22 deletions

View File

@ -0,0 +1,47 @@
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Querying;
using ServiceStack;
namespace MediaBrowser.Api.Library
{
[Route("/Library/FileOrganization/Results", "GET")]
[Api(Description = "Gets file organization results")]
public class GetFileOrganizationActivity : IReturn<QueryResult<FileOrganizationResult>>
{
/// <summary>
/// Skips over a given number of items within the results. Use for paging.
/// </summary>
/// <value>The start index.</value>
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? StartIndex { get; set; }
/// <summary>
/// The maximum number of items to return
/// </summary>
/// <value>The limit.</value>
[ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? Limit { get; set; }
}
public class FileOrganizationService : BaseApiService
{
private readonly IFileOrganizationService _iFileOrganizationService;
public FileOrganizationService(IFileOrganizationService iFileOrganizationService)
{
_iFileOrganizationService = iFileOrganizationService;
}
public object Get(GetFileOrganizationActivity request)
{
var result = _iFileOrganizationService.GetResults(new FileOrganizationResultQuery
{
Limit = request.Limit,
StartIndex = request.Limit
});
return ToOptimizedResult(result);
}
}
}

View File

@ -87,6 +87,7 @@
<Compile Include="ItemRefreshService.cs" /> <Compile Include="ItemRefreshService.cs" />
<Compile Include="ItemUpdateService.cs" /> <Compile Include="ItemUpdateService.cs" />
<Compile Include="LibraryService.cs" /> <Compile Include="LibraryService.cs" />
<Compile Include="Library\FileOrganizationService.cs" />
<Compile Include="Library\LibraryHelpers.cs" /> <Compile Include="Library\LibraryHelpers.cs" />
<Compile Include="Library\LibraryService.cs" /> <Compile Include="Library\LibraryService.cs" />
<Compile Include="Library\LibraryStructureService.cs" /> <Compile Include="Library\LibraryStructureService.cs" />

View File

@ -1,5 +1,5 @@
using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.FileOrganization;
using System.Collections.Generic; using MediaBrowser.Model.Querying;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.FileOrganization
/// </summary> /// </summary>
/// <param name="query">The query.</param> /// <param name="query">The query.</param>
/// <returns>IEnumerable{FileOrganizationResult}.</returns> /// <returns>IEnumerable{FileOrganizationResult}.</returns>
IEnumerable<FileOrganizationResult> GetResults(FileOrganizationResultQuery query); QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query);
} }
} }

View File

@ -1,5 +1,5 @@
using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.FileOrganization;
using System.Collections.Generic; using MediaBrowser.Model.Querying;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,6 +20,6 @@ namespace MediaBrowser.Controller.Persistence
/// </summary> /// </summary>
/// <param name="query">The query.</param> /// <param name="query">The query.</param>
/// <returns>IEnumerable{FileOrganizationResult}.</returns> /// <returns>IEnumerable{FileOrganizationResult}.</returns>
IEnumerable<FileOrganizationResult> GetResults(FileOrganizationResultQuery query); QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query);
} }
} }

View File

@ -68,9 +68,7 @@ namespace MediaBrowser.Providers.TV
.OfType<Episode>() .OfType<Episode>()
.ToList(); .ToList();
series.SpecialFeatureIds = episodes var physicalEpisodes = episodes.Where(i => i.LocationType != LocationType.Virtual)
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
.Select(i => i.Id)
.ToList(); .ToList();
series.SeasonCount = episodes series.SeasonCount = episodes
@ -79,7 +77,12 @@ namespace MediaBrowser.Providers.TV
.Distinct() .Distinct()
.Count(); .Count();
series.DateLastEpisodeAdded = episodes.Select(i => i.DateCreated) series.SpecialFeatureIds = physicalEpisodes
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
.Select(i => i.Id)
.ToList();
series.DateLastEpisodeAdded = physicalEpisodes.Select(i => i.DateCreated)
.OrderByDescending(i => i) .OrderByDescending(i => i)
.FirstOrDefault(); .FirstOrDefault();
@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.TV
if (_config.Configuration.EnableInternetProviders) if (_config.Configuration.EnableInternetProviders)
{ {
hasNewEpisodes = await AddMissingEpisodes(group, seriesDataPath, episodeLookup, cancellationToken) hasNewEpisodes = await AddMissingEpisodes(group.ToList(), seriesDataPath, episodeLookup, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -225,7 +228,7 @@ namespace MediaBrowser.Providers.TV
/// <param name="episodeLookup">The episode lookup.</param> /// <param name="episodeLookup">The episode lookup.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task<bool> AddMissingEpisodes(IEnumerable<Series> series, string seriesDataPath, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken) private async Task<bool> AddMissingEpisodes(List<Series> series, string seriesDataPath, IEnumerable<Tuple<int, int>> episodeLookup, CancellationToken cancellationToken)
{ {
var existingEpisodes = series.SelectMany(s => s.RecursiveChildren.OfType<Episode>()).ToList(); var existingEpisodes = series.SelectMany(s => s.RecursiveChildren.OfType<Episode>()).ToList();

View File

@ -2,7 +2,7 @@
using MediaBrowser.Controller.FileOrganization; using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.FileOrganization;
using System.Collections.Generic; using MediaBrowser.Model.Querying;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -30,7 +30,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return _repo.SaveResult(result, cancellationToken); return _repo.SaveResult(result, cancellationToken);
} }
public IEnumerable<FileOrganizationResult> GetResults(FileOrganizationResultQuery query) public QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query)
{ {
return _repo.GetResults(query); return _repo.GetResults(query);
} }

View File

@ -2,6 +2,7 @@
using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization; using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using System; using System;
@ -18,14 +19,16 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IFileOrganizationService _iFileSortingRepository; private readonly IFileOrganizationService _iFileSortingRepository;
private readonly IDirectoryWatchers _directoryWatchers;
public OrganizerScheduledTask(IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IFileSystem fileSystem, IFileOrganizationService iFileSortingRepository) public OrganizerScheduledTask(IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IFileSystem fileSystem, IFileOrganizationService iFileSortingRepository, IDirectoryWatchers directoryWatchers)
{ {
_config = config; _config = config;
_logger = logger; _logger = logger;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_iFileSortingRepository = iFileSortingRepository; _iFileSortingRepository = iFileSortingRepository;
_directoryWatchers = directoryWatchers;
} }
public string Name public string Name
@ -45,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
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.TvFileOrganizationOptions, cancellationToken, progress); return new TvFileSorter(_libraryManager, _logger, _fileSystem, _iFileSortingRepository, _directoryWatchers).Sort(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress);
} }
public IEnumerable<ITaskTrigger> GetDefaultTriggers() public IEnumerable<ITaskTrigger> GetDefaultTriggers()

View File

@ -1,6 +1,7 @@
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.FileOrganization; using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Resolvers;
@ -24,15 +25,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IFileOrganizationService _iFileSortingRepository; private readonly IFileOrganizationService _iFileSortingRepository;
private readonly IDirectoryWatchers _directoryWatchers;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public TvFileSorter(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IFileOrganizationService iFileSortingRepository) public TvFileSorter(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IFileOrganizationService iFileSortingRepository, IDirectoryWatchers directoryWatchers)
{ {
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_iFileSortingRepository = iFileSortingRepository; _iFileSortingRepository = iFileSortingRepository;
_directoryWatchers = directoryWatchers;
} }
public async Task Sort(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress) public async Task Sort(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress)
@ -48,6 +51,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
progress.Report(10); progress.Report(10);
var scanLibrary = false;
if (eligibleFiles.Count > 0) if (eligibleFiles.Count > 0)
{ {
var allSeries = _libraryManager.RootFolder var allSeries = _libraryManager.RootFolder
@ -59,7 +64,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
foreach (var file in eligibleFiles) foreach (var file in eligibleFiles)
{ {
await SortFile(file.FullName, options, allSeries).ConfigureAwait(false); var result = await SortFile(file.FullName, options, allSeries).ConfigureAwait(false);
if (result.Status == FileSortingStatus.Success)
{
scanLibrary = true;
}
numComplete++; numComplete++;
double percent = numComplete; double percent = numComplete;
@ -88,6 +98,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
} }
} }
if (scanLibrary)
{
await _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None)
.ConfigureAwait(false);
}
progress.Report(100); progress.Report(100);
} }
@ -118,7 +134,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <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, TvFileOrganizationOptions options, IEnumerable<Series> allSeries) private async Task<FileOrganizationResult> SortFile(string path, TvFileOrganizationOptions options, IEnumerable<Series> allSeries)
{ {
_logger.Info("Sorting file {0}", path); _logger.Info("Sorting file {0}", path);
@ -169,7 +185,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_logger.Warn(msg); _logger.Warn(msg);
} }
return LogResult(result); await LogResult(result).ConfigureAwait(false);
return result;
} }
/// <summary> /// <summary>
@ -236,6 +254,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="copy">if set to <c>true</c> [copy].</param> /// <param name="copy">if set to <c>true</c> [copy].</param>
private void PerformFileSorting(TvFileOrganizationOptions options, FileOrganizationResult result, bool copy) private void PerformFileSorting(TvFileOrganizationOptions options, FileOrganizationResult result, bool copy)
{ {
_directoryWatchers.TemporarilyIgnore(result.TargetPath);
try try
{ {
if (copy) if (copy)
@ -250,11 +270,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
catch (Exception ex) catch (Exception ex)
{ {
var errorMsg = string.Format("Failed to move file from {0} to {1}", result.OriginalPath, result.TargetPath); var errorMsg = string.Format("Failed to move file from {0} to {1}", result.OriginalPath, result.TargetPath);
result.Status = FileSortingStatus.Failure; result.Status = FileSortingStatus.Failure;
result.ErrorMessage = errorMsg; result.ErrorMessage = errorMsg;
_logger.ErrorException(errorMsg, ex); _logger.ErrorException(errorMsg, ex);
return; return;
} }
finally
{
_directoryWatchers.RemoveTempIgnore(result.TargetPath);
}
if (copy) if (copy)
{ {

View File

@ -2,8 +2,8 @@
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using System; using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
@ -62,9 +62,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
return Task.FromResult(true); return Task.FromResult(true);
} }
public IEnumerable<FileOrganizationResult> GetResults(FileOrganizationResultQuery query) public QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query)
{ {
return new List<FileOrganizationResult>(); return new QueryResult<FileOrganizationResult>();
} }
/// <summary> /// <summary>