From 3a868e28b3e3d9f0a13fc38c680047010d627b0f Mon Sep 17 00:00:00 2001 From: softworkz Date: Wed, 23 Sep 2015 06:12:46 +0200 Subject: Auto-Organize: Added feature to remember/persist series matching in manual organization dialog #2 When a filename cannot be auto-matched to an existing series name, the organization must be performed manually. Unfortunately not just once, but again and again for each episode coming in. This change proposes a simple but solid method to optionally persist the matching condition from within the manual organization dialog. This approach will make Emby "learn" how to organize files in the future without user interaction. --- .../FileOrganization/EpisodeFileOrganizer.cs | 69 ++++++++++++++++++---- 1 file changed, 58 insertions(+), 11 deletions(-) (limited to 'MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs') diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 73cc5ab01..a952b60d5 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -46,12 +46,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public Task OrganizeEpisodeFile(string path, CancellationToken cancellationToken) { - var options = _config.GetAutoOrganizeOptions().TvOptions; + var options = _config.GetAutoOrganizeOptions(); return OrganizeEpisodeFile(path, options, false, cancellationToken); } - public async Task OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken) + public async Task OrganizeEpisodeFile(string path, AutoOrganizeOptions options, bool overwriteExisting, CancellationToken cancellationToken) { _logger.Info("Sorting file {0}", path); @@ -110,6 +110,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization premiereDate, options, overwriteExisting, + false, result, cancellationToken).ConfigureAwait(false); } @@ -145,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return result; } - public async Task OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken) + public async Task OrganizeWithCorrection(EpisodeFileOrganizationRequest request, AutoOrganizeOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); @@ -159,6 +160,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization null, options, true, + request.RememberCorrection, result, cancellationToken).ConfigureAwait(false); @@ -173,12 +175,13 @@ namespace MediaBrowser.Server.Implementations.FileOrganization int? episodeNumber, int? endingEpiosdeNumber, DateTime? premiereDate, - TvFileOrganizationOptions options, + AutoOrganizeOptions options, bool overwriteExisting, + bool rememberCorrection, FileOrganizationResult result, CancellationToken cancellationToken) { - var series = GetMatchingSeries(seriesName, result); + var series = GetMatchingSeries(seriesName, result, options); if (series == null) { @@ -197,6 +200,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization premiereDate, options, overwriteExisting, + rememberCorrection, result, cancellationToken); } @@ -207,15 +211,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization int? episodeNumber, int? endingEpiosdeNumber, DateTime? premiereDate, - TvFileOrganizationOptions options, + AutoOrganizeOptions options, bool overwriteExisting, + bool rememberCorrection, FileOrganizationResult result, CancellationToken cancellationToken) { _logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path); + var originalExtractedSeriesString = result.ExtractedName; + // Proceed to sort the file - var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false); + var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options.TvOptions, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(newPath)) { @@ -234,7 +241,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization if (!overwriteExisting) { - if (options.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath)) + if (options.TvOptions.CopyOriginalFile && fileExists && IsSameEpisode(sourcePath, newPath)) { _logger.Info("File {0} already copied to new path {1}, stopping organization", sourcePath, newPath); result.Status = FileSortingStatus.SkippedExisting; @@ -251,7 +258,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } - PerformFileSorting(options, result); + PerformFileSorting(options.TvOptions, result); if (overwriteExisting) { @@ -285,6 +292,31 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } } + + if (rememberCorrection) + { + SaveSmartMatchString(originalExtractedSeriesString, series, options); + } + } + + private void SaveSmartMatchString(string matchString, Series series, AutoOrganizeOptions options) + { + SmartMatchInfo info = options.SmartMatchInfos.Find(i => i.Id == series.Id); + + if (info == null) + { + info = new SmartMatchInfo(); + info.Id = series.Id; + info.OrganizerType = FileOrganizerType.Episode; + info.Name = series.Name; + options.SmartMatchInfos.Add(info); + } + + if (!info.MatchStrings.Contains(matchString, StringComparer.OrdinalIgnoreCase)) + { + info.MatchStrings.Add(matchString); + _config.SaveAutoOrganizeOptions(options); + } } private void DeleteLibraryFile(string path, bool renameRelatedFiles, string targetPath) @@ -435,7 +467,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } - private Series GetMatchingSeries(string seriesName, FileOrganizationResult result) + private Series GetMatchingSeries(string seriesName, FileOrganizationResult result, AutoOrganizeOptions options) { var parsedName = _libraryManager.ParseName(seriesName); @@ -445,13 +477,28 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.ExtractedName = nameWithoutYear; result.ExtractedYear = yearInName; - return _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) + var series = _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) .Cast() .Select(i => NameUtils.GetMatchScore(nameWithoutYear, yearInName, i)) .Where(i => i.Item2 > 0) .OrderByDescending(i => i.Item2) .Select(i => i.Item1) .FirstOrDefault(); + + if (series == null) + { + SmartMatchInfo info = options.SmartMatchInfos.Where(e => e.MatchStrings.Contains(seriesName, StringComparer.OrdinalIgnoreCase)).FirstOrDefault(); + + if (info != null) + { + series = _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) + .Cast() + .Where(i => i.Id == info.Id) + .FirstOrDefault(); + } + } + + return series ?? new Series(); } /// -- cgit v1.2.3 From 0e49ccfd077bf114a2a663249d81a2891c46639d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 7 Feb 2016 00:15:26 -0500 Subject: update smart match feature --- .../FileOrganization/AutoOrganizeOptions.cs | 5 ++--- .../FileOrganization/SmartMatchInfo.cs | 9 +++------ .../FileOrganization/EpisodeFileOrganizer.cs | 21 +++++++++++++-------- .../FileOrganization/FileOrganizationService.cs | 19 ++++++++++++------- 4 files changed, 30 insertions(+), 24 deletions(-) (limited to 'MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs') diff --git a/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs index 071897b51..830d55bf5 100644 --- a/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs +++ b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs @@ -1,5 +1,4 @@  -using System.Collections.Generic; namespace MediaBrowser.Model.FileOrganization { public class AutoOrganizeOptions @@ -14,12 +13,12 @@ namespace MediaBrowser.Model.FileOrganization /// Gets or sets a list of smart match entries. /// /// The smart match entries. - public List SmartMatchInfos { get; set; } + public SmartMatchInfo[] SmartMatchInfos { get; set; } public AutoOrganizeOptions() { TvOptions = new TvFileOrganizationOptions(); - SmartMatchInfos = new List(); + SmartMatchInfos = new SmartMatchInfo[]{}; } } } diff --git a/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs b/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs index 808c0b006..a6bc66e49 100644 --- a/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs +++ b/MediaBrowser.Model/FileOrganization/SmartMatchInfo.cs @@ -1,19 +1,16 @@  -using System; -using System.Collections.Generic; - namespace MediaBrowser.Model.FileOrganization { public class SmartMatchInfo { - public Guid Id { get; set; } + public string Id { get; set; } public string Name { get; set; } public FileOrganizerType OrganizerType { get; set; } - public List MatchStrings { get; set; } + public string[] MatchStrings { get; set; } public SmartMatchInfo() { - MatchStrings = new List(); + MatchStrings = new string[] { }; } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index a952b60d5..dcce91c31 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -301,20 +301,25 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private void SaveSmartMatchString(string matchString, Series series, AutoOrganizeOptions options) { - SmartMatchInfo info = options.SmartMatchInfos.Find(i => i.Id == series.Id); + var seriesIdString = series.Id.ToString("N"); + SmartMatchInfo info = options.SmartMatchInfos.FirstOrDefault(i => string.Equals(i.Id, seriesIdString)); if (info == null) { info = new SmartMatchInfo(); - info.Id = series.Id; + info.Id = series.Id.ToString("N"); info.OrganizerType = FileOrganizerType.Episode; info.Name = series.Name; - options.SmartMatchInfos.Add(info); + var list = options.SmartMatchInfos.ToList(); + list.Add(info); + options.SmartMatchInfos = list.ToArray(); } if (!info.MatchStrings.Contains(matchString, StringComparer.OrdinalIgnoreCase)) { - info.MatchStrings.Add(matchString); + var list = info.MatchStrings.ToList(); + list.Add(matchString); + info.MatchStrings = list.ToArray(); _config.SaveAutoOrganizeOptions(options); } } @@ -487,14 +492,14 @@ namespace MediaBrowser.Server.Implementations.FileOrganization if (series == null) { - SmartMatchInfo info = options.SmartMatchInfos.Where(e => e.MatchStrings.Contains(seriesName, StringComparer.OrdinalIgnoreCase)).FirstOrDefault(); + SmartMatchInfo info = options.SmartMatchInfos.FirstOrDefault(e => e.MatchStrings.Contains(seriesName, StringComparer.OrdinalIgnoreCase)); if (info != null) { - series = _libraryManager.RootFolder.GetRecursiveChildren(i => i is Series) + series = _libraryManager.RootFolder + .GetRecursiveChildren(i => i is Series) .Cast() - .Where(i => i.Id == info.Id) - .FirstOrDefault(); + .FirstOrDefault(i => string.Equals(i.Id.ToString("N"), info.Id)); } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index 3dd6a9be0..ce388bd8e 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -140,12 +140,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var options = GetAutoOrganizeptions(); - var items = options.SmartMatchInfos.Skip(query.StartIndex ?? 0).Take(query.Limit ?? Int32.MaxValue); + var items = options.SmartMatchInfos.Skip(query.StartIndex ?? 0).Take(query.Limit ?? Int32.MaxValue).ToArray(); return new QueryResult() { - Items = items.ToArray(), - TotalRecordCount = items.Count() + Items = items, + TotalRecordCount = options.SmartMatchInfos.Length }; } @@ -165,14 +165,19 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var options = GetAutoOrganizeptions(); - SmartMatchInfo info = options.SmartMatchInfos.Find(i => i.Id == Id); + SmartMatchInfo info = options.SmartMatchInfos.FirstOrDefault(i => string.Equals(i.Id, IdString)); if (info != null && info.MatchStrings.Contains(matchString)) { - info.MatchStrings.Remove(matchString); - if (info.MatchStrings.Count == 0) + var list = info.MatchStrings.ToList(); + list.Remove(matchString); + info.MatchStrings = list.ToArray(); + + if (info.MatchStrings.Length == 0) { - options.SmartMatchInfos.Remove(info); + var infos = options.SmartMatchInfos.ToList(); + infos.Remove(info); + options.SmartMatchInfos = infos.ToArray(); } _config.SaveAutoOrganizeOptions(options); -- cgit v1.2.3