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.
recyclarr/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatTransactionPhas...

117 lines
4.3 KiB

using Recyclarr.Cli.Pipelines.CustomFormat.Models;
using Recyclarr.Cli.Pipelines.Generic;
using Recyclarr.Common.Extensions;
using Recyclarr.Config.Models;
using Recyclarr.TrashGuide.CustomFormat;
namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases;
public class CustomFormatTransactionPhase(ILogger log) : ITransactionPipelinePhase<CustomFormatPipelineContext>
{
public void Execute(CustomFormatPipelineContext context, IServiceConfiguration config)
{
var transactions = new CustomFormatTransactionData();
foreach (var guideCf in context.ConfigOutput)
{
log.Debug("Process transaction for guide CF {TrashId} ({Name})", guideCf.TrashId, guideCf.Name);
guideCf.Id = context.Cache.FindId(guideCf) ?? 0;
var serviceCf = FindServiceCfByName(context.ApiFetchOutput, guideCf.Name);
if (serviceCf is not null)
{
ProcessExistingCf(config, guideCf, serviceCf, transactions);
continue;
}
serviceCf = FindServiceCfById(context.ApiFetchOutput, guideCf.Id);
if (serviceCf is not null)
{
// We do not use AddUpdatedCustomFormat() here because it's impossible for the CFs to be identical if we
// got to this point. Reason: We reach this code if the names are not the same. At the very least, this
// means the name needs to be updated in the service.
transactions.UpdatedCustomFormats.Add(guideCf);
}
else
{
transactions.NewCustomFormats.Add(guideCf);
}
}
if (config.DeleteOldCustomFormats)
{
transactions.DeletedCustomFormats.AddRange(context.Cache.Mappings
// Custom format must be in the cache but NOT in the user's config
.Where(map => context.ConfigOutput.All(cf => cf.TrashId != map.TrashId))
// Also, that cache-only CF must exist in the service (otherwise there is nothing to delete)
.Where(map => context.ApiFetchOutput.Any(cf => cf.Id == map.CustomFormatId)));
}
context.TransactionOutput = transactions;
}
private void ProcessExistingCf(
IServiceConfiguration config,
CustomFormatData guideCf,
CustomFormatData serviceCf,
CustomFormatTransactionData transactions)
{
if (config.ReplaceExistingCustomFormats)
{
// replace:
// - Use the ID from the service, not the cache, and do an update
if (guideCf.Id != serviceCf.Id)
{
log.Debug(
"Format IDs for CF {Name} did not match which indicates a manually-created CF is " +
"replaced, or that the cache is out of sync with the service ({GuideId} != {ServiceId})",
serviceCf.Name, guideCf.Id, serviceCf.Id);
guideCf.Id = serviceCf.Id;
}
AddUpdatedCustomFormat(guideCf, serviceCf, transactions);
}
else
{
// NO replace:
// - ids must match (can't rename another cf to the same name), otherwise error
if (guideCf.Id != serviceCf.Id)
{
transactions.ConflictingCustomFormats.Add(
new ConflictingCustomFormat(guideCf, serviceCf.Id));
}
else
{
AddUpdatedCustomFormat(guideCf, serviceCf, transactions);
}
}
}
private static void AddUpdatedCustomFormat(
CustomFormatData guideCf,
CustomFormatData serviceCf,
CustomFormatTransactionData transactions)
{
if (!CustomFormatData.Comparer.Equals(guideCf, serviceCf))
{
transactions.UpdatedCustomFormats.Add(guideCf);
}
else
{
transactions.UnchangedCustomFormats.Add(guideCf);
}
}
private static CustomFormatData? FindServiceCfByName(IEnumerable<CustomFormatData> serviceCfs, string cfName)
{
return serviceCfs.FirstOrDefault(rcf => cfName.EqualsIgnoreCase(rcf.Name));
}
private static CustomFormatData? FindServiceCfById(IEnumerable<CustomFormatData> serviceCfs, int cfId)
{
return serviceCfs.FirstOrDefault(rcf => cfId == rcf.Id);
}
}