This commit is contained in:
Tyrrrz 2021-09-16 01:08:14 +03:00
parent af11064a85
commit ea31b1b270
19 changed files with 67 additions and 98 deletions

View file

@ -54,18 +54,21 @@ namespace DiscordChatExporter.Cli.Commands.Base
private ChannelExporter? _channelExporter;
protected ChannelExporter Exporter => _channelExporter ??= new ChannelExporter(Discord);
protected async ValueTask ExportAsync(IConsole console, IReadOnlyList<Channel> channels)
protected async ValueTask ExecuteAsync(IConsole console, IReadOnlyList<Channel> channels)
{
await console.Output.WriteLineAsync($"Exporting {channels.Count} channel(s)...");
if (ShouldReuseMedia && !ShouldDownloadMedia)
{
throw new CommandException("Option --reuse-media cannot be used without --media.");
}
var errors = new ConcurrentDictionary<Channel, string>();
// Wrap everything in a progress ticker
// Export
await console.Output.WriteLineAsync($"Exporting {channels.Count} channel(s)...");
await console.CreateProgressTicker().StartAsync(async progressContext =>
{
await channels.ParallelForEachAsync(async channel =>
{
// Export
try
{
await progressContext.StartTaskAsync($"{channel.Category} / {channel.Name}", async progress =>
@ -89,7 +92,7 @@ namespace DiscordChatExporter.Cli.Commands.Base
await Exporter.ExportChannelAsync(request, progress);
});
}
catch (DiscordChatExporterException ex) when (!ex.IsCritical)
catch (DiscordChatExporterException ex) when (!ex.IsFatal)
{
errors[channel] = ex.Message;
}
@ -127,22 +130,25 @@ namespace DiscordChatExporter.Cli.Commands.Base
await console.Output.WriteLineAsync();
}
// Fail the command if ALL channels failed to export.
// Having some of the channels fail to export is fine and expected.
// Fail the command only if ALL channels failed to export.
// Having some of the channels fail to export is expected.
if (errors.Count >= channels.Count)
{
throw new CommandException("Export failed.");
}
}
public override ValueTask ExecuteAsync(IConsole console)
protected async ValueTask ExecuteAsync(IConsole console, IReadOnlyList<Snowflake> channelIds)
{
if (ShouldReuseMedia && !ShouldDownloadMedia)
var channels = new List<Channel>();
foreach (var channelId in channelIds)
{
throw new CommandException("Option --reuse-media cannot be used without --media.");
var channel = await Discord.GetChannelAsync(channelId);
channels.Add(channel);
}
return default;
await ExecuteAsync(console, channels);
}
}
}

View file

@ -14,7 +14,8 @@ namespace DiscordChatExporter.Cli.Commands.Base
[CommandOption("bot", 'b', EnvironmentVariable = "DISCORD_TOKEN_BOT", Description = "Authenticate as a bot.")]
public bool IsBotToken { get; init; }
private AuthToken GetAuthToken() => new(
private AuthToken? _authToken;
private AuthToken AuthToken => _authToken ??= new AuthToken(
IsBotToken
? AuthTokenKind.Bot
: AuthTokenKind.User,
@ -22,7 +23,7 @@ namespace DiscordChatExporter.Cli.Commands.Base
);
private DiscordClient? _discordClient;
protected DiscordClient Discord => _discordClient ??= new DiscordClient(GetAuthToken());
protected DiscordClient Discord => _discordClient ??= new DiscordClient(AuthToken);
public abstract ValueTask ExecuteAsync(IConsole console);
}

View file

@ -15,14 +15,9 @@ namespace DiscordChatExporter.Cli.Commands
public override async ValueTask ExecuteAsync(IConsole console)
{
await base.ExecuteAsync(console);
// Get channel metadata
await console.Output.WriteLineAsync("Fetching channels...");
var channels = new List<Channel>();
// Aggregate channels from all guilds
await console.Output.WriteLineAsync("Fetching channels...");
await foreach (var guild in Discord.GetUserGuildsAsync())
{
// Skip DMs if instructed to
@ -39,8 +34,7 @@ namespace DiscordChatExporter.Cli.Commands
}
}
// Export
await ExportAsync(console, channels);
await base.ExecuteAsync(console, channels);
}
}
}

View file

