mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-06-02 23:59:50 -04:00
Preliminary support for threads (#1032)
This commit is contained in:
parent
9048557b17
commit
25caf04445
3 changed files with 111 additions and 0 deletions
|
@ -20,6 +20,12 @@ public class GetChannelsCommand : DiscordCommandBase
|
|||
)]
|
||||
public required Snowflake GuildId { get; init; }
|
||||
|
||||
[CommandOption(
|
||||
"include-threads",
|
||||
Description = "Display threads alongside channels."
|
||||
)]
|
||||
public bool IncludeTHreads { get; init; }
|
||||
|
||||
public override async ValueTask ExecuteAsync(IConsole console)
|
||||
{
|
||||
var cancellationToken = console.RegisterCancellationHandler();
|
||||
|
@ -44,6 +50,32 @@ public class GetChannelsCommand : DiscordCommandBase
|
|||
// Channel category / name
|
||||
using (console.WithForegroundColor(ConsoleColor.White))
|
||||
await console.Output.WriteLineAsync($"{channel.Category.Name} / {channel.Name}");
|
||||
|
||||
if (IncludeThreads)
|
||||
{
|
||||
var threads = (await Discord.GetGuildChannelThreadsAsync(channel.Id.ToString(), cancellationToken))
|
||||
.OrderBy(c => c.Name)
|
||||
.ToArray();
|
||||
|
||||
foreach (var thread in threads)
|
||||
{
|
||||
// Indent
|
||||
await console.Output.WriteAsync('\t');
|
||||
|
||||
// Thread ID
|
||||
await console.Output.WriteAsync(
|
||||
thread.Id.ToString().PadRight(18, ' ')
|
||||
);
|
||||
|
||||
// Separator
|
||||
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||
await console.Output.WriteAsync(" | ");
|
||||
|
||||
// Thread / thread name
|
||||
using (console.WithForegroundColor(ConsoleColor.White))
|
||||
await console.Output.WriteLineAsync($"Thread / {thread.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
DiscordChatExporter.Core/Discord/Data/ThreadChannel.cs
Normal file
50
DiscordChatExporter.Core/Discord/Data/ThreadChannel.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using DiscordChatExporter.Core.Discord.Data.Common;
|
||||
using DiscordChatExporter.Core.Utils.Extensions;
|
||||
using JsonExtensions.Reading;
|
||||
|
||||
namespace DiscordChatExporter.Core.Discord.Data;
|
||||
|
||||
// https://discord.com/developers/docs/resources/channel#channel-object-example-thread-channel
|
||||
public partial record ThreadChannel(
|
||||
Snowflake Id,
|
||||
ChannelKind Kind,
|
||||
Snowflake GuildId,
|
||||
string Name,
|
||||
Snowflake? LastMessageId) : IHasId
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public partial record ThreadChannel
|
||||
{
|
||||
public static ThreadChannel Parse(JsonElement json)
|
||||
{
|
||||
var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
|
||||
var kind = (ChannelKind)json.GetProperty("type").GetInt32();
|
||||
|
||||
var guildId =
|
||||
json.GetPropertyOrNull("guild_id")?.GetNonWhiteSpaceStringOrNull()?.Pipe(Snowflake.Parse) ?? default;
|
||||
|
||||
var name =
|
||||
// Guild channel
|
||||
json.GetPropertyOrNull("name")?.GetNonWhiteSpaceStringOrNull() ??
|
||||
|
||||
// Fallback
|
||||
id.ToString();
|
||||
|
||||
var lastMessageId = json
|
||||
.GetPropertyOrNull("last_message_id")?
|
||||
.GetNonWhiteSpaceStringOrNull()?
|
||||
.Pipe(Snowflake.Parse);
|
||||
|
||||
return new ThreadChannel(
|
||||
id,
|
||||
kind,
|
||||
guildId,
|
||||
name,
|
||||
lastMessageId
|
||||
);
|
||||
}
|
||||
}
|
|
@ -200,6 +200,35 @@ public class DiscordClient
|
|||
return Guild.Parse(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ThreadChannel> GetGuildChannelThreadsAsync(
|
||||
string channelId,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
int currentOffset = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
var url = new UrlBuilder()
|
||||
.SetPath($"channels/{channelId}/threads/search")
|
||||
.SetQueryParameter("offset", currentOffset.ToString())
|
||||
.Build();
|
||||
|
||||
var response = await TryGetJsonResponseAsync(url, cancellationToken);
|
||||
|
||||
if (response is null)
|
||||
break;
|
||||
|
||||
foreach (var threadJson in response.Value.GetProperty("threads").EnumerateArray())
|
||||
yield return ThreadChannel.Parse(threadJson);
|
||||
|
||||
if (!response.Value.GetProperty("has_more").GetBoolean())
|
||||
{
|
||||
break;
|
||||
}
|
||||
currentOffset += response.Value.GetProperty("threads").GetArrayLength();
|
||||
}
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<Channel> GetGuildChannelsAsync(
|
||||
Snowflake guildId,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue