diff --git a/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs b/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs index 354d9e0e..95acf168 100644 --- a/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs +++ b/DiscordChatExporter.Cli/Commands/Base/ExportCommandBase.cs @@ -115,11 +115,18 @@ public abstract class ExportCommandBase : DiscordCommandBase } [CommandOption( - "prev-export", - Description = "What the exporter should do if the channel had already been exported." + "export-exists", + Description = "What the exporter should do if a channel had already been exported." )] public ExportExistsHandling ExportExistsHandling { get; init; } = ExportExistsHandling.Abort; + [CommandOption( + "search-existing-exports", + Description = "Whether the target directory should be searched for existing export(s) of the channel(s). " + + "This is required to find an existing export if the channel, channel parent or guild name has changed." + )] + public bool SearchForExistingExports { get; init; } + [Obsolete("This option doesn't do anything. Kept for backwards compatibility.")] [CommandOption( "dateformat", @@ -272,6 +279,7 @@ public abstract class ExportCommandBase : DiscordCommandBase After, Before, ExportExistsHandling, + SearchForExistingExports, PartitionLimit, MessageFilter, ShouldFormatMarkdown, diff --git a/DiscordChatExporter.Cli/Utils/Extensions/ConsoleExtensions.cs b/DiscordChatExporter.Cli/Utils/Extensions/ConsoleExtensions.cs index dd132e8a..f311dc87 100644 --- a/DiscordChatExporter.Cli/Utils/Extensions/ConsoleExtensions.cs +++ b/DiscordChatExporter.Cli/Utils/Extensions/ConsoleExtensions.cs @@ -78,21 +78,21 @@ public class ConsoleProgressLogger(IAnsiConsole console) : ProgressLogger /// The ConsoleProgressLogger logs the success message to the console. public override void LogSuccess(ExportRequest request, string message) { - LogMessage("SUCCESS", "[green]", request, message); + LogMessage("SUCCESS", "green", request, message); } /// /// The ConsoleProgressLogger logs the informational message to the console. public override void LogInfo(ExportRequest request, string message) { - LogMessage("INFO", "[default]", request, message); + LogMessage("INFO", "default", request, message); } /// /// The ConsoleProgressLogger logs the warning message to the console. public override void LogWarning(ExportRequest request, string message) { - LogMessage("WARNING", "[yellow]", request, message); + LogMessage("WARNING", "yellow", request, message); } /// @@ -100,7 +100,7 @@ public class ConsoleProgressLogger(IAnsiConsole console) : ProgressLogger public override void LogError(ExportRequest? request, string message) { IncrementCounter(ExportResult.ExportError); - LogMessage("ERROR", "[red]", request, message); + LogMessage("ERROR", "red", request, message); } /// @@ -120,8 +120,8 @@ public class ConsoleProgressLogger(IAnsiConsole console) : ProgressLogger channelInfo = request.Guild.Name + " / " + request.Channel.GetHierarchicalName() + " | "; - var logMessage = $"{color}{paddedCategory}{channelInfo}{message}[/]"; - console.MarkupLine(logMessage); + FormattableString logMessage = $"[{color}]{paddedCategory}{channelInfo}{message}[/]"; + console.MarkupLineInterpolated(logMessage); } /// diff --git a/DiscordChatExporter.Core/Exporting/ChannelExporter.cs b/DiscordChatExporter.Core/Exporting/ChannelExporter.cs index 2348b5c7..ae3a30db 100644 --- a/DiscordChatExporter.Core/Exporting/ChannelExporter.cs +++ b/DiscordChatExporter.Core/Exporting/ChannelExporter.cs @@ -35,13 +35,11 @@ public class ChannelExporter(DiscordClient discord) return; } - // TODO: Add a way for the user to choose the setting - var searchForExistingExport = true; if ( !DetectExistingExport( request, logger, - searchForExistingExport, + request.SearchForExistingExports, outputDirFilesDict, out var existingExportFile ) @@ -215,7 +213,7 @@ public class ChannelExporter(DiscordClient discord) logger.LogError( request, "Found multiple existing channel exports under different file names: " - + string.Join(", ", regexFiles) + + string.Join(", ", regexFiles.Select(fileName => $"\"{fileName}\"")) + "." ); return false; @@ -223,7 +221,7 @@ public class ChannelExporter(DiscordClient discord) logger.LogInfo( request, - "Found existing channel export under file name " + regexFiles[0] + "." + $"Found existing channel export under file name \"{regexFiles[0]}\"." ); existingExportFile = Path.Combine(request.OutputDirPath, regexFiles[0]); return true; diff --git a/DiscordChatExporter.Core/Exporting/ExportRequest.cs b/DiscordChatExporter.Core/Exporting/ExportRequest.cs index 5abe25fb..248e6754 100644 --- a/DiscordChatExporter.Core/Exporting/ExportRequest.cs +++ b/DiscordChatExporter.Core/Exporting/ExportRequest.cs @@ -32,6 +32,8 @@ public partial class ExportRequest public ExportExistsHandling ExportExistsHandling { get; } + public bool SearchForExistingExports { get; } + public Snowflake? LastPriorMessage { get; set; } public PartitionLimit PartitionLimit { get; } @@ -59,6 +61,7 @@ public partial class ExportRequest Snowflake? after, Snowflake? before, ExportExistsHandling exportExistsHandling, + bool searchForExistingExports, PartitionLimit partitionLimit, MessageFilter messageFilter, bool shouldFormatMarkdown, @@ -74,6 +77,7 @@ public partial class ExportRequest After = after; Before = before; ExportExistsHandling = exportExistsHandling; + SearchForExistingExports = searchForExistingExports; PartitionLimit = partitionLimit; MessageFilter = messageFilter; ShouldFormatMarkdown = shouldFormatMarkdown; diff --git a/DiscordChatExporter.Gui/Services/SettingsService.cs b/DiscordChatExporter.Gui/Services/SettingsService.cs index a56da7e1..bb2ed219 100644 --- a/DiscordChatExporter.Gui/Services/SettingsService.cs +++ b/DiscordChatExporter.Gui/Services/SettingsService.cs @@ -39,6 +39,9 @@ public partial class SettingsService() [ObservableProperty] public partial ExportExistsHandling ExportExistsHandling { get; set; } + [ObservableProperty] + public partial bool SearchForExistingExports { get; set; } + [ObservableProperty] public partial string? Locale { get; set; } diff --git a/DiscordChatExporter.Gui/ViewModels/Components/DashboardViewModel.cs b/DiscordChatExporter.Gui/ViewModels/Components/DashboardViewModel.cs index 2f9761b0..be843c6b 100644 --- a/DiscordChatExporter.Gui/ViewModels/Components/DashboardViewModel.cs +++ b/DiscordChatExporter.Gui/ViewModels/Components/DashboardViewModel.cs @@ -272,6 +272,7 @@ public partial class DashboardViewModel : ViewModelBase dialog.After?.Pipe(timestamp => Snowflake.FromDate(timestamp, true)), dialog.Before?.Pipe(timestamp => Snowflake.FromDate(timestamp)), _settingsService.ExportExistsHandling, + _settingsService.SearchForExistingExports, dialog.PartitionLimit, dialog.MessageFilter, dialog.ShouldFormatMarkdown, diff --git a/DiscordChatExporter.Gui/ViewModels/Dialogs/SettingsViewModel.cs b/DiscordChatExporter.Gui/ViewModels/Dialogs/SettingsViewModel.cs index 8d96f0d1..8283703e 100644 --- a/DiscordChatExporter.Gui/ViewModels/Dialogs/SettingsViewModel.cs +++ b/DiscordChatExporter.Gui/ViewModels/Dialogs/SettingsViewModel.cs @@ -71,6 +71,12 @@ public class SettingsViewModel : DialogViewModelBase set => _settingsService.ExportExistsHandling = value; } + public bool SearchForExistingExports + { + get => _settingsService.SearchForExistingExports; + set => _settingsService.SearchForExistingExports = value; + } + // These items have to be non-nullable because Avalonia ComboBox doesn't allow a null value to be selected public IReadOnlyList AvailableLocales { get; } = [ diff --git a/DiscordChatExporter.Gui/Views/Dialogs/SettingsView.axaml b/DiscordChatExporter.Gui/Views/Dialogs/SettingsView.axaml index b1cc5abf..29f99a82 100644 --- a/DiscordChatExporter.Gui/Views/Dialogs/SettingsView.axaml +++ b/DiscordChatExporter.Gui/Views/Dialogs/SettingsView.axaml @@ -136,14 +136,23 @@ - + ToolTip.Tip="What the exporter should do if a channel had already been exported"> + + + + + + +