| 1 | using System.Text.RegularExpressions; |
| 2 | using Markdig; |
| 3 | |
| 4 | namespace TelegramNotifier; |
| 5 | |
| 6 | /// <summary> |
| 7 | /// Converts Markdown to Telegram-allowed HTML so that WTelegramClient's HtmlToEntities can be used. |
| 8 | /// Telegram supports only: <b>, <i>, <code>, <pre>, <a href="">, <s>, <u>, <tg-spoiler>. |
| 9 | /// </summary> |
| 10 | public static class TelegramFormatHelper |
| 11 | { |
| 12 | /// <summary> |
| 13 | /// Converts Markdown to Telegram-compatible HTML (flat tags, no nesting). |
| 14 | /// Then use Client.HtmlToEntities(ref html) and SendMessageAsync(peer, html, entities). |
| 15 | /// </summary> |
| 16 | public static string MdToTelegramHtml(string markdown) |
| 17 | { |
| 18 | if (string.IsNullOrWhiteSpace(markdown)) |
| 19 | return markdown; |
| 20 | |
| 21 | string html = Markdown.ToHtml(markdown.Trim()); |
| 22 | |
| 23 | // Telegram uses <b>/<i>, not <strong>/<em> |
| 24 | html = html.Replace("<strong>", "<b>").Replace("</strong>", "</b>"); |
| 25 | html = html.Replace("<em>", "<i>").Replace("</em>", "</i>"); |
| 26 | |
| 27 | // Headings → bold + newline (Telegram has no heading entity) |
| 28 | html = Regex.Replace(html, @"<h[1-6]\b[^>]*>(.*?)</h[1-6]>", "<b>$1</b>\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 29 | |
| 30 | // Paragraphs: strip tag, keep newlines |
| 31 | html = Regex.Replace(html, @"</p>\s*<p>", "\n\n", RegexOptions.Singleline); |
| 32 | html = Regex.Replace(html, @"<p\b[^>]*>|</p>", "\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 33 | |
| 34 | // Lists: Telegram has no list entity; leave <ul>/<li> as-is and strip to plain + newlines, or keep • in text. Strip list tags for clean entity-less text. |
| 35 | html = Regex.Replace(html, @"<ul\b[^>]*>|</ul>", "\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 36 | html = Regex.Replace(html, @"<ol\b[^>]*>|</ol>", "\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 37 | html = Regex.Replace(html, @"<li\b[^>]*>(.*?)</li>", "• $1\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 38 | |
| 39 | // Blockquote: strip or keep as text; strip tags |
| 40 | html = Regex.Replace(html, @"<blockquote\b[^>]*>|</blockquote>", "\n", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 41 | |
| 42 | // <pre><code>...</code></pre> → <pre>...</pre> (Telegram accepts pre) |
| 43 | html = Regex.Replace(html, @"<pre\b[^>]*>\s*<code[^>]*>(.*?)</code>\s*</pre>", "<pre>$1</pre>", RegexOptions.Singleline | RegexOptions.IgnoreCase); |
| 44 | |
| 45 | return html.Trim(); |
| 46 | } |
| 47 | } |
| 48 | |