экранирования перед использованием "MarkdownV2" в parse_mode

Ответить
ya
^-^
Сообщения: 2673
Зарегистрирован: 16 дек 2021, 19:56

экранирования перед использованием "MarkdownV2" в parse_mode

Сообщение ya »

экранирования перед использованием "MarkdownV2" в parse_mode
При указании параметра "MarkdownV2" в parse_mode выводит такую ошибку во время работы программы, и программа падает

Error: Bad Request: can't parse entities: Character '.' is reserved and must be escaped with the preceding '\'
В MarkdownV2 необходимо экранировать все специальные символы, чтобы избежать ошибок парсинга.

Какие символы нужно экранировать в MarkdownV2?
Список зарезервированных символов:

Код: Выделить всё

_ * [ ] ( ) ~ ` > # + - = | { } . !
Как правильно экранировать?
Перед каждым из этих символов ставьте обратный слеш \.

Пример функции для экранирования:

Код: Выделить всё

#include <string>

std::string escapeMarkdownV2(const std::string& text) {
    std::string escaped;
    const std::string special_chars = "_*[]()~`>#+-=|{}.!";

    for (char c : text) {
        if (special_chars.find(c) != std::string::npos) {
            escaped += '\\';
        }
        escaped += c;
    }
    return escaped;
}
Использование:

Код: Выделить всё

std::string message = escapeMarkdownV2("Это пример. Текст с точками и _подчеркиванием_");
bot.getApi().sendMessage(message->chat->id, message, nullptr, nullptr, keyboard, "MarkdownV2");
http://reo7sp.github.io/tgbot-cpp/class_tg_bot_1_1_api.html#ac32f2c493cccf92747faab5016ec9bc0
https://core.telegram.org/bots/api#formatting-options
ya
^-^
Сообщения: 2673
Зарегистрирован: 16 дек 2021, 19:56

Re: экранирования перед использованием "MarkdownV2" в parse_mode

Сообщение ya »

для Markdown

Код: Выделить всё

#include <string>
#include <algorithm>

std::string escapeMarkdown(const std::string& text) {
    std::string result = text;
    const std::string specialChars = R"(\_*[]()~`>#+-=|{}.!")";

    for (char c : specialChars) {
        std::string s(1, c);
        std::string replacement = "\\" + s;
        size_t pos = 0;
        while ((pos = result.find(c, pos)) != std::string::npos) {
            result.replace(pos, 1, "\\" + c);
            pos += 2; // пропускаем добавленный слэш
        }
    }

    return result;
}
ya
^-^
Сообщения: 2673
Зарегистрирован: 16 дек 2021, 19:56

Re: экранирования перед использованием "MarkdownV2" в parse_mode

Сообщение ya »

для Markdown

Код: Выделить всё

„_“, „*“, „`“, „[“

Код: Выделить всё

'_', '*', '`', '['

Код: Выделить всё

#include <string>
#include <iostream>
#include <algorithm>
#include <locale>
#include <codecvt>

std::string escapeMarkdown(const std::string& text) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    std::wstring wtext = converter.from_bytes(text);

    std::wstring result = wtext;
    const std::wstring specialChars = L"(_*[]()~`>#+-=|{}.!\"&%$@:+<>)"; // Добавил больше символов

    for (wchar_t c : specialChars) {
        std::wstring s(1, c);
        std::wstring replacement = L"\\" + s;
        size_t pos = 0;
        while ((pos = result.find(c, pos)) != std::wstring::npos) {
            result.replace(pos, 1, L"\\" + c);
            pos += 2;
        }
    }

    return converter.to_bytes(result);
}
ya
^-^
Сообщения: 2673
Зарегистрирован: 16 дек 2021, 19:56

Re: экранирования перед использованием "MarkdownV2" в parse_mode

Сообщение ya »

Код: Выделить всё

    #include <iostream>
    #include <string>
     
    int main()
    {
        std::string spec_symbols = "/^$.|?*+(){}";
        std::string input_string = "^This/ specific? |query$ does{{}} work*";
        std::string insert_str = "\\\\";
        const std::size_t step = 3;
     
        std::cout << "Before:\n" << input_string << std::endl;
        for (auto c : spec_symbols)
        {
            std::size_t pos = 0;
            while ((pos = input_string.find(c, pos)) != std::string::npos)
            {
                input_string.insert(pos, insert_str);
                pos += step;
            }
        }
        std::cout << "After:\n" << input_string << std::endl;
        return 0;
    }
Ответить