@ -5,7 +5,6 @@ using CliFx.Attributes;
using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands.Base;
using DiscordChatExporter.Core.Discord;
using DiscordChatExporter.Core.Discord.Data;
namespace DiscordChatExporter.Cli.Commands
{
@ -16,23 +15,7 @@ namespace DiscordChatExporter.Cli.Commands
[CommandOption("channel", 'c', IsRequired = true, Description = "Channel ID(s).")]
public IReadOnlyList<Snowflake> ChannelIds { get; init; } = Array.Empty<Snowflake>();
public override async ValueTask ExecuteAsync(IConsole console)
{
await base.ExecuteAsync(console);
// Get channel metadata
await console.Output.WriteLineAsync("Fetching channel(s)...");
var channels = new List<Channel>();
foreach (var channelId in ChannelIds)
{
var channel = await Discord.GetChannelAsync(channelId);
channels.Add(channel);
}
// Export
await ExportAsync(console, channels);
}
public override async ValueTask ExecuteAsync(IConsole console) =>
await base.ExecuteAsync(console, ChannelIds);
}
}

View file

@ -13,15 +13,11 @@ namespace DiscordChatExporter.Cli.Commands
{
public override async ValueTask ExecuteAsync(IConsole console)
{
await base.ExecuteAsync(console);
// Get channel metadata
await console.Output.WriteLineAsync("Fetching channels...");
var channels = await Discord.GetGuildChannelsAsync(Guild.DirectMessages.Id);
var textChannels = channels.Where(c => c.IsTextChannel).ToArray();
// Export
await ExportAsync(console, textChannels);
await base.ExecuteAsync(console, textChannels);
}
}
}

View file

@ -16,15 +16,11 @@ namespace DiscordChatExporter.Cli.Commands
public override async ValueTask ExecuteAsync(IConsole console)
{
await base.ExecuteAsync(console);
// Get channel metadata
await console.Output.WriteLineAsync("Fetching channels...");
var channels = await Discord.GetGuildChannelsAsync(GuildId);
var textChannels = channels.Where(c => c.IsTextChannel).ToArray();
// Export
await ExportAsync(console, textChannels);
await base.ExecuteAsync(console, textChannels);
}
}
}

View file

@ -36,9 +36,7 @@ namespace DiscordChatExporter.Cli.Commands
// Channel category / name
using (console.WithForegroundColor(ConsoleColor.White))
await console.Output.WriteAsync($"{channel.Category} / {channel.Name}");
await console.Output.WriteLineAsync();
await console.Output.WriteLineAsync($"{channel.Category} / {channel.Name}");
}
}
}

View file

@ -33,9 +33,7 @@ namespace DiscordChatExporter.Cli.Commands
// Channel category / name
using (console.WithForegroundColor(ConsoleColor.White))
await console.Output.WriteAsync($"{channel.Category} / {channel.Name}");
await console.Output.WriteLineAsync();
await console.Output.WriteLineAsync($"{channel.Category} / {channel.Name}");
}
}
}

View file

@ -26,9 +26,7 @@ namespace DiscordChatExporter.Cli.Commands
// Guild name
using (console.WithForegroundColor(ConsoleColor.White))
await console.Output.WriteAsync(guild.Name);
await console.Output.WriteLineAsync();
await console.Output.WriteLineAsync(guild.Name);
}
}
}

View file

@ -11,6 +11,7 @@ namespace DiscordChatExporter.Cli.Commands
{
public ValueTask ExecuteAsync(IConsole console)
{
// User token
using (console.WithForegroundColor(ConsoleColor.White))
console.Output.WriteLine("To get user token:");
@ -25,6 +26,7 @@ namespace DiscordChatExporter.Cli.Commands
console.Output.WriteLine(" * Automating user accounts is technically against TOS, use at your own risk.");
console.Output.WriteLine();
// Bot token
using (console.WithForegroundColor(ConsoleColor.White))
console.Output.WriteLine("To get bot token:");
@ -34,6 +36,7 @@ namespace DiscordChatExporter.Cli.Commands
console.Output.WriteLine(" 4. Under Token click Copy");
console.Output.WriteLine();
// Guild or channel ID
using (console.WithForegroundColor(ConsoleColor.White))
console.Output.WriteLine("To get guild ID or guild channel ID:");
@ -44,6 +47,7 @@ namespace DiscordChatExporter.Cli.Commands
console.Output.WriteLine(" 5. Right click on the desired guild or channel and click Copy ID");
console.Output.WriteLine();
// Direct message channel ID
using (console.WithForegroundColor(ConsoleColor.White))
console.Output.WriteLine("To get direct message channel ID:");
@ -55,9 +59,9 @@ namespace DiscordChatExporter.Cli.Commands
console.Output.WriteLine(" 6. Copy the first long sequence of numbers inside the URL");
console.Output.WriteLine();
// Wiki link
using (console.WithForegroundColor(ConsoleColor.White))
console.Output.WriteLine("For more information, check out the wiki:");
using (console.WithForegroundColor(ConsoleColor.DarkCyan))
console.Output.WriteLine("https://github.com/Tyrrrz/DiscordChatExporter/wiki");