Fixed: Include matching value of preferred word regex, not the actual regex
This commit is contained in:
parent
1222aeaab6
commit
78b3c9552b
|
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Mocker.SetConstant<ITermMatcher>(Mocker.Resolve<TermMatcher>());
|
Mocker.SetConstant<ITermMatcherService>(Mocker.Resolve<TermMatcherService>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenRestictions(string required, string ignored)
|
private void GivenRestictions(string required, string ignored)
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace NzbDrone.Core.Test.Profiles.Releases.PreferredWordService
|
||||||
|
|
||||||
private void GivenMatchingTerms(params string[] terms)
|
private void GivenMatchingTerms(params string[] terms)
|
||||||
{
|
{
|
||||||
Mocker.GetMock<ITermMatcher>()
|
Mocker.GetMock<ITermMatcherService>()
|
||||||
.Setup(s => s.IsMatch(It.IsAny<string>(), _title))
|
.Setup(s => s.IsMatch(It.IsAny<string>(), _title))
|
||||||
.Returns<string, string>((term, title) => terms.Contains(term));
|
.Returns<string, string>((term, title) => terms.Contains(term));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
private readonly IReleaseProfileService _releaseProfileService;
|
private readonly IReleaseProfileService _releaseProfileService;
|
||||||
private readonly ITermMatcher _termMatcher;
|
private readonly ITermMatcherService _termMatcherService;
|
||||||
|
|
||||||
public ReleaseRestrictionsSpecification(ITermMatcher termMatcher, IReleaseProfileService releaseProfileService, Logger logger)
|
public ReleaseRestrictionsSpecification(ITermMatcherService termMatcherService, IReleaseProfileService releaseProfileService, Logger logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_releaseProfileService = releaseProfileService;
|
_releaseProfileService = releaseProfileService;
|
||||||
_termMatcher = termMatcher;
|
_termMatcherService = termMatcherService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
|
@ -67,7 +67,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
private List<string> ContainsAny(List<string> terms, string title)
|
private List<string> ContainsAny(List<string> terms, string title)
|
||||||
{
|
{
|
||||||
return terms.Where(t => _termMatcher.IsMatch(t, title)).ToList();
|
return terms.Where(t => _termMatcherService.IsMatch(t, title)).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1012,6 +1012,9 @@
|
||||||
<Compile Include="Profiles\Qualities\QualityProfileService.cs" />
|
<Compile Include="Profiles\Qualities\QualityProfileService.cs" />
|
||||||
<Compile Include="Profiles\Qualities\QualityIndex.cs" />
|
<Compile Include="Profiles\Qualities\QualityIndex.cs" />
|
||||||
<Compile Include="Profiles\Releases\PreferredWordService.cs" />
|
<Compile Include="Profiles\Releases\PreferredWordService.cs" />
|
||||||
|
<Compile Include="Profiles\Releases\TermMatchers\CaseInsensitiveTermMatcher.cs" />
|
||||||
|
<Compile Include="Profiles\Releases\TermMatchers\ITermMatcher.cs" />
|
||||||
|
<Compile Include="Profiles\Releases\TermMatchers\RegexTermMatcher.cs" />
|
||||||
<Compile Include="ProgressMessaging\ProgressMessageContext.cs" />
|
<Compile Include="ProgressMessaging\ProgressMessageContext.cs" />
|
||||||
<Compile Include="Qualities\QualityDetectionSource.cs" />
|
<Compile Include="Qualities\QualityDetectionSource.cs" />
|
||||||
<Compile Include="Qualities\QualityFinder.cs" />
|
<Compile Include="Qualities\QualityFinder.cs" />
|
||||||
|
@ -1145,7 +1148,7 @@
|
||||||
<Compile Include="Profiles\Releases\ReleaseProfile.cs" />
|
<Compile Include="Profiles\Releases\ReleaseProfile.cs" />
|
||||||
<Compile Include="Profiles\Releases\ReleaseProfileRepository.cs" />
|
<Compile Include="Profiles\Releases\ReleaseProfileRepository.cs" />
|
||||||
<Compile Include="Profiles\Releases\ReleaseProfileService.cs" />
|
<Compile Include="Profiles\Releases\ReleaseProfileService.cs" />
|
||||||
<Compile Include="Profiles\Releases\TermMatcher.cs" />
|
<Compile Include="Profiles\Releases\TermMatcherService.cs" />
|
||||||
<Compile Include="Rest\JsonNetSerializer.cs" />
|
<Compile Include="Rest\JsonNetSerializer.cs" />
|
||||||
<Compile Include="Rest\RestClientFactory.cs" />
|
<Compile Include="Rest\RestClientFactory.cs" />
|
||||||
<Compile Include="Rest\RestException.cs" />
|
<Compile Include="Rest\RestException.cs" />
|
||||||
|
|
|
@ -617,7 +617,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
{
|
{
|
||||||
if (preferredWords == null)
|
if (preferredWords == null)
|
||||||
{
|
{
|
||||||
preferredWords = _preferredWordService.GetMatchingPreferredWords(series, episodeFile.GetSceneOrFileName(), true);
|
preferredWords = _preferredWordService.GetMatchingPreferredWords(series, episodeFile.GetSceneOrFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenHandlers["{Preferred Words}"] = m => string.Join(" ", preferredWords);
|
tokenHandlers["{Preferred Words}"] = m => string.Join(" ", preferredWords);
|
||||||
|
|
|
@ -2,25 +2,26 @@ using NLog;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Profiles.Releases
|
namespace NzbDrone.Core.Profiles.Releases
|
||||||
{
|
{
|
||||||
public interface IPreferredWordService
|
public interface IPreferredWordService
|
||||||
{
|
{
|
||||||
int Calculate(Series series, string title);
|
int Calculate(Series series, string title);
|
||||||
List<string> GetMatchingPreferredWords(Series series, string title, bool isRenaming);
|
List<string> GetMatchingPreferredWords(Series series, string title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PreferredWordService : IPreferredWordService
|
public class PreferredWordService : IPreferredWordService
|
||||||
{
|
{
|
||||||
private readonly IReleaseProfileService _releaseProfileService;
|
private readonly IReleaseProfileService _releaseProfileService;
|
||||||
private readonly ITermMatcher _termMatcher;
|
private readonly ITermMatcherService _termMatcherService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public PreferredWordService(IReleaseProfileService releaseProfileService, ITermMatcher termMatcher, Logger logger)
|
public PreferredWordService(IReleaseProfileService releaseProfileService, ITermMatcherService termMatcherService, Logger logger)
|
||||||
{
|
{
|
||||||
_releaseProfileService = releaseProfileService;
|
_releaseProfileService = releaseProfileService;
|
||||||
_termMatcher = termMatcher;
|
_termMatcherService = termMatcherService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +29,22 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
{
|
{
|
||||||
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
||||||
|
|
||||||
var matchingPairs = GetMatchingPairs(series, title, false);
|
var releaseProfiles = _releaseProfileService.AllForTags(series.Tags);
|
||||||
|
var matchingPairs = new List<KeyValuePair<string, int>>();
|
||||||
|
|
||||||
|
foreach (var releaseProfile in releaseProfiles)
|
||||||
|
{
|
||||||
|
foreach (var preferredPair in releaseProfile.Preferred)
|
||||||
|
{
|
||||||
|
var term = preferredPair.Key;
|
||||||
|
|
||||||
|
if (_termMatcherService.IsMatch(term, title))
|
||||||
|
{
|
||||||
|
matchingPairs.Add(preferredPair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var score = matchingPairs.Sum(p => p.Value);
|
var score = matchingPairs.Sum(p => p.Value);
|
||||||
|
|
||||||
_logger.Trace("Calculated preferred word score for '{0}': {1}", title, score);
|
_logger.Trace("Calculated preferred word score for '{0}': {1}", title, score);
|
||||||
|
@ -36,25 +52,16 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetMatchingPreferredWords(Series series, string title, bool isRenaming)
|
public List<string> GetMatchingPreferredWords(Series series, string title)
|
||||||
{
|
|
||||||
var matchingPairs = GetMatchingPairs(series, title, isRenaming);
|
|
||||||
|
|
||||||
return matchingPairs.OrderByDescending(p => p.Value)
|
|
||||||
.Select(p => p.Key)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<KeyValuePair<string, int>> GetMatchingPairs(Series series, string title, bool isRenaming)
|
|
||||||
{
|
{
|
||||||
var releaseProfiles = _releaseProfileService.AllForTags(series.Tags);
|
var releaseProfiles = _releaseProfileService.AllForTags(series.Tags);
|
||||||
var result = new List<KeyValuePair<string, int>>();
|
var matchingPairs = new List<KeyValuePair<string, int>>();
|
||||||
|
|
||||||
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
||||||
|
|
||||||
foreach (var releaseProfile in releaseProfiles)
|
foreach (var releaseProfile in releaseProfiles)
|
||||||
{
|
{
|
||||||
if (isRenaming && !releaseProfile.IncludePreferredWhenRenaming)
|
if (!releaseProfile.IncludePreferredWhenRenaming)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -62,15 +69,18 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
foreach (var preferredPair in releaseProfile.Preferred)
|
foreach (var preferredPair in releaseProfile.Preferred)
|
||||||
{
|
{
|
||||||
var term = preferredPair.Key;
|
var term = preferredPair.Key;
|
||||||
|
var matchingTerm = _termMatcherService.MatchingTerm(term, title);
|
||||||
|
|
||||||
if (_termMatcher.IsMatch(term, title))
|
if (matchingTerm.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
result.Add(preferredPair);
|
matchingPairs.Add(new KeyValuePair<string, int>(matchingTerm, preferredPair.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return matchingPairs.OrderByDescending(p => p.Value)
|
||||||
|
.Select(p => p.Key)
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using NzbDrone.Common.Cache;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Profiles.Releases
|
|
||||||
{
|
|
||||||
public interface ITermMatcher
|
|
||||||
{
|
|
||||||
bool IsMatch(string term, string value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TermMatcher : ITermMatcher
|
|
||||||
{
|
|
||||||
private ICached<Predicate<string>> _matcherCache;
|
|
||||||
|
|
||||||
public TermMatcher(ICacheManager cacheManager)
|
|
||||||
{
|
|
||||||
_matcherCache = cacheManager.GetCache<Predicate<string>>(GetType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsMatch(string term, string value)
|
|
||||||
{
|
|
||||||
return GetMatcher(term)(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Predicate<string> GetMatcher(string term)
|
|
||||||
{
|
|
||||||
return _matcherCache.Get(term, () => CreateMatcherInternal(term), TimeSpan.FromHours(24));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate<string> CreateMatcherInternal(string term)
|
|
||||||
{
|
|
||||||
Regex regex;
|
|
||||||
if (PerlRegexFactory.TryCreateRegex(term, out regex))
|
|
||||||
{
|
|
||||||
return regex.IsMatch;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new CaseInsensitiveTermMatcher(term).IsMatch;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class CaseInsensitiveTermMatcher
|
|
||||||
{
|
|
||||||
private readonly string _term;
|
|
||||||
|
|
||||||
public CaseInsensitiveTermMatcher(string term)
|
|
||||||
{
|
|
||||||
_term = term.ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsMatch(string value)
|
|
||||||
{
|
|
||||||
return value.ToLowerInvariant().Contains(_term);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
using NzbDrone.Core.Profiles.Releases.TermMatchers;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Profiles.Releases
|
||||||
|
{
|
||||||
|
public interface ITermMatcherService
|
||||||
|
{
|
||||||
|
bool IsMatch(string term, string value);
|
||||||
|
string MatchingTerm(string term, string value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TermMatcherService : ITermMatcherService
|
||||||
|
{
|
||||||
|
private ICached<ITermMatcher> _matcherCache;
|
||||||
|
|
||||||
|
public TermMatcherService(ICacheManager cacheManager)
|
||||||
|
{
|
||||||
|
_matcherCache = cacheManager.GetCache<ITermMatcher>(GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMatch(string term, string value)
|
||||||
|
{
|
||||||
|
return GetMatcher(term).IsMatch(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MatchingTerm(string term, string value)
|
||||||
|
{
|
||||||
|
return GetMatcher(term).MatchingTerm(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITermMatcher GetMatcher(string term)
|
||||||
|
{
|
||||||
|
return _matcherCache.Get(term, () => CreateMatcherInternal(term), TimeSpan.FromHours(24));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITermMatcher CreateMatcherInternal(string term)
|
||||||
|
{
|
||||||
|
Regex regex;
|
||||||
|
if (PerlRegexFactory.TryCreateRegex(term, out regex))
|
||||||
|
{
|
||||||
|
return new RegexTermMatcher(regex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new CaseInsensitiveTermMatcher(term);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
namespace NzbDrone.Core.Profiles.Releases.TermMatchers
|
||||||
|
{
|
||||||
|
public sealed class CaseInsensitiveTermMatcher : ITermMatcher
|
||||||
|
{
|
||||||
|
private readonly string _term;
|
||||||
|
|
||||||
|
public CaseInsensitiveTermMatcher(string term)
|
||||||
|
{
|
||||||
|
_term = term.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMatch(string value)
|
||||||
|
{
|
||||||
|
return value.ToLowerInvariant().Contains(_term);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MatchingTerm(string value)
|
||||||
|
{
|
||||||
|
return _term;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace NzbDrone.Core.Profiles.Releases.TermMatchers
|
||||||
|
{
|
||||||
|
public interface ITermMatcher
|
||||||
|
{
|
||||||
|
bool IsMatch(string value);
|
||||||
|
string MatchingTerm(string value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Profiles.Releases.TermMatchers
|
||||||
|
{
|
||||||
|
public class RegexTermMatcher : ITermMatcher
|
||||||
|
{
|
||||||
|
private readonly Regex _regex;
|
||||||
|
|
||||||
|
public RegexTermMatcher(Regex regex)
|
||||||
|
{
|
||||||
|
_regex = regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMatch(string value)
|
||||||
|
{
|
||||||
|
return _regex.IsMatch(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MatchingTerm(string value)
|
||||||
|
{
|
||||||
|
return _regex.Match(value).Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue