Added UI options to set the file exists handling

The setting the exporter uses to handle existing export files has been made configurable in both the CLI and the GUI (instead of being hardcoded):
- A prev-export option has been added to all CLI export commands, which sets the file exists handling for the respective command.
- A Previous Export option has been added to the GUI settings, which sets the file exists handling that's used for exports.
This commit is contained in:
Kornelius Rohrschneider 2025-10-26 01:28:24 +02:00
parent 5251ae0e95
commit ad33600e70
No known key found for this signature in database
GPG key ID: 51CF1ED1E24F7D78
7 changed files with 41 additions and 5 deletions

View file

@ -114,6 +114,12 @@ public abstract class ExportCommandBase : DiscordCommandBase
init => field = value is not null ? Path.GetFullPath(value) : null; init => field = value is not null ? Path.GetFullPath(value) : null;
} }
[CommandOption(
"prev-export",
Description = "What the exporter should do if the channel had already been exported."
)]
public FileExistsHandling FileExistsHandling { get; init; } = FileExistsHandling.Abort;
[Obsolete("This option doesn't do anything. Kept for backwards compatibility.")] [Obsolete("This option doesn't do anything. Kept for backwards compatibility.")]
[CommandOption( [CommandOption(
"dateformat", "dateformat",
@ -265,6 +271,7 @@ public abstract class ExportCommandBase : DiscordCommandBase
ExportFormat, ExportFormat,
After, After,
Before, Before,
FileExistsHandling,
PartitionLimit, PartitionLimit,
MessageFilter, MessageFilter,
ShouldFormatMarkdown, ShouldFormatMarkdown,

View file

@ -32,10 +32,8 @@ public class ChannelExporter(DiscordClient discord)
// TODO: Maybe add a way to search for old files after a username change // TODO: Maybe add a way to search for old files after a username change
if (File.Exists(request.OutputFilePath)) if (File.Exists(request.OutputFilePath))
{ {
// TODO: Add a way for the user to choose the setting // TODO: Maybe add an "Ask" option in the future
var choice = FileExistsHandling.Abort; switch (request.FileExistsHandling)
switch (choice)
{ {
case FileExistsHandling.Abort: case FileExistsHandling.Abort:
Console.WriteLine("Channel aborted"); Console.WriteLine("Channel aborted");
@ -69,7 +67,7 @@ public class ChannelExporter(DiscordClient discord)
break; break;
default: default:
throw new InvalidOperationException( throw new InvalidOperationException(
$"Unknown FileExistsHandling value '{choice}'." $"Unknown FileExistsHandling value '{request.FileExistsHandling}'."
); );
} }
} }

View file

@ -30,6 +30,8 @@ public partial class ExportRequest
public Snowflake? Before { get; } public Snowflake? Before { get; }
public FileExistsHandling FileExistsHandling { get; }
public Snowflake? LastPriorMessage { get; set; } public Snowflake? LastPriorMessage { get; set; }
public PartitionLimit PartitionLimit { get; } public PartitionLimit PartitionLimit { get; }
@ -56,6 +58,7 @@ public partial class ExportRequest
ExportFormat format, ExportFormat format,
Snowflake? after, Snowflake? after,
Snowflake? before, Snowflake? before,
FileExistsHandling fileExistsHandling,
PartitionLimit partitionLimit, PartitionLimit partitionLimit,
MessageFilter messageFilter, MessageFilter messageFilter,
bool shouldFormatMarkdown, bool shouldFormatMarkdown,
@ -70,6 +73,7 @@ public partial class ExportRequest
Format = format; Format = format;
After = after; After = after;
Before = before; Before = before;
FileExistsHandling = fileExistsHandling;
PartitionLimit = partitionLimit; PartitionLimit = partitionLimit;
MessageFilter = messageFilter; MessageFilter = messageFilter;
ShouldFormatMarkdown = shouldFormatMarkdown; ShouldFormatMarkdown = shouldFormatMarkdown;

View file

@ -36,6 +36,9 @@ public partial class SettingsService()
[ObservableProperty] [ObservableProperty]
public partial ThreadInclusionMode ThreadInclusionMode { get; set; } public partial ThreadInclusionMode ThreadInclusionMode { get; set; }
[ObservableProperty]
public partial FileExistsHandling FileExistsHandling { get; set; }
[ObservableProperty] [ObservableProperty]
public partial string? Locale { get; set; } public partial string? Locale { get; set; }

View file

@ -270,6 +270,7 @@ public partial class DashboardViewModel : ViewModelBase
dialog.SelectedFormat, dialog.SelectedFormat,
dialog.After?.Pipe(timestamp => Snowflake.FromDate(timestamp, true)), dialog.After?.Pipe(timestamp => Snowflake.FromDate(timestamp, true)),
dialog.Before?.Pipe(timestamp => Snowflake.FromDate(timestamp)), dialog.Before?.Pipe(timestamp => Snowflake.FromDate(timestamp)),
_settingsService.FileExistsHandling,
dialog.PartitionLimit, dialog.PartitionLimit,
dialog.MessageFilter, dialog.MessageFilter,
dialog.ShouldFormatMarkdown, dialog.ShouldFormatMarkdown,

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using DiscordChatExporter.Core.Exporting;
using DiscordChatExporter.Core.Utils.Extensions; using DiscordChatExporter.Core.Utils.Extensions;
using DiscordChatExporter.Gui.Framework; using DiscordChatExporter.Gui.Framework;
using DiscordChatExporter.Gui.Models; using DiscordChatExporter.Gui.Models;
@ -61,6 +62,15 @@ public class SettingsViewModel : DialogViewModelBase
set => _settingsService.ThreadInclusionMode = value; set => _settingsService.ThreadInclusionMode = value;
} }
public IReadOnlyList<FileExistsHandling> AvailableFileExistHandlingOptions { get; } =
Enum.GetValues<FileExistsHandling>();
public FileExistsHandling FileExistsHandling
{
get => _settingsService.FileExistsHandling;
set => _settingsService.FileExistsHandling = value;
}
// These items have to be non-nullable because Avalonia ComboBox doesn't allow a null value to be selected // These items have to be non-nullable because Avalonia ComboBox doesn't allow a null value to be selected
public IReadOnlyList<string> AvailableLocales { get; } = public IReadOnlyList<string> AvailableLocales { get; } =
[ [

View file

@ -131,6 +131,19 @@
Value="{Binding ParallelLimit}" /> Value="{Binding ParallelLimit}" />
</StackPanel> </StackPanel>
</DockPanel> </DockPanel>
<!-- File Exists Handling -->
<DockPanel
Margin="16,8"
LastChildFill="False"
ToolTip.Tip="What the exporter should do if the channel had already been exported">
<TextBlock DockPanel.Dock="Left" Text="Previous Export" />
<ComboBox
Width="150"
DockPanel.Dock="Right"
ItemsSource="{Binding AvailableFileExistHandlingOptions}"
SelectedItem="{Binding FileExistsHandling}" />
</DockPanel>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</Border> </Border>