C# Telegram Bot Форматирование сообщений от пользователей
Подскажите как рассылать сообщения от пользователей с сохранением форматирования текста. Написал такой код:
StringBuilder Formatter(StringBuilder message, MessageEntity messageEntity, bool start)
{
switch (messageEntity.Type)
{
case MessageEntityType.Bold:
return FormatterMarkDown(message, messageEntity.Offset, messageEntity.Length, "*", 2, start);
case MessageEntityType.Italic:
return FormatterMarkDown(message, messageEntity.Offset, messageEntity.Length, "_", 2, start);
case MessageEntityType.Strikethrough:
return FormatterMarkDown(message, messageEntity.Offset, messageEntity.Length, "~", 2, start);
case MessageEntityType.Underline:
return FormatterMarkDown(message, messageEntity.Offset, messageEntity.Length, "__", 4, start);
case MessageEntityType.Code:
return FormatterMarkDown(message, messageEntity.Offset, messageEntity.Length, "`", 2, start);
case MessageEntityType.Spoiler:
return FormatterMarkDown(message, messageEntity.Offset, messageEntity.Length, "||", 2, start);
}
return message;
}
StringBuilder FormatterMarkDown(StringBuilder message, int offset, int length, string symbol, int left, bool start)
{
string temp = message.ToString().Substring(offset, length);
if (!start)
offset = offset + left;
temp = temp.Insert(0, symbol) + symbol;
message = message.Remove(offset, length).Insert(offset, temp);
return message;
}
Он работает если в тексте не попадаются символы которые нужно экранировать, можно перед форматированием экранировать все символы которые не поддерживаются, но тогда у MessageEntity офсеты и длина текста сбивается.
Ответы (2 шт):
Может кому пригодится, код для форматирования текста от пользователей с разметкой.
Результат:

Символы на которые ругается при MarkDown в html отправляются более корректно, не выдаёт ошибок Код:
StringBuilder message = new StringBuilder(update.Message.Text);
if (update.Message.Entities != null)
{
var entities = update.Message.Entities.ToList().GroupBy(n => n.Offset).Select(g => g.Last()).ToList(); //Удаляем дубликаты офсетов
foreach (var res in entities.OrderByDescending(x => x.Offset)) //Сортируем по убыванию, чтобы не сбивались офсеты при форматирование
{
message = Formatter(message, res);
}
}
StringBuilder Formatter(StringBuilder message, MessageEntity messageEntity)
{
switch (messageEntity.Type)
{
case MessageEntityType.Bold:
return FormatterToHtml(message, messageEntity.Offset, messageEntity.Length, "<b>", "</b>"); // Жирный текст
case MessageEntityType.Italic:
return FormatterToHtml(message, messageEntity.Offset, messageEntity.Length, "<i>", "</i>"); //Курсив
case MessageEntityType.Strikethrough:
return FormatterToHtml(message, messageEntity.Offset, messageEntity.Length, "<s>", "</s>"); //Добавляет зачеркивание текста
case MessageEntityType.Underline:
return FormatterToHtml(message, messageEntity.Offset, messageEntity.Length, "<u>", "</u>"); //Выделяет текст подчеркиванием
case MessageEntityType.Code:
//Выделяет текст моноширинным шрифтом. Используется для выделения большого фрагмента кода с сохранением переносов и пробелов
return FormatterToHtml(message, messageEntity.Offset, messageEntity.Length, "<pre>", "</pre>");
case MessageEntityType.Spoiler:
return FormatterToHtml(message, messageEntity.Offset, messageEntity.Length, "<tg-spoiler>", "</tg-spoiler>"); // Скрытый текст
}
return message;
}
StringBuilder FormatterToHtml(StringBuilder message, int offset, int length, string symbol, string symbolEnd)
{
string temp = message.ToString().Substring(offset, length);
message = message.Remove(offset, length).Insert(offset, symbol + temp + symbolEnd);
return message;
}
Есть способ полегче. Вместо ParseMode, можно передавать массив messageEntity(если передавать их оба, то приоритет отдаётся ParseMode'у), а массив MessageEntity можно достать напрямую из сообщения:
var messageEntities = message.Entities;
Если же нужно достать entities из Caption (подпись к документу, видео, фото и т.д), то они достаются так:
var captionEntities = message.CaptionEntities;