using System.Collections.Generic; using System.Linq; using FluentValidation; using FluentValidation.Validators; using NzbDrone.Common.Extensions; namespace Readarr.Api.V1.Profiles.Quality { public static class QualityItemsValidator { public static IRuleBuilderOptions> ValidItems(this IRuleBuilder> ruleBuilder) { ruleBuilder.SetValidator(new NotEmptyValidator(null)); ruleBuilder.SetValidator(new AllowedValidator()); ruleBuilder.SetValidator(new QualityNameValidator()); ruleBuilder.SetValidator(new GroupItemValidator()); ruleBuilder.SetValidator(new ItemGroupIdValidator()); ruleBuilder.SetValidator(new UniqueIdValidator()); ruleBuilder.SetValidator(new UniqueQualityIdValidator()); return ruleBuilder.SetValidator(new ItemGroupNameValidator()); } } public class AllowedValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Must contain at least one allowed quality"; protected override bool IsValid(PropertyValidatorContext context) { return context.PropertyValue is IList list && list.Any(c => c.Allowed); } } public class GroupItemValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Groups must contain multiple qualities"; protected override bool IsValid(PropertyValidatorContext context) { if (context.PropertyValue is not IList items) { return false; } return !items.Any(i => i.Name.IsNotNullOrWhiteSpace() && i.Items.Count <= 1); } } public class QualityNameValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Individual qualities should not be named"; protected override bool IsValid(PropertyValidatorContext context) { if (context.PropertyValue is not IList items) { return false; } return !items.Any(i => i.Name.IsNotNullOrWhiteSpace() && i.Quality != null); } } public class ItemGroupNameValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Groups must have a name"; protected override bool IsValid(PropertyValidatorContext context) { if (context.PropertyValue is not IList items) { return false; } return !items.Any(i => i.Quality == null && i.Name.IsNullOrWhiteSpace()); } } public class ItemGroupIdValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Groups must have an ID"; protected override bool IsValid(PropertyValidatorContext context) { if (context.PropertyValue is not IList items) { return false; } return !items.Any(i => i.Quality == null && i.Id == 0); } } public class UniqueIdValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Groups must have a unique ID"; protected override bool IsValid(PropertyValidatorContext context) { if (context.PropertyValue is not IList items) { return false; } var ids = items.Where(i => i.Id > 0).Select(i => i.Id); var groupedIds = ids.GroupBy(i => i); return groupedIds.All(g => g.Count() == 1); } } public class UniqueQualityIdValidator : PropertyValidator { protected override string GetDefaultMessageTemplate() => "Qualities can only be used once"; protected override bool IsValid(PropertyValidatorContext context) { if (context.PropertyValue is not IList items) { return false; } var qualityIds = new HashSet(); foreach (var item in items) { if (item.Id > 0) { foreach (var quality in item.Items) { if (qualityIds.Contains(quality.Quality.Id)) { return false; } qualityIds.Add(quality.Quality.Id); } } else { if (qualityIds.Contains(item.Quality.Id)) { return false; } qualityIds.Add(item.Quality.Id); } } return true; } } }