parent
068ea1e934
commit
f31ac39e37
@ -0,0 +1,120 @@
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class add_webrip_and_br480_qualites_in_profileFixture : MigrationTest<add_webrip_and_br480_qualites_in_profile>
|
||||
{
|
||||
private string GenerateQualityJson(int quality, bool allowed)
|
||||
{
|
||||
return $"{{ \"quality\": {quality}, \"allowed\": {allowed.ToString().ToLowerInvariant()} }}";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_webrip_qualities_and_group_with_webdl()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Profiles").Row(new
|
||||
{
|
||||
Id = 0,
|
||||
Name = "SDTV",
|
||||
Cutoff = 1,
|
||||
Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.WEBRip480p, false)}, {GenerateQualityJson((int)Quality.WEBRip720p, false)}, {GenerateQualityJson((int)Quality.WEBRip1080p, false)}, {GenerateQualityJson((int)Quality.WEBRip2160p, false)}]"
|
||||
});
|
||||
});
|
||||
|
||||
var profiles = db.Query<Profile117>("SELECT Items FROM Profiles LIMIT 1");
|
||||
|
||||
var items = profiles.First().Items;
|
||||
items.Should().HaveCount(6);
|
||||
items.Select(v => v.Quality).Should().BeEquivalentTo(1, null, null, null, null, null);
|
||||
items.Select(v => v.Items.Count).Should().BeEquivalentTo(0, 2, 2, 2, 2, 2);
|
||||
items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false, false, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_bluray480p_quality_and_group_with_dvd()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Profiles").Row(new
|
||||
{
|
||||
Id = 0,
|
||||
Name = "SDTV",
|
||||
Cutoff = 1,
|
||||
Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.DVD, false)}, {GenerateQualityJson((int)Quality.Bluray480p, false)}]"
|
||||
});
|
||||
});
|
||||
|
||||
var profiles = db.Query<Profile117>("SELECT Items FROM Profiles LIMIT 1");
|
||||
|
||||
var items = profiles.First().Items;
|
||||
items.Should().HaveCount(6);
|
||||
items.Select(v => v.Quality).Should().BeEquivalentTo(1, null, null, null, null, null);
|
||||
items.Select(v => v.Items.Count).Should().BeEquivalentTo(0, 2, 2, 2, 2, 2);
|
||||
items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false, false, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_webrip_and_webdl_if_webdl_is_missing()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Profiles").Row(new
|
||||
{
|
||||
Id = 0,
|
||||
Name = "SDTV",
|
||||
Cutoff = 1,
|
||||
Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.WEBRip480p, false)}, {GenerateQualityJson((int)Quality.WEBRip720p, false)}, {GenerateQualityJson((int)Quality.WEBRip1080p, false)}]"
|
||||
});
|
||||
});
|
||||
|
||||
var profiles = db.Query<Profile117>("SELECT Items FROM Profiles LIMIT 1");
|
||||
|
||||
var items = profiles.First().Items;
|
||||
items.Should().HaveCount(6);
|
||||
items.Select(v => v.Quality).Should().BeEquivalentTo(1, null, null, null, null, null);
|
||||
items.Select(v => v.Items.Count).Should().BeEquivalentTo(0, 2, 2, 2, 2, 2);
|
||||
items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false, false, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_group_webrip_and_webdl_with_the_same_resolution()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Profiles").Row(new
|
||||
{
|
||||
Id = 0,
|
||||
Name = "SDTV",
|
||||
Cutoff = 1,
|
||||
Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.WEBRip480p, false)}, {GenerateQualityJson((int)Quality.WEBRip720p, false)}, {GenerateQualityJson((int)Quality.WEBRip1080p, false)}, {GenerateQualityJson((int)Quality.WEBRip2160p, false)}]"
|
||||
});
|
||||
});
|
||||
|
||||
var profiles = db.Query<Profile117>("SELECT Items FROM Profiles LIMIT 1");
|
||||
var items = profiles.First().Items;
|
||||
|
||||
items[1].Items.First().Quality.Should().Be((int)Quality.WEBRip480p);
|
||||
items[1].Items.Last().Quality.Should().Be((int)Quality.WEBDL480p);
|
||||
|
||||
items[2].Items.First().Quality.Should().Be((int)Quality.DVD);
|
||||
items[2].Items.Last().Quality.Should().Be((int)Quality.Bluray480p);
|
||||
|
||||
items[3].Items.First().Quality.Should().Be((int)Quality.WEBRip720p);
|
||||
items[3].Items.Last().Quality.Should().Be((int)Quality.WEBDL720p);
|
||||
|
||||
items[4].Items.First().Quality.Should().Be((int)Quality.WEBRip1080p);
|
||||
items[4].Items.Last().Quality.Should().Be((int)Quality.WEBDL1080p);
|
||||
|
||||
items[5].Items.First().Quality.Should().Be((int)Quality.WEBRip2160p);
|
||||
items[5].Items.Last().Quality.Should().Be((int)Quality.WEBDL2160p);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using FluentMigrator;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(117)]
|
||||
public class add_webrip_and_br480_qualites_in_profile : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(ConvertProfile);
|
||||
}
|
||||
|
||||
private void ConvertProfile(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
var updater = new ProfileUpdater116(conn, tran);
|
||||
|
||||
updater.CreateGroupAt(8, 1000, "WEB 480p", new[] {12, 8}); // Group WEBRip480p with WEBDL480p
|
||||
updater.CreateGroupAt(2, 1001, "DVD", new[] {2, 13}); // Group Bluray480p with DVD
|
||||
updater.CreateGroupAt(5, 1002, "WEB 720p", new[] {14, 5}); // Group WEBRip720p with WEBDL720p
|
||||
updater.CreateGroupAt(3, 1003, "WEB 1080p", new[] {15, 3}); // Group WEBRip1080p with WEBDL1080p
|
||||
updater.CreateGroupAt(18, 1004, "WEB 2160p", new[] {17, 18}); // Group WEBRip2160p with WEBDL2160p
|
||||
|
||||
updater.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
public class Profile117
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int Cutoff { get; set; }
|
||||
public List<ProfileItem117> Items { get; set; }
|
||||
}
|
||||
|
||||
public class ProfileItem117
|
||||
{
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public int? Quality { get; set; }
|
||||
public List<ProfileItem117> Items { get; set; }
|
||||
public bool Allowed { get; set; }
|
||||
|
||||
public ProfileItem117()
|
||||
{
|
||||
Items = new List<ProfileItem117>();
|
||||
}
|
||||
}
|
||||
|
||||
public class ProfileUpdater116
|
||||
{
|
||||
private readonly IDbConnection _connection;
|
||||
private readonly IDbTransaction _transaction;
|
||||
|
||||
private List<Profile117> _profiles;
|
||||
private HashSet<Profile117> _changedProfiles = new HashSet<Profile117>();
|
||||
|
||||
public ProfileUpdater116(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
_connection = conn;
|
||||
_transaction = tran;
|
||||
|
||||
_profiles = GetProfiles();
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
foreach (var profile in _changedProfiles)
|
||||
{
|
||||
using (var updateProfileCmd = _connection.CreateCommand())
|
||||
{
|
||||
updateProfileCmd.Transaction = _transaction;
|
||||
updateProfileCmd.CommandText =
|
||||
"UPDATE Profiles SET Name = ?, Cutoff = ?, Items = ? WHERE Id = ?";
|
||||
updateProfileCmd.AddParameter(profile.Name);
|
||||
updateProfileCmd.AddParameter(profile.Cutoff);
|
||||
updateProfileCmd.AddParameter(profile.Items.ToJson());
|
||||
updateProfileCmd.AddParameter(profile.Id);
|
||||
|
||||
updateProfileCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
_changedProfiles.Clear();
|
||||
}
|
||||
|
||||
public void CreateGroupAt(int find, int groupId, string name, int[] qualities)
|
||||
{
|
||||
foreach (var profile in _profiles)
|
||||
{
|
||||
var findIndex = profile.Items.FindIndex(v => v.Quality == find);
|
||||
|
||||
if (findIndex > -1)
|
||||
{
|
||||
var findQuality = profile.Items[findIndex];
|
||||
|
||||
profile.Items.Insert(findIndex, new ProfileItem117
|
||||
{
|
||||
Id = groupId,
|
||||
Name = name,
|
||||
Quality = null,
|
||||
Items = qualities.Select(q => new ProfileItem117
|
||||
{
|
||||
Quality = q,
|
||||
Allowed = findQuality.Allowed
|
||||
}).ToList(),
|
||||
Allowed = findQuality.Allowed
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the ID isn't found for some reason (mangled migration 71?)
|
||||
|
||||
profile.Items.Add(new ProfileItem117
|
||||
{
|
||||
Id = groupId,
|
||||
Name = name,
|
||||
Quality = null,
|
||||
Items = qualities.Select(q => new ProfileItem117
|
||||
{
|
||||
Quality = q,
|
||||
Allowed = false
|
||||
}).ToList(),
|
||||
Allowed = false
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var quality in qualities)
|
||||
{
|
||||
var index = profile.Items.FindIndex(v => v.Quality == quality);
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
profile.Items.RemoveAt(index);
|
||||
}
|
||||
|
||||
if (profile.Cutoff == quality)
|
||||
{
|
||||
profile.Cutoff = groupId;
|
||||
}
|
||||
}
|
||||
|
||||
_changedProfiles.Add(profile);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Profile117> GetProfiles()
|
||||
{
|
||||
var profiles = new List<Profile117>();
|
||||
|
||||
using (var getProfilesCmd = _connection.CreateCommand())
|
||||
{
|
||||
getProfilesCmd.Transaction = _transaction;
|
||||
getProfilesCmd.CommandText = @"SELECT Id, Name, Cutoff, Items FROM Profiles";
|
||||
|
||||
using (var profileReader = getProfilesCmd.ExecuteReader())
|
||||
{
|
||||
while (profileReader.Read())
|
||||
{
|
||||
profiles.Add(new Profile117
|
||||
{
|
||||
Id = profileReader.GetInt32(0),
|
||||
Name = profileReader.GetString(1),
|
||||
Cutoff = profileReader.GetInt32(2),
|
||||
Items = Json.Deserialize<List<ProfileItem117>>(profileReader.GetString(3))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Validators;
|
||||
|
||||
namespace Sonarr.Api.V3.Profiles.Quality
|
||||
{
|
||||
public static class QualityCutoffValidator
|
||||
{
|
||||
public static IRuleBuilderOptions<T, int> ValidCutoff<T>(this IRuleBuilder<T, int> ruleBuilder)
|
||||
{
|
||||
return ruleBuilder.SetValidator(new ValidCutoffValidator<T>());
|
||||
}
|
||||
}
|
||||
|
||||
public class ValidCutoffValidator<T> : PropertyValidator
|
||||
{
|
||||
public ValidCutoffValidator()
|
||||
: base("Cutoff must be an allowed quality or group")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override bool IsValid(PropertyValidatorContext context)
|
||||
{
|
||||
var cutoff = (int)context.PropertyValue;
|
||||
dynamic instance = context.ParentContext.InstanceToValidate;
|
||||
var items = instance.Items as IList<QualityProfileQualityItemResource>;
|
||||
|
||||
var cutoffItem = items.SingleOrDefault(i => (i.Quality == null && i.Id == cutoff) || i.Quality?.Id == cutoff);
|
||||
|
||||
if (cutoffItem == null) return false;
|
||||
|
||||
if (!cutoffItem.Allowed) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue