При разработке интеграции 1С с мессенджером Telegram программисты часто сталкиваются с ситуацией, когда текстовые сообщения или команды доходят до адресата в искаженном виде. Одной из наиболее типичных проблем является исчезновение символа «+» (плюс). Например, вместо ожидаемой команды /+ 1 пользователь видит в чате / 1. Рассмотрим подробно, почему это происходит, и разберем способы исправления этой ошибки.
Проблема кроется не в самом Telegram и не в платформе 1С как таковой, а в стандартах передачи данных по протоколу HTTP. Чаще всего для взаимодействия с Telegram API разработчики используют метод GET, передавая параметры сообщения прямо в строке адреса (URL).
Согласно спецификации RFC 1738, символ + в строке запроса является зарезервированным. Он интерпретируется веб-сервером (в данном случае сервером Telegram) как пробел. Именно поэтому, когда вы отправляете строку "/+ 1", принимающая сторона «справедливо» заменяет плюс на пробел, и на выходе получается "/ 1". Для того чтобы передать плюс именно как символ, его необходимо подвергнуть специальному преобразованию — URL-кодированию (Percent-encoding).
Самый простой способ заставить Telegram корректно отображать спецсимволы при использовании GET-запросов — это закодировать строку перед отправкой. В платформе 1С для этого предусмотрена встроенная функция КодироватьСтроку().
Разберем ситуацию на примере кода, предоставленного автором темы. Вместо прямой склейки строк, применим кодирование:
// Исходный текст сообщения
ТекстСообщения = "/+ 1 - выполняется установка начала рабочего дня" + Символы.ПС + "/- 1 - выполняется установка конца рабочего дня";
// Неправильный способ формирования URL (плюс превратится в пробел)
// Ресурс = "sendMessage?chat_id=" + Идентификатор + "&text=" + ТекстСообщения;
// Правильный способ с использованием кодирования
ЗакодированныйТекст = КодироватьСтроку(ТекстСообщения, СпособКодированияСтроки.КодировкаURL);
Ресурс = "sendMessage?chat_id=" + Формат(ИдентификаторЧат, "ЧГ=0") + "&text=" + ЗакодированныйТекст;
При использовании СпособКодированияСтроки.КодировкаURL символ + будет заменен на шестнадцатеричную последовательность %2B. Когда сервер Telegram получит такой запрос, он выполнит обратное декодирование и отобразит пользователю исходный символ +.
Важный нюанс: при кодировании всей строки целиком символ / (слэш) может превратиться в %2F. В большинстве случаев Telegram корректно распознает это как команду, но если вы хотите сохранить структуру URL-параметров максимально «чистой», кодируйте только те части строки, которые содержат пользовательский ввод или спецсимволы.
Использование метода GET для передачи длинных текстовых сообщений считается плохой практикой (bad practice). Существуют ограничения на длину URL-строки, а проблемы с кодировкой спецсимволов (не только плюса, но и &, #, ?) будут возникать постоянно. Проанализируем более надежный подход — отправку данных методом POST с телом в формате JSON.
При передаче данных в теле POST-запроса необходимость в URL-кодировании текстовых параметров отпадает, так как данные передаются не в заголовке запроса, а в его теле. Посмотрим на пример реализации:
// Формируем структуру данных для Telegram
ДанныеЗапроса = Новый Структура;
ДанныеЗапроса.Вставить("chat_id", ИдентификаторЧат);
ДанныеЗапроса.Вставить("text", "/+ 1 - установка начала дня");
// Сериализуем структуру в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеЗапроса);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Настройка HTTP-запроса
Запрос = Новый HTTPЗапрос("sendMessage");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Отправка через HTTPСоединение
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
В данном случае 1С передает данные в чистом виде UTF-8. Это исключает любые искажения символов +, кириллицы и эмодзи. Кроме того, использование POST позволяет отправлять сообщения практически неограниченной длины.
Если в вашем коде используется параметр parse_mode = 'MarkdownV2', то символ + может пропадать или вызывать ошибку Bad Request по другой причине. В синтаксисе MarkdownV2 плюс является служебным символом.
Проанализируем правила экранирования: в режиме MarkdownV2 любые символы с кодами от 1 до 126, которые используются как спецсимволы (включая _, *, [, ], (, ), ~, `, >, #, +, -, =, |, {, }, ., !), должны быть экранированы обратным слэшем \.
Пример правильной строки для MarkdownV2:
СтрокаСообщения = "/\+ 1 - выполняется установка";
Если вы не планируете использовать жирный шрифт или курсив, рекомендуем использовать parse_mode = 'HTML' или вовсе не указывать этот параметр. В HTML-режиме плюс не требует экранирования, нужно будет следить только за символами <, > и &.
Важно помнить о техническом ограничении самого Telegram: командой (клиentities) считается только то слово, которое начинается со слэша и содержит только латинские буквы, цифры и подчеркивания. Символ + технически не может быть частью «синей кликабельной ссылки» команды.
/+команда, Telegram не подсветит это как команду./add_work_day вместо /+ 1.Если же использование плюса — это требование интерфейса, то ваш бот на стороне 1С должен обрабатывать входящее сообщение не как команду (Command), а как обычный текст, анализируя первые символы строки самостоятельно.
Разберем по шагам алгоритм действий, если у вас пропадают символы при работе с ботом:
GET, обязательно применяйте КодироватьСтроку(Текст, СпособКодированияСтроки.КодировкаURL).UTF-8 без BOM (Byte Order Mark).\+.Соблюдение этих правил гарантирует, что ваши сообщения в Telegram будут выглядеть именно так, как вы задумали в коде 1С.