using System.IO.Abstractions; using AutoMapper; using Recyclarr.Config.Models; using Recyclarr.Config.Parsing.PostProcessing; using Recyclarr.Platform; using Serilog.Context; namespace Recyclarr.Config.Parsing; public class ConfigurationLoader( ILogger log, ConfigParser parser, IMapper mapper, ConfigValidationExecutor validator, IEnumerable postProcessors) : IConfigurationLoader { public IReadOnlyCollection Load(IFileInfo file) { using var logScope = LogContext.PushProperty(LogProperty.Scope, file.Name); return ProcessLoadedConfigs(parser.Load(file)); } public IReadOnlyCollection Load(string yaml) { return ProcessLoadedConfigs(parser.Load(yaml)); } public IReadOnlyCollection Load(Func streamFactory) { return ProcessLoadedConfigs(parser.Load(streamFactory)); } private IReadOnlyCollection ProcessLoadedConfigs(RootConfigYaml? config) { if (config is null) { return Array.Empty(); } config = postProcessors.Aggregate(config, (current, processor) => processor.Process(current)); if (config.IsConfigEmpty()) { log.Warning("Configuration is empty"); } if (!validator.Validate(config, YamlValidatorRuleSets.RootConfig)) { return Array.Empty(); } var convertedConfigs = new List(); convertedConfigs.AddRange(MapConfigs(config.Radarr)); convertedConfigs.AddRange(MapConfigs(config.Sonarr)); return convertedConfigs; } private IEnumerable MapConfigs( IReadOnlyDictionary? configs) where TServiceConfig : ServiceConfiguration where TConfigYaml : ServiceConfigYaml { if (configs is null) { return Array.Empty(); } return configs.Select(x => mapper.Map(x.Value) with {InstanceName = x.Key}); } }