diff --git a/DiscordChatExporter.Core.Models/Emoji.cs b/DiscordChatExporter.Core.Models/Emoji.cs index 19af4e4..c49ccd9 100644 --- a/DiscordChatExporter.Core.Models/Emoji.cs +++ b/DiscordChatExporter.Core.Models/Emoji.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Text; using Tyrrrz.Extensions; namespace DiscordChatExporter.Core.Models @@ -28,14 +29,21 @@ namespace DiscordChatExporter.Core.Models public partial class Emoji { - private static IEnumerable GetCodePoints(string emoji) + private static IEnumerable GetRunes(string emoji) { - for (var i = 0; i < emoji.Length; i += char.IsHighSurrogate(emoji[i]) ? 2 : 1) - yield return char.ConvertToUtf32(emoji, i); + var lastIndex = 0; + while (lastIndex < emoji.Length && Rune.TryGetRuneAt(emoji, lastIndex, out var rune)) + { + // Skip variant selector rune + if (rune.Value != 0xfe0f) + yield return rune; + + lastIndex += rune.Utf16SequenceLength; + } } - private static string GetTwemojiName(string emoji) => - GetCodePoints(emoji).Select(i => i.ToString("x")).JoinToString("-"); + private static string GetTwemojiName(IEnumerable runes) => + runes.Select(r => r.Value.ToString("x")).JoinToString("-"); public static string GetImageUrl(string? id, string name, bool isAnimated) { @@ -50,9 +58,17 @@ namespace DiscordChatExporter.Core.Models return $"https://cdn.discordapp.com/emojis/{id}.png"; } - // Standard unicode emoji (via twemoji) - var twemojiName = GetTwemojiName(name); - return $"https://twemoji.maxcdn.com/2/72x72/{twemojiName}.png"; + // Standard unicode emoji + var emojiRunes = GetRunes(name).ToArray(); + if (emojiRunes.Any()) + { + // Get corresponding Twemoji image + var twemojiName = GetTwemojiName(emojiRunes); + return $"https://twemoji.maxcdn.com/2/72x72/{twemojiName}.png"; + } + + // Fallback in case of failure + return name; } } } \ No newline at end of file