New: Add min pages and ignored terms to metadata profiles

pull/1016/head
ta264 4 years ago
parent 23142a59d7
commit 00e4555736

@ -15,6 +15,9 @@ import { inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import styles from './EditMetadataProfileModalContent.css'; import styles from './EditMetadataProfileModalContent.css';
// Tab, enter, and comma
const tagInputDelimiters = [9, 13, 188];
function EditMetadataProfileModalContent(props) { function EditMetadataProfileModalContent(props) {
const { const {
isFetching, isFetching,
@ -38,7 +41,9 @@ function EditMetadataProfileModalContent(props) {
skipMissingIsbn, skipMissingIsbn,
skipPartsAndSets, skipPartsAndSets,
skipSeriesSecondary, skipSeriesSecondary,
allowedLanguages allowedLanguages,
ignored,
minPages
} = item; } = item;
return ( return (
@ -92,6 +97,21 @@ function EditMetadataProfileModalContent(props) {
/> />
</FormGroup> </FormGroup>
<FormGroup>
<FormLabel>
{translate('MinimumPages')}
</FormLabel>
<FormInputGroup
type={inputTypes.NUMBER}
name="minPages"
{...minPages}
helpText={translate('MinPagesHelpText')}
min={0}
onChange={onInputChange}
/>
</FormGroup>
<FormGroup> <FormGroup>
<FormLabel> <FormLabel>
{translate('SkipBooksWithMissingReleaseDate')} {translate('SkipBooksWithMissingReleaseDate')}
@ -157,6 +177,23 @@ function EditMetadataProfileModalContent(props) {
/> />
</FormGroup> </FormGroup>
<FormGroup>
<FormLabel>
{translate('MustNotContain')}
</FormLabel>
<FormInputGroup
type={inputTypes.TEXT_TAG}
name="ignored"
helpText={translate('IgnoredHelpText')}
kind={kinds.DANGER}
placeholder={translate('IgnoredPlaceHolder')}
delimiters={tagInputDelimiters}
{...ignored}
onChange={onInputChange}
/>
</FormGroup>
</Form> </Form>
} }
</ModalBody> </ModalBody>

@ -0,0 +1,15 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(008)]
public class extend_metadata_profiles : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("MetadataProfiles").AddColumn("MinPages").AsInt32().NotNullable().WithDefaultValue(0);
Alter.Table("MetadataProfiles").AddColumn("Ignored").AsString().Nullable();
}
}
}

@ -349,6 +349,8 @@
"MinimumFreeSpace": "Minimum Free Space", "MinimumFreeSpace": "Minimum Free Space",
"MinimumFreeSpaceWhenImportingHelpText": "Prevent import if it would leave less than this amount of disk space available", "MinimumFreeSpaceWhenImportingHelpText": "Prevent import if it would leave less than this amount of disk space available",
"MinimumLimits": "Minimum Limits", "MinimumLimits": "Minimum Limits",
"MinimumPages": "Minimum Pages",
"MinPagesHelpText": "Ignore books with fewer pages than this",
"MinimumPopularity": "Minimum Popularity", "MinimumPopularity": "Minimum Popularity",
"Missing": "Missing", "Missing": "Missing",
"MissingBooks": "Missing Books", "MissingBooks": "Missing Books",

@ -11,5 +11,7 @@ namespace NzbDrone.Core.Profiles.Metadata
public bool SkipPartsAndSets { get; set; } public bool SkipPartsAndSets { get; set; }
public bool SkipSeriesSecondary { get; set; } public bool SkipSeriesSecondary { get; set; }
public string AllowedLanguages { get; set; } public string AllowedLanguages { get; set; }
public int MinPages { get; set; }
public string Ignored { get; set; }
} }
} }

