parent
f6fbd3cfee
commit
ada01a1116
|
@ -46,13 +46,13 @@ class TextTagInputConnector extends Component {
|
||||||
// to oddities with restrictions (as an example).
|
// to oddities with restrictions (as an example).
|
||||||
|
|
||||||
const newValue = [...valueArray];
|
const newValue = [...valueArray];
|
||||||
const newTags = split(tag.name);
|
const newTags = tag.name.startsWith('/') ? [tag.name] : split(tag.name);
|
||||||
|
|
||||||
newTags.forEach((newTag) => {
|
newTags.forEach((newTag) => {
|
||||||
newValue.push(newTag.trim());
|
newValue.push(newTag.trim());
|
||||||
});
|
});
|
||||||
|
|
||||||
onChange({ name, value: newValue.join(',') });
|
onChange({ name, value: newValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
onTagDelete = ({ index }) => {
|
onTagDelete = ({ index }) => {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import FormLabel from 'Components/Form/FormLabel';
|
||||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||||
import styles from './EditReleaseProfileModalContent.css';
|
import styles from './EditReleaseProfileModalContent.css';
|
||||||
|
|
||||||
const tagInputDelimiters = ['Tab', 'Enter', ','];
|
const tagInputDelimiters = ['Tab', 'Enter'];
|
||||||
|
|
||||||
function EditReleaseProfileModalContent(props) {
|
function EditReleaseProfileModalContent(props) {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -90,7 +90,7 @@ class ReleaseProfile extends Component {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
split(required).map((item) => {
|
required.map((item) => {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ class ReleaseProfile extends Component {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
split(ignored).map((item) => {
|
ignored.map((item) => {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -195,8 +195,8 @@ ReleaseProfile.propTypes = {
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
enabled: PropTypes.bool.isRequired,
|
enabled: PropTypes.bool.isRequired,
|
||||||
required: PropTypes.string.isRequired,
|
required: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
ignored: PropTypes.string.isRequired,
|
ignored: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
preferred: PropTypes.arrayOf(PropTypes.object).isRequired,
|
preferred: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
indexerId: PropTypes.number.isRequired,
|
indexerId: PropTypes.number.isRequired,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.Profiles.Releases;
|
using NzbDrone.Core.Profiles.Releases;
|
||||||
|
@ -27,8 +28,8 @@ namespace NzbDrone.Api.Restrictions
|
||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
|
|
||||||
Required = model.Required,
|
Required = string.Join(",", model.Required),
|
||||||
Ignored = model.Ignored,
|
Ignored = string.Join(",", model.Ignored),
|
||||||
Tags = new HashSet<int>(model.Tags)
|
Tags = new HashSet<int>(model.Tags)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -41,8 +42,8 @@ namespace NzbDrone.Api.Restrictions
|
||||||
{
|
{
|
||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
|
|
||||||
Required = resource.Required,
|
Required = resource.Required.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
|
||||||
Ignored = resource.Ignored,
|
Ignored = resource.Ignored.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
|
||||||
Tags = new HashSet<int>(resource.Tags)
|
Tags = new HashSet<int>(resource.Tags)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
@ -33,7 +34,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
Mocker.SetConstant<ITermMatcherService>(Mocker.Resolve<TermMatcherService>());
|
Mocker.SetConstant<ITermMatcherService>(Mocker.Resolve<TermMatcherService>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenRestictions(string required, string ignored)
|
private void GivenRestictions(List<string> required, List<string> ignored)
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IReleaseProfileService>()
|
Mocker.GetMock<IReleaseProfileService>()
|
||||||
.Setup(s => s.EnabledForTags(It.IsAny<HashSet<int>>(), It.IsAny<int>()))
|
.Setup(s => s.EnabledForTags(It.IsAny<HashSet<int>>(), It.IsAny<int>()))
|
||||||
|
@ -60,7 +61,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_true_when_title_contains_one_required_term()
|
public void should_be_true_when_title_contains_one_required_term()
|
||||||
{
|
{
|
||||||
GivenRestictions("WEBRip", null);
|
GivenRestictions(new List<string> { "WEBRip" }, null);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_false_when_title_does_not_contain_any_required_terms()
|
public void should_be_false_when_title_does_not_contain_any_required_terms()
|
||||||
{
|
{
|
||||||
GivenRestictions("doesnt,exist", null);
|
GivenRestictions(new List<string> { "doesnt", "exist" }, null);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
@ -76,7 +77,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_true_when_title_does_not_contain_any_ignored_terms()
|
public void should_be_true_when_title_does_not_contain_any_ignored_terms()
|
||||||
{
|
{
|
||||||
GivenRestictions(null, "ignored");
|
GivenRestictions(null, new List<string> { "ignored" });
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
@ -84,7 +85,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_false_when_title_contains_one_anded_ignored_terms()
|
public void should_be_false_when_title_contains_one_anded_ignored_terms()
|
||||||
{
|
{
|
||||||
GivenRestictions(null, "edited");
|
GivenRestictions(null, new List<string> { "edited" });
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
@ -95,7 +96,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[TestCase("X264,NOTTHERE")]
|
[TestCase("X264,NOTTHERE")]
|
||||||
public void should_ignore_case_when_matching_required(string required)
|
public void should_ignore_case_when_matching_required(string required)
|
||||||
{
|
{
|
||||||
GivenRestictions(required, null);
|
GivenRestictions(required.Split(',').ToList(), null);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
@ -106,7 +107,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[TestCase("X264,NOTTHERE")]
|
[TestCase("X264,NOTTHERE")]
|
||||||
public void should_ignore_case_when_matching_ignored(string ignored)
|
public void should_ignore_case_when_matching_ignored(string ignored)
|
||||||
{
|
{
|
||||||
GivenRestictions(null, ignored);
|
GivenRestictions(null, ignored.Split(',').ToList());
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
@ -120,7 +121,11 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.Setup(s => s.EnabledForTags(It.IsAny<HashSet<int>>(), It.IsAny<int>()))
|
.Setup(s => s.EnabledForTags(It.IsAny<HashSet<int>>(), It.IsAny<int>()))
|
||||||
.Returns(new List<ReleaseProfile>
|
.Returns(new List<ReleaseProfile>
|
||||||
{
|
{
|
||||||
new ReleaseProfile { Required = "x264", Ignored = "www.Speed.cd" }
|
new ReleaseProfile
|
||||||
|
{
|
||||||
|
Required = new List<string> { "x264" },
|
||||||
|
Ignored = new List<string> { "www.Speed.cd" }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
|
@ -132,7 +137,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[TestCase(@"/\.WEB/", true)]
|
[TestCase(@"/\.WEB/", true)]
|
||||||
public void should_match_perl_regex(string pattern, bool expected)
|
public void should_match_perl_regex(string pattern, bool expected)
|
||||||
{
|
{
|
||||||
GivenRestictions(pattern, null);
|
GivenRestictions(pattern.Split(',').ToList(), null);
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().Be(expected);
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(162)]
|
||||||
|
public class release_profile_to_array : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Execute.WithConnection(ChangeRequiredIgnoredTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ChangeRequiredIgnoredTypes(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
using (var getEmailCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
getEmailCmd.Transaction = tran;
|
||||||
|
getEmailCmd.CommandText = "SELECT Id, Required, Ignored FROM ReleaseProfiles";
|
||||||
|
|
||||||
|
using (var reader = getEmailCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
var id = reader.GetInt32(0);
|
||||||
|
var required = reader.GetString(1).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var ignored = reader.GetString(2).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
using (var updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = "UPDATE ReleaseProfiles SET Required = ?, Ignored = ? WHERE Id = ?";
|
||||||
|
updateCmd.AddParameter(required.ToJson());
|
||||||
|
updateCmd.AddParameter(ignored.ToJson());
|
||||||
|
updateCmd.AddParameter(id);
|
||||||
|
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,12 +32,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
var title = subject.Release.Title;
|
var title = subject.Release.Title;
|
||||||
var releaseProfiles = _releaseProfileService.EnabledForTags(subject.Series.Tags, subject.Release.IndexerId);
|
var releaseProfiles = _releaseProfileService.EnabledForTags(subject.Series.Tags, subject.Release.IndexerId);
|
||||||
|
|
||||||
var required = releaseProfiles.Where(r => r.Required.IsNotNullOrWhiteSpace());
|
var required = releaseProfiles.Where(r => r.Required.Any());
|
||||||
var ignored = releaseProfiles.Where(r => r.Ignored.IsNotNullOrWhiteSpace());
|
var ignored = releaseProfiles.Where(r => r.Ignored.Any());
|
||||||
|
|
||||||
foreach (var r in required)
|
foreach (var r in required)
|
||||||
{
|
{
|
||||||
var requiredTerms = r.Required.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList();
|
var requiredTerms = r.Required;
|
||||||
|
|
||||||
var foundTerms = ContainsAny(requiredTerms, title);
|
var foundTerms = ContainsAny(requiredTerms, title);
|
||||||
if (foundTerms.Empty())
|
if (foundTerms.Empty())
|
||||||
|
@ -50,7 +50,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
foreach (var r in ignored)
|
foreach (var r in ignored)
|
||||||
{
|
{
|
||||||
var ignoredTerms = r.Ignored.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
var ignoredTerms = r.Ignored;
|
||||||
|
|
||||||
var foundTerms = ContainsAny(ignoredTerms, title);
|
var foundTerms = ContainsAny(ignoredTerms, title);
|
||||||
if (foundTerms.Any())
|
if (foundTerms.Any())
|
||||||
|
|
|
@ -7,8 +7,8 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
public string Required { get; set; }
|
public List<string> Required { get; set; }
|
||||||
public string Ignored { get; set; }
|
public List<string> Ignored { get; set; }
|
||||||
public List<KeyValuePair<string, int>> Preferred { get; set; }
|
public List<KeyValuePair<string, int>> Preferred { get; set; }
|
||||||
public bool IncludePreferredWhenRenaming { get; set; }
|
public bool IncludePreferredWhenRenaming { get; set; }
|
||||||
public int IndexerId { get; set; }
|
public int IndexerId { get; set; }
|
||||||
|
@ -17,6 +17,8 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
public ReleaseProfile()
|
public ReleaseProfile()
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
|
Required = new List<string>();
|
||||||
|
Ignored = new List<string>();
|
||||||
Preferred = new List<KeyValuePair<string, int>>();
|
Preferred = new List<KeyValuePair<string, int>>();
|
||||||
IncludePreferredWhenRenaming = true;
|
IncludePreferredWhenRenaming = true;
|
||||||
Tags = new HashSet<int>();
|
Tags = new HashSet<int>();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using FluentValidation.Results;
|
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Profiles.Releases;
|
using NzbDrone.Core.Profiles.Releases;
|
||||||
|
@ -28,7 +27,7 @@ namespace Sonarr.Api.V3.Profiles.Release
|
||||||
|
|
||||||
SharedValidator.RuleFor(d => d).Custom((restriction, context) =>
|
SharedValidator.RuleFor(d => d).Custom((restriction, context) =>
|
||||||
{
|
{
|
||||||
if (restriction.Ignored.IsNullOrWhiteSpace() && restriction.Required.IsNullOrWhiteSpace() && restriction.Preferred.Empty())
|
if (restriction.Ignored.Empty() && restriction.Required.Empty() && restriction.Preferred.Empty())
|
||||||
{
|
{
|
||||||
context.AddFailure("'Must contain', 'Must not contain' or 'Preferred' is required");
|
context.AddFailure("'Must contain', 'Must not contain' or 'Preferred' is required");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ namespace Sonarr.Api.V3.Profiles.Release
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
public string Required { get; set; }
|
public List<string> Required { get; set; }
|
||||||
public string Ignored { get; set; }
|
public List<string> Ignored { get; set; }
|
||||||
public List<KeyValuePair<string, int>> Preferred { get; set; }
|
public List<KeyValuePair<string, int>> Preferred { get; set; }
|
||||||
public bool IncludePreferredWhenRenaming { get; set; }
|
public bool IncludePreferredWhenRenaming { get; set; }
|
||||||
public int IndexerId { get; set; }
|
public int IndexerId { get; set; }
|
||||||
|
|
Loading…
Reference in New Issue