386 lines
21 KiB
C#
386 lines
21 KiB
C#
using Akka.Configuration;
|
|
using Newtonsoft.Json;
|
|
using OF_DL.Entities;
|
|
using Serilog;
|
|
using System.Text;
|
|
using OF_DL.Enumerations;
|
|
using Config = OF_DL.Entities.Config;
|
|
|
|
namespace OF_DL.Services
|
|
{
|
|
public class ConfigService(ILoggingService loggingService) : IConfigService
|
|
{
|
|
public Config? CurrentConfig { get; private set; }
|
|
public bool IsCliNonInteractive { get; private set; }
|
|
|
|
public async Task<bool> LoadConfigurationAsync(string[] args)
|
|
{
|
|
try
|
|
{
|
|
IsCliNonInteractive = false;
|
|
|
|
// Migrate from config.json to config.conf if needed
|
|
await MigrateFromJsonToConfAsync();
|
|
|
|
// Load config.conf or create default
|
|
if (File.Exists("config.conf"))
|
|
{
|
|
Log.Debug("config.conf located successfully");
|
|
if (!await LoadConfigFromFileAsync("config.conf"))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log.Debug("config.conf not found, creating default");
|
|
await CreateDefaultConfigFileAsync();
|
|
if (!await LoadConfigFromFileAsync("config.conf"))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Check for command-line arguments
|
|
if (args != null && args.Length > 0)
|
|
{
|
|
const string NON_INTERACTIVE_ARG = "--non-interactive";
|
|
if (args.Any(a => a.Equals(NON_INTERACTIVE_ARG, StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
IsCliNonInteractive = true;
|
|
Log.Debug("NonInteractiveMode set via command line");
|
|
}
|
|
|
|
Log.Debug("Additional arguments:");
|
|
foreach (string argument in args)
|
|
{
|
|
Log.Debug(argument);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Configuration loading failed");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task SaveConfigurationAsync(string filePath = "config.conf")
|
|
{
|
|
if (CurrentConfig == null)
|
|
{
|
|
Log.Warning("Attempted to save null config to file");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
var hoconConfig = BuildHoconFromConfig(CurrentConfig);
|
|
await File.WriteAllTextAsync(filePath, hoconConfig);
|
|
Log.Debug($"Config saved to file: {filePath}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to save config to file");
|
|
}
|
|
}
|
|
|
|
public void UpdateConfig(Config newConfig)
|
|
{
|
|
CurrentConfig = newConfig;
|
|
|
|
// Update logging level
|
|
loggingService.UpdateLoggingLevel(newConfig.LoggingLevel);
|
|
|
|
// Apply text sanitization preference globally
|
|
OF_DL.Utils.XmlUtils.Passthrough = newConfig.DisableTextSanitization;
|
|
|
|
Log.Debug("Configuration updated");
|
|
string configString = JsonConvert.SerializeObject(newConfig, Formatting.Indented);
|
|
Log.Debug(configString);
|
|
}
|
|
|
|
private async Task MigrateFromJsonToConfAsync()
|
|
{
|
|
if (!File.Exists("config.json"))
|
|
return;
|
|
|
|
try
|
|
{
|
|
Log.Debug("config.json found, migrating to config.conf");
|
|
string jsonText = await File.ReadAllTextAsync("config.json");
|
|
var jsonConfig = JsonConvert.DeserializeObject<Config>(jsonText);
|
|
|
|
if (jsonConfig != null)
|
|
{
|
|
var hoconConfig = BuildHoconFromConfig(jsonConfig);
|
|
await File.WriteAllTextAsync("config.conf", hoconConfig);
|
|
File.Delete("config.json");
|
|
Log.Information("config.conf created successfully from config.json");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to migrate config.json to config.conf");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private async Task<bool> LoadConfigFromFileAsync(string filePath)
|
|
{
|
|
try
|
|
{
|
|
string hoconText = await File.ReadAllTextAsync(filePath);
|
|
var hoconConfig = ConfigurationFactory.ParseString(hoconText);
|
|
|
|
CurrentConfig = new Config
|
|
{
|
|
// Auth
|
|
DisableBrowserAuth = hoconConfig.GetBoolean("Auth.DisableBrowserAuth"),
|
|
|
|
// FFmpeg Settings
|
|
FFmpegPath = hoconConfig.GetString("External.FFmpegPath"),
|
|
|
|
// Download Settings
|
|
DownloadAvatarHeaderPhoto = hoconConfig.GetBoolean("Download.Media.DownloadAvatarHeaderPhoto"),
|
|
DownloadPaidPosts = hoconConfig.GetBoolean("Download.Media.DownloadPaidPosts"),
|
|
DownloadPosts = hoconConfig.GetBoolean("Download.Media.DownloadPosts"),
|
|
DownloadArchived = hoconConfig.GetBoolean("Download.Media.DownloadArchived"),
|
|
DownloadStreams = hoconConfig.GetBoolean("Download.Media.DownloadStreams"),
|
|
DownloadStories = hoconConfig.GetBoolean("Download.Media.DownloadStories"),
|
|
DownloadHighlights = hoconConfig.GetBoolean("Download.Media.DownloadHighlights"),
|
|
DownloadMessages = hoconConfig.GetBoolean("Download.Media.DownloadMessages"),
|
|
DownloadPaidMessages = hoconConfig.GetBoolean("Download.Media.DownloadPaidMessages"),
|
|
DownloadImages = hoconConfig.GetBoolean("Download.Media.DownloadImages"),
|
|
DownloadVideos = hoconConfig.GetBoolean("Download.Media.DownloadVideos"),
|
|
DownloadAudios = hoconConfig.GetBoolean("Download.Media.DownloadAudios"),
|
|
IgnoreOwnMessages = hoconConfig.GetBoolean("Download.IgnoreOwnMessages"),
|
|
DownloadPostsIncrementally = hoconConfig.GetBoolean("Download.DownloadPostsIncrementally"),
|
|
BypassContentForCreatorsWhoNoLongerExist = hoconConfig.GetBoolean("Download.BypassContentForCreatorsWhoNoLongerExist"),
|
|
DownloadDuplicatedMedia = hoconConfig.GetBoolean("Download.DownloadDuplicatedMedia"),
|
|
SkipAds = hoconConfig.GetBoolean("Download.SkipAds"),
|
|
DownloadPath = hoconConfig.GetString("Download.DownloadPath"),
|
|
DownloadOnlySpecificDates = hoconConfig.GetBoolean("Download.DownloadOnlySpecificDates"),
|
|
DownloadDateSelection = Enum.Parse<DownloadDateSelection>(hoconConfig.GetString("Download.DownloadDateSelection"), true),
|
|
CustomDate = !string.IsNullOrWhiteSpace(hoconConfig.GetString("Download.CustomDate")) ? DateTime.Parse(hoconConfig.GetString("Download.CustomDate")) : null,
|
|
ShowScrapeSize = hoconConfig.GetBoolean("Download.ShowScrapeSize"),
|
|
DisableTextSanitization = bool.TryParse(hoconConfig.GetString("Download.DisableTextSanitization", "false"), out var dts) ? dts : false,
|
|
DownloadVideoResolution = ParseVideoResolution(hoconConfig.GetString("Download.DownloadVideoResolution", "source")),
|
|
|
|
// File Settings
|
|
PaidPostFileNameFormat = hoconConfig.GetString("File.PaidPostFileNameFormat"),
|
|
PostFileNameFormat = hoconConfig.GetString("File.PostFileNameFormat"),
|
|
PaidMessageFileNameFormat = hoconConfig.GetString("File.PaidMessageFileNameFormat"),
|
|
MessageFileNameFormat = hoconConfig.GetString("File.MessageFileNameFormat"),
|
|
RenameExistingFilesWhenCustomFormatIsSelected = hoconConfig.GetBoolean("File.RenameExistingFilesWhenCustomFormatIsSelected"),
|
|
|
|
// Folder Settings
|
|
FolderPerPaidPost = hoconConfig.GetBoolean("Folder.FolderPerPaidPost"),
|
|
FolderPerPost = hoconConfig.GetBoolean("Folder.FolderPerPost"),
|
|
FolderPerPaidMessage = hoconConfig.GetBoolean("Folder.FolderPerPaidMessage"),
|
|
FolderPerMessage = hoconConfig.GetBoolean("Folder.FolderPerMessage"),
|
|
|
|
// Subscription Settings
|
|
IncludeExpiredSubscriptions = hoconConfig.GetBoolean("Subscriptions.IncludeExpiredSubscriptions"),
|
|
IncludeRestrictedSubscriptions = hoconConfig.GetBoolean("Subscriptions.IncludeRestrictedSubscriptions"),
|
|
IgnoredUsersListName = hoconConfig.GetString("Subscriptions.IgnoredUsersListName"),
|
|
|
|
// Interaction Settings
|
|
NonInteractiveMode = hoconConfig.GetBoolean("Interaction.NonInteractiveMode"),
|
|
NonInteractiveModeListName = hoconConfig.GetString("Interaction.NonInteractiveModeListName"),
|
|
NonInteractiveModePurchasedTab = hoconConfig.GetBoolean("Interaction.NonInteractiveModePurchasedTab"),
|
|
|
|
// Performance Settings
|
|
Timeout = string.IsNullOrWhiteSpace(hoconConfig.GetString("Performance.Timeout")) ? -1 : hoconConfig.GetInt("Performance.Timeout"),
|
|
LimitDownloadRate = hoconConfig.GetBoolean("Performance.LimitDownloadRate"),
|
|
DownloadLimitInMbPerSec = hoconConfig.GetInt("Performance.DownloadLimitInMbPerSec"),
|
|
|
|
// Logging/Debug Settings
|
|
LoggingLevel = Enum.Parse<LoggingLevel>(hoconConfig.GetString("Logging.LoggingLevel"), true)
|
|
};
|
|
|
|
// Validate file name formats
|
|
ValidateFileNameFormat(CurrentConfig.PaidPostFileNameFormat, "PaidPostFileNameFormat");
|
|
ValidateFileNameFormat(CurrentConfig.PostFileNameFormat, "PostFileNameFormat");
|
|
ValidateFileNameFormat(CurrentConfig.PaidMessageFileNameFormat, "PaidMessageFileNameFormat");
|
|
ValidateFileNameFormat(CurrentConfig.MessageFileNameFormat, "MessageFileNameFormat");
|
|
|
|
// Load creator-specific configs
|
|
var creatorConfigsSection = hoconConfig.GetConfig("CreatorConfigs");
|
|
if (creatorConfigsSection != null)
|
|
{
|
|
foreach (var key in creatorConfigsSection.AsEnumerable())
|
|
{
|
|
var creatorKey = key.Key;
|
|
var creatorHocon = creatorConfigsSection.GetConfig(creatorKey);
|
|
if (!CurrentConfig.CreatorConfigs.ContainsKey(creatorKey) && creatorHocon != null)
|
|
{
|
|
CurrentConfig.CreatorConfigs.Add(key.Key, new CreatorConfig
|
|
{
|
|
PaidPostFileNameFormat = creatorHocon.GetString("PaidPostFileNameFormat"),
|
|
PostFileNameFormat = creatorHocon.GetString("PostFileNameFormat"),
|
|
PaidMessageFileNameFormat = creatorHocon.GetString("PaidMessageFileNameFormat"),
|
|
MessageFileNameFormat = creatorHocon.GetString("MessageFileNameFormat")
|
|
});
|
|
|
|
ValidateFileNameFormat(CurrentConfig.CreatorConfigs[key.Key].PaidPostFileNameFormat, $"{key.Key}.PaidPostFileNameFormat");
|
|
ValidateFileNameFormat(CurrentConfig.CreatorConfigs[key.Key].PostFileNameFormat, $"{key.Key}.PostFileNameFormat");
|
|
ValidateFileNameFormat(CurrentConfig.CreatorConfigs[key.Key].PaidMessageFileNameFormat, $"{key.Key}.PaidMessageFileNameFormat");
|
|
ValidateFileNameFormat(CurrentConfig.CreatorConfigs[key.Key].MessageFileNameFormat, $"{key.Key}.MessageFileNameFormat");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update logging level
|
|
loggingService.UpdateLoggingLevel(CurrentConfig.LoggingLevel);
|
|
|
|
// Apply text sanitization preference globally
|
|
OF_DL.Utils.XmlUtils.Passthrough = CurrentConfig.DisableTextSanitization;
|
|
|
|
Log.Debug("Configuration loaded successfully");
|
|
string configString = JsonConvert.SerializeObject(CurrentConfig, Formatting.Indented);
|
|
Log.Debug(configString);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to parse config file");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private async Task CreateDefaultConfigFileAsync()
|
|
{
|
|
Config defaultConfig = new Config();
|
|
var hoconConfig = BuildHoconFromConfig(defaultConfig);
|
|
await File.WriteAllTextAsync("config.conf", hoconConfig);
|
|
Log.Information("Created default config.conf file");
|
|
}
|
|
|
|
private string BuildHoconFromConfig(Config config)
|
|
{
|
|
var hocon = new StringBuilder();
|
|
|
|
hocon.AppendLine("# Auth");
|
|
hocon.AppendLine("Auth {");
|
|
hocon.AppendLine($" DisableBrowserAuth = {config.DisableBrowserAuth.ToString().ToLower()}");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# External Tools");
|
|
hocon.AppendLine("External {");
|
|
hocon.AppendLine($" FFmpegPath = \"{config.FFmpegPath}\"");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Download Settings");
|
|
hocon.AppendLine("Download {");
|
|
hocon.AppendLine(" Media {");
|
|
hocon.AppendLine($" DownloadAvatarHeaderPhoto = {config.DownloadAvatarHeaderPhoto.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadPaidPosts = {config.DownloadPaidPosts.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadPosts = {config.DownloadPosts.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadArchived = {config.DownloadArchived.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadStreams = {config.DownloadStreams.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadStories = {config.DownloadStories.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadHighlights = {config.DownloadHighlights.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadMessages = {config.DownloadMessages.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadPaidMessages = {config.DownloadPaidMessages.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadImages = {config.DownloadImages.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadVideos = {config.DownloadVideos.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadAudios = {config.DownloadAudios.ToString().ToLower()}");
|
|
hocon.AppendLine(" }");
|
|
hocon.AppendLine($" IgnoreOwnMessages = {config.IgnoreOwnMessages.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadPostsIncrementally = {config.DownloadPostsIncrementally.ToString().ToLower()}");
|
|
hocon.AppendLine($" BypassContentForCreatorsWhoNoLongerExist = {config.BypassContentForCreatorsWhoNoLongerExist.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadDuplicatedMedia = {config.DownloadDuplicatedMedia.ToString().ToLower()}");
|
|
hocon.AppendLine($" SkipAds = {config.SkipAds.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadPath = \"{config.DownloadPath}\"");
|
|
hocon.AppendLine($" DownloadOnlySpecificDates = {config.DownloadOnlySpecificDates.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadDateSelection = \"{config.DownloadDateSelection.ToString().ToLower()}\"");
|
|
hocon.AppendLine($" CustomDate = \"{config.CustomDate?.ToString("yyyy-MM-dd")}\"");
|
|
hocon.AppendLine($" ShowScrapeSize = {config.ShowScrapeSize.ToString().ToLower()}");
|
|
hocon.AppendLine($" DisableTextSanitization = {config.DisableTextSanitization.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadVideoResolution = \"{(config.DownloadVideoResolution == VideoResolution.source ? "source" : config.DownloadVideoResolution.ToString().TrimStart('_'))}\"");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# File Settings");
|
|
hocon.AppendLine("File {");
|
|
hocon.AppendLine($" PaidPostFileNameFormat = \"{config.PaidPostFileNameFormat}\"");
|
|
hocon.AppendLine($" PostFileNameFormat = \"{config.PostFileNameFormat}\"");
|
|
hocon.AppendLine($" PaidMessageFileNameFormat = \"{config.PaidMessageFileNameFormat}\"");
|
|
hocon.AppendLine($" MessageFileNameFormat = \"{config.MessageFileNameFormat}\"");
|
|
hocon.AppendLine($" RenameExistingFilesWhenCustomFormatIsSelected = {config.RenameExistingFilesWhenCustomFormatIsSelected.ToString().ToLower()}");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Creator-Specific Configurations");
|
|
hocon.AppendLine("CreatorConfigs {");
|
|
foreach (var creatorConfig in config.CreatorConfigs)
|
|
{
|
|
hocon.AppendLine($" \"{creatorConfig.Key}\" {{");
|
|
hocon.AppendLine($" PaidPostFileNameFormat = \"{creatorConfig.Value.PaidPostFileNameFormat}\"");
|
|
hocon.AppendLine($" PostFileNameFormat = \"{creatorConfig.Value.PostFileNameFormat}\"");
|
|
hocon.AppendLine($" PaidMessageFileNameFormat = \"{creatorConfig.Value.PaidMessageFileNameFormat}\"");
|
|
hocon.AppendLine($" MessageFileNameFormat = \"{creatorConfig.Value.MessageFileNameFormat}\"");
|
|
hocon.AppendLine(" }");
|
|
}
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Folder Settings");
|
|
hocon.AppendLine("Folder {");
|
|
hocon.AppendLine($" FolderPerPaidPost = {config.FolderPerPaidPost.ToString().ToLower()}");
|
|
hocon.AppendLine($" FolderPerPost = {config.FolderPerPost.ToString().ToLower()}");
|
|
hocon.AppendLine($" FolderPerPaidMessage = {config.FolderPerPaidMessage.ToString().ToLower()}");
|
|
hocon.AppendLine($" FolderPerMessage = {config.FolderPerMessage.ToString().ToLower()}");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Subscription Settings");
|
|
hocon.AppendLine("Subscriptions {");
|
|
hocon.AppendLine($" IncludeExpiredSubscriptions = {config.IncludeExpiredSubscriptions.ToString().ToLower()}");
|
|
hocon.AppendLine($" IncludeRestrictedSubscriptions = {config.IncludeRestrictedSubscriptions.ToString().ToLower()}");
|
|
hocon.AppendLine($" IgnoredUsersListName = \"{config.IgnoredUsersListName}\"");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Interaction Settings");
|
|
hocon.AppendLine("Interaction {");
|
|
hocon.AppendLine($" NonInteractiveMode = {config.NonInteractiveMode.ToString().ToLower()}");
|
|
hocon.AppendLine($" NonInteractiveModeListName = \"{config.NonInteractiveModeListName}\"");
|
|
hocon.AppendLine($" NonInteractiveModePurchasedTab = {config.NonInteractiveModePurchasedTab.ToString().ToLower()}");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Performance Settings");
|
|
hocon.AppendLine("Performance {");
|
|
hocon.AppendLine($" Timeout = {(config.Timeout.HasValue ? config.Timeout.Value : -1)}");
|
|
hocon.AppendLine($" LimitDownloadRate = {config.LimitDownloadRate.ToString().ToLower()}");
|
|
hocon.AppendLine($" DownloadLimitInMbPerSec = {config.DownloadLimitInMbPerSec}");
|
|
hocon.AppendLine("}");
|
|
|
|
hocon.AppendLine("# Logging/Debug Settings");
|
|
hocon.AppendLine("Logging {");
|
|
hocon.AppendLine($" LoggingLevel = \"{config.LoggingLevel.ToString().ToLower()}\"");
|
|
hocon.AppendLine("}");
|
|
|
|
return hocon.ToString();
|
|
}
|
|
|
|
private void ValidateFileNameFormat(string? format, string settingName)
|
|
{
|
|
if (!string.IsNullOrEmpty(format) &&
|
|
!format.Contains("{mediaId}", StringComparison.OrdinalIgnoreCase) &&
|
|
!format.Contains("{filename}", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"{settingName} is not unique enough. Please include either '{{mediaId}}' or '{{filename}}' to ensure files are not overwritten.");
|
|
}
|
|
}
|
|
|
|
private VideoResolution ParseVideoResolution(string value)
|
|
{
|
|
if (value.Equals("source", StringComparison.OrdinalIgnoreCase))
|
|
return VideoResolution.source;
|
|
|
|
return Enum.Parse<VideoResolution>("_" + value, ignoreCase: true);
|
|
}
|
|
}
|
|
}
|