Short-circuit if trying to export an empty channel or a channel with mismatching boundaries

Closes #1024
pull/1037/head
Tyrrrz 2 years ago
parent faad994332
commit 9048557b17

@ -169,10 +169,10 @@ public abstract class ExportCommandBase : DiscordCommandBase
); );
} }
// Export
var cancellationToken = console.RegisterCancellationHandler(); var cancellationToken = console.RegisterCancellationHandler();
var errors = new ConcurrentDictionary<Channel, string>(); var errors = new ConcurrentDictionary<Channel, string>();
// Export
await console.Output.WriteLineAsync($"Exporting {channels.Count} channel(s)..."); await console.Output.WriteLineAsync($"Exporting {channels.Count} channel(s)...");
await console.CreateProgressTicker().StartAsync(async progressContext => await console.CreateProgressTicker().StartAsync(async progressContext =>
{ {

@ -333,10 +333,9 @@ public class DiscordClient
IProgress<Percentage>? progress = null, IProgress<Percentage>? progress = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default) [EnumeratorCancellation] CancellationToken cancellationToken = default)
{ {
// Get the last message in the specified range. // Get the last message in the specified range, so we can later calculate progress based on its date.
// This snapshots the boundaries, which means that messages posted after the export started // This also snapshots the boundaries, which means that messages posted after the export started
// will not appear in the output. // will not appear in the output.
// Additionally, it provides the date of the last message, which is used to calculate progress.
var lastMessage = await TryGetLastMessageAsync(channelId, before, cancellationToken); var lastMessage = await TryGetLastMessageAsync(channelId, before, cancellationToken);
if (lastMessage is null || lastMessage.Timestamp < after?.ToDate()) if (lastMessage is null || lastMessage.Timestamp < after?.ToDate())
yield break; yield break;

@ -59,4 +59,8 @@ public partial record struct Snowflake : IComparable<Snowflake>, IComparable
return Value.CompareTo(other.Value); return Value.CompareTo(other.Value);
} }
public static bool operator >(Snowflake left, Snowflake right) => left.CompareTo(right) > 0;
public static bool operator <(Snowflake left, Snowflake right) => left.CompareTo(right) < 0;
} }

@ -18,13 +18,20 @@ public class ChannelExporter
IProgress<Percentage>? progress = null, IProgress<Percentage>? progress = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
// Check if the channel is empty
if (request.Channel.LastMessageId is null)
throw DiscordChatExporterException.ChannelIsEmpty();
// Check if the 'after' boundary is valid
if (request.After is not null && request.Channel.LastMessageId < request.After)
throw DiscordChatExporterException.ChannelIsEmpty();
// Build context // Build context
var context = new ExportContext(_discord, request); var context = new ExportContext(_discord, request);
await context.PopulateChannelsAndRolesAsync(cancellationToken); await context.PopulateChannelsAndRolesAsync(cancellationToken);
// Export messages // Export messages
await using var messageExporter = new MessageExporter(context); await using var messageExporter = new MessageExporter(context);
await foreach (var message in _discord.GetMessagesAsync( await foreach (var message in _discord.GetMessagesAsync(
request.Channel.Id, request.Channel.Id,
request.After, request.After,

Loading…
Cancel
Save