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)