mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-13 09:18:01 +02:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c043376f9 | |||
| 77366cc9b4 | |||
| ffdca7b799 | |||
| 30cba7959f |
@@ -1,3 +1,8 @@
|
|||||||
|
### v2.12.1 (12-Apr-2019)
|
||||||
|
|
||||||
|
- [GUI] Fixed an issue where the app crashed when trying to export multiple channels.
|
||||||
|
- [HTML] Fixed an issue where some of the emojis were rendered via Twemoji while Discord renders them as plain text.
|
||||||
|
|
||||||
### v2.12 (11-Apr-2019)
|
### v2.12 (11-Apr-2019)
|
||||||
|
|
||||||
- Improved markdown parsing performance which speeds up the final stage of exporting by around 4.5 times.
|
- Improved markdown parsing performance which speeds up the final stage of exporting by around 4.5 times.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<metadata>
|
<metadata>
|
||||||
<id>discordchatexporter</id>
|
<id>discordchatexporter</id>
|
||||||
<title>DiscordChatExporter</title>
|
<title>DiscordChatExporter</title>
|
||||||
<version>2.12</version>
|
<version>2.12.1</version>
|
||||||
<owners>Tyrrrz</owners>
|
<owners>Tyrrrz</owners>
|
||||||
<authors>Tyrrrz</authors>
|
<authors>Tyrrrz</authors>
|
||||||
<copyright>Copyright (C) Alexey Golub</copyright>
|
<copyright>Copyright (C) Alexey Golub</copyright>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ $installDirPath = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
|||||||
$packageArgs = @{
|
$packageArgs = @{
|
||||||
packageName = $packageName
|
packageName = $packageName
|
||||||
unzipLocation = $installDirPath
|
unzipLocation = $installDirPath
|
||||||
url = 'https://github.com/Tyrrrz/DiscordChatExporter/releases/download/2.12/DiscordChatExporter.zip'
|
url = 'https://github.com/Tyrrrz/DiscordChatExporter/releases/download/2.12.1/DiscordChatExporter.zip'
|
||||||
}
|
}
|
||||||
Install-ChocolateyZipPackage @packageArgs
|
Install-ChocolateyZipPackage @packageArgs
|
||||||
|
|
||||||
@@ -19,6 +19,6 @@ New-Item (Join-Path $installDirPath "DiscordChatExporter.exe.gui") -ItemType Fil
|
|||||||
$packageArgs = @{
|
$packageArgs = @{
|
||||||
packageName = $packageName
|
packageName = $packageName
|
||||||
unzipLocation = $installDirPath
|
unzipLocation = $installDirPath
|
||||||
url = 'https://github.com/Tyrrrz/DiscordChatExporter/releases/download/2.12/DiscordChatExporter.CLI.zip'
|
url = 'https://github.com/Tyrrrz/DiscordChatExporter/releases/download/2.12.1/DiscordChatExporter.CLI.zip'
|
||||||
}
|
}
|
||||||
Install-ChocolateyZipPackage @packageArgs
|
Install-ChocolateyZipPackage @packageArgs
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>net46;netcoreapp2.1</TargetFrameworks>
|
<TargetFrameworks>net46;netcoreapp2.1</TargetFrameworks>
|
||||||
<Version>2.12</Version>
|
<Version>2.12.1</Version>
|
||||||
<Company>Tyrrrz</Company>
|
<Company>Tyrrrz</Company>
|
||||||
<Copyright>Copyright (c) Alexey Golub</Copyright>
|
<Copyright>Copyright (c) Alexey Golub</Copyright>
|
||||||
<ApplicationIcon>..\favicon.ico</ApplicationIcon>
|
<ApplicationIcon>..\favicon.ico</ApplicationIcon>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommandLineParser" Version="2.3.0" />
|
<PackageReference Include="CommandLineParser" Version="2.3.0" />
|
||||||
<PackageReference Include="Stylet" Version="1.1.22" />
|
<PackageReference Include="Stylet" Version="1.1.22" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.0" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace DiscordChatExporter.Cli.Verbs
|
|||||||
var exportService = Container.Instance.Get<ExportService>();
|
var exportService = Container.Instance.Get<ExportService>();
|
||||||
|
|
||||||
// Configure settings
|
// Configure settings
|
||||||
if (!Options.DateFormat.EmptyIfNull().IsWhiteSpace())
|
if (!Options.DateFormat.IsNullOrWhiteSpace())
|
||||||
settingsService.DateFormat = Options.DateFormat;
|
settingsService.DateFormat = Options.DateFormat;
|
||||||
|
|
||||||
// Track progress
|
// Track progress
|
||||||
@@ -37,7 +37,7 @@ namespace DiscordChatExporter.Cli.Verbs
|
|||||||
|
|
||||||
// Generate file path if not set or is a directory
|
// Generate file path if not set or is a directory
|
||||||
var filePath = Options.OutputPath;
|
var filePath = Options.OutputPath;
|
||||||
if (filePath.EmptyIfNull().IsWhiteSpace() || ExportHelper.IsDirectoryPath(filePath))
|
if (filePath.IsNullOrWhiteSpace() || ExportHelper.IsDirectoryPath(filePath))
|
||||||
{
|
{
|
||||||
// Generate default file name
|
// Generate default file name
|
||||||
var fileName = ExportHelper.GetDefaultExportFileName(Options.ExportFormat, chatLog.Guild,
|
var fileName = ExportHelper.GetDefaultExportFileName(Options.ExportFormat, chatLog.Guild,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace DiscordChatExporter.Cli.Verbs
|
|||||||
var exportService = Container.Instance.Get<ExportService>();
|
var exportService = Container.Instance.Get<ExportService>();
|
||||||
|
|
||||||
// Configure settings
|
// Configure settings
|
||||||
if (!Options.DateFormat.EmptyIfNull().IsWhiteSpace())
|
if (!Options.DateFormat.IsNullOrWhiteSpace())
|
||||||
settingsService.DateFormat = Options.DateFormat;
|
settingsService.DateFormat = Options.DateFormat;
|
||||||
|
|
||||||
// Get channels
|
// Get channels
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace DiscordChatExporter.Cli.Verbs
|
|||||||
var exportService = Container.Instance.Get<ExportService>();
|
var exportService = Container.Instance.Get<ExportService>();
|
||||||
|
|
||||||
// Configure settings
|
// Configure settings
|
||||||
if (!Options.DateFormat.EmptyIfNull().IsWhiteSpace())
|
if (!Options.DateFormat.IsNullOrWhiteSpace())
|
||||||
settingsService.DateFormat = Options.DateFormat;
|
settingsService.DateFormat = Options.DateFormat;
|
||||||
|
|
||||||
// Get channels
|
// Get channels
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.0" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -113,7 +113,7 @@ namespace DiscordChatExporter.Core.Markdown
|
|||||||
// Capture <:lul:123456> or <a:lul:123456>
|
// Capture <:lul:123456> or <a:lul:123456>
|
||||||
private static readonly IMatcher<Node> CustomEmojiNodeMatcher = new RegexMatcher<Node>(
|
private static readonly IMatcher<Node> CustomEmojiNodeMatcher = new RegexMatcher<Node>(
|
||||||
new Regex("<(a)?:(.+?):(\\d+?)>", DefaultRegexOptions),
|
new Regex("<(a)?:(.+?):(\\d+?)>", DefaultRegexOptions),
|
||||||
m => new EmojiNode(m.Value, m.Groups[3].Value, m.Groups[2].Value, !m.Groups[1].Value.IsEmpty()));
|
m => new EmojiNode(m.Value, m.Groups[3].Value, m.Groups[2].Value, !m.Groups[1].Value.IsNullOrWhiteSpace()));
|
||||||
|
|
||||||
/* Links */
|
/* Links */
|
||||||
|
|
||||||
@@ -140,6 +140,12 @@ namespace DiscordChatExporter.Core.Markdown
|
|||||||
@"¯\_(ツ)_/¯",
|
@"¯\_(ツ)_/¯",
|
||||||
s => new TextNode(s));
|
s => new TextNode(s));
|
||||||
|
|
||||||
|
// Capture some specific emojis that don't get rendered
|
||||||
|
// This escapes it from matching for emoji
|
||||||
|
private static readonly IMatcher<Node> IgnoredEmojiTextNodeMatcher = new RegexMatcher<Node>(
|
||||||
|
new Regex("(\\u26A7|\\u2640|\\u2642|\\u2695|\\u267E|\\u00A9|\\u00AE|\\u2122)", DefaultRegexOptions),
|
||||||
|
m => new TextNode(m.Value, m.Groups[1].Value));
|
||||||
|
|
||||||
// Capture any "symbol/other" character or surrogate pair preceeded by a backslash
|
// Capture any "symbol/other" character or surrogate pair preceeded by a backslash
|
||||||
// This escapes it from matching for emoji
|
// This escapes it from matching for emoji
|
||||||
private static readonly IMatcher<Node> EscapedSymbolTextNodeMatcher = new RegexMatcher<Node>(
|
private static readonly IMatcher<Node> EscapedSymbolTextNodeMatcher = new RegexMatcher<Node>(
|
||||||
@@ -155,6 +161,13 @@ namespace DiscordChatExporter.Core.Markdown
|
|||||||
// Combine all matchers into one
|
// Combine all matchers into one
|
||||||
// Matchers that have similar patterns are ordered from most specific to least specific
|
// Matchers that have similar patterns are ordered from most specific to least specific
|
||||||
private static readonly IMatcher<Node> AggregateNodeMatcher = new AggregateMatcher<Node>(
|
private static readonly IMatcher<Node> AggregateNodeMatcher = new AggregateMatcher<Node>(
|
||||||
|
// Escaped text
|
||||||
|
ShrugTextNodeMatcher,
|
||||||
|
IgnoredEmojiTextNodeMatcher,
|
||||||
|
EscapedSymbolTextNodeMatcher,
|
||||||
|
EscapedCharacterTextNodeMatcher,
|
||||||
|
|
||||||
|
// Formatting
|
||||||
ItalicBoldFormattedNodeMatcher,
|
ItalicBoldFormattedNodeMatcher,
|
||||||
ItalicUnderlineFormattedNodeMatcher,
|
ItalicUnderlineFormattedNodeMatcher,
|
||||||
BoldFormattedNodeMatcher,
|
BoldFormattedNodeMatcher,
|
||||||
@@ -163,21 +176,26 @@ namespace DiscordChatExporter.Core.Markdown
|
|||||||
ItalicAltFormattedNodeMatcher,
|
ItalicAltFormattedNodeMatcher,
|
||||||
StrikethroughFormattedNodeMatcher,
|
StrikethroughFormattedNodeMatcher,
|
||||||
SpoilerFormattedNodeMatcher,
|
SpoilerFormattedNodeMatcher,
|
||||||
|
|
||||||
|
// Code blocks
|
||||||
MultilineCodeBlockNodeMatcher,
|
MultilineCodeBlockNodeMatcher,
|
||||||
InlineCodeBlockNodeMatcher,
|
InlineCodeBlockNodeMatcher,
|
||||||
|
|
||||||
|
// Mentions
|
||||||
EveryoneMentionNodeMatcher,
|
EveryoneMentionNodeMatcher,
|
||||||
HereMentionNodeMatcher,
|
HereMentionNodeMatcher,
|
||||||
UserMentionNodeMatcher,
|
UserMentionNodeMatcher,
|
||||||
ChannelMentionNodeMatcher,
|
ChannelMentionNodeMatcher,
|
||||||
RoleMentionNodeMatcher,
|
RoleMentionNodeMatcher,
|
||||||
StandardEmojiNodeMatcher,
|
|
||||||
CustomEmojiNodeMatcher,
|
// Links
|
||||||
TitledLinkNodeMatcher,
|
TitledLinkNodeMatcher,
|
||||||
AutoLinkNodeMatcher,
|
AutoLinkNodeMatcher,
|
||||||
HiddenLinkNodeMatcher,
|
HiddenLinkNodeMatcher,
|
||||||
ShrugTextNodeMatcher,
|
|
||||||
EscapedSymbolTextNodeMatcher,
|
// Emoji
|
||||||
EscapedCharacterTextNodeMatcher);
|
StandardEmojiNodeMatcher,
|
||||||
|
CustomEmojiNodeMatcher);
|
||||||
|
|
||||||
private static IReadOnlyList<Node> Parse(string input, IMatcher<Node> matcher) =>
|
private static IReadOnlyList<Node> Parse(string input, IMatcher<Node> matcher) =>
|
||||||
matcher.MatchAll(input, s => new TextNode(s)).Select(r => r.Value).ToArray();
|
matcher.MatchAll(input, s => new TextNode(s)).Select(r => r.Value).ToArray();
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace DiscordChatExporter.Core.Markdown.Nodes
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Markdown.Nodes
|
||||||
{
|
{
|
||||||
public class EmojiNode : Node
|
public class EmojiNode : Node
|
||||||
{
|
{
|
||||||
@@ -8,7 +10,7 @@
|
|||||||
|
|
||||||
public bool IsAnimated { get; }
|
public bool IsAnimated { get; }
|
||||||
|
|
||||||
public bool IsCustomEmoji => Id != null;
|
public bool IsCustomEmoji => !Id.IsNullOrWhiteSpace();
|
||||||
|
|
||||||
public EmojiNode(string source, string id, string name, bool isAnimated)
|
public EmojiNode(string source, string id, string name, bool isAnimated)
|
||||||
: base(source)
|
: base(source)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.0" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -40,7 +40,7 @@ namespace DiscordChatExporter.Core.Models
|
|||||||
public static string GetImageUrl(string id, string name, bool isAnimated)
|
public static string GetImageUrl(string id, string name, bool isAnimated)
|
||||||
{
|
{
|
||||||
// Custom emoji
|
// Custom emoji
|
||||||
if (id != null)
|
if (!id.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
// Animated
|
// Animated
|
||||||
if (isAnimated)
|
if (isAnimated)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace DiscordChatExporter.Core.Models
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
{
|
{
|
||||||
// https://discordapp.com/developers/docs/resources/guild#guild-object
|
// https://discordapp.com/developers/docs/resources/guild#guild-object
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@
|
|||||||
{
|
{
|
||||||
public static string GetIconUrl(string id, string iconHash)
|
public static string GetIconUrl(string id, string iconHash)
|
||||||
{
|
{
|
||||||
return iconHash != null
|
return !iconHash.IsNullOrWhiteSpace()
|
||||||
? $"https://cdn.discordapp.com/icons/{id}/{iconHash}.png"
|
? $"https://cdn.discordapp.com/icons/{id}/{iconHash}.png"
|
||||||
: "https://cdn.discordapp.com/embed/avatars/0.png";
|
: "https://cdn.discordapp.com/embed/avatars/0.png";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Core.Models
|
namespace DiscordChatExporter.Core.Models
|
||||||
{
|
{
|
||||||
@@ -39,7 +40,7 @@ namespace DiscordChatExporter.Core.Models
|
|||||||
public static string GetAvatarUrl(string id, int discriminator, string avatarHash)
|
public static string GetAvatarUrl(string id, int discriminator, string avatarHash)
|
||||||
{
|
{
|
||||||
// Custom avatar
|
// Custom avatar
|
||||||
if (avatarHash != null)
|
if (!avatarHash.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
// Animated
|
// Animated
|
||||||
if (avatarHash.StartsWith("a_", StringComparison.Ordinal))
|
if (avatarHash.StartsWith("a_", StringComparison.Ordinal))
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace DiscordChatExporter.Core.Rendering
|
|||||||
return true;
|
return true;
|
||||||
}).Select(g => new MessageGroup(g.First().Author, g.First().Timestamp, g));
|
}).Select(g => new MessageGroup(g.First().Author, g.First().Timestamp, g));
|
||||||
|
|
||||||
private string FormatMarkdown(Node node, bool isTopLevel, bool isSingle)
|
private string FormatMarkdown(Node node, bool isJumbo)
|
||||||
{
|
{
|
||||||
// Text node
|
// Text node
|
||||||
if (node is TextNode textNode)
|
if (node is TextNode textNode)
|
||||||
@@ -92,7 +92,7 @@ namespace DiscordChatExporter.Core.Rendering
|
|||||||
if (node is MultilineCodeBlockNode multilineCodeBlockNode)
|
if (node is MultilineCodeBlockNode multilineCodeBlockNode)
|
||||||
{
|
{
|
||||||
// Set language class for syntax highlighting
|
// Set language class for syntax highlighting
|
||||||
var languageCssClass = multilineCodeBlockNode.Language != null
|
var languageCssClass = !multilineCodeBlockNode.Language.IsNullOrWhiteSpace()
|
||||||
? "language-" + multilineCodeBlockNode.Language
|
? "language-" + multilineCodeBlockNode.Language
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
@@ -136,8 +136,8 @@ namespace DiscordChatExporter.Core.Rendering
|
|||||||
// Get emoji image URL
|
// Get emoji image URL
|
||||||
var emojiImageUrl = Emoji.GetImageUrl(emojiNode.Id, emojiNode.Name, emojiNode.IsAnimated);
|
var emojiImageUrl = Emoji.GetImageUrl(emojiNode.Id, emojiNode.Name, emojiNode.IsAnimated);
|
||||||
|
|
||||||
// Emoji can be jumboable if it's the only top-level node
|
// Make emoji large if it's jumbo
|
||||||
var jumboableCssClass = isTopLevel && isSingle ? "emoji--large" : null;
|
var jumboableCssClass = isJumbo ? "emoji--large" : null;
|
||||||
|
|
||||||
return $"<img class=\"emoji {jumboableCssClass}\" alt=\"{emojiNode.Name}\" title=\"{emojiNode.Name}\" src=\"{emojiImageUrl}\" />";
|
return $"<img class=\"emoji {jumboableCssClass}\" alt=\"{emojiNode.Name}\" title=\"{emojiNode.Name}\" src=\"{emojiImageUrl}\" />";
|
||||||
}
|
}
|
||||||
@@ -154,8 +154,10 @@ namespace DiscordChatExporter.Core.Rendering
|
|||||||
|
|
||||||
private string FormatMarkdown(IReadOnlyList<Node> nodes, bool isTopLevel)
|
private string FormatMarkdown(IReadOnlyList<Node> nodes, bool isTopLevel)
|
||||||
{
|
{
|
||||||
var isSingle = nodes.Count == 1;
|
// Emojis are jumbo if all top-level nodes are emoji nodes, disregarding whitespace
|
||||||
return nodes.Select(n => FormatMarkdown(n, isTopLevel, isSingle)).JoinToString("");
|
var isJumbo = isTopLevel && nodes.Where(n => !n.Source.IsNullOrWhiteSpace()).All(n => n is EmojiNode);
|
||||||
|
|
||||||
|
return nodes.Select(n => FormatMarkdown(n, isJumbo)).JoinToString("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FormatMarkdown(string markdown) => FormatMarkdown(MarkdownParser.Parse(markdown), true);
|
private string FormatMarkdown(string markdown) => FormatMarkdown(MarkdownParser.Parse(markdown), true);
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ namespace DiscordChatExporter.Core.Services
|
|||||||
var guildId = json["guild_id"]?.Value<string>();
|
var guildId = json["guild_id"]?.Value<string>();
|
||||||
|
|
||||||
// If the guild ID is blank, it's direct messages
|
// If the guild ID is blank, it's direct messages
|
||||||
if (guildId == null)
|
if (guildId.IsNullOrWhiteSpace())
|
||||||
guildId = Guild.DirectMessages.Id;
|
guildId = Guild.DirectMessages.Id;
|
||||||
|
|
||||||
// Try to extract name
|
// Try to extract name
|
||||||
var name = json["name"]?.Value<string>();
|
var name = json["name"]?.Value<string>();
|
||||||
|
|
||||||
// If the name is blank, it's direct messages
|
// If the name is blank, it's direct messages
|
||||||
if (name == null)
|
if (name.IsNullOrWhiteSpace())
|
||||||
name = json["recipients"].Select(ParseUser).Select(u => u.Name).JoinToString(", ");
|
name = json["recipients"].Select(ParseUser).Select(u => u.Name).JoinToString(", ");
|
||||||
|
|
||||||
return new Channel(id, parentId, guildId, name, topic, type);
|
return new Channel(id, parentId, guildId, name, topic, type);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace DiscordChatExporter.Core.Services
|
|||||||
var value = parameter.SubstringAfter("=");
|
var value = parameter.SubstringAfter("=");
|
||||||
|
|
||||||
// Skip empty values
|
// Skip empty values
|
||||||
if (value.IsEmpty())
|
if (value.IsNullOrWhiteSpace())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
request.RequestUri = request.RequestUri.SetQueryParameter(key, value);
|
request.RequestUri = request.RequestUri.SetQueryParameter(key, value);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<PackageReference Include="Failsafe" Version="1.1.0" />
|
<PackageReference Include="Failsafe" Version="1.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||||
<PackageReference Include="Onova" Version="2.4.2" />
|
<PackageReference Include="Onova" Version="2.4.2" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.0" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.1" />
|
||||||
<PackageReference Include="Tyrrrz.Settings" Version="1.3.4" />
|
<PackageReference Include="Tyrrrz.Settings" Version="1.3.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace DiscordChatExporter.Core.Services
|
|||||||
{
|
{
|
||||||
// Create output directory
|
// Create output directory
|
||||||
var dirPath = Path.GetDirectoryName(filePath);
|
var dirPath = Path.GetDirectoryName(filePath);
|
||||||
if (!dirPath.EmptyIfNull().IsWhiteSpace())
|
if (!dirPath.IsNullOrWhiteSpace())
|
||||||
Directory.CreateDirectory(dirPath);
|
Directory.CreateDirectory(dirPath);
|
||||||
|
|
||||||
// Render chat log to output file
|
// Render chat log to output file
|
||||||
@@ -74,7 +74,7 @@ namespace DiscordChatExporter.Core.Services
|
|||||||
var partitionFilePath = $"{fileNameWithoutExt} [{partitionNumber} of {partitions.Length}]{fileExt}";
|
var partitionFilePath = $"{fileNameWithoutExt} [{partitionNumber} of {partitions.Length}]{fileExt}";
|
||||||
|
|
||||||
// Compose full file path
|
// Compose full file path
|
||||||
if (!dirPath.EmptyIfNull().IsWhiteSpace())
|
if (!dirPath.IsNullOrWhiteSpace())
|
||||||
partitionFilePath = Path.Combine(dirPath, partitionFilePath);
|
partitionFilePath = Path.Combine(dirPath, partitionFilePath);
|
||||||
|
|
||||||
// Export
|
// Export
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using DiscordChatExporter.Core.Models;
|
using DiscordChatExporter.Core.Models;
|
||||||
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Core.Services.Helpers
|
namespace DiscordChatExporter.Core.Services.Helpers
|
||||||
{
|
{
|
||||||
@@ -11,7 +12,7 @@ namespace DiscordChatExporter.Core.Services.Helpers
|
|||||||
public static bool IsDirectoryPath(string path) =>
|
public static bool IsDirectoryPath(string path) =>
|
||||||
path.Last() == Path.DirectorySeparatorChar ||
|
path.Last() == Path.DirectorySeparatorChar ||
|
||||||
path.Last() == Path.AltDirectorySeparatorChar ||
|
path.Last() == Path.AltDirectorySeparatorChar ||
|
||||||
Path.GetExtension(path) == null;
|
(Path.GetExtension(path).IsNullOrWhiteSpace() && !File.Exists(path));
|
||||||
|
|
||||||
public static string GetDefaultExportFileName(ExportFormat format, Guild guild, Channel channel,
|
public static string GetDefaultExportFileName(ExportFormat format, Guild guild, Channel channel,
|
||||||
DateTimeOffset? after = null, DateTimeOffset? before = null)
|
DateTimeOffset? after = null, DateTimeOffset? before = null)
|
||||||
|
|||||||
@@ -148,7 +148,7 @@
|
|||||||
<Version>2.0.20525</Version>
|
<Version>2.0.20525</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Tyrrrz.Extensions">
|
<PackageReference Include="Tyrrrz.Extensions">
|
||||||
<Version>1.6.0</Version>
|
<Version>1.6.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
[assembly: AssemblyTitle("DiscordChatExporter")]
|
[assembly: AssemblyTitle("DiscordChatExporter")]
|
||||||
[assembly: AssemblyCompany("Tyrrrz")]
|
[assembly: AssemblyCompany("Tyrrrz")]
|
||||||
[assembly: AssemblyCopyright("Copyright (c) Alexey Golub")]
|
[assembly: AssemblyCopyright("Copyright (c) Alexey Golub")]
|
||||||
[assembly: AssemblyVersion("2.12")]
|
[assembly: AssemblyVersion("2.12.1")]
|
||||||
[assembly: AssemblyFileVersion("2.12")]
|
[assembly: AssemblyFileVersion("2.12.1")]
|
||||||
@@ -6,6 +6,7 @@ using DiscordChatExporter.Core.Services;
|
|||||||
using DiscordChatExporter.Core.Services.Helpers;
|
using DiscordChatExporter.Core.Services.Helpers;
|
||||||
using DiscordChatExporter.Gui.ViewModels.Components;
|
using DiscordChatExporter.Gui.ViewModels.Components;
|
||||||
using DiscordChatExporter.Gui.ViewModels.Framework;
|
using DiscordChatExporter.Gui.ViewModels.Framework;
|
||||||
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
namespace DiscordChatExporter.Gui.ViewModels.Dialogs
|
namespace DiscordChatExporter.Gui.ViewModels.Dialogs
|
||||||
{
|
{
|
||||||
@@ -84,7 +85,7 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If canceled - return
|
// If canceled - return
|
||||||
if (OutputPath == null)
|
if (OutputPath.IsNullOrWhiteSpace())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Close dialog
|
// Close dialog
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace DiscordChatExporter.Gui.ViewModels
|
|||||||
await _dialogManager.ShowDialogAsync(dialog);
|
await _dialogManager.ShowDialogAsync(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanPopulateGuildsAndChannels => !IsBusy && !TokenValue.EmptyIfNull().IsWhiteSpace();
|
public bool CanPopulateGuildsAndChannels => !IsBusy && !TokenValue.IsNullOrWhiteSpace();
|
||||||
|
|
||||||
public async void PopulateGuildsAndChannels()
|
public async void PopulateGuildsAndChannels()
|
||||||
{
|
{
|
||||||
@@ -235,7 +235,7 @@ namespace DiscordChatExporter.Gui.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanExportChannels => !IsBusy && SelectedChannels.EmptyIfNull().Any();
|
public bool CanExportChannels => !IsBusy && !SelectedChannels.IsNullOrEmpty();
|
||||||
|
|
||||||
public async void ExportChannels()
|
public async void ExportChannels()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user