mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-06-05 01:03:44 -04:00
Refactor
This commit is contained in:
parent
9583e2684d
commit
9601e0acea
3 changed files with 41 additions and 34 deletions
|
@ -39,11 +39,17 @@ public partial record Channel(
|
||||||
_ => "Default"
|
_ => "Default"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public bool IsEmpty => LastMessageId is null;
|
||||||
|
|
||||||
// Only needed for WPF data binding. Don't use anywhere else.
|
// Only needed for WPF data binding. Don't use anywhere else.
|
||||||
public bool IsVoice => Kind.IsVoice();
|
public bool IsVoice => Kind.IsVoice();
|
||||||
|
|
||||||
// Only needed for WPF data binding. Don't use anywhere else.
|
// Only needed for WPF data binding. Don't use anywhere else.
|
||||||
public bool IsThread => Kind.IsThread();
|
public bool IsThread => Kind.IsThread();
|
||||||
|
|
||||||
|
public bool MayHaveMessagesAfter(Snowflake messageId) => !IsEmpty && messageId < LastMessageId;
|
||||||
|
|
||||||
|
public bool MayHaveMessagesBefore(Snowflake messageId) => !IsEmpty && messageId > Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial record Channel
|
public partial record Channel
|
||||||
|
|
|
@ -286,23 +286,25 @@ public class DiscordClient
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var tokenKind = _resolvedTokenKind ??= await GetTokenKindAsync(cancellationToken);
|
var tokenKind = _resolvedTokenKind ??= await GetTokenKindAsync(cancellationToken);
|
||||||
var channels = await GetGuildChannelsAsync(guildId, cancellationToken);
|
var channels = (await GetGuildChannelsAsync(guildId, cancellationToken))
|
||||||
|
|
||||||
var filteredChannels = channels
|
|
||||||
// Categories cannot have threads
|
// Categories cannot have threads
|
||||||
.Where(c => c.Kind != ChannelKind.GuildCategory)
|
.Where(c => c.Kind != ChannelKind.GuildCategory)
|
||||||
// Voice channels cannot have threads
|
// Voice channels cannot have threads
|
||||||
.Where(c => !c.Kind.IsVoice())
|
.Where(c => !c.Kind.IsVoice())
|
||||||
// Ordinary channel or forum channel without LastMessageId cannot have threads
|
// Empty channels cannot have threads
|
||||||
.Where(c => c.LastMessageId != null)
|
.Where(c => !c.IsEmpty)
|
||||||
// Ff --before is specified, skip channels created after the specified date
|
// If the 'before' boundary is specified, skip channels that don't have messages
|
||||||
.Where(c => before == null || before > c.Id);
|
// for that range, because thread-start event should always be accompanied by a message.
|
||||||
|
// Note that we don't perform a similar check for the 'after' boundary, because
|
||||||
|
// threads may have messages in range, even if the parent channel doesn't.
|
||||||
|
.Where(c => before is null || c.MayHaveMessagesBefore(before.Value))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
// User accounts can only fetch threads using the search endpoint
|
// User accounts can only fetch threads using the search endpoint
|
||||||
if (tokenKind == TokenKind.User)
|
if (tokenKind == TokenKind.User)
|
||||||
{
|
{
|
||||||
// Active threads
|
// Active threads
|
||||||
foreach (var channel in filteredChannels)
|
foreach (var channel in channels)
|
||||||
{
|
{
|
||||||
var currentOffset = 0;
|
var currentOffset = 0;
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -320,7 +322,7 @@ public class DiscordClient
|
||||||
if (response is null)
|
if (response is null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var containsOlder = false;
|
var breakOuter = false;
|
||||||
|
|
||||||
foreach (
|
foreach (
|
||||||
var threadJson in response.Value.GetProperty("threads").EnumerateArray()
|
var threadJson in response.Value.GetProperty("threads").EnumerateArray()
|
||||||
|
@ -328,19 +330,19 @@ public class DiscordClient
|
||||||
{
|
{
|
||||||
var thread = Channel.Parse(threadJson, channel);
|
var thread = Channel.Parse(threadJson, channel);
|
||||||
|
|
||||||
// if --after is specified, we can break early, because the threads are sorted by last message time
|
// If the 'after' boundary is specified, we can break early,
|
||||||
if (after is not null && after > thread.LastMessageId)
|
// because threads are sorted by last message time.
|
||||||
|
if (after is not null && !thread.MayHaveMessagesAfter(after.Value))
|
||||||
{
|
{
|
||||||
containsOlder = true;
|
breakOuter = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return thread;
|
yield return thread;
|
||||||
|
|
||||||
currentOffset++;
|
currentOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containsOlder)
|
if (breakOuter)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!response.Value.GetProperty("has_more").GetBoolean())
|
if (!response.Value.GetProperty("has_more").GetBoolean())
|
||||||
|
@ -351,7 +353,7 @@ public class DiscordClient
|
||||||
// Archived threads
|
// Archived threads
|
||||||
if (includeArchived)
|
if (includeArchived)
|
||||||
{
|
{
|
||||||
foreach (var channel in filteredChannels)
|
foreach (var channel in channels)
|
||||||
{
|
{
|
||||||
var currentOffset = 0;
|
var currentOffset = 0;
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -369,7 +371,7 @@ public class DiscordClient
|
||||||
if (response is null)
|
if (response is null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var containsOlder = false;
|
var breakOuter = false;
|
||||||
|
|
||||||
foreach (
|
foreach (
|
||||||
var threadJson in response.Value.GetProperty("threads").EnumerateArray()
|
var threadJson in response.Value.GetProperty("threads").EnumerateArray()
|
||||||
|
@ -377,19 +379,19 @@ public class DiscordClient
|
||||||
{
|
{
|
||||||
var thread = Channel.Parse(threadJson, channel);
|
var thread = Channel.Parse(threadJson, channel);
|
||||||
|
|
||||||
// if --after is specified, we can break early, because the threads are sorted by last message time
|
// If the 'after' boundary is specified, we can break early,
|
||||||
if (after is not null && after > thread.LastMessageId)
|
// because threads are sorted by last message time.
|
||||||
|
if (after is not null && !thread.MayHaveMessagesAfter(after.Value))
|
||||||
{
|
{
|
||||||
containsOlder = true;
|
breakOuter = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return thread;
|
yield return thread;
|
||||||
|
|
||||||
currentOffset++;
|
currentOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containsOlder)
|
if (breakOuter)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!response.Value.GetProperty("has_more").GetBoolean())
|
if (!response.Value.GetProperty("has_more").GetBoolean())
|
||||||
|
@ -403,7 +405,7 @@ public class DiscordClient
|
||||||
{
|
{
|
||||||
// Active threads
|
// Active threads
|
||||||
{
|
{
|
||||||
var parentsById = filteredChannels.ToDictionary(c => c.Id);
|
var parentsById = channels.ToDictionary(c => c.Id);
|
||||||
|
|
||||||
var response = await GetJsonResponseAsync(
|
var response = await GetJsonResponseAsync(
|
||||||
$"guilds/{guildId}/threads/active",
|
$"guilds/{guildId}/threads/active",
|
||||||
|
@ -425,7 +427,7 @@ public class DiscordClient
|
||||||
// Archived threads
|
// Archived threads
|
||||||
if (includeArchived)
|
if (includeArchived)
|
||||||
{
|
{
|
||||||
foreach (var channel in filteredChannels)
|
foreach (var channel in channels)
|
||||||
{
|
{
|
||||||
// Public archived threads
|
// Public archived threads
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,14 +20,16 @@ public class ChannelExporter
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Forum channels don't have messages, they are just a list of threads
|
||||||
|
if (request.Channel.Kind == ChannelKind.GuildForum)
|
||||||
|
throw new DiscordChatExporterException("Channel is a forum.");
|
||||||
|
|
||||||
// Check if the channel is empty
|
// Check if the channel is empty
|
||||||
if (request.Channel.LastMessageId is null)
|
if (request.Channel.IsEmpty)
|
||||||
{
|
|
||||||
throw new DiscordChatExporterException("Channel does not contain any messages.");
|
throw new DiscordChatExporterException("Channel does not contain any messages.");
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the 'after' boundary is valid
|
// Check if the 'after' boundary is valid
|
||||||
if (request.After is not null && request.Channel.LastMessageId < request.After)
|
if (request.After is not null && !request.Channel.MayHaveMessagesAfter(request.After.Value))
|
||||||
{
|
{
|
||||||
throw new DiscordChatExporterException(
|
throw new DiscordChatExporterException(
|
||||||
"Channel does not contain any messages within the specified period."
|
"Channel does not contain any messages within the specified period."
|
||||||
|
@ -35,19 +37,16 @@ public class ChannelExporter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the 'before' boundary is valid
|
// Check if the 'before' boundary is valid
|
||||||
if (request.Before is not null && request.Channel.Id > request.Before)
|
if (
|
||||||
|
request.Before is not null
|
||||||
|
&& !request.Channel.MayHaveMessagesBefore(request.Before.Value)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
throw new DiscordChatExporterException(
|
throw new DiscordChatExporterException(
|
||||||
"Channel does not contain any messages within the specified period."
|
"Channel does not contain any messages within the specified period."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip forum channels, they are exported as threads
|
|
||||||
if (request.Channel.Kind == ChannelKind.GuildForum)
|
|
||||||
{
|
|
||||||
throw new DiscordChatExporterException("Channel is a forum.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build context
|
// Build context
|
||||||
var context = new ExportContext(_discord, request);
|
var context = new ExportContext(_discord, request);
|
||||||
await context.PopulateChannelsAndRolesAsync(cancellationToken);
|
await context.PopulateChannelsAndRolesAsync(cancellationToken);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue