C# Telegram Bot Форматирование сообщений от пользователей

Рейтинг: 0Ответов: 2Опубликовано: 09.06.2023

Подскажите как рассылать сообщения от пользователей с сохранением форматирования текста. Написал такой код:

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 офсеты и длина текста сбивается.

Ответы

▲ 0

Может кому пригодится, код для форматирования текста от пользователей с разметкой. Результат: введите сюда описание изображения

Символы на которые ругается при 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;
        }
▲ 0

Есть способ полегче. Вместо ParseMode, можно передавать массив messageEntity(если передавать их оба, то приоритет отдаётся ParseMode'у), а массив MessageEntity можно достать напрямую из сообщения:

var messageEntities = message.Entities;

Если же нужно достать entities из Caption (подпись к документу, видео, фото и т.д), то они достаются так:

var captionEntities = message.CaptionEntities;