private static string AddMessageReactionHTMLWithEmojiPack(
            NKDiscordChatWidget.DiscordBot.Classes.EventMessageCreate.EventMessageCreate_Reaction reaction,
            EmojiPackType emojiPack
            )
        {
            var longs = Utf8ToUnicode.ToUnicodeCode(reaction.emoji.name);
            var u     = longs.Any(code => !UnicodeEmojiEngine.IsInIntervalEmoji(code, emojiPack));

            if (u)
            {
                // Реакция без ID, но при этом не является эмодзи, рисуем как есть
                return(HttpUtility.HtmlEncode(reaction.emoji.name));
            }

            // Реакция без ID и является эмодзи, поэтому рисуем как картинку
            var localEmojiList = UnicodeEmojiEngine.RenderEmojiAsStringList(
                emojiPack, longs);
            var emojiHtml = "";

            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var item in localEmojiList)
            {
                if (!item.isSuccess)
                {
                    // Этого символа нет в паке, выводим как есть. Куда деваться
                    emojiHtml += HttpUtility.HtmlEncode(item.rawText);
                    continue;
                }

                // hint: localEmojiList.Count может быть больше 1 в случае сложных эмодзи типа :one:
                var emojiSubFolderName = UnicodeEmojiEngine.GetImageSubFolder(emojiPack);
                var emojiExtension     = UnicodeEmojiEngine.GetImageExtension(emojiPack);
                var url = string.Format("/images/emoji/{0}/{1}.{2}",
                                        emojiSubFolderName,
                                        item.emojiCode,
                                        emojiExtension
                                        );

                emojiHtml += string.Format("<img src='{0}' alt=':{1}:'>",
                                           HttpUtility.HtmlEncode(url),
                                           HttpUtility.HtmlEncode(reaction.emoji.name)
                                           );
            }

            return(emojiHtml);
        }
        public static string RenderEmojiStringListAsHtml(
            IEnumerable <UnicodeEmojiEngine.EmojiRenderResult> codes,
            EmojiPackType pack,
            Dictionary <string, string> waitDictionary,
            int emojiShow
            )
        {
            var text = "";
            var emojiSubFolderName = UnicodeEmojiEngine.GetImageSubFolder(pack);
            var emojiExtension     = UnicodeEmojiEngine.GetImageExtension(pack);

            foreach (var item in codes)
            {
                if (item.isSuccess)
                {
                    var wait = GetWaitString();
                    var url  = string.Format("/images/emoji/{0}/{1}.{2}",
                                             emojiSubFolderName,
                                             item.emojiCode,
                                             emojiExtension
                                             );

                    waitDictionary[wait] = string.Format(
                        "<span class='emoji unicode-emoji {0}'><img src='{1}' alt=':{2}:'></span>",
                        (emojiShow == 1) ? "blur" : "",
                        HttpUtility.HtmlEncode(url),
                        HttpUtility.HtmlEncode(item.emojiCode)
                        );

                    text += wait;
                }
                else
                {
                    text += item.rawText;
                }
            }

            return(text);
        }
        /// <summary>
        /// Парсинг эмодзи из дополнительных plain'ов в Unicode
        /// </summary>
        /// <param name="text">Текст с сырым Markdown</param>
        /// <param name="chatOption">Опции чата, заданные стримером для виджета</param>
        /// <param name="waitDictionary">Dictionary для саб-блоков</param>
        /// <returns></returns>
        public static string MarkEmojiUnicode(
            string text,
            ChatDrawOption chatOption,
            Dictionary <string, string> waitDictionary
            )
        {
            if (!UnicodeEmojiEngine.emojiList[chatOption.unicode_emoji_displaying].Any())
            {
                return(text);
            }

            var activeEmoji = new List <long>();

            var longs        = Utf8ToUnicode.ToUnicodeCode(text);
            var textAfter    = "";
            var containEmoji = false;

            foreach (var code in longs)
            {
                if (!UnicodeEmojiEngine.IsInIntervalEmoji(code, chatOption.unicode_emoji_displaying))
                {
                    // Этот символ НЕ является unicode emoji
                    if (activeEmoji.Any())
                    {
                        // У нас непустой буффер emoji символов, надо их записать в строку
                        var localEmojiList = UnicodeEmojiEngine.RenderEmojiAsStringList(
                            chatOption.unicode_emoji_displaying, activeEmoji);
                        textAfter += RenderEmojiStringListAsHtml(
                            localEmojiList,
                            chatOption.unicode_emoji_displaying,
                            waitDictionary,
                            chatOption.emoji_relative
                            );
                        activeEmoji = new List <long>();
                    }

                    textAfter += Utf8ToUnicode.UnicodeCodeToString(code);

                    continue;
                }

                // Этот символ ЯВЛЯЕТСЯ unicode emoji
                containEmoji = true;
                activeEmoji.Add(code);
            } // foreach

            if (activeEmoji.Any())
            {
                // У нас не пустой буффер emoji символов, надо их записать в строку
                var localEmojiList = UnicodeEmojiEngine.RenderEmojiAsStringList(
                    chatOption.unicode_emoji_displaying, activeEmoji);
                textAfter += RenderEmojiStringListAsHtml(
                    localEmojiList,
                    chatOption.unicode_emoji_displaying,
                    waitDictionary,
                    chatOption.emoji_relative
                    );
            }

            if (containEmoji)
            {
                text = textAfter;
            }

            return(text);
        }