@ -9,6 +9,7 @@ using NzbDrone.Core.ImportLists;
using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Profiles.Releases;
using NzbDrone.Core.RootFolders; using NzbDrone.Core.RootFolders;
namespace NzbDrone.Core.Profiles.Metadata namespace NzbDrone.Core.Profiles.Metadata
@ -36,6 +37,7 @@ namespace NzbDrone.Core.Profiles.Metadata
private readonly IMediaFileService _mediaFileService; private readonly IMediaFileService _mediaFileService;
private readonly IImportListFactory _importListFactory; private readonly IImportListFactory _importListFactory;
private readonly IRootFolderService _rootFolderService; private readonly IRootFolderService _rootFolderService;
private readonly ITermMatcherService _termMatcherService;
private readonly Logger _logger; private readonly Logger _logger;
public MetadataProfileService(IMetadataProfileRepository profileRepository, public MetadataProfileService(IMetadataProfileRepository profileRepository,
@ -44,6 +46,7 @@ namespace NzbDrone.Core.Profiles.Metadata
IMediaFileService mediaFileService, IMediaFileService mediaFileService,
IImportListFactory importListFactory, IImportListFactory importListFactory,
IRootFolderService rootFolderService, IRootFolderService rootFolderService,
ITermMatcherService termMatcherService,
Logger logger) Logger logger)
{ {
_profileRepository = profileRepository; _profileRepository = profileRepository;
@ -52,6 +55,7 @@ namespace NzbDrone.Core.Profiles.Metadata
_mediaFileService = mediaFileService; _mediaFileService = mediaFileService;
_importListFactory = importListFactory; _importListFactory = importListFactory;
_rootFolderService = rootFolderService; _rootFolderService = rootFolderService;
_termMatcherService = termMatcherService;
_logger = logger; _logger = logger;
} }
@ -129,6 +133,8 @@ namespace NzbDrone.Core.Profiles.Metadata
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipMissingDate || x.ReleaseDate.HasValue, "release date is missing"); FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipMissingDate || x.ReleaseDate.HasValue, "release date is missing");
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipPartsAndSets || !IsPartOrSet(x, seriesLinks.GetValueOrDefault(x), titles), "book is part of set"); FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipPartsAndSets || !IsPartOrSet(x, seriesLinks.GetValueOrDefault(x), titles), "book is part of set");
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipSeriesSecondary || !seriesLinks.ContainsKey(x) || seriesLinks[x].Any(y => y.IsPrimary), "book is a secondary series item"); FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !p.SkipSeriesSecondary || !seriesLinks.ContainsKey(x) || seriesLinks[x].Any(y => y.IsPrimary), "book is a secondary series item");
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => x.Editions.Value.Any(e => e.PageCount > p.MinPages) || x.Editions.Value.All(e => e.PageCount == 0), "minimum page count not met");
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => !MatchesTerms(x.Title, p.Ignored), "contains ignored terms");
foreach (var book in hash) foreach (var book in hash)
{ {
@ -137,7 +143,7 @@ namespace NzbDrone.Core.Profiles.Metadata
book.Editions = FilterEditions(book.Editions.Value, localEditions, localFiles, profile); book.Editions = FilterEditions(book.Editions.Value, localEditions, localFiles, profile);
} }
FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => x.Editions.Value.Any(), "all editions filterd out"); FilterByPredicate(hash, x => x.ForeignBookId, localHash, profile, (x, p) => x.Editions.Value.Any(), "all editions filtered out");
return hash.ToList(); return hash.ToList();
} }
@ -153,6 +159,7 @@ namespace NzbDrone.Core.Profiles.Metadata
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !allowedLanguages.Any() || allowedLanguages.Contains(x.Language?.ToLower() ?? "null"), "edition language not allowed"); FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !allowedLanguages.Any() || allowedLanguages.Contains(x.Language?.ToLower() ?? "null"), "edition language not allowed");
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !p.SkipMissingIsbn || x.Isbn13.IsNotNullOrWhiteSpace() || x.Asin.IsNotNullOrWhiteSpace(), "isbn and asin is missing"); FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !p.SkipMissingIsbn || x.Isbn13.IsNotNullOrWhiteSpace() || x.Asin.IsNotNullOrWhiteSpace(), "isbn and asin is missing");
FilterByPredicate(hash, x => x.ForeignEditionId, localHash, profile, (x, p) => !MatchesTerms(x.Title, p.Ignored), "contains ignored terms");
return hash.ToList(); return hash.ToList();
} }
@ -195,6 +202,24 @@ namespace NzbDrone.Core.Profiles.Metadata
return false; return false;
} }
private bool MatchesTerms(string value, string terms)
{
if (terms.IsNullOrWhiteSpace() || value.IsNullOrWhiteSpace())
{
return false;
}
var split = terms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
var foundTerms = ContainsAny(split, value);
return foundTerms.Any();
}
private List<string> ContainsAny(List<string> terms, string title)
{
return terms.Where(t => _termMatcherService.IsMatch(t, title)).ToList();
}
public void Handle(ApplicationStartedEvent message) public void Handle(ApplicationStartedEvent message)
{ {
var profiles = All(); var profiles = All();

@ -14,6 +14,8 @@ namespace Readarr.Api.V1.Profiles.Metadata
public bool SkipPartsAndSets { get; set; } public bool SkipPartsAndSets { get; set; }
public bool SkipSeriesSecondary { get; set; } public bool SkipSeriesSecondary { get; set; }
public string AllowedLanguages { get; set; } public string AllowedLanguages { get; set; }
public int MinPages { get; set; }
public string Ignored { get; set; }
} }
public static class MetadataProfileResourceMapper public static class MetadataProfileResourceMapper
@ -34,7 +36,9 @@ namespace Readarr.Api.V1.Profiles.Metadata
SkipMissingIsbn = model.SkipMissingIsbn, SkipMissingIsbn = model.SkipMissingIsbn,
SkipPartsAndSets = model.SkipPartsAndSets, SkipPartsAndSets = model.SkipPartsAndSets,
SkipSeriesSecondary = model.SkipSeriesSecondary, SkipSeriesSecondary = model.SkipSeriesSecondary,
AllowedLanguages = model.AllowedLanguages AllowedLanguages = model.AllowedLanguages,
MinPages = model.MinPages,
Ignored = model.Ignored
}; };
} }
@ -54,7 +58,9 @@ namespace Readarr.Api.V1.Profiles.Metadata
SkipMissingIsbn = resource.SkipMissingIsbn, SkipMissingIsbn = resource.SkipMissingIsbn,
SkipPartsAndSets = resource.SkipPartsAndSets, SkipPartsAndSets = resource.SkipPartsAndSets,
SkipSeriesSecondary = resource.SkipSeriesSecondary, SkipSeriesSecondary = resource.SkipSeriesSecondary,
AllowedLanguages = resource.AllowedLanguages AllowedLanguages = resource.AllowedLanguages,
MinPages = resource.MinPages,
Ignored = resource.Ignored
}; };
} }

Loading…
Cancel
Save