/// <summary> /// Спойлеры /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <param name="mentions">Список упоминаний, сделанных в сообщении</param> /// <param name="usedEmbedsUrls">Список использованных Url'ов в embed</param> /// <returns></returns> public static string MarkSpoilers( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild, List <EventMessageCreate.EventMessageCreate_Mention> mentions, HashSet <string> usedEmbedsUrls ) { text = rSpoilerMark.Replace(text, m1 => { var subBlock = RenderMarkdownBlockAsHTMLInnerBlock( m1.Groups[1].Value, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls ); var wait = GetWaitString(); waitDictionary[wait] = string.Format( "<span class='spoiler {1}'><span class='spoiler-content'>{0}</span></span>", subBlock, (chatOption.text_spoiler == 1) ? "spoiler-show" : "" ); return(wait); }); return(text); }
/// <summary> /// Жирный наклонный текст /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <param name="mentions">Список упоминаний, сделанных в сообщении</param> /// <param name="usedEmbedsUrls">Список использованных Url'ов в embed</param> /// <returns></returns> public static string MarkBoldItalic( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild, List <EventMessageCreate.EventMessageCreate_Mention> mentions, HashSet <string> usedEmbedsUrls ) { text = rBoldItalic.Replace(text, m1 => { var subBlock = RenderMarkdownBlockAsHTMLInnerBlock( m1.Groups[1].Value, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls ); var wait = GetWaitString(); waitDictionary[wait] = string.Format("<strong><em>{0}</em></strong>", subBlock); return(wait); }); return(text); }
/// <summary> /// Упоминание в тексте целой роли с сервера /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <returns></returns> public static string MarkMentionsRole( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild ) { text = rMentionRole.Replace(text, m1 => { string roleID = m1.Groups[1].Value; // Role role = guild.roles.FirstOrDefault(t => t.id == roleID); if (role == null) { return(string.Format("<Role Unknown #{0}>", roleID)); } string nickColor = role.color.ToString("X"); nickColor = "#" + nickColor.PadLeft(6, '0'); var wait = GetWaitString(); waitDictionary[wait] = string.Format("<span class='role mention' style='color: {1};'>@{0}</span>", HttpUtility.HtmlEncode(role.name), nickColor ); return(wait); }); return(text); }
/// <summary> /// Упоминание в сообщении конкретного человека /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <param name="mentions">Список упоминаний, сделанных в сообщении</param> /// <returns></returns> public static string MarkMentionsPeople( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild, List <EventMessageCreate.EventMessageCreate_Mention> mentions ) { // Упоминание человека text = rMentionNick.Replace(text, m1 => { string mentionID = m1.Groups[1].Value; if (mentions == null) { // Приколы дискорда return(string.Format("<Пользователь Unknown #{0}>", mentionID)); } EventMessageCreate.EventMessageCreate_Mention mention = mentions.FirstOrDefault(eMention => eMention.id == mentionID); if (mention == null) { return(string.Format("<Пользователь Unknown #{0}>", mentionID)); } // Выбираем наиболее приоритетную роль var nickColor = "inherit"; if ((guild.roles != null) && (mention.member?.roles != null) && (chatOption.message_mentions_style == 1)) { var mention_roles_local = guild.roles.Where(t => mention.member.roles.Contains(t.id)).ToList(); mention_roles_local.Sort((a, b) => b.position.CompareTo(a.position)); var role = mention_roles_local.Any() ? mention_roles_local.First() : null; if (role != null) { nickColor = role.color.ToString("X"); nickColor = "#" + nickColor.PadLeft(6, '0'); } } // var wait = GetWaitString(); waitDictionary[wait] = string.Format("<span class='user mention' {1}>@{0}</span>", HttpUtility.HtmlEncode(mention.member?.nick ?? mention.username), (chatOption.message_mentions_style == 1) ? string.Format(" style='color: {0};'", nickColor) : "" ); return(wait); }); return(text); }
/// <summary> /// Emoji (картинки) /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <returns></returns> public static string MarkEmojiImages( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild ) { var thisGuildEmojis = new HashSet <string>(); foreach (var emoji in guild.emojis) { thisGuildEmojis.Add(emoji.id); } // Эмодзи внутри текста text = rEmojiWithinText.Replace(text, m1 => { string emojiID = m1.Groups[3].Value; bool isRelative = thisGuildEmojis.Contains(emojiID); int emojiShow = isRelative ? chatOption.emoji_relative : chatOption.emoji_stranger; if (emojiShow == 2) { return(":" + m1.Groups[2].Value + ":"); } var wait = GetWaitString(); var url = string.Format("https://cdn.discordapp.com/emojis/{0}.{1}", emojiID, (m1.Groups[1].Value == "a") ? "gif" : "png" ); waitDictionary[wait] = string.Format("<span class='emoji {2}'><img src='{0}' alt=':{1}:'></span>", HttpUtility.HtmlEncode(url), HttpUtility.HtmlEncode(m1.Groups[2].Value), (emojiShow == 1) ? "blur" : "" ); return(wait); }); return(text); }
/// <summary> /// Наклонный (курсивный) текст через звёздочки /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <param name="mentions">Список упоминаний, сделанных в сообщении</param> /// <param name="usedEmbedsUrls">Список использованных Url'ов в embed</param> /// <returns></returns> public static string MarkItalicViaAsterisk( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild, List <EventMessageCreate.EventMessageCreate_Mention> mentions, HashSet <string> usedEmbedsUrls ) { text = rSingleAsterisk.Replace(text, m1 => { var firstChar = m1.Groups[1].Value.Substring(0, 1); if (firstChar == " ") { return(m1.Groups[0].Value); } var lastChar = m1.Groups[1].Value.Substring(m1.Groups[1].Value.Length - 1); if (lastChar == " ") { return(m1.Groups[0].Value); } var subBlock = RenderMarkdownBlockAsHTMLInnerBlock( m1.Groups[1].Value, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls ); var wait = GetWaitString(); waitDictionary[wait] = string.Format("<em>{0}</em>", subBlock); return(wait); }); return(text); }
/// <summary> /// Обработка разметки сообщения внутри логического блока сообщения (root-сообщение, цитата, спойлер) /// </summary> /// <param name="text">Текст с сырым Markdown</param> /// <param name="chatOption">Опции чата, заданные стримером для виджета</param> /// <param name="waitDictionary">Dictionary для саб-блоков</param> /// <param name="guild">Гильдия (сервер), внутри которого написано сообщение</param> /// <param name="mentions">Список упоминаний, сделанных в сообщении</param> /// <param name="usedEmbedsUrls">Список использованных Url'ов в embed</param> /// <returns></returns> private static string RenderMarkdownBlockAsHTMLInnerBlock( string text, ChatDrawOption chatOption, Dictionary <string, string> waitDictionary, EventGuildCreate guild, List <EventMessageCreate.EventMessageCreate_Mention> mentions, HashSet <string> usedEmbedsUrls ) { while (true) { var highlights = new List <dynamic>(); foreach (var pair in new List <dynamic>() { new { regexp = rWithoutMark, deleg = (Func <string>)(() => MarkNoFormatting(text, chatOption, waitDictionary)) }, new { regexp = rLink, deleg = (Func <string>)(() => MarkLinks(text, chatOption, waitDictionary, usedEmbedsUrls)) }, new { regexp = rEmojiWithinText, deleg = (Func <string>)(() => MarkEmojiImages(text, chatOption, waitDictionary, guild)) }, // mentions new { regexp = rMentionNick, deleg = (Func <string>)(() => MarkMentionsPeople(text, chatOption, waitDictionary, guild, mentions)) }, new { regexp = rMentionRole, deleg = (Func <string>)(() => MarkMentionsRole(text, chatOption, waitDictionary, guild)) }, // simple mark new { regexp = rSpoilerMark, deleg = (Func <string>)(() => MarkSpoilers(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rBoldItalic, deleg = (Func <string>)(() => MarkBoldItalic(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rBold, deleg = (Func <string>)(() => MarkBold(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rTripleUnderscore, deleg = (Func <string>)(() => MarkUnderscoreItalic(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rDoubleUnderscore, deleg = (Func <string>)(() => MarkUnderscore(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rSingleAsterisk, deleg = (Func <string>)(() => MarkItalicViaAsterisk(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rItalicUnderscore, deleg = (Func <string>)(() => MarkItalicViaUnderscore(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, new { regexp = rDelete, deleg = (Func <string>)(() => MarkDelete(text, chatOption, waitDictionary, guild, mentions, usedEmbedsUrls)) }, }) { Regex regex = pair.regexp; var m = regex.Match(text); if (!m.Success) { continue; } highlights.Add(new { index = m.Index, pair.deleg }); if (m.Index == 0) { break; } } if (!highlights.Any()) { // Не осталось маркировки, выходим break; } highlights.Sort((a, b) => a.index.CompareTo(b.index)); var u = false; // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (var highlight in highlights) { Func <string> delegateLocal = highlight.deleg; var result = delegateLocal.Invoke(); if (result != text) { text = result; u = true; break; } } if (!u) { // hint: Это warning однозначный break; } } text = MarkEmojiUnicode(text, chatOption, waitDictionary); return(text); }