Przeglądaj źródła

#680 - file organization

Luke Pulverenti 11 lat temu
rodzic
commit
69fed2c376

+ 47 - 0
MediaBrowser.Api/Library/FileOrganizationService.cs

@@ -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);
+        }
+    }
+}

+ 1 - 0
MediaBrowser.Api/MediaBrowser.Api.csproj

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

+ 2 - 2
MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs

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

+ 2 - 2
MediaBrowser.Controller/Persistence/IFileOrganizationRepository.cs

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

+ 10 - 7
MediaBrowser.Providers/TV/SeriesPostScanTask.cs

@@ -59,7 +59,7 @@ namespace MediaBrowser.Providers.TV
             await new MissingEpisodeProvider(_logger, _config).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
 
             var numComplete = 0;
-
+            
             foreach (var series in seriesList)
             {
                 cancellationToken.ThrowIfCancellationRequested();
@@ -68,9 +68,7 @@ namespace MediaBrowser.Providers.TV
                     .OfType<Episode>()
                     .ToList();
 
-                series.SpecialFeatureIds = episodes
-                    .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
-                    .Select(i => i.Id)
+                var physicalEpisodes = episodes.Where(i => i.LocationType != LocationType.Virtual)
                     .ToList();
 
                 series.SeasonCount = episodes
@@ -79,7 +77,12 @@ namespace MediaBrowser.Providers.TV
                     .Distinct()
                     .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)
                     .FirstOrDefault();
 
@@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.TV
 
             if (_config.Configuration.EnableInternetProviders)
             {
-                hasNewEpisodes = await AddMissingEpisodes(group, seriesDataPath, episodeLookup, cancellationToken)
+                hasNewEpisodes = await AddMissingEpisodes(group.ToList(), seriesDataPath, episodeLookup, cancellationToken)
                     .ConfigureAwait(false);
             }
 
@@ -225,7 +228,7 @@ namespace MediaBrowser.Providers.TV
         /// <param name="episodeLookup">The episode lookup.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <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();
 

+ 2 - 2
MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs

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

+ 5 - 2
MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.FileOrganization;
+using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Logging;
 using System;
@@ -18,14 +19,16 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
         private readonly ILibraryManager _libraryManager;
         private readonly IFileSystem _fileSystem;
         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;
             _logger = logger;
             _libraryManager = libraryManager;
             _fileSystem = fileSystem;
             _iFileSortingRepository = iFileSortingRepository;
+            _directoryWatchers = directoryWatchers;
         }
 
         public string Name
@@ -45,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
 
         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()

+ 30 - 4
MediaBrowser.Server.Implementations/FileOrganization/TvFileSorter.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.FileOrganization;
+using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Resolvers;
@@ -24,15 +25,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
         private readonly ILogger _logger;
         private readonly IFileSystem _fileSystem;
         private readonly IFileOrganizationService _iFileSortingRepository;
+        private readonly IDirectoryWatchers _directoryWatchers;
 
         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;
             _logger = logger;
             _fileSystem = fileSystem;
             _iFileSortingRepository = iFileSortingRepository;
+            _directoryWatchers = directoryWatchers;
         }
 
         public async Task Sort(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress)
@@ -48,6 +51,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
 
             progress.Report(10);
 
+            var scanLibrary = false;
+
             if (eligibleFiles.Count > 0)
             {
                 var allSeries = _libraryManager.RootFolder
@@ -59,7 +64,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
 
                 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++;
                     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);
         }
 
@@ -118,7 +134,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
         /// <param name="path">The path.</param>
         /// <param name="options">The options.</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);
 
@@ -169,7 +185,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
                 _logger.Warn(msg);
             }
 
-            return LogResult(result);
+            await LogResult(result).ConfigureAwait(false);
+
+            return result;
         }
 
         /// <summary>
@@ -236,6 +254,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
         /// <param name="copy">if set to <c>true</c> [copy].</param>
         private void PerformFileSorting(TvFileOrganizationOptions options, FileOrganizationResult result, bool copy)
         {
+            _directoryWatchers.TemporarilyIgnore(result.TargetPath);
+
             try
             {
                 if (copy)
@@ -250,11 +270,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
             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;
             }
+            finally
+            {
+                _directoryWatchers.RemoveTempIgnore(result.TargetPath);
+            }
 
             if (copy)
             {

+ 3 - 3
MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs

@@ -2,8 +2,8 @@
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.FileOrganization;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
 using System;
-using System.Collections.Generic;
 using System.Data;
 using System.IO;
 using System.Threading;
@@ -62,9 +62,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
             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>