From bd9dc6455fa59f0719e94416aa68f89bb13bf938 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Mon, 13 Aug 2018 22:49:13 +0300 Subject: [PATCH] Refactor CLI (#81) --- DiscordChatExporter.Cli/CliOptions.cs | 26 ---- DiscordChatExporter.Cli/Container.cs | 18 +-- .../DiscordChatExporter.Cli.csproj | 2 +- DiscordChatExporter.Cli/Program.cs | 124 ++++-------------- .../Verbs/ExportChatVerb.cs | 69 ++++++++++ .../Verbs/GetChannelsVerb.cs | 33 +++++ .../Verbs/GetDirectMessageChannelsVerb.cs | 30 +++++ .../Verbs/GetGuildsVerb.cs | 30 +++++ .../Verbs/Options/ExportChatOptions.cs | 31 +++++ .../Verbs/Options/GetChannelsOptions.cs | 11 ++ .../GetDirectMessageChannelsOptions.cs | 9 ++ .../Verbs/Options/GetGuildsOptions.cs | 9 ++ .../Verbs/Options/TokenOptions.cs | 16 +++ .../Verbs/Options/UpdateAppOptions.cs | 9 ++ .../Verbs/UpdateAppVerb.cs | 38 ++++++ DiscordChatExporter.Cli/Verbs/Verb.cs | 18 +++ .../ViewModels/IMainViewModel.cs | 12 -- .../ViewModels/MainViewModel.cs | 56 -------- DiscordChatExporter.Gui/App.xaml | 2 - DiscordChatExporter.Gui/App.xaml.cs | 15 +-- DiscordChatExporter.Gui/Container.cs | 10 +- .../ViewModels/MainViewModel.cs | 1 + Readme.md | 2 +- 23 files changed, 341 insertions(+), 230 deletions(-) delete mode 100644 DiscordChatExporter.Cli/CliOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/ExportChatVerb.cs create mode 100644 DiscordChatExporter.Cli/Verbs/GetChannelsVerb.cs create mode 100644 DiscordChatExporter.Cli/Verbs/GetDirectMessageChannelsVerb.cs create mode 100644 DiscordChatExporter.Cli/Verbs/GetGuildsVerb.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Options/ExportChatOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Options/GetChannelsOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Options/GetDirectMessageChannelsOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Options/GetGuildsOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Options/TokenOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Options/UpdateAppOptions.cs create mode 100644 DiscordChatExporter.Cli/Verbs/UpdateAppVerb.cs create mode 100644 DiscordChatExporter.Cli/Verbs/Verb.cs delete mode 100644 DiscordChatExporter.Cli/ViewModels/IMainViewModel.cs delete mode 100644 DiscordChatExporter.Cli/ViewModels/MainViewModel.cs diff --git a/DiscordChatExporter.Cli/CliOptions.cs b/DiscordChatExporter.Cli/CliOptions.cs deleted file mode 100644 index 665803a..0000000 --- a/DiscordChatExporter.Cli/CliOptions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using DiscordChatExporter.Core.Models; - -namespace DiscordChatExporter.Cli -{ - public class CliOptions - { - public string TokenValue { get; set; } - - public bool IsBotToken { get; set; } - - public string ChannelId { get; set; } - - public ExportFormat ExportFormat { get; set; } - - public string FilePath { get; set; } - - public DateTime? From { get; set; } - - public DateTime? To { get; set; } - - public string DateFormat { get; set; } - - public int MessageGroupLimit { get; set; } - } -} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Container.cs b/DiscordChatExporter.Cli/Container.cs index 0120cfb..e16dec5 100644 --- a/DiscordChatExporter.Cli/Container.cs +++ b/DiscordChatExporter.Cli/Container.cs @@ -1,5 +1,4 @@ using CommonServiceLocator; -using DiscordChatExporter.Cli.ViewModels; using DiscordChatExporter.Core.Services; using GalaSoft.MvvmLight.Ioc; @@ -7,15 +6,7 @@ namespace DiscordChatExporter.Cli { public class Container { - public IMainViewModel MainViewModel => Resolve(); - public ISettingsService SettingsService => Resolve(); - - private T Resolve(string key = null) - { - return ServiceLocator.Current.GetInstance(key); - } - - public void Init() + public Container() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Reset(); @@ -25,13 +16,12 @@ namespace DiscordChatExporter.Cli SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); - - // View models - SimpleIoc.Default.Register(true); + SimpleIoc.Default.Register(); } - public void Cleanup() + public T Resolve(string key = null) { + return ServiceLocator.Current.GetInstance(key); } } } \ No newline at end of file diff --git a/DiscordChatExporter.Cli/DiscordChatExporter.Cli.csproj b/DiscordChatExporter.Cli/DiscordChatExporter.Cli.csproj index baf25bb..7a9ee6e 100644 --- a/DiscordChatExporter.Cli/DiscordChatExporter.Cli.csproj +++ b/DiscordChatExporter.Cli/DiscordChatExporter.Cli.csproj @@ -10,8 +10,8 @@ + - diff --git a/DiscordChatExporter.Cli/Program.cs b/DiscordChatExporter.Cli/Program.cs index 6b1a5ae..21d7d2a 100644 --- a/DiscordChatExporter.Cli/Program.cs +++ b/DiscordChatExporter.Cli/Program.cs @@ -1,34 +1,14 @@ using System; -using System.Reflection; -using DiscordChatExporter.Core.Models; -using Fclp; -using Tyrrrz.Extensions; +using CommandLine; +using DiscordChatExporter.Cli.Verbs; +using DiscordChatExporter.Cli.Verbs.Options; namespace DiscordChatExporter.Cli { public static class Program { - private static readonly Container Container = new Container(); - - private static void ShowHelp() + private static void ShowTokenHelp() { - var version = Assembly.GetExecutingAssembly().GetName().Version; - var availableFormats = Enum.GetNames(typeof(ExportFormat)); - - Console.WriteLine($"=== Discord Chat Exporter (Command Line Interface) v{version} ==="); - Console.WriteLine(); - Console.WriteLine("[-t] [--token] Discord authorization token."); - Console.WriteLine("[-b] [--bot] Whether this is a bot token."); - Console.WriteLine("[-c] [--channel] Discord channel ID."); - Console.WriteLine("[-f] [--format] Export format. Optional."); - Console.WriteLine("[-o] [--output] Output file path. Optional."); - Console.WriteLine(" [--datefrom] Limit to messages after this date. Optional."); - Console.WriteLine(" [--dateto] Limit to messages before this date. Optional."); - Console.WriteLine(" [--dateformat] Date format. Optional."); - Console.WriteLine(" [--grouplimit] Message group limit. Optional."); - Console.WriteLine(); - Console.WriteLine($"Available export formats: {availableFormats.JoinToString(", ")}"); - Console.WriteLine(); Console.WriteLine("# To get user token:"); Console.WriteLine(" - Open Discord app"); Console.WriteLine(" - Log in if you haven't"); @@ -43,83 +23,33 @@ namespace DiscordChatExporter.Cli Console.WriteLine(" - Open your application's settings"); Console.WriteLine(" - Navigate to the Bot section on the left"); Console.WriteLine(" - Under Token click Copy"); - Console.WriteLine(); - Console.WriteLine("# To get channel ID:"); - Console.WriteLine(" - Open Discord app"); - Console.WriteLine(" - Log in if you haven't"); - Console.WriteLine(" - Go to any channel you want to export"); - Console.WriteLine(" - Press Ctrl+Shift+I to show developer tools"); - Console.WriteLine(" - Navigate to the Console tab"); - Console.WriteLine(" - Type \"document.URL\" and press Enter"); - Console.WriteLine(" - Copy the long sequence of numbers after last slash"); - } - - private static CliOptions ParseOptions(string[] args) - { - var argsParser = new FluentCommandLineParser(); - - var settings = Container.SettingsService; - - argsParser.Setup(o => o.TokenValue).As('t', "token").Required(); - argsParser.Setup(o => o.IsBotToken).As('b', "bot").SetDefault(false); - argsParser.Setup(o => o.ChannelId).As('c', "channel").Required(); - argsParser.Setup(o => o.ExportFormat).As('f', "format").SetDefault(ExportFormat.HtmlDark); - argsParser.Setup(o => o.FilePath).As('o', "output").SetDefault(null); - argsParser.Setup(o => o.From).As("datefrom").SetDefault(null); - argsParser.Setup(o => o.To).As("dateto").SetDefault(null); - argsParser.Setup(o => o.DateFormat).As("dateformat").SetDefault(settings.DateFormat); - argsParser.Setup(o => o.MessageGroupLimit).As("grouplimit").SetDefault(settings.MessageGroupLimit); - - var parsed = argsParser.Parse(args); - - // Show help if no arguments - if (parsed.EmptyArgs) - { - ShowHelp(); - Environment.Exit(0); - } - // Show error if there are any - else if (parsed.HasErrors) - { - Console.Error.Write(parsed.ErrorText); - Environment.Exit(-1); - } - - return argsParser.Object; } public static void Main(string[] args) { - // Init container - Container.Init(); - - // Parse options - var options = ParseOptions(args); - - // Inject some settings - var settings = Container.SettingsService; - settings.DateFormat = options.DateFormat; - settings.MessageGroupLimit = options.MessageGroupLimit; - - // Create token - var token = new AuthToken( - options.IsBotToken ? AuthTokenType.Bot : AuthTokenType.User, - options.TokenValue); - - // Export - var vm = Container.MainViewModel; - vm.ExportAsync( - token, - options.ChannelId, - options.FilePath, - options.ExportFormat, - options.From, - options.To).GetAwaiter().GetResult(); - - // Cleanup container - Container.Cleanup(); - - Console.WriteLine("Export complete."); + // Get all verb types + var verbTypes = new[] + { + typeof(ExportChatOptions), + typeof(GetChannelsOptions), + typeof(GetDirectMessageChannelsOptions), + typeof(GetGuildsOptions), + typeof(UpdateAppOptions) + }; + + // Parse command line arguments + var parsedArgs = Parser.Default.ParseArguments(args, verbTypes); + + // Execute commands + parsedArgs.WithParsed(o => new ExportChatVerb(o).Execute()); + parsedArgs.WithParsed(o => new GetChannelsVerb(o).Execute()); + parsedArgs.WithParsed(o => new GetDirectMessageChannelsVerb(o).Execute()); + parsedArgs.WithParsed(o => new GetGuildsVerb(o).Execute()); + parsedArgs.WithParsed(o => new UpdateAppVerb(o).Execute()); + + // Show token help if error + if (parsedArgs.Tag == ParserResultType.NotParsed) + ShowTokenHelp(); } } } \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/ExportChatVerb.cs b/DiscordChatExporter.Cli/Verbs/ExportChatVerb.cs new file mode 100644 index 0000000..a791f2d --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/ExportChatVerb.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using DiscordChatExporter.Cli.Verbs.Options; +using DiscordChatExporter.Core.Models; +using DiscordChatExporter.Core.Services; +using Tyrrrz.Extensions; + +namespace DiscordChatExporter.Cli.Verbs +{ + public class ExportChatVerb : Verb + { + public ExportChatVerb(ExportChatOptions options) + : base(options) + { + } + + public override async Task ExecuteAsync() + { + // Get services + var container = new Container(); + var settingsService = container.Resolve(); + var dataService = container.Resolve(); + var messageGroupService = container.Resolve(); + var exportService = container.Resolve(); + + // Configure settings + if (Options.DateFormat.IsNotBlank()) + settingsService.DateFormat = Options.DateFormat; + if (Options.MessageGroupLimit > 0) + settingsService.MessageGroupLimit = Options.MessageGroupLimit; + + // Get channel and guild + var channel = await dataService.GetChannelAsync(Options.GetToken(), Options.ChannelId); + var guild = channel.GuildId == Guild.DirectMessages.Id + ? Guild.DirectMessages + : await dataService.GetGuildAsync(Options.GetToken(), channel.GuildId); + + // Generate file path if not set + var filePath = Options.FilePath; + if (filePath.IsBlank()) + { + filePath = $"{guild.Name} - {channel.Name}.{Options.ExportFormat.GetFileExtension()}" + .Replace(Path.GetInvalidFileNameChars(), '_'); + } + + // TODO: extract this to make it reusable across implementations + // Get messages + var messages = + await dataService.GetChannelMessagesAsync(Options.GetToken(), channel.Id, + Options.After, Options.Before); + + // Group messages + var messageGroups = messageGroupService.GroupMessages(messages); + + // Get mentionables + var mentionables = await dataService.GetMentionablesAsync(Options.GetToken(), guild.Id, messages); + + // Create log + var log = new ChatLog(guild, channel, Options.After, Options.Before, messageGroups, mentionables); + + // Export + exportService.Export(Options.ExportFormat, filePath, log); + + // Print result + Console.WriteLine($"Exported chat to [{filePath}]"); + } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/GetChannelsVerb.cs b/DiscordChatExporter.Cli/Verbs/GetChannelsVerb.cs new file mode 100644 index 0000000..36cdd6a --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/GetChannelsVerb.cs @@ -0,0 +1,33 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using DiscordChatExporter.Cli.Verbs.Options; +using DiscordChatExporter.Core.Models; +using DiscordChatExporter.Core.Services; +using Tyrrrz.Extensions; + +namespace DiscordChatExporter.Cli.Verbs +{ + public class GetChannelsVerb : Verb + { + public GetChannelsVerb(GetChannelsOptions options) + : base(options) + { + } + + public override async Task ExecuteAsync() + { + // Get data service + var container = new Container(); + var dataService = container.Resolve(); + + // Get channels + var channels = await dataService.GetGuildChannelsAsync(Options.GetToken(), Options.GuildId); + + // Print result + foreach (var channel in channels.Where(c => c.Type.IsEither(ChannelType.GuildTextChat)) + .OrderBy(c => c.Name)) + Console.WriteLine($"{channel.Id} | {channel.Name}"); + } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/GetDirectMessageChannelsVerb.cs b/DiscordChatExporter.Cli/Verbs/GetDirectMessageChannelsVerb.cs new file mode 100644 index 0000000..020a814 --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/GetDirectMessageChannelsVerb.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using DiscordChatExporter.Cli.Verbs.Options; +using DiscordChatExporter.Core.Services; + +namespace DiscordChatExporter.Cli.Verbs +{ + public class GetDirectMessageChannelsVerb : Verb + { + public GetDirectMessageChannelsVerb(GetDirectMessageChannelsOptions options) + : base(options) + { + } + + public override async Task ExecuteAsync() + { + // Get data service + var container = new Container(); + var dataService = container.Resolve(); + + // Get channels + var channels = await dataService.GetDirectMessageChannelsAsync(Options.GetToken()); + + // Print result + foreach (var channel in channels.OrderBy(c => c.Name)) + Console.WriteLine($"{channel.Id} | {channel.Name}"); + } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/GetGuildsVerb.cs b/DiscordChatExporter.Cli/Verbs/GetGuildsVerb.cs new file mode 100644 index 0000000..309e1ae --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/GetGuildsVerb.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using DiscordChatExporter.Cli.Verbs.Options; +using DiscordChatExporter.Core.Services; + +namespace DiscordChatExporter.Cli.Verbs +{ + public class GetGuildsVerb : Verb + { + public GetGuildsVerb(GetGuildsOptions options) + : base(options) + { + } + + public override async Task ExecuteAsync() + { + // Get data service + var container = new Container(); + var dataService = container.Resolve(); + + // Get guilds + var guilds = await dataService.GetUserGuildsAsync(Options.GetToken()); + + // Print result + foreach (var guild in guilds.OrderBy(g => g.Name)) + Console.WriteLine($"{guild.Id} | {guild.Name}"); + } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Options/ExportChatOptions.cs b/DiscordChatExporter.Cli/Verbs/Options/ExportChatOptions.cs new file mode 100644 index 0000000..870fd2a --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Options/ExportChatOptions.cs @@ -0,0 +1,31 @@ +using System; +using CommandLine; +using DiscordChatExporter.Core.Models; + +namespace DiscordChatExporter.Cli.Verbs.Options +{ + [Verb("export", HelpText = "Export channel chat log to a file.")] + public class ExportChatOptions : TokenOptions + { + [Option('c', "channel", Required = true, HelpText = "Channel ID.")] + public string ChannelId { get; set; } + + [Option('f', "format", Default = ExportFormat.HtmlDark, HelpText = "Output file format.")] + public ExportFormat ExportFormat { get; set; } + + [Option('o', "output", Default = null, HelpText = "Output file path.")] + public string FilePath { get; set; } + + [Option("after", Default = null, HelpText = "Limit to messages sent after this date.")] + public DateTime? After { get; set; } + + [Option("before", Default = null, HelpText = "Limit to messages sent before this date.")] + public DateTime? Before { get; set; } + + [Option("dateformat", Default = null, HelpText = "Date format used in output.")] + public string DateFormat { get; set; } + + [Option("grouplimit", Default = 0, HelpText = "Message group limit.")] + public int MessageGroupLimit { get; set; } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Options/GetChannelsOptions.cs b/DiscordChatExporter.Cli/Verbs/Options/GetChannelsOptions.cs new file mode 100644 index 0000000..117fc16 --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Options/GetChannelsOptions.cs @@ -0,0 +1,11 @@ +using CommandLine; + +namespace DiscordChatExporter.Cli.Verbs.Options +{ + [Verb("channels", HelpText = "Get the list of channels in the given guild.")] + public class GetChannelsOptions : TokenOptions + { + [Option('g', "guild", Required = true, HelpText = "Guild ID.")] + public string GuildId { get; set; } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Options/GetDirectMessageChannelsOptions.cs b/DiscordChatExporter.Cli/Verbs/Options/GetDirectMessageChannelsOptions.cs new file mode 100644 index 0000000..c352e86 --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Options/GetDirectMessageChannelsOptions.cs @@ -0,0 +1,9 @@ +using CommandLine; + +namespace DiscordChatExporter.Cli.Verbs.Options +{ + [Verb("dm", HelpText = "Get the list of direct message channels.")] + public class GetDirectMessageChannelsOptions : TokenOptions + { + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Options/GetGuildsOptions.cs b/DiscordChatExporter.Cli/Verbs/Options/GetGuildsOptions.cs new file mode 100644 index 0000000..4e61acd --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Options/GetGuildsOptions.cs @@ -0,0 +1,9 @@ +using CommandLine; + +namespace DiscordChatExporter.Cli.Verbs.Options +{ + [Verb("guilds", HelpText = "Get the list of accessible guilds.")] + public class GetGuildsOptions : TokenOptions + { + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Options/TokenOptions.cs b/DiscordChatExporter.Cli/Verbs/Options/TokenOptions.cs new file mode 100644 index 0000000..6262a3f --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Options/TokenOptions.cs @@ -0,0 +1,16 @@ +using CommandLine; +using DiscordChatExporter.Core.Models; + +namespace DiscordChatExporter.Cli.Verbs.Options +{ + public class TokenOptions + { + [Option('t', "token", Required = true, HelpText = "Authorization token.")] + public string TokenValue { get; set; } + + [Option('b', "bot", Default = false, HelpText = "Whether this authorization token belongs to a bot.")] + public bool IsBotToken { get; set; } + + public AuthToken GetToken() => new AuthToken(IsBotToken ? AuthTokenType.Bot : AuthTokenType.User, TokenValue); + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Options/UpdateAppOptions.cs b/DiscordChatExporter.Cli/Verbs/Options/UpdateAppOptions.cs new file mode 100644 index 0000000..fbb4392 --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Options/UpdateAppOptions.cs @@ -0,0 +1,9 @@ +using CommandLine; + +namespace DiscordChatExporter.Cli.Verbs.Options +{ + [Verb("update", HelpText = "Updates this application to the latest version.")] + public class UpdateAppOptions + { + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/UpdateAppVerb.cs b/DiscordChatExporter.Cli/Verbs/UpdateAppVerb.cs new file mode 100644 index 0000000..3367ad7 --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/UpdateAppVerb.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading.Tasks; +using DiscordChatExporter.Cli.Verbs.Options; +using DiscordChatExporter.Core.Services; + +namespace DiscordChatExporter.Cli.Verbs +{ + public class UpdateAppVerb : Verb + { + public UpdateAppVerb(UpdateAppOptions options) + : base(options) + { + } + + public override async Task ExecuteAsync() + { + // Get update service + var container = new Container(); + var updateService = container.Resolve(); + + // TODO: this is configured only for GUI + // Get update version + var updateVersion = await updateService.CheckPrepareUpdateAsync(); + + if (updateVersion != null) + { + Console.WriteLine($"Updating to version {updateVersion}"); + + updateService.NeedRestart = false; + updateService.FinalizeUpdate(); + } + else + { + Console.WriteLine("There are no application updates available."); + } + } + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/Verbs/Verb.cs b/DiscordChatExporter.Cli/Verbs/Verb.cs new file mode 100644 index 0000000..82dafe4 --- /dev/null +++ b/DiscordChatExporter.Cli/Verbs/Verb.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; + +namespace DiscordChatExporter.Cli.Verbs +{ + public abstract class Verb + { + protected TOptions Options { get; } + + protected Verb(TOptions options) + { + Options = options; + } + + public abstract Task ExecuteAsync(); + + public virtual void Execute() => ExecuteAsync().GetAwaiter().GetResult(); + } +} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/ViewModels/IMainViewModel.cs b/DiscordChatExporter.Cli/ViewModels/IMainViewModel.cs deleted file mode 100644 index 63cac0c..0000000 --- a/DiscordChatExporter.Cli/ViewModels/IMainViewModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Threading.Tasks; -using DiscordChatExporter.Core.Models; - -namespace DiscordChatExporter.Cli.ViewModels -{ - public interface IMainViewModel - { - Task ExportAsync(AuthToken token, string channelId, string filePath, ExportFormat format, DateTime? from, - DateTime? to); - } -} \ No newline at end of file diff --git a/DiscordChatExporter.Cli/ViewModels/MainViewModel.cs b/DiscordChatExporter.Cli/ViewModels/MainViewModel.cs deleted file mode 100644 index f532fb6..0000000 --- a/DiscordChatExporter.Cli/ViewModels/MainViewModel.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using DiscordChatExporter.Core.Models; -using DiscordChatExporter.Core.Services; -using Tyrrrz.Extensions; - -namespace DiscordChatExporter.Cli.ViewModels -{ - public class MainViewModel : IMainViewModel - { - private readonly IDataService _dataService; - private readonly IMessageGroupService _messageGroupService; - private readonly IExportService _exportService; - - public MainViewModel(IDataService dataService, IMessageGroupService messageGroupService, - IExportService exportService) - { - _dataService = dataService; - _messageGroupService = messageGroupService; - _exportService = exportService; - } - - public async Task ExportAsync(AuthToken token, string channelId, string filePath, ExportFormat format, - DateTime? from, DateTime? to) - { - // Get channel and guild - var channel = await _dataService.GetChannelAsync(token, channelId); - var guild = channel.GuildId == Guild.DirectMessages.Id - ? Guild.DirectMessages - : await _dataService.GetGuildAsync(token, channel.GuildId); - - // Generate file path if not set - if (filePath.IsBlank()) - { - filePath = $"{guild.Name} - {channel.Name}.{format.GetFileExtension()}" - .Replace(Path.GetInvalidFileNameChars(), '_'); - } - - // Get messages - var messages = await _dataService.GetChannelMessagesAsync(token, channel.Id, from, to); - - // Group messages - var messageGroups = _messageGroupService.GroupMessages(messages); - - // Get mentionables - var mentionables = await _dataService.GetMentionablesAsync(token, guild.Id, messages); - - // Create log - var log = new ChatLog(guild, channel, from, to, messageGroups, mentionables); - - // Export - _exportService.Export(format, filePath, log); - } - } -} \ No newline at end of file diff --git a/DiscordChatExporter.Gui/App.xaml b/DiscordChatExporter.Gui/App.xaml index ea53d08..c456ec8 100644 --- a/DiscordChatExporter.Gui/App.xaml +++ b/DiscordChatExporter.Gui/App.xaml @@ -4,8 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters" xmlns:local="clr-namespace:DiscordChatExporter.Gui" - Exit="App_Exit" - Startup="App_Startup" StartupUri="Views/MainWindow.xaml"> diff --git a/DiscordChatExporter.Gui/App.xaml.cs b/DiscordChatExporter.Gui/App.xaml.cs index 8a2c3e2..57df507 100644 --- a/DiscordChatExporter.Gui/App.xaml.cs +++ b/DiscordChatExporter.Gui/App.xaml.cs @@ -1,19 +1,6 @@ -using System.Windows; - -namespace DiscordChatExporter.Gui +namespace DiscordChatExporter.Gui { public partial class App { - private Container Container => (Container) Resources["Container"]; - - private void App_Startup(object sender, StartupEventArgs e) - { - Container.Init(); - } - - private void App_Exit(object sender, ExitEventArgs e) - { - Container.Cleanup(); - } } } \ No newline at end of file diff --git a/DiscordChatExporter.Gui/Container.cs b/DiscordChatExporter.Gui/Container.cs index 6ed5089..ddb6139 100644 --- a/DiscordChatExporter.Gui/Container.cs +++ b/DiscordChatExporter.Gui/Container.cs @@ -11,12 +11,7 @@ namespace DiscordChatExporter.Gui public IMainViewModel MainViewModel => Resolve(); public ISettingsViewModel SettingsViewModel => Resolve(); - private T Resolve(string key = null) - { - return ServiceLocator.Current.GetInstance(key); - } - - public void Init() + public Container() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Reset(); @@ -34,8 +29,9 @@ namespace DiscordChatExporter.Gui SimpleIoc.Default.Register(true); } - public void Cleanup() + private T Resolve(string key = null) { + return ServiceLocator.Current.GetInstance(key); } } } \ No newline at end of file diff --git a/DiscordChatExporter.Gui/ViewModels/MainViewModel.cs b/DiscordChatExporter.Gui/ViewModels/MainViewModel.cs index 4f94830..fc75091 100644 --- a/DiscordChatExporter.Gui/ViewModels/MainViewModel.cs +++ b/DiscordChatExporter.Gui/ViewModels/MainViewModel.cs @@ -256,6 +256,7 @@ namespace DiscordChatExporter.Gui.ViewModels try { + // TODO: extract this to make it reusable across implementations // Get messages var messages = await _dataService.GetChannelMessagesAsync(token, channel.Id, from, to, progressHandler); diff --git a/Readme.md b/Readme.md index 2519e4e..ab9dfac 100644 --- a/Readme.md +++ b/Readme.md @@ -32,7 +32,7 @@ DiscordChatExporter can be used to export message history from a [Discord](https - [Scriban](https://github.com/lunet-io/scriban) - [Polly](https://github.com/App-vNext/Polly) - [Onova](https://github.com/Tyrrrz/Onova) -- [FluentCommandLineParser](https://github.com/fclp/fluent-command-line-parser) +- [CommandLineParser](https://github.com/commandlineparser/commandline) - [Tyrrrz.Extensions](https://github.com/Tyrrrz/Extensions) - [Tyrrrz.WpfExtensions](https://github.com/Tyrrrz/WpfExtensions) - [Tyrrrz.Settings](https://github.com/Tyrrrz/Settings)