From 95d581797bc536285f7de5a312dd69ceaa6d7db9 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Fri, 1 Sep 2017 15:45:19 +0300 Subject: [PATCH] Add dark theme and theme switch (#4) * Add dark theme * Refactor a bit * Add back Light theme and add a switch * Update readme --- .../DiscordChatExporter.csproj | 4 +- DiscordChatExporter/Models/Options.cs | 5 +- DiscordChatExporter/Models/Theme.cs | 8 ++ DiscordChatExporter/Program.cs | 9 +- .../Resources/HtmlExportService/DarkTheme.css | 105 +++++++++++++++ .../HtmlExportService/LightTheme.css | 105 +++++++++++++++ .../Resources/HtmlExportService/Template.html | 17 +++ .../Services/ExportTemplate.html | 122 ------------------ ...{ExportService.cs => HtmlExportService.cs} | 36 +++++- Readme.md | 12 +- 10 files changed, 288 insertions(+), 135 deletions(-) create mode 100644 DiscordChatExporter/Models/Theme.cs create mode 100644 DiscordChatExporter/Resources/HtmlExportService/DarkTheme.css create mode 100644 DiscordChatExporter/Resources/HtmlExportService/LightTheme.css create mode 100644 DiscordChatExporter/Resources/HtmlExportService/Template.html delete mode 100644 DiscordChatExporter/Services/ExportTemplate.html rename DiscordChatExporter/Services/{ExportService.cs => HtmlExportService.cs} (85%) diff --git a/DiscordChatExporter/DiscordChatExporter.csproj b/DiscordChatExporter/DiscordChatExporter.csproj index 82515ea..ee724c3 100644 --- a/DiscordChatExporter/DiscordChatExporter.csproj +++ b/DiscordChatExporter/DiscordChatExporter.csproj @@ -9,7 +9,9 @@ - + + + diff --git a/DiscordChatExporter/Models/Options.cs b/DiscordChatExporter/Models/Options.cs index 41585b4..8170638 100644 --- a/DiscordChatExporter/Models/Options.cs +++ b/DiscordChatExporter/Models/Options.cs @@ -6,10 +6,13 @@ public string ChannelId { get; } - public Options(string token, string channelId) + public Theme Theme { get; } + + public Options(string token, string channelId, Theme theme) { Token = token; ChannelId = channelId; + Theme = theme; } } } \ No newline at end of file diff --git a/DiscordChatExporter/Models/Theme.cs b/DiscordChatExporter/Models/Theme.cs new file mode 100644 index 0000000..c527812 --- /dev/null +++ b/DiscordChatExporter/Models/Theme.cs @@ -0,0 +1,8 @@ +namespace DiscordChatExporter.Models +{ + public enum Theme + { + Light, + Dark + } +} \ No newline at end of file diff --git a/DiscordChatExporter/Program.cs b/DiscordChatExporter/Program.cs index b281938..bf37b2e 100644 --- a/DiscordChatExporter/Program.cs +++ b/DiscordChatExporter/Program.cs @@ -11,7 +11,7 @@ namespace DiscordChatExporter public static class Program { private static readonly DiscordApiService DiscordApiService = new DiscordApiService(); - private static readonly ExportService ExportService = new ExportService(); + private static readonly HtmlExportService HtmlExportService = new HtmlExportService(); private static Options GetOptions(string[] args) { @@ -37,8 +37,11 @@ namespace DiscordChatExporter if (token.IsBlank() || channelId.IsBlank()) throw new ArgumentException("Some or all required command line arguments are missing"); + // Exract optional arguments + var theme = argsDic.GetOrDefault("theme").ParseEnumOrDefault(); + // Create option set - return new Options(token, channelId); + return new Options(token, channelId, theme); } private static async Task MainAsync(string[] args) @@ -53,7 +56,7 @@ namespace DiscordChatExporter // Export Console.WriteLine("Exporting messages..."); - ExportService.Export($"{options.ChannelId}.html", chatLog); + HtmlExportService.Export($"{options.ChannelId}.html", chatLog, options.Theme); } public static void Main(string[] args) diff --git a/DiscordChatExporter/Resources/HtmlExportService/DarkTheme.css b/DiscordChatExporter/Resources/HtmlExportService/DarkTheme.css new file mode 100644 index 0000000..e128a72 --- /dev/null +++ b/DiscordChatExporter/Resources/HtmlExportService/DarkTheme.css @@ -0,0 +1,105 @@ +body { + font-family: Whitney, Helvetica Neue, Helvetica, Arial, sans-serif; + font-size: 16px; + + background-color: #36393E; +} + +a { + text-decoration: none; + + color: #0096CF; +} + +a:hover { + text-decoration: underline; +} + +div.pre, span.pre { + font-family: Consolas, Courier New, Courier, Monospace; + + padding-right: 2px; + padding-left: 2px; + + background-color: #2F3136; +} + +div#info { + max-width: 100%; + margin-bottom: 20px; + + color: rgba(255, 255, 255, 0.7); +} + +div#log { + max-width: 100%; +} + +div.msg { + display: flex; + + margin-right: 10px; + margin-left: 10px; + padding-top: 15px; + padding-bottom: 15px; + + border-top: 1px solid rgba(255, 255, 255, 0.04); +} + +div.msg-avatar { + width: 40px; + height: 40px; +} + +img.msg-avatar { + width: 40px; + height: 40px; + + border-radius: 50%; +} + +div.msg-body { + margin-left: 20px; + + flex: 1; +} + +span.msg-user { + font-size: 1rem; + + color: #FFFFFF; +} + +span.msg-date { + font-size: .75rem; + + margin-left: 5px; + + color: rgba(255, 255, 255, 0.2); +} + +span.msg-edited { + font-size: .8rem; + + margin-left: 5px; + + color: rgba(255, 255, 255, 0.2); +} + +div.msg-content { + font-size: .9375rem; + + padding-top: 5px; + + color: rgba(255, 255, 255, 0.7); +} + +div.msg-attachment { + margin-top: 5px; + margin-bottom: 5px; +} + +img.msg-attachment { + max-width: 50%; + max-height: 500px; +} \ No newline at end of file diff --git a/DiscordChatExporter/Resources/HtmlExportService/LightTheme.css b/DiscordChatExporter/Resources/HtmlExportService/LightTheme.css new file mode 100644 index 0000000..c7d6022 --- /dev/null +++ b/DiscordChatExporter/Resources/HtmlExportService/LightTheme.css @@ -0,0 +1,105 @@ +body { + font-family: Whitney, Helvetica Neue, Helvetica, Arial, sans-serif; + font-size: 16px; + + background-color: #FFFFFF; +} + +a { + text-decoration: none; + + color: #00B0F4; +} + +a:hover { + text-decoration: underline; +} + +div.pre, span.pre { + font-family: Consolas, Courier New, Courier, Monospace; + + padding-right: 2px; + padding-left: 2px; + + background-color: #F9F9F9; +} + +div#info { + max-width: 100%; + margin-bottom: 20px; + + color: #737F8D; +} + +div#log { + max-width: 100%; +} + +div.msg { + display: flex; + + margin-right: 10px; + margin-left: 10px; + padding-top: 15px; + padding-bottom: 15px; + + border-top: 1px solid #ECEEEF; +} + +div.msg-avatar { + width: 40px; + height: 40px; +} + +img.msg-avatar { + width: 40px; + height: 40px; + + border-radius: 50%; +} + +div.msg-body { + margin-left: 20px; + + flex: 1; +} + +span.msg-user { + font-size: 1rem; + + color: #2F3136; +} + +span.msg-date { + font-size: .75rem; + + margin-left: 5px; + + color: #99AAB5; +} + +span.msg-edited { + font-size: .8rem; + + margin-left: 5px; + + color: #99AAB5; +} + +div.msg-content { + font-size: .9375rem; + + padding-top: 5px; + + color: #737F8D; +} + +div.msg-attachment { + margin-top: 5px; + margin-bottom: 5px; +} + +img.msg-attachment { + max-width: 50%; + max-height: 500px; +} \ No newline at end of file diff --git a/DiscordChatExporter/Resources/HtmlExportService/Template.html b/DiscordChatExporter/Resources/HtmlExportService/Template.html new file mode 100644 index 0000000..54704ba --- /dev/null +++ b/DiscordChatExporter/Resources/HtmlExportService/Template.html @@ -0,0 +1,17 @@ + + + + + + Discord Chat Log + + + + + + +
+
+ + \ No newline at end of file diff --git a/DiscordChatExporter/Services/ExportTemplate.html b/DiscordChatExporter/Services/ExportTemplate.html deleted file mode 100644 index f0173f0..0000000 --- a/DiscordChatExporter/Services/ExportTemplate.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - Discord Chat Log - - - - - - - -
-
- - \ No newline at end of file diff --git a/DiscordChatExporter/Services/ExportService.cs b/DiscordChatExporter/Services/HtmlExportService.cs similarity index 85% rename from DiscordChatExporter/Services/ExportService.cs rename to DiscordChatExporter/Services/HtmlExportService.cs index e4dc57f..0eb5132 100644 --- a/DiscordChatExporter/Services/ExportService.cs +++ b/DiscordChatExporter/Services/HtmlExportService.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; +using System.Resources; using System.Text.RegularExpressions; using DiscordChatExporter.Models; using HtmlAgilityPack; @@ -8,13 +10,18 @@ using Tyrrrz.Extensions; namespace DiscordChatExporter.Services { - public class ExportService + public class HtmlExportService { private HtmlDocument GetTemplate() { - const string templateName = "DiscordChatExporter.Services.ExportTemplate.html"; + string templateName = "DiscordChatExporter.Resources.HtmlExportService.Template.html"; + var assembly = Assembly.GetExecutingAssembly(); - using (var stream = assembly.GetManifestResourceStream(templateName)) + var stream = assembly.GetManifestResourceStream(templateName); + if (stream == null) + throw new MissingManifestResourceException("Could not find template resource"); + + using (stream) { var doc = new HtmlDocument(); doc.Load(stream); @@ -22,6 +29,22 @@ namespace DiscordChatExporter.Services } } + private string GetStyle(Theme theme) + { + string styleName = $"DiscordChatExporter.Resources.HtmlExportService.{theme}Theme.css"; + + var assembly = Assembly.GetExecutingAssembly(); + var stream = assembly.GetManifestResourceStream(styleName); + if (stream == null) + throw new MissingManifestResourceException("Could not find theme style resource"); + + using (stream) + using (var reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + private IEnumerable GroupMessages(IEnumerable messages) { var result = new List(); @@ -99,9 +122,14 @@ namespace DiscordChatExporter.Services return content; } - public void Export(string filePath, ChatLog chatLog) + public void Export(string filePath, ChatLog chatLog, Theme theme) { var doc = GetTemplate(); + string style = GetStyle(theme); + + // Set theme + var themeHtml = doc.GetElementbyId("theme"); + themeHtml.InnerHtml = style; // Info var infoHtml = doc.GetElementbyId("info"); diff --git a/Readme.md b/Readme.md index ba82610..b8f1ec3 100644 --- a/Readme.md +++ b/Readme.md @@ -12,7 +12,7 @@ Command line executable that can export [Discord](https://discordapp.com) channe ## Features -- Produces output styled similar to the Discord's light theme +- Supports both dark and light theme - Displays user avatars - Groups messages by author and time - Handles Discord markdown characters @@ -23,18 +23,18 @@ Command line executable that can export [Discord](https://discordapp.com) channe ## Usage -The program expects an access token and channel ID as parameters. +The program expects an access token and channel ID as parameters. At minimum, the execution should look like this: `DiscordChatExporter.exe /token:REkOTVqm9RWOTNOLCdiuMpWd.QiglBz.Lub0E0TZ1xX4ZxCtnwtpBhWt3v1 /channelId:459360869055190534` -#### Getting access token: +#### Getting access token - Open Discord desktop or web client - Press `Ctrl+Shift+I` - Navigate to `Application > Storage > Local Storage > https://discordapp.com` - Find the value for `token` and extract it -#### Getting channel ID: +#### Getting channel ID - Open Discord desktop or web client - Navigate to any DM or server channel @@ -46,6 +46,10 @@ The program expects an access token and channel ID as parameters. - If it's a server channel, the format looks like this: `https://discordapp.com/channels/WHATEVER/CHANNEL_ID` +#### Optional arguments + +- `/theme:[Dark/Light]` - sets the style of the output + ## Libraries used - [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack)