diff --git a/DiscordChatExporter.Core/Discord/Data/Emoji.cs b/DiscordChatExporter.Core/Discord/Data/Emoji.cs
index 64bcbe6b..d3a6b81c 100644
--- a/DiscordChatExporter.Core/Discord/Data/Emoji.cs
+++ b/DiscordChatExporter.Core/Discord/Data/Emoji.cs
@@ -10,14 +10,14 @@ namespace DiscordChatExporter.Core.Discord.Data;
// https://discord.com/developers/docs/resources/emoji#emoji-object
public partial record Emoji(
// Only present on custom emoji
- string? Id,
+ Snowflake? Id,
// Name of custom emoji (e.g. LUL) or actual representation of standard emoji (e.g. 🙂)
string Name,
bool IsAnimated,
string ImageUrl)
{
// Name of custom emoji (e.g. LUL) or name of standard emoji (e.g. slight_smile)
- public string Code => !string.IsNullOrWhiteSpace(Id)
+ public string Code => Id is not null
? Name
: EmojiIndex.TryGetCode(Name) ?? Name;
}
@@ -32,18 +32,18 @@ public partial record Emoji
.Select(r => r.Value.ToString("x"))
);
- private static string GetImageUrl(string id, bool isAnimated) => isAnimated
+ private static string GetImageUrl(Snowflake id, bool isAnimated) => isAnimated
? $"https://cdn.discordapp.com/emojis/{id}.gif"
: $"https://cdn.discordapp.com/emojis/{id}.png";
private static string GetImageUrl(string name) =>
$"https://twemoji.maxcdn.com/2/svg/{GetTwemojiName(name)}.svg";
- public static string GetImageUrl(string? id, string? name, bool isAnimated)
+ public static string GetImageUrl(Snowflake? id, string? name, bool isAnimated)
{
// Custom emoji
- if (!string.IsNullOrWhiteSpace(id))
- return GetImageUrl(id, isAnimated);
+ if (id is not null)
+ return GetImageUrl(id.Value, isAnimated);
// Standard emoji
if (!string.IsNullOrWhiteSpace(name))
@@ -55,7 +55,7 @@ public partial record Emoji
public static Emoji Parse(JsonElement json)
{
- var id = json.GetPropertyOrNull("id")?.GetNonWhiteSpaceStringOrNull();
+ var id = json.GetPropertyOrNull("id")?.GetNonWhiteSpaceStringOrNull()?.Pipe(Snowflake.Parse);
var name = json.GetPropertyOrNull("name")?.GetNonWhiteSpaceStringOrNull();
var isAnimated = json.GetPropertyOrNull("animated")?.GetBooleanOrNull() ?? false;
diff --git a/DiscordChatExporter.Core/Exporting/Writers/JsonMessageWriter.cs b/DiscordChatExporter.Core/Exporting/Writers/JsonMessageWriter.cs
index 69aff4f6..9d68d76a 100644
--- a/DiscordChatExporter.Core/Exporting/Writers/JsonMessageWriter.cs
+++ b/DiscordChatExporter.Core/Exporting/Writers/JsonMessageWriter.cs
@@ -169,7 +169,7 @@ internal class JsonMessageWriter : MessageWriter
// Emoji
_writer.WriteStartObject("emoji");
- _writer.WriteString("id", reaction.Emoji.Id);
+ _writer.WriteString("id", reaction.Emoji.Id.ToString());
_writer.WriteString("name", reaction.Emoji.Name);
_writer.WriteBoolean("isAnimated", reaction.Emoji.IsAnimated);
_writer.WriteString("imageUrl", await Context.ResolveMediaUrlAsync(reaction.Emoji.ImageUrl, cancellationToken));
diff --git a/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/HtmlMarkdownVisitor.cs b/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/HtmlMarkdownVisitor.cs
index 20db27c0..634f2316 100644
--- a/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/HtmlMarkdownVisitor.cs
+++ b/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/HtmlMarkdownVisitor.cs
@@ -3,7 +3,6 @@ using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
-using DiscordChatExporter.Core.Discord;
using DiscordChatExporter.Core.Discord.Data;
using DiscordChatExporter.Core.Markdown;
using DiscordChatExporter.Core.Markdown.Parsing;
@@ -108,17 +107,16 @@ internal partial class HtmlMarkdownVisitor : MarkdownVisitor
protected override MarkdownNode VisitMention(MentionNode mention)
{
- var mentionId = Snowflake.TryParse(mention.Id);
if (mention.Kind == MentionKind.Meta)
{
_buffer
.Append("")
- .Append("@").Append(HtmlEncode(mention.Id))
+ .Append("@").Append(HtmlEncode(mention.Id.ToString()))
.Append("");
}
else if (mention.Kind == MentionKind.User)
{
- var member = mentionId?.Pipe(_context.TryGetMember);
+ var member = _context.TryGetMember(mention.Id);
var fullName = member?.User.FullName ?? "Unknown";
var nick = member?.Nick ?? "Unknown";
@@ -129,7 +127,7 @@ internal partial class HtmlMarkdownVisitor : MarkdownVisitor
}
else if (mention.Kind == MentionKind.Channel)
{
- var channel = mentionId?.Pipe(_context.TryGetChannel);
+ var channel = _context.TryGetChannel(mention.Id);
var symbol = channel?.IsVoiceChannel == true ? "🔊" : "#";
var name = channel?.Name ?? "deleted-channel";
@@ -140,7 +138,7 @@ internal partial class HtmlMarkdownVisitor : MarkdownVisitor
}
else if (mention.Kind == MentionKind.Role)
{
- var role = mentionId?.Pipe(_context.TryGetRole);
+ var role = _context.TryGetRole(mention.Id);
var name = role?.Name ?? "deleted-role";
var color = role?.Color;
diff --git a/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/PlainTextMarkdownVisitor.cs b/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/PlainTextMarkdownVisitor.cs
index 1c3f614d..a44a08ee 100644
--- a/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/PlainTextMarkdownVisitor.cs
+++ b/DiscordChatExporter.Core/Exporting/Writers/MarkdownVisitors/PlainTextMarkdownVisitor.cs
@@ -1,8 +1,6 @@
using System.Text;
-using DiscordChatExporter.Core.Discord;
using DiscordChatExporter.Core.Markdown;
using DiscordChatExporter.Core.Markdown.Parsing;
-using DiscordChatExporter.Core.Utils.Extensions;
namespace DiscordChatExporter.Core.Exporting.Writers.MarkdownVisitors;
@@ -36,21 +34,20 @@ internal partial class PlainTextMarkdownVisitor : MarkdownVisitor
protected override MarkdownNode VisitMention(MentionNode mention)
{
- var mentionId = Snowflake.TryParse(mention.Id);
if (mention.Kind == MentionKind.Meta)
{
_buffer.Append($"@{mention.Id}");
}
else if (mention.Kind == MentionKind.User)
{
- var member = mentionId?.Pipe(_context.TryGetMember);
+ var member = _context.TryGetMember(mention.Id);
var name = member?.User.Name ?? "Unknown";
_buffer.Append($"@{name}");
}
else if (mention.Kind == MentionKind.Channel)
{
- var channel = mentionId?.Pipe(_context.TryGetChannel);
+ var channel = _context.TryGetChannel(mention.Id);
var name = channel?.Name ?? "deleted-channel";
_buffer.Append($"#{name}");
@@ -61,7 +58,7 @@ internal partial class PlainTextMarkdownVisitor : MarkdownVisitor
}
else if (mention.Kind == MentionKind.Role)
{
- var role = mentionId?.Pipe(_context.TryGetRole);
+ var role = _context.TryGetRole(mention.Id);
var name = role?.Name ?? "deleted-role";
_buffer.Append($"@{name}");
diff --git a/DiscordChatExporter.Core/Markdown/EmojiNode.cs b/DiscordChatExporter.Core/Markdown/EmojiNode.cs
index 22242d13..b998e88a 100644
--- a/DiscordChatExporter.Core/Markdown/EmojiNode.cs
+++ b/DiscordChatExporter.Core/Markdown/EmojiNode.cs
@@ -1,21 +1,22 @@
-using DiscordChatExporter.Core.Utils;
+using DiscordChatExporter.Core.Discord;
+using DiscordChatExporter.Core.Utils;
namespace DiscordChatExporter.Core.Markdown;
internal record EmojiNode(
// Only present on custom emoji
- string? Id,
+ Snowflake? Id,
// Name of custom emoji (e.g. LUL) or actual representation of standard emoji (e.g. 🙂)
string Name,
bool IsAnimated) : MarkdownNode
{
+ public bool IsCustomEmoji => Id is not null;
+
// Name of custom emoji (e.g. LUL) or name of standard emoji (e.g. slight_smile)
- public string Code => !string.IsNullOrWhiteSpace(Id)
+ public string Code => IsCustomEmoji
? Name
: EmojiIndex.TryGetCode(Name) ?? Name;
- public bool IsCustomEmoji => !string.IsNullOrWhiteSpace(Id);
-
public EmojiNode(string name)
: this(null, name, false)
{
diff --git a/DiscordChatExporter.Core/Markdown/MentionNode.cs b/DiscordChatExporter.Core/Markdown/MentionNode.cs
index 748f7f0d..cc6458e1 100644
--- a/DiscordChatExporter.Core/Markdown/MentionNode.cs
+++ b/DiscordChatExporter.Core/Markdown/MentionNode.cs
@@ -1,3 +1,5 @@
-namespace DiscordChatExporter.Core.Markdown;
+using DiscordChatExporter.Core.Discord;
-internal record MentionNode(string Id, MentionKind Kind) : MarkdownNode;
\ No newline at end of file
+namespace DiscordChatExporter.Core.Markdown;
+
+internal record MentionNode(Snowflake Id, MentionKind Kind) : MarkdownNode;
\ No newline at end of file
diff --git a/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs b/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs
index 906bfac6..2229402b 100644
--- a/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs
+++ b/DiscordChatExporter.Core/Markdown/Parsing/MarkdownParser.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
+using DiscordChatExporter.Core.Discord;
using DiscordChatExporter.Core.Utils;
namespace DiscordChatExporter.Core.Markdown.Parsing;
@@ -123,31 +124,31 @@ internal static partial class MarkdownParser
// Capture @everyone
private static readonly IMatcher EveryoneMentionNodeMatcher = new StringMatcher(
"@everyone",
- _ => new MentionNode("everyone", MentionKind.Meta)
+ _ => new MentionNode(Snowflake.Zero, MentionKind.Meta)
);
// Capture @here
private static readonly IMatcher HereMentionNodeMatcher = new StringMatcher(
"@here",
- _ => new MentionNode("here", MentionKind.Meta)
+ _ => new MentionNode(Snowflake.Zero, MentionKind.Meta)
);
// Capture <@123456> or <@!123456>
private static readonly IMatcher UserMentionNodeMatcher = new RegexMatcher(
new Regex("<@!?(\\d+)>", DefaultRegexOptions),
- (_, m) => new MentionNode(m.Groups[1].Value, MentionKind.User)
+ (_, m) => new MentionNode(Snowflake.Parse(m.Groups[1].Value), MentionKind.User)
);
// Capture <#123456>
private static readonly IMatcher ChannelMentionNodeMatcher = new RegexMatcher(
new Regex("<#!?(\\d+)>", DefaultRegexOptions),
- (_, m) => new MentionNode(m.Groups[1].Value, MentionKind.Channel)
+ (_, m) => new MentionNode(Snowflake.Parse(m.Groups[1].Value), MentionKind.Channel)
);
// Capture <@&123456>
private static readonly IMatcher RoleMentionNodeMatcher = new RegexMatcher(
new Regex("<@&(\\d+)>", DefaultRegexOptions),
- (_, m) => new MentionNode(m.Groups[1].Value, MentionKind.Role)
+ (_, m) => new MentionNode(Snowflake.Parse(m.Groups[1].Value), MentionKind.Role)
);
/* Emoji */
@@ -177,7 +178,11 @@ internal static partial class MarkdownParser
// Capture <:lul:123456> or
private static readonly IMatcher CustomEmojiNodeMatcher = new RegexMatcher(
new Regex("<(a)?:(.+?):(\\d+?)>", DefaultRegexOptions),
- (_, m) => new EmojiNode(m.Groups[3].Value, m.Groups[2].Value, !string.IsNullOrWhiteSpace(m.Groups[1].Value))
+ (_, m) => new EmojiNode(
+ Snowflake.Parse(m.Groups[3].Value),
+ m.Groups[2].Value,
+ !string.IsNullOrWhiteSpace(m.Groups[1].Value)
+ )
);
/* Links */