mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-05-23 11:16:59 -04:00
[CLI] Update CliFx and use Spectre.Console for progress reporting
This commit is contained in:
parent
6f90c367b9
commit
017ed5ae6d
13 changed files with 193 additions and 121 deletions
|
@ -1,12 +1,12 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
using CliFx.Exceptions;
|
using CliFx.Exceptions;
|
||||||
using CliFx.Utilities;
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
using DiscordChatExporter.Core.Discord.Data;
|
using DiscordChatExporter.Core.Discord.Data;
|
||||||
using DiscordChatExporter.Core.Exporting;
|
using DiscordChatExporter.Core.Exporting;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Commands.Base
|
namespace DiscordChatExporter.Cli.Commands.Base
|
||||||
{
|
{
|
||||||
|
@ -39,14 +39,8 @@ namespace DiscordChatExporter.Cli.Commands.Base
|
||||||
private ChannelExporter? _channelExporter;
|
private ChannelExporter? _channelExporter;
|
||||||
protected ChannelExporter Exporter => _channelExporter ??= new ChannelExporter(Discord);
|
protected ChannelExporter Exporter => _channelExporter ??= new ChannelExporter(Discord);
|
||||||
|
|
||||||
protected async ValueTask ExportAsync(IConsole console, Guild guild, Channel channel)
|
protected async ValueTask ExportChannelAsync(Guild guild, Channel channel, ProgressContext progressContext)
|
||||||
{
|
{
|
||||||
await console.Output.WriteAsync(
|
|
||||||
$"Exporting channel '{channel.Category} / {channel.Name}'... "
|
|
||||||
);
|
|
||||||
|
|
||||||
var progress = console.CreateProgressTicker();
|
|
||||||
|
|
||||||
var request = new ExportRequest(
|
var request = new ExportRequest(
|
||||||
guild,
|
guild,
|
||||||
channel,
|
channel,
|
||||||
|
@ -60,22 +54,19 @@ namespace DiscordChatExporter.Cli.Commands.Base
|
||||||
DateFormat
|
DateFormat
|
||||||
);
|
);
|
||||||
|
|
||||||
await Exporter.ExportChannelAsync(request, progress);
|
var progress = progressContext.AddTask(
|
||||||
|
$"{channel.Category} / {channel.Name}",
|
||||||
|
new ProgressTaskSettings {MaxValue = 1}
|
||||||
|
);
|
||||||
|
|
||||||
await console.Output.WriteLineAsync();
|
try
|
||||||
await console.Output.WriteLineAsync("Done.");
|
{
|
||||||
}
|
await Exporter.ExportChannelAsync(request, progress);
|
||||||
|
}
|
||||||
protected async ValueTask ExportAsync(IConsole console, Channel channel)
|
finally
|
||||||
{
|
{
|
||||||
var guild = await Discord.GetGuildAsync(channel.GuildId);
|
progress.StopTask();
|
||||||
await ExportAsync(console, guild, channel);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected async ValueTask ExportAsync(IConsole console, Snowflake channelId)
|
|
||||||
{
|
|
||||||
var channel = await Discord.GetChannelAsync(channelId);
|
|
||||||
await ExportAsync(console, channel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ValueTask ExecuteAsync(IConsole console)
|
public override ValueTask ExecuteAsync(IConsole console)
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
using System.Collections.Concurrent;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
using CliFx.Utilities;
|
using CliFx.Exceptions;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
|
using DiscordChatExporter.Cli.Utils.Extensions;
|
||||||
using DiscordChatExporter.Core.Discord.Data;
|
using DiscordChatExporter.Core.Discord.Data;
|
||||||
using DiscordChatExporter.Core.Exceptions;
|
using DiscordChatExporter.Core.Exceptions;
|
||||||
using DiscordChatExporter.Core.Exporting;
|
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
using DiscordChatExporter.Core.Utils.Extensions;
|
||||||
using Gress;
|
|
||||||
using Tyrrrz.Extensions;
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Commands.Base
|
namespace DiscordChatExporter.Cli.Commands.Base
|
||||||
|
@ -20,63 +19,60 @@ namespace DiscordChatExporter.Cli.Commands.Base
|
||||||
[CommandOption("parallel", Description = "Limits how many channels can be exported in parallel.")]
|
[CommandOption("parallel", Description = "Limits how many channels can be exported in parallel.")]
|
||||||
public int ParallelLimit { get; init; } = 1;
|
public int ParallelLimit { get; init; } = 1;
|
||||||
|
|
||||||
protected async ValueTask ExportMultipleAsync(IConsole console, IReadOnlyList<Channel> channels)
|
protected async ValueTask ExportChannelsAsync(IConsole console, IReadOnlyList<Channel> channels)
|
||||||
{
|
{
|
||||||
// This uses a different route from ExportCommandBase.ExportAsync() because it runs
|
await console.Output.WriteLineAsync($"Exporting {channels.Count} channel(s)...");
|
||||||
// in parallel and needs another way to report progress to console.
|
|
||||||
|
|
||||||
await console.Output.WriteAsync(
|
var errors = new ConcurrentDictionary<Channel, string>();
|
||||||
$"Exporting {channels.Count} channels... "
|
|
||||||
|
await console.CreateProgressTicker().StartAsync(async progressContext =>
|
||||||
|
{
|
||||||
|
await channels.ParallelForEachAsync(async channel =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var guild = await Discord.GetGuildAsync(channel.GuildId);
|
||||||
|
await ExportChannelAsync(guild, channel, progressContext);
|
||||||
|
}
|
||||||
|
catch (DiscordChatExporterException ex) when (!ex.IsCritical)
|
||||||
|
{
|
||||||
|
errors[channel] = ex.Message;
|
||||||
|
}
|
||||||
|
}, ParallelLimit.ClampMin(1));
|
||||||
|
|
||||||
|
await console.Output.WriteLineAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Print result
|
||||||
|
await console.Output.WriteLineAsync(
|
||||||
|
$"Successfully exported {channels.Count - errors.Count} channel(s)."
|
||||||
);
|
);
|
||||||
|
|
||||||
var progress = console.CreateProgressTicker();
|
// Print errors
|
||||||
|
if (errors.Any())
|
||||||
var operations = progress.Wrap().CreateOperations(channels.Count);
|
|
||||||
|
|
||||||
var successfulExportCount = 0;
|
|
||||||
var errors = new ConcurrentBag<(Channel, string)>();
|
|
||||||
|
|
||||||
await channels.Zip(operations).ParallelForEachAsync(async tuple =>
|
|
||||||
{
|
{
|
||||||
var (channel, operation) = tuple;
|
using (console.WithForegroundColor(ConsoleColor.Red))
|
||||||
|
await console.Output.WriteLineAsync($"Failed to export {errors.Count} channel(s):");
|
||||||
|
|
||||||
try
|
foreach (var (channel, error) in errors)
|
||||||
{
|
{
|
||||||
var guild = await Discord.GetGuildAsync(channel.GuildId);
|
await console.Output.WriteAsync($"{channel.Category} / {channel.Name}: ");
|
||||||
|
|
||||||
var request = new ExportRequest(
|
using (console.WithForegroundColor(ConsoleColor.Red))
|
||||||
guild,
|
await console.Output.WriteLineAsync(error);
|
||||||
channel,
|
|
||||||
OutputPath,
|
|
||||||
ExportFormat,
|
|
||||||
After,
|
|
||||||
Before,
|
|
||||||
PartitionLimit,
|
|
||||||
ShouldDownloadMedia,
|
|
||||||
ShouldReuseMedia,
|
|
||||||
DateFormat
|
|
||||||
);
|
|
||||||
|
|
||||||
await Exporter.ExportChannelAsync(request, operation);
|
|
||||||
|
|
||||||
Interlocked.Increment(ref successfulExportCount);
|
|
||||||
}
|
}
|
||||||
catch (DiscordChatExporterException ex) when (!ex.IsCritical)
|
|
||||||
{
|
|
||||||
errors.Add((channel, ex.Message));
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
operation.Dispose();
|
|
||||||
}
|
|
||||||
}, ParallelLimit.ClampMin(1));
|
|
||||||
|
|
||||||
await console.Output.WriteLineAsync();
|
await console.Output.WriteLineAsync();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var (channel, error) in errors)
|
// Fail the command if ALL channels failed to export.
|
||||||
await console.Error.WriteLineAsync($"Channel '{channel}': {error}");
|
// Having some of the channels fail to export is fine and expected.
|
||||||
|
if (errors.Count >= channels.Count)
|
||||||
|
{
|
||||||
|
throw new CommandException("Export failed.");
|
||||||
|
}
|
||||||
|
|
||||||
await console.Output.WriteLineAsync($"Successfully exported {successfulExportCount} channel(s).");
|
await console.Output.WriteLineAsync("Done.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,17 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
using CliFx;
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Commands.Base
|
namespace DiscordChatExporter.Cli.Commands.Base
|
||||||
{
|
{
|
||||||
public abstract class TokenCommandBase : ICommand
|
public abstract class TokenCommandBase : ICommand
|
||||||
{
|
{
|
||||||
[CommandOption("token", 't', IsRequired = true, EnvironmentVariableName = "DISCORD_TOKEN", Description = "Authentication token.")]
|
[CommandOption("token", 't', IsRequired = true, EnvironmentVariable = "DISCORD_TOKEN", Description = "Authentication token.")]
|
||||||
public string TokenValue { get; init; } = "";
|
public string TokenValue { get; init; } = "";
|
||||||
|
|
||||||
[CommandOption("bot", 'b', EnvironmentVariableName = "DISCORD_TOKEN_BOT", Description = "Authenticate as a bot.")]
|
[CommandOption("bot", 'b', EnvironmentVariable = "DISCORD_TOKEN_BOT", Description = "Authenticate as a bot.")]
|
||||||
public bool IsBotToken { get; init; }
|
public bool IsBotToken { get; init; }
|
||||||
|
|
||||||
private AuthToken GetAuthToken() => new(
|
private AuthToken GetAuthToken() => new(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
using DiscordChatExporter.Core.Discord.Data;
|
using DiscordChatExporter.Core.Discord.Data;
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
{
|
{
|
||||||
await base.ExecuteAsync(console);
|
await base.ExecuteAsync(console);
|
||||||
|
|
||||||
|
// Get channel metadata
|
||||||
|
await console.Output.WriteLineAsync("Fetching channels...");
|
||||||
|
|
||||||
var channels = new List<Channel>();
|
var channels = new List<Channel>();
|
||||||
|
|
||||||
// Aggregate channels from all guilds
|
// Aggregate channels from all guilds
|
||||||
|
@ -32,7 +35,8 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await ExportMultipleAsync(console, channels);
|
// Export
|
||||||
|
await ExportChannelsAsync(console, channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
|
using DiscordChatExporter.Cli.Utils.Extensions;
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Commands
|
namespace DiscordChatExporter.Cli.Commands
|
||||||
|
@ -15,7 +16,19 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
public override async ValueTask ExecuteAsync(IConsole console)
|
public override async ValueTask ExecuteAsync(IConsole console)
|
||||||
{
|
{
|
||||||
await base.ExecuteAsync(console);
|
await base.ExecuteAsync(console);
|
||||||
await ExportAsync(console, ChannelId);
|
|
||||||
|
// Get channel metadata
|
||||||
|
await console.Output.WriteLineAsync("Fetching channel...");
|
||||||
|
var channel = await Discord.GetChannelAsync(ChannelId);
|
||||||
|
var guild = await Discord.GetGuildAsync(channel.GuildId);
|
||||||
|
|
||||||
|
// Export
|
||||||
|
await console.Output.WriteLineAsync("Exporting...");
|
||||||
|
await console.CreateProgressTicker().StartAsync(async progressContext =>
|
||||||
|
{
|
||||||
|
await ExportChannelAsync(guild, channel, progressContext);
|
||||||
|
});
|
||||||
|
await console.Output.WriteLineAsync("Done.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
using DiscordChatExporter.Core.Discord.Data;
|
using DiscordChatExporter.Core.Discord.Data;
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
using DiscordChatExporter.Core.Utils.Extensions;
|
||||||
|
@ -14,8 +14,12 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
{
|
{
|
||||||
await base.ExecuteAsync(console);
|
await base.ExecuteAsync(console);
|
||||||
|
|
||||||
|
// Get channel metadata
|
||||||
|
await console.Output.WriteLineAsync("Fetching channels...");
|
||||||
var channels = await Discord.GetGuildChannelsAsync(Guild.DirectMessages.Id);
|
var channels = await Discord.GetGuildChannelsAsync(Guild.DirectMessages.Id);
|
||||||
await ExportMultipleAsync(console, channels);
|
|
||||||
|
// Export
|
||||||
|
await ExportChannelsAsync(console, channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
using DiscordChatExporter.Core.Utils.Extensions;
|
||||||
|
@ -17,8 +17,12 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
{
|
{
|
||||||
await base.ExecuteAsync(console);
|
await base.ExecuteAsync(console);
|
||||||
|
|
||||||
|
// Get channel metadata
|
||||||
|
await console.Output.WriteLineAsync("Fetching channels...");
|
||||||
var channels = await Discord.GetGuildChannelsAsync(GuildId);
|
var channels = await Discord.GetGuildChannelsAsync(GuildId);
|
||||||
await ExportMultipleAsync(console, channels);
|
|
||||||
|
// Export
|
||||||
|
await ExportChannelsAsync(console, channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
using DiscordChatExporter.Core.Discord.Data.Common;
|
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
using DiscordChatExporter.Core.Utils.Extensions;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Commands
|
namespace DiscordChatExporter.Cli.Commands
|
||||||
|
@ -21,9 +21,18 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
|
|
||||||
foreach (var channel in channels.OrderBy(c => c.Category.Position).ThenBy(c => c.Name))
|
foreach (var channel in channels.OrderBy(c => c.Category.Position).ThenBy(c => c.Name))
|
||||||
{
|
{
|
||||||
await console.Output.WriteLineAsync(
|
// Channel ID
|
||||||
$"{channel.Id} | {channel.Category} / {channel.Name}"
|
await console.Output.WriteAsync(channel.Id.ToString());
|
||||||
);
|
|
||||||
|
// Separator
|
||||||
|
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||||
|
await console.Output.WriteAsync(" | ");
|
||||||
|
|
||||||
|
// Channel category / name
|
||||||
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
|
await console.Output.WriteAsync($"{channel.Category} / {channel.Name}");
|
||||||
|
|
||||||
|
await console.Output.WriteLineAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
using DiscordChatExporter.Core.Discord.Data;
|
using DiscordChatExporter.Core.Discord.Data;
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
using DiscordChatExporter.Core.Utils.Extensions;
|
||||||
|
@ -17,9 +18,18 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
|
|
||||||
foreach (var channel in channels.OrderBy(c => c.Name))
|
foreach (var channel in channels.OrderBy(c => c.Name))
|
||||||
{
|
{
|
||||||
await console.Output.WriteLineAsync(
|
// Channel ID
|
||||||
$"{channel.Id} | {channel.Category} / {channel.Name}"
|
await console.Output.WriteAsync(channel.Id.ToString());
|
||||||
);
|
|
||||||
|
// Separator
|
||||||
|
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||||
|
await console.Output.WriteAsync(" | ");
|
||||||
|
|
||||||
|
// Channel category / name
|
||||||
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
|
await console.Output.WriteAsync($"{channel.Category} / {channel.Name}");
|
||||||
|
|
||||||
|
await console.Output.WriteLineAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
using DiscordChatExporter.Cli.Commands.Base;
|
using DiscordChatExporter.Cli.Commands.Base;
|
||||||
using DiscordChatExporter.Core.Utils.Extensions;
|
using DiscordChatExporter.Core.Utils.Extensions;
|
||||||
|
|
||||||
|
@ -16,9 +17,18 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
|
|
||||||
foreach (var guild in guilds.OrderBy(g => g.Name))
|
foreach (var guild in guilds.OrderBy(g => g.Name))
|
||||||
{
|
{
|
||||||
await console.Output.WriteLineAsync(
|
// Guild ID
|
||||||
$"{guild.Id} | {guild.Name}"
|
await console.Output.WriteAsync(guild.Id.ToString());
|
||||||
);
|
|
||||||
|
// Separator
|
||||||
|
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||||
|
await console.Output.WriteAsync(" | ");
|
||||||
|
|
||||||
|
// Guild name
|
||||||
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
|
await console.Output.WriteAsync(guild.Name);
|
||||||
|
|
||||||
|
await console.Output.WriteLineAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CliFx;
|
using CliFx;
|
||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Commands
|
namespace DiscordChatExporter.Cli.Commands
|
||||||
{
|
{
|
||||||
|
@ -10,9 +11,9 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
{
|
{
|
||||||
public ValueTask ExecuteAsync(IConsole console)
|
public ValueTask ExecuteAsync(IConsole console)
|
||||||
{
|
{
|
||||||
console.WithForegroundColor(ConsoleColor.White, () =>
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
console.Output.WriteLine("To get user token:")
|
console.Output.WriteLine("To get user token:");
|
||||||
);
|
|
||||||
console.Output.WriteLine(" 1. Open Discord");
|
console.Output.WriteLine(" 1. Open Discord");
|
||||||
console.Output.WriteLine(" 2. Press Ctrl+Shift+I to show developer tools");
|
console.Output.WriteLine(" 2. Press Ctrl+Shift+I to show developer tools");
|
||||||
console.Output.WriteLine(" 3. Navigate to the Application tab");
|
console.Output.WriteLine(" 3. Navigate to the Application tab");
|
||||||
|
@ -22,18 +23,18 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
console.Output.WriteLine(" * Automating user accounts is technically against TOS, use at your own risk.");
|
console.Output.WriteLine(" * Automating user accounts is technically against TOS, use at your own risk.");
|
||||||
console.Output.WriteLine();
|
console.Output.WriteLine();
|
||||||
|
|
||||||
console.WithForegroundColor(ConsoleColor.White, () =>
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
console.Output.WriteLine("To get bot token:")
|
console.Output.WriteLine("To get bot token:");
|
||||||
);
|
|
||||||
console.Output.WriteLine(" 1. Go to Discord developer portal");
|
console.Output.WriteLine(" 1. Go to Discord developer portal");
|
||||||
console.Output.WriteLine(" 2. Open your application's settings");
|
console.Output.WriteLine(" 2. Open your application's settings");
|
||||||
console.Output.WriteLine(" 3. Navigate to the Bot section on the left");
|
console.Output.WriteLine(" 3. Navigate to the Bot section on the left");
|
||||||
console.Output.WriteLine(" 4. Under Token click Copy");
|
console.Output.WriteLine(" 4. Under Token click Copy");
|
||||||
console.Output.WriteLine();
|
console.Output.WriteLine();
|
||||||
|
|
||||||
console.WithForegroundColor(ConsoleColor.White, () =>
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
console.Output.WriteLine("To get guild ID or guild channel ID:")
|
console.Output.WriteLine("To get guild ID or guild channel ID:");
|
||||||
);
|
|
||||||
console.Output.WriteLine(" 1. Open Discord");
|
console.Output.WriteLine(" 1. Open Discord");
|
||||||
console.Output.WriteLine(" 2. Open Settings");
|
console.Output.WriteLine(" 2. Open Settings");
|
||||||
console.Output.WriteLine(" 3. Go to Appearance section");
|
console.Output.WriteLine(" 3. Go to Appearance section");
|
||||||
|
@ -41,9 +42,9 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
console.Output.WriteLine(" 5. Right click on the desired guild or channel and click Copy ID");
|
console.Output.WriteLine(" 5. Right click on the desired guild or channel and click Copy ID");
|
||||||
console.Output.WriteLine();
|
console.Output.WriteLine();
|
||||||
|
|
||||||
console.WithForegroundColor(ConsoleColor.White, () =>
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
console.Output.WriteLine("To get direct message channel ID:")
|
console.Output.WriteLine("To get direct message channel ID:");
|
||||||
);
|
|
||||||
console.Output.WriteLine(" 1. Open Discord");
|
console.Output.WriteLine(" 1. Open Discord");
|
||||||
console.Output.WriteLine(" 2. Open the desired direct message channel");
|
console.Output.WriteLine(" 2. Open the desired direct message channel");
|
||||||
console.Output.WriteLine(" 3. Press Ctrl+Shift+I to show developer tools");
|
console.Output.WriteLine(" 3. Press Ctrl+Shift+I to show developer tools");
|
||||||
|
@ -52,12 +53,11 @@ namespace DiscordChatExporter.Cli.Commands
|
||||||
console.Output.WriteLine(" 6. Copy the first long sequence of numbers inside the URL");
|
console.Output.WriteLine(" 6. Copy the first long sequence of numbers inside the URL");
|
||||||
console.Output.WriteLine();
|
console.Output.WriteLine();
|
||||||
|
|
||||||
console.WithForegroundColor(ConsoleColor.White,
|
using (console.WithForegroundColor(ConsoleColor.White))
|
||||||
() => console.Output.WriteLine("For more information, check out the wiki:")
|
console.Output.WriteLine("For more information, check out the wiki:");
|
||||||
);
|
|
||||||
console.WithForegroundColor(ConsoleColor.Blue,
|
using (console.WithForegroundColor(ConsoleColor.DarkCyan))
|
||||||
() => console.Output.WriteLine("https://github.com/Tyrrrz/DiscordChatExporter/wiki")
|
console.Output.WriteLine("https://github.com/Tyrrrz/DiscordChatExporter/wiki");
|
||||||
);
|
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CliFx" Version="1.6.0" />
|
<PackageReference Include="CliFx" Version="2.0.0" />
|
||||||
<PackageReference Include="Gress" Version="1.2.0" />
|
<PackageReference Include="Spectre.Console" Version="0.38.0" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
using CliFx.Infrastructure;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Cli.Utils.Extensions
|
||||||
|
{
|
||||||
|
internal static class ConsoleExtensions
|
||||||
|
{
|
||||||
|
public static IAnsiConsole CreateAnsiConsole(this IConsole console) => AnsiConsole.Create(
|
||||||
|
new AnsiConsoleSettings
|
||||||
|
{
|
||||||
|
Ansi = AnsiSupport.Detect,
|
||||||
|
ColorSystem = ColorSystemSupport.Detect,
|
||||||
|
Out = console.Output
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
public static Progress CreateProgressTicker(this IConsole console) => console
|
||||||
|
.CreateAnsiConsole()
|
||||||
|
.Progress()
|
||||||
|
.AutoClear(false)
|
||||||
|
.AutoRefresh(true)
|
||||||
|
.HideCompleted(false)
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn {Alignment = Justify.Left},
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue