OF-DL/OF DL.Gui/Services/ConfigValidationService.cs

86 lines
3.6 KiB
C#

using OF_DL.Models.Config;
namespace OF_DL.Gui.Services;
internal static class ConfigValidationService
{
public static IReadOnlyDictionary<string, string> Validate(Config config)
{
Dictionary<string, string> errors = new(StringComparer.Ordinal);
ValidatePath(config.DownloadPath, nameof(Config.DownloadPath), errors, requireExistingFile: false);
ValidatePath(config.FFmpegPath, nameof(Config.FFmpegPath), errors, requireExistingFile: true);
ValidatePath(config.FFprobePath, nameof(Config.FFprobePath), errors, requireExistingFile: true);
if (config.Timeout.HasValue && config.Timeout.Value <= 0 && config.Timeout.Value != -1)
{
errors[nameof(Config.Timeout)] = "Timeout must be -1 or greater than 0.";
}
if (config.LimitDownloadRate && config.DownloadLimitInMbPerSec <= 0)
{
errors[nameof(Config.DownloadLimitInMbPerSec)] =
"DownloadLimitInMbPerSec must be greater than 0 when LimitDownloadRate is enabled.";
}
if (config.DownloadOnlySpecificDates && !config.CustomDate.HasValue)
{
errors[nameof(Config.CustomDate)] = "CustomDate is required when DownloadOnlySpecificDates is enabled.";
}
ValidateFileNameFormat(config.PaidPostFileNameFormat, nameof(Config.PaidPostFileNameFormat), errors);
ValidateFileNameFormat(config.PostFileNameFormat, nameof(Config.PostFileNameFormat), errors);
ValidateFileNameFormat(config.PaidMessageFileNameFormat, nameof(Config.PaidMessageFileNameFormat), errors);
ValidateFileNameFormat(config.MessageFileNameFormat, nameof(Config.MessageFileNameFormat), errors);
foreach (KeyValuePair<string, CreatorConfig> creatorConfig in config.CreatorConfigs)
{
ValidateFileNameFormat(creatorConfig.Value.PaidPostFileNameFormat,
$"{nameof(Config.CreatorConfigs)}.{creatorConfig.Key}.PaidPostFileNameFormat", errors);
ValidateFileNameFormat(creatorConfig.Value.PostFileNameFormat,
$"{nameof(Config.CreatorConfigs)}.{creatorConfig.Key}.PostFileNameFormat", errors);
ValidateFileNameFormat(creatorConfig.Value.PaidMessageFileNameFormat,
$"{nameof(Config.CreatorConfigs)}.{creatorConfig.Key}.PaidMessageFileNameFormat", errors);
ValidateFileNameFormat(creatorConfig.Value.MessageFileNameFormat,
$"{nameof(Config.CreatorConfigs)}.{creatorConfig.Key}.MessageFileNameFormat", errors);
}
return errors;
}
private static void ValidatePath(string? path, string fieldName, IDictionary<string, string> errors,
bool requireExistingFile)
{
if (string.IsNullOrWhiteSpace(path))
{
return;
}
if (path.Any(character => Path.GetInvalidPathChars().Contains(character)))
{
errors[fieldName] = "Path contains invalid characters.";
return;
}
if (requireExistingFile && !File.Exists(path))
{
errors[fieldName] = "Path must point to an existing file.";
}
}
private static void ValidateFileNameFormat(string? format, string fieldName, IDictionary<string, string> errors)
{
if (string.IsNullOrWhiteSpace(format))
{
return;
}
bool hasUniqueToken = format.Contains("{mediaId}", StringComparison.OrdinalIgnoreCase) ||
format.Contains("{filename}", StringComparison.OrdinalIgnoreCase);
if (!hasUniqueToken)
{
errors[fieldName] = "Format must include {mediaId} or {filename} to avoid file collisions.";
}
}
}