/// <inheritdoc/> public async Task PerformOrganization(string resultId) { var result = _repo.GetResult(resultId); var options = _config.GetAutoOrganizeOptions(); if (string.IsNullOrEmpty(result.TargetPath)) { throw new ArgumentException("No target path available."); } FileOrganizationResult organizeResult; switch (result.Type) { case FileOrganizerType.Episode: var episodeOrganizer = new EpisodeFileOrganizer( this, _fileSystem, _loggerFactory.CreateLogger <EpisodeFileOrganizer>(), _libraryManager, _libraryMonitor, _providerManager); organizeResult = await episodeOrganizer.OrganizeEpisodeFile(result.OriginalPath, options.TvOptions, CancellationToken.None) .ConfigureAwait(false); break; case FileOrganizerType.Movie: var movieOrganizer = new MovieFileOrganizer( this, _fileSystem, _loggerFactory.CreateLogger <MovieFileOrganizer>(), _libraryManager, _libraryMonitor, _providerManager); organizeResult = await movieOrganizer.OrganizeMovieFile(result.OriginalPath, options.MovieOptions, true, CancellationToken.None) .ConfigureAwait(false); break; default: throw new OrganizationException("No organizer exist for the type " + result.Type); } if (organizeResult.Status != FileSortingStatus.Success) { throw new OrganizationException(result.StatusMessage); } }
/// <summary> /// Perform organization for the movie watch folders. /// </summary> /// <param name="options">The organization options.</param> /// <param name="progress">The <see cref="IProgress{T}"/> to use for reporting operation progress.</param> /// <param name="cancellationToken">A cancellation token for the operation.</param> /// <returns>A task representing the operation completion.</returns> public async Task Organize( MovieFileOrganizationOptions options, IProgress <double> progress, CancellationToken cancellationToken) { // Get all valid watch locations var libraryFolderPaths = _libraryManager.GetVirtualFolders().SelectMany(i => i.Locations).ToList(); var watchLocations = options.WatchLocations .Where(i => IsValidWatchLocation(i, libraryFolderPaths)) .ToList(); var eligibleFiles = watchLocations.SelectMany(GetFilesToOrganize) .OrderBy(_fileSystem.GetCreationTimeUtc) .Where(i => CanOrganize(i, options)) .ToList(); var processedFolders = new HashSet <string>(); progress.Report(10); if (eligibleFiles.Count > 0) { var numComplete = 0; var organizer = new MovieFileOrganizer(_organizationService, _fileSystem, _logger, _libraryManager, _libraryMonitor, _providerManager); foreach (var file in eligibleFiles) { cancellationToken.ThrowIfCancellationRequested(); try { var result = await organizer.OrganizeMovieFile(file.FullName, options, options.OverwriteExistingFiles, cancellationToken).ConfigureAwait(false); if (result.Status == FileSortingStatus.Success && !processedFolders.Contains(file.DirectoryName, StringComparer.OrdinalIgnoreCase)) { processedFolders.Add(file.DirectoryName); } } catch (OperationCanceledException) { break; } catch (Exception ex) { _logger.LogError(ex, "Error organizing episode {0}", file.FullName); } numComplete++; double percent = numComplete; percent /= eligibleFiles.Count; progress.Report(10 + (89 * percent)); } } cancellationToken.ThrowIfCancellationRequested(); progress.Report(99); List <string> deleteExtensions = options.LeftOverFileExtensionsToDelete .Select(i => i.Trim().TrimStart('.')) .Where(i => !string.IsNullOrEmpty(i)) .Select(i => "." + i) .ToList(); // Normal Clean Clean(processedFolders, watchLocations, options.DeleteEmptyFolders, deleteExtensions); // Extended Clean if (options.ExtendedClean) { Clean(watchLocations, watchLocations, options.DeleteEmptyFolders, deleteExtensions); } progress.Report(100); }