using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Common.Configuration; using ValidationException = Common.Exceptions.ValidationException; namespace Data.Models.Configuration.DownloadCleaner; public sealed record DownloadCleanerConfig : IJobConfig { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; init; } = Guid.NewGuid(); public bool Enabled { get; init; } public string CronExpression { get; init; } = "0 0 * * * ?"; /// /// Indicates whether to use the CronExpression directly or convert from a user-friendly schedule /// public bool UseAdvancedScheduling { get; init; } public List Categories { get; init; } = []; public bool DeletePrivate { get; init; } /// /// Indicates whether unlinked download handling is enabled /// public bool UnlinkedEnabled { get; init; } = false; public string UnlinkedTargetCategory { get; init; } = "cleanuparr-unlinked"; public bool UnlinkedUseTag { get; init; } public string UnlinkedIgnoredRootDir { get; init; } = string.Empty; public List UnlinkedCategories { get; init; } = []; public void Validate() { if (!Enabled) { return; } if (Categories.GroupBy(x => x.Name).Any(x => x.Count() > 1)) { throw new ValidationException("duplicated clean categories found"); } Categories.ForEach(x => x.Validate()); // Only validate unlinked settings if unlinked handling is enabled if (!UnlinkedEnabled) { return; } if (string.IsNullOrEmpty(UnlinkedTargetCategory)) { throw new ValidationException("unlinked target category is required"); } if (UnlinkedCategories?.Count is null or 0) { throw new ValidationException("no unlinked categories configured"); } if (UnlinkedCategories.Contains(UnlinkedTargetCategory)) { throw new ValidationException($"The unlinked target category should not be present in unlinked categories"); } if (UnlinkedCategories.Any(string.IsNullOrEmpty)) { throw new ValidationException("empty unlinked category filter found"); } if (!string.IsNullOrEmpty(UnlinkedIgnoredRootDir) && !Directory.Exists(UnlinkedIgnoredRootDir)) { throw new ValidationException($"{UnlinkedIgnoredRootDir} root directory does not exist"); } } }