You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.5 KiB
93 lines
3.5 KiB
using Newtonsoft.Json.Linq;
|
|
using Recyclarr.Common.Extensions;
|
|
using Recyclarr.TrashLib.Config.Services;
|
|
using Recyclarr.TrashLib.Services.CustomFormat.Api;
|
|
using Recyclarr.TrashLib.Services.CustomFormat.Models;
|
|
|
|
namespace Recyclarr.TrashLib.Services.CustomFormat.Processors.PersistenceSteps;
|
|
|
|
internal class QualityProfileApiPersistenceStep : IQualityProfileApiPersistenceStep
|
|
{
|
|
private readonly IQualityProfileService _api;
|
|
private readonly List<string> _invalidProfileNames = new();
|
|
private readonly Dictionary<string, List<UpdatedFormatScore>> _updatedScores = new();
|
|
|
|
public IDictionary<string, List<UpdatedFormatScore>> UpdatedScores => _updatedScores;
|
|
public IReadOnlyCollection<string> InvalidProfileNames => _invalidProfileNames;
|
|
|
|
public QualityProfileApiPersistenceStep(IQualityProfileService api)
|
|
{
|
|
_api = api;
|
|
}
|
|
|
|
public async Task Process(
|
|
IServiceConfiguration config,
|
|
IDictionary<string, QualityProfileCustomFormatScoreMapping> cfScores)
|
|
{
|
|
var serviceProfiles = await _api.GetQualityProfiles(config);
|
|
|
|
// Match quality profiles in Radarr to ones the user put in their config.
|
|
// For each match, we return a tuple including the list of custom format scores ("formatItems").
|
|
// Using GroupJoin() because we want a LEFT OUTER JOIN so we can list which quality profiles in config
|
|
// do not match profiles in Radarr.
|
|
var profileScores = cfScores.GroupJoin(serviceProfiles,
|
|
s => s.Key,
|
|
p => p.Value<string>("name"),
|
|
(s, p) => (s.Key, s.Value, p.SelectMany(pi => pi.Children<JObject>("formatItems")).ToList()),
|
|
StringComparer.InvariantCultureIgnoreCase);
|
|
|
|
foreach (var (profileName, scoreMap, formatItems) in profileScores)
|
|
{
|
|
if (formatItems.Count == 0)
|
|
{
|
|
_invalidProfileNames.Add(profileName);
|
|
continue;
|
|
}
|
|
|
|
foreach (var json in formatItems)
|
|
{
|
|
var map = FindScoreEntry(json, scoreMap);
|
|
|
|
int? scoreToUse = null;
|
|
FormatScoreUpdateReason? reason = null;
|
|
|
|
if (map != null)
|
|
{
|
|
scoreToUse = map.Score;
|
|
reason = FormatScoreUpdateReason.Updated;
|
|
}
|
|
else if (scoreMap.ResetUnmatchedScores)
|
|
{
|
|
scoreToUse = 0;
|
|
reason = FormatScoreUpdateReason.Reset;
|
|
}
|
|
|
|
if (scoreToUse == null || reason == null || json.Value<int>("score") == scoreToUse)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
json["score"] = scoreToUse.Value;
|
|
_updatedScores.GetOrCreate(profileName)
|
|
.Add(new UpdatedFormatScore(json.ValueOrThrow<string>("name"), scoreToUse.Value, reason.Value));
|
|
}
|
|
|
|
if (!_updatedScores.TryGetValue(profileName, out var updatedScores) || updatedScores.Count == 0)
|
|
{
|
|
// No scores to update, so don't bother with the API call
|
|
continue;
|
|
}
|
|
|
|
var jsonRoot = (JObject) formatItems.First().Root;
|
|
await _api.UpdateQualityProfile(config, jsonRoot, jsonRoot.Value<int>("id"));
|
|
}
|
|
}
|
|
|
|
private static FormatMappingEntry? FindScoreEntry(JObject formatItem,
|
|
QualityProfileCustomFormatScoreMapping scoreMap)
|
|
{
|
|
return scoreMap.Mapping.FirstOrDefault(
|
|
m => formatItem.Value<int>("format") == m.CustomFormat.FormatId);
|
|
}
|
|
}
|