diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-01-22 12:05:06 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-01-22 12:05:06 -0500 |
| commit | 9d40b684bf6af4e987e226c78c11d6daf6f5cd9b (patch) | |
| tree | 937312aa29772d0e042929798e936710fbc7c74c /MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs | |
| parent | cf1dac60f632646fa6ccdc715eee9fa5cf240bf3 (diff) | |
#680 - episode organization
Diffstat (limited to 'MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs')
| -rw-r--r-- | MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs new file mode 100644 index 000000000..ad3208b77 --- /dev/null +++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -0,0 +1,176 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.FileOrganization; +using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.FileOrganization; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.FileOrganization +{ + public class TvFolderOrganizer + { + private readonly IDirectoryWatchers _directoryWatchers; + private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; + private readonly IFileOrganizationService _organizationService; + private readonly IServerConfigurationManager _config; + + public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IDirectoryWatchers directoryWatchers, IFileOrganizationService organizationService, IServerConfigurationManager config) + { + _libraryManager = libraryManager; + _logger = logger; + _fileSystem = fileSystem; + _directoryWatchers = directoryWatchers; + _organizationService = organizationService; + _config = config; + } + + public async Task Organize(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress) + { + var minFileBytes = options.MinFileSizeMb * 1024 * 1024; + + var watchLocations = options.WatchLocations.ToList(); + + var eligibleFiles = watchLocations.SelectMany(GetFilesToOrganize) + .OrderBy(_fileSystem.GetCreationTimeUtc) + .Where(i => EntityResolutionHelper.IsVideoFile(i.FullName) && i.Length >= minFileBytes) + .ToList(); + + progress.Report(10); + + var scanLibrary = false; + + if (eligibleFiles.Count > 0) + { + var numComplete = 0; + + foreach (var file in eligibleFiles) + { + var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, + _directoryWatchers); + + var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false).ConfigureAwait(false); + + if (result.Status == FileSortingStatus.Success) + { + scanLibrary = true; + } + + numComplete++; + double percent = numComplete; + percent /= eligibleFiles.Count; + + progress.Report(10 + (89 * percent)); + } + } + + cancellationToken.ThrowIfCancellationRequested(); + progress.Report(99); + + foreach (var path in watchLocations) + { + if (options.LeftOverFileExtensionsToDelete.Length > 0) + { + DeleteLeftOverFiles(path, options.LeftOverFileExtensionsToDelete); + } + + if (options.DeleteEmptyFolders) + { + DeleteEmptyFolders(path); + } + } + + if (scanLibrary) + { + await _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None) + .ConfigureAwait(false); + } + + progress.Report(100); + } + + /// <summary> + /// Gets the files to organize. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>IEnumerable{FileInfo}.</returns> + private IEnumerable<FileInfo> GetFilesToOrganize(string path) + { + try + { + return new DirectoryInfo(path) + .EnumerateFiles("*", SearchOption.AllDirectories) + .ToList(); + } + catch (IOException ex) + { + _logger.ErrorException("Error getting files from {0}", ex, path); + + return new List<FileInfo>(); + } + } + + /// <summary> + /// Deletes the left over files. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="extensions">The extensions.</param> + private void DeleteLeftOverFiles(string path, IEnumerable<string> extensions) + { + var eligibleFiles = new DirectoryInfo(path) + .EnumerateFiles("*", SearchOption.AllDirectories) + .Where(i => extensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)) + .ToList(); + + foreach (var file in eligibleFiles) + { + try + { + File.Delete(file.FullName); + } + catch (IOException ex) + { + _logger.ErrorException("Error deleting file {0}", ex, file.FullName); + } + } + } + + /// <summary> + /// Deletes the empty folders. + /// </summary> + /// <param name="path">The path.</param> + private void DeleteEmptyFolders(string path) + { + try + { + foreach (var d in Directory.EnumerateDirectories(path)) + { + DeleteEmptyFolders(d); + } + + var entries = Directory.EnumerateFileSystemEntries(path); + + if (!entries.Any()) + { + try + { + Directory.Delete(path); + } + catch (UnauthorizedAccessException) { } + catch (DirectoryNotFoundException) { } + } + } + catch (UnauthorizedAccessException) { } + } + } +} |
