I've made some updates to Recyclarr's CF "field" handling for specifications, specifically addressing the issues regarding processing language specifications Here's a quick rundown of how Recyclarr processes fields for a language spec after this change: When loading the following fields from the guide: ```json "fields": { "value": 8, "exceptLanguage": false } ``` Recyclarr transforms it into the API-compatible format: ```json "fields": [ { "name": "value", "value": 8 }, { "name": "exceptLanguage", "value": false } ] ``` Next, it retrieves CF data from the API. For instance, if the API returns: ```json "fields": [ { "name": "value", "value": 10 }, { "name": "foo", "value": "bar" }, { "name": "exceptLanguage", "value": true } ] ``` Recyclarr compares the two sets of fields by matching the `name` attributes from the guide to those from the API. Any fields present in the API but absent in the guide are ignored. The values for matching fields are then updated accordingly, and these changes are pushed back. For this example: - The field `value` is updated from `8` to `10`. - The field `exceptLanguage` is updated from `false` to `true`. - The field `foo` is ignored since there's no corresponding field in the guide.qodana
parent
2a2d0275ba
commit
59fab961bb
@ -0,0 +1,14 @@
|
||||
namespace Recyclarr.Common.Extensions;
|
||||
|
||||
#pragma warning disable CS8851
|
||||
public static class HashCodeExtensions
|
||||
{
|
||||
public static int CalcHashCode<T>(this IEnumerable<T> source)
|
||||
{
|
||||
return source.Aggregate(new HashCode(), (hash, item) =>
|
||||
{
|
||||
hash.Add(item);
|
||||
return hash;
|
||||
}).ToHashCode();
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
namespace Recyclarr.TrashGuide.CustomFormat;
|
||||
|
||||
public sealed class CustomFormatDataEqualityComparer : IEqualityComparer<CustomFormatData>
|
||||
{
|
||||
public bool Equals(CustomFormatData? x, CustomFormatData? y)
|
||||
{
|
||||
if (ReferenceEquals(x, y))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, null) || ReferenceEquals(y, null) || x.GetType() != y.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.Id.Equals(y.Id) &&
|
||||
x.Name.Equals(y.Name, StringComparison.Ordinal) &&
|
||||
x.IncludeCustomFormatWhenRenaming.Equals(y.IncludeCustomFormatWhenRenaming) &&
|
||||
AllSpecificationsEqual(x.Specifications, y.Specifications);
|
||||
}
|
||||
|
||||
private static bool AllSpecificationsEqual(
|
||||
IReadOnlyCollection<CustomFormatSpecificationData> first,
|
||||
IReadOnlyCollection<CustomFormatSpecificationData> second)
|
||||
{
|
||||
if (first.Count != second.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return first
|
||||
.FullOuterHashJoin(second, x => x.Name, x => x.Name, _ => false, _ => false, SpecificationEqual)
|
||||
.All(x => x);
|
||||
}
|
||||
|
||||
private static bool SpecificationEqual(CustomFormatSpecificationData a, CustomFormatSpecificationData b)
|
||||
{
|
||||
return a.Name.Equals(b.Name, StringComparison.Ordinal) &&
|
||||
a.Implementation.Equals(b.Implementation, StringComparison.Ordinal) &&
|
||||
a.Negate.Equals(b.Negate) &&
|
||||
a.Required.Equals(b.Required) &&
|
||||
AllFieldsEqual(a.Fields, b.Fields);
|
||||
}
|
||||
|
||||
private static bool AllFieldsEqual(
|
||||
IReadOnlyCollection<CustomFormatFieldData> first,
|
||||
IReadOnlyCollection<CustomFormatFieldData> second)
|
||||
{
|
||||
if (first.Count != second.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return first
|
||||
.FullOuterHashJoin(second, x => x.Name, x => x.Name, _ => false, _ => false, FieldEqual)
|
||||
.All(x => x);
|
||||
}
|
||||
|
||||
private static bool FieldEqual(CustomFormatFieldData a, CustomFormatFieldData b)
|
||||
{
|
||||
return a.Value?.Equals(b.Value) ?? false;
|
||||
}
|
||||
|
||||
public int GetHashCode(CustomFormatData obj)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = obj.TrashId.GetHashCode();
|
||||
hashCode = (hashCode * 397) ^ obj.Id;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue