Хоть и с большим запозданием, публикую шпаргалку по telegram bot api, может, будет полезна.
Прикладываю официальную документацию, и готовый набор методов для работы с telegram. Обработку тестировал на 8.3.15.1747.
Ссылки:
Официальная документация
Документация с частичным переводом (документация не полная, но рабочая)
В тексте я буду давать ссылки на вторую документацию т.к. для ее просмотра не нужны премудрости для обхода блокировок.
Соединение
В документации написано:
Все запросы к Telegram Bot API должны осуществляться через HTTPS в следующем виде: https://api.telegram.org/bot<token>/НАЗВАНИЕ_МЕТОДА
Подчеркнуто, что соединение именно HTTPS, а значит не забываем указывать порт 443 и создать объект ЗащищенноеСоединениеOpenSSL
Код создания соединения :
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПрокcиПорт = 3128;
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
Прокси
Прокси нужен для обхода блокировок РосКомНадзора, если у вас провайдер не блокирует сайт telegram.org, то прокси можно не создавать.
Есть огромное количество сайтов предоставляющий список таких бесплатных прокси, я использую https://free.proxy-sale.com/https/ т.к. там есть возможность скачать списков нужном мне формате для автоматической загрузки.
Я реализовал у себя регистр сведений, где храню флаг доступности, ip и порт прокси. Флаг доступности актуализируется регламентным заданием
Проверка соединения
Для проверки соединения или проверки работает прокси или нет реализован специальный GET-метод getMe
Я специально буду повторять блоки кода, дабы Вы копировали сразу рабочий вариант, конечно это все нужно обернуть в функции и процедуры
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ТаймаутСоединения = 2;//Ставим таймаут в пару секунд, чтобы долго не ждать исключения при неудачной проверке соединения
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,ТаймаутСоединения,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot" + МойToken.token + "/getMe";
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
ПроксиДоступен = Истина;
Исключение
ПроксиДоступен = Ложь;
КонецПопытки;
Сообщить("Прокси доступен - " + ПроксиДоступен);
Метод getMe вернет в теле ответа JSON структуру
{
"ok": true,
"result": {
"id": 12345678912,
"is_bot": true,
"first_name": "Представление имени моего бота",
"username": "unikalnoe_imya_bot",
"can_join_groups": true,
"can_read_all_group_messages": false,
"supports_inline_queries": true
}
}
"ok":true - Означает, что авторизация прошла успешно и Ваш токен валидный.
Получение сообщений
Для получения сообщений существуют 2 совершенно разных способа
- Через HTTP-запросы к методу getUpdates
- Через Webhook
Запрос к методу getUpdates инициирует 1С, и есть 2 варианта использования
Short polling - это классическая схема, когда отправляя запрос мы сразу получаем результат его выполнения.
В случае с getUpdates мы сразу получаем ответ, где в поле result будет массив объектов с типом Update
Примитивный запрос на получение всех сообщений
Данный запрос каждый раз будет возвращать повторяющиеся данные и отслеживание новых сообщений ложится на 1С
т.е. вы заводите РС с обработанными update_id и каждый раз анализируете - обработан полученный id или нет. Можно завести константу с последним обработанным update_id и сравнивать ее на < или > с полученным
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot" + МойToken + "/getUpdates";
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка получения запроса";
КонецПопытки;
Пример ответа:
{
"ok": true,
"result": [
{
"update_id": 910197276,
"message": {
"message_id": 55,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585628272,
"text": "Привет"
}
}
]
}
Запрос на получение новых сообщений после последнего запроса
Данный запрос получает все сообщения полученные после сообщения с update_id = 910197276
Для этого использовали параметр offset, которому присвоили значение IDПоследнегоСообщения+1
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
НомерПоследнегоСообщения = 910197276;
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
НомерНачальногоСообщения = Формат(НомерПоследнегоСообщения + 1, "ЧДЦ=0; ЧГ=");
АдресЗапроса = "bot"
+ МойToken.token
+ "/getUpdates"
+ "?offset="
+ НомерНачальногоСообщения;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка получения запроса";
КонецПопытки;
Ответ
{
"ok": true,
"result": [
{
"update_id": 910197277,
"message": {
"message_id": 56,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585628372,
"text": "Как жизнь?"
}
}
]
}
Long polling - это схема, когда сервер возвращает ответ на запрос не сразу, а в момент появления данных. Проще говоря ваше HTTP соединение висит пока не появятся новые сообщения или не закончится таймаут.
Для работы в такой схеме необходимо договориться с сервером - какой таймаут считать допустимым, для этого у метода getUpdates есть параметр timeout, для удобства еще будем отправлять номер начального сообщения (offset)
Запрос на ожидание получения новых сообщений
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
Таймаут = 120;
НомерПоследнегоСообщения = 910197276;
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,Таймаут,Новый ЗащищенноеСоединениеOpenSSL());
НомерНачальногоСообщения = Формат(НомерПоследнегоСообщения + 1, "ЧДЦ=0; ЧГ=");
АдресЗапроса = "bot"
+ МойToken
+ "/getUpdates"
+ "?timeout="
+ Таймаут
+ "&offset="
+ НомерНачальногоСообщения;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка получения запроса";
КонецПопытки;
Получение сообщений через Webhook
Данные способ подразумевает наличие опубликованного наружу HTTP-сервиса, куда и будут приходить запросы от telegram с новыми сообщениями
Следует отметить 2 важные детали - сервис должен быть HTTPS и обрабатывать POST-запросы
Для переключения режима обмена на вебхуки существует метод setWebhook
Основной плюс данного метода - отсутствие необходимости в рег.заданиях, которые с определенным интервалом опрашивают или ждут ответа от сервера telegram. Новые сообщения приходят в режиме реального времени, причем если ваш сервис будет недоступен, то запрос будет повторен (сколько раз и с каким интервалом не понятно)
Обработка входящих сообщений
Сообщения, полученные от сервера telegram это массив объектов с типом Update. У данного типа есть обязательное поле update_id и ряд опциональных, зависящих от типа входящего сообщения. Основное доп.поле - message с типом Message заполнено у входящих текстовых сообщениях, входящих файлах, фотографиях, аудио сообщениях, входящем сообщении с контактом, георасположением, видео и стикеры.
Второе доп.поле - callback_query с типом CallbackQuery - это результат нажатия на кнопку клавиатуры InlineKeyboardMarkup
Примеры сообщений с типом Message
{
"update_id": 910197306,
"message": {
"message_id": 86,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585918817,
"text": "Привет"
}
}
{
"update_id": 910197307,
"message": {
"message_id": 87,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585918914,
"photo": [{
"file_id": "AgACAgIAAxkBAANXXoczwpsWTe0vVGbgqoIE2F-QLUMAAsawMRuPMzhI42EHxc1ukRTFUsWSLgADAQADAgADbQADL3YAAhgE",
"file_unique_id": "AQADxVLFki4AAy92AAI",
"file_size": 6109,
"width": 320,
"height": 116
}, {
"file_id": "AgACAgIAAxkBAANXXoczwpsWTe0vVGbgqoIE2F-QLUMAAsawMRuPMzhI42EHxc1ukRTFUsWSLgADAQADAgADeAADMHYAAhgE",
"file_unique_id": "AQADxVLFki4AAzB2AAI",
"file_size": 21653,
"width": 800,
"height": 289
}, {
"file_id": "AgACAgIAAxkBAANXXoczwpsWTe0vVGbgqoIE2F-QLUMAAsawMRuPMzhI42EHxc1ukRTFUsWSLgADAQADAgADeQADLXYAAhgE",
"file_unique_id": "AQADxVLFki4AAy12AAI",
"file_size": 29564,
"width": 1080,
"height": 390
}
]
}
}
{
"update_id": 910197308,
"message": {
"message_id": 88,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585918960,
"document": {
"file_name": "планческие-скалы-собер-баш.gpx",
"mime_type": "application/octet-stream",
"file_id": "BQACAgIAAxkBAANYXocz8Iiqq7kpgxE3bIEdkzgg9lEAAscIAAKPMzhIERX5PAABX3kxGAQ",
"file_unique_id": "AgADxwgAAo8zOEg",
"file_size": 25422
}
}
}
{
"update_id": 910197309,
"message": {
"message_id": 89,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585918994,
"voice": {
"duration": 2,
"mime_type": "audio/ogg",
"file_id": "AwACAgIAAxkBAANZXoc0ErVnVqUEVoHi4zcfqzu49h4AAsgIAAKPMzhIZr__wXIAAc3bGAQ",
"file_unique_id": "AgADyAgAAo8zOEg",
"file_size": 7373
}
}
}
{
"update_id": 910197310,
"message": {
"message_id": 90,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585919030,
"location": {
"latitude": 37.236881,
"longitude": 39.827734
}
}
}
{
"update_id": 910197311,
"message": {
"message_id": 91,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585919128,
"poll": {
"id": "5203966058699948035",
"question": "Как тебе такое Илон Маск",
"options": [{
"text": "Да",
"voter_count": 0
}, {
"text": "Нет",
"voter_count": 0
}
],
"total_voter_count": 0,
"is_closed": false,
"is_anonymous": true,
"type": "regular",
"allows_multiple_answers": false
}
}
}
{
"update_id": 910197322,
"message": {
"message_id": 100,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585920052,
"contact": {
"phone_number": "88777898892",
"first_name": "",
"vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:\nORG:\nTITLE;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=D0=93=D0=BE=D1=80=D0=B3=D0=B0=D0=B7\nTEL;CELL:8877789-88-92\nEND:VCARD"
}
}
}
{
"update_id": 910197324,
"message": {
"message_id": 102,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585920126,
"audio": {
"duration": 201,
"mime_type": "audio/mp3",
"title": "90",
"performer": "Монеточка",
"file_id": "CQACAgIAAxkBAANmXoc4ft2Lvo9TAxiyyCcUq1ipBnAAAswIAAKPMzhI7jXuFr4VwA8YBA",
"file_unique_id": "AgADzAgAAo8zOEg",
"file_size": 8080469
},
"caption": "Музычка"
}
}
{
"update_id": 910197317,
"message": {
"message_id": 95,
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585919845,
"text": "Кнопка 1"
}
}
{
"update_id": 910197312,
"callback_query": {
"id": "3790937497865976306",
"from": {
"id": 882646417,
"is_bot": false,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"language_code": "ru"
},
"message": {
"message_id": 92,
"from": {
"id": 1148631456,
"is_bot": true,
"first_name": "Имя моего бота",
"username": "LeonGLbot"
},
"chat": {
"id": 882646417,
"first_name": "Александр",
"last_name": "Леонов",
"username": "Rentgengl",
"type": "private"
},
"date": 1585919611,
"text": "Внимание, опрос\nКак тебе такое, Илон Маск?",
"entities": [{
"offset": 0,
"length": 15,
"type": "bold"
}, {
"offset": 16,
"length": 26,
"type": "italic"
}
],
"reply_markup": {
"inline_keyboard": [
[{
"text": "Обычная кнопка",
"callback_data": "ОтветНаСообщение1"
}
],
[{
"text": "Ссылка",
"url": "//infostart.ru/"
}, {
"text": "Переслать контакт",
"switch_inline_query": "Это отличный канал"
}, {
"text": "Ответить каналу",
"switch_inline_query_current_chat": "Это точно"
}
]
]
}
},
"chat_instance": "2548144641495767324",
"data": "ОтветНаСообщение1"
}
}
Загрузка полученных файлов
Т.к. в сообщении приходит только идентификатор файла, то необходимо его как то получить.
Для этого существует GET-метод getFile, у которого есть один обязательный параметр file_id
Метод возвращает объект типа File, это еще не файл, но он уже доступен по ссылке, которую необходимо собрать из полученных данных.
Ссылка имеет вид https://api.telegram.org/file/bot<token>/<file_path>, где file_path - это свойство объекта File
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ФайлID = "CQACAgIAAxkBAANmXoc4ft2Lvo9TAxiyyCcUq1ipBnAAAswIAAKPMzhI7jXuFr4VwA8YBA";
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/getFile"
+ "?file_id="
+ ФайлID;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка получения данных файла " + ОписаниеОшибки();
КонецПопытки;
Если ОтветHTTP.КодСостояния <> 200 Тогда
ВызватьИсключение "Сервер вернул ошибку " + ОтветHTTP.КодСостояния;
КонецЕсли;
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ОтветHTTP.ПолучитьТелоКакСтроку());
ДанныеОтвета = ПрочитатьJSON(ЧтениеJSON, Ложь);
ЧтениеJSON.Закрыть();
Если ДанныеОтвета.ok = Ложь Тогда
ВызватьИсключение "Ошибка в отправленных данных";
КонецЕсли;
АдресЗапроса = "file/bot"
+ МойToken
+ "/"
+ ДанныеОтвета.result.file_path
+ "?file_id="
+ ФайлID;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Исключение
ВызватьИсключение "Ошибка загрузки файла";
КонецПопытки;
ДвоичныеДанные = ОтветHTTP.ПолучитьТелоКакДвоичныеДанные();
ДвоичныеДанные.Записать("C:\1.mp3");
Ответ сервиса getFile
{
"ok": true,
"result": {
"file_id": "CQACAgIAAxkBAANmXoc4ft2Lvo9TAxiyyCcUq1ipBnAAAswIAAKPMzhI7jXuFr4VwA8YBA",
"file_unique_id": "AgADzAgAAo8zOEg",
"file_size": 8080469,
"file_path": "music/file_0.mp3"
}
}
Отправка сообщения
Для отправки сообщения используется GET-метод sendMessage, обязательных параметров всего два chat_id и text
chat_id можно взять из полученных сообщений
Отправка простого сообщения
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ЧатID = "882646417";
ТекстСообщения = "Привет мир!";
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/sendMessage"
+ "?chat_id="
+ ЧатID
+ "&text="
+ ТекстСообщения;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка отправки сообщения";
КонецПопытки;
При этом запросе сервер ответит, что все Ок
{
"ok": true,
"result": {
"message_id": 63,
"from": {
"id": 123456789,
"is_bot": true,
"first_name": "Представление имени моего бота",
"username": "unikalnoe_imya_bot"
},
"chat": {
"id": 882646417,
"first_name": "\u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440",
"last_name": "\u041b\u0435\u043e\u043d\u043e\u0432",
"username": "Rentgengl",
"type": "private"
},
"date": 1585714087,
"text": "\u041f\u0440\u0438\u0432\u0435\u0442 \u043c\u0438\u0440!"
}
}
У метода sendMessage есть еще ряд необязательных параметров, один из них это parse_mode, который включает нужный синтаксис оформления текста сообщения. Таких режимов два - HTML и Markdown
Проще говоря, этот параметр говорит по каким правилам должно оформляться сообщение
Я приведу пример отправки сообщения в синтаксисе HTML
Отправка оформленного сообщения
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ЧатID = "882646417";
ТекстСообщения = "<b>Жирный</b>, <strong>Жирный</strong>
|<i>Курсив</i>, <em>Курсив</em>
|<a href=""//infostart.ru/"">Ссылка на Infostart</a>
|<code>встроенный код фиксированной ширины встроенный код фиксированной ширины встроенный код фиксированной ширины</code>
|<pre>предварительно отформатированный кодовый блок фиксированной ширины</pre>";
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/sendMessage"
+ "?chat_id="
+ ЧатID
+ "&text="
+ ТекстСообщения
+ "&parse_mode=HTML";
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка отправки сообщения";
КонецПопытки;
В чат при этом запросе прилетит вот такое сообщение
Показ привью отправленной ссылки можно отключить с помощью параметра disable_web_page_preview
Для этого нужно к запросу добавить строку &disable_web_page_preview=true
Также у метода есть параметр reply_to_message_id, который принимает идентификатор сообщения, на которое делается ответ.
Кнопки (клавиатуры)
У метода sendMessage есть еще один очень интересный параметр - reply_markup, который отвечает за быстрые ответы.
Типов таких быстрых ответов на данный момент 4: InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardHide и ForceReply.
Это клавиатура, которая привязана к сообщению. У этого объекта всего одно поле inline_keyboard, которое содержит массив строк с массивами кнопок (2 мерный массив кнопок или массив массивов с кнопками)
Кнопка - это объект InlineKeyboardButton, у которого только одно обязательное поле - text
Есть еще ряд полей, основное из которых - callback_data. Это данные, которые будут отправлены после нажатия кнопки пользователем. Сюда можно записывать идентификаторы из 1С (документа или справочника), числа и т.д. для последующей обработки.
Второй полезный параметр - url, в котором указывается ссылка, которая будет открыта при нажатии на кнопку
Пример JSON-описания клавиатуры
{
"inline_keyboard": [
[{
"text": "Обычная кнопка",
"callback_data": "ОтветНаСообщение1"
}
],
[{
"text": "Ссылка",
"callback_data": "ОтветНаСообщение2",
"url": "infostart.ru"
}, {
"text": "Переслать контакт",
"switch_inline_query": "Это отличный канал"
}, {
"text": "Ответить каналу",
"switch_inline_query_current_chat": "Это точно"
}
]]
}
Представление клавиатуры
Код 1С
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ЧатID = "882646417";
ТекстСообщения = "<b>Внимание, опрос</b>
|<i>Как тебе такое, Илон Маск?</i>";
ТекстКнопок = "
|{
| ""inline_keyboard"": [
| [{
| ""text"": ""Обычная кнопка"",
| ""callback_data"": ""ОтветНаСообщение1""
| }
| ],
| [{
| ""text"": ""Ссылка"",
| ""url"": ""//infostart.ru/""
| }, {
| ""text"": ""Переслать контакт"",
| ""switch_inline_query"": ""Это отличный канал""
| }, {
| ""text"": ""Ответить каналу"",
| ""switch_inline_query_current_chat"": ""Это точно""
| }
| ]]}";
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/sendMessage"
+ "?chat_id="
+ ЧатID
+ "&text="
+ ТекстСообщения
+ "&parse_mode=HTML"
+ "&reply_markup="
+ ТекстКнопок;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка отправки сообщения";
КонецПопытки;
Набор кнопок, которые не привязаны к конкретному сообщению а закреплены внизу окна диалога.
Объект имеет одно обязательное поле keyboard, которое содержит массив массивов кнопок с более простым типом нежели InlineKeyboard - KeyboardButton с основным полем text, данный объект можно не использовать и сразу формировать массив строк.
Еще один важный параметр клавиатуры, но не обязательным, является resize_keyboard, который отвечает за "авто высоту" кнопок.
По умолчанию данный параметр установлен в false и клавиатура растягивается на высоту основной клавиатуры, что выглядит громоздко (см. скрин в примере).
Еще один опциональный параметр - one_time_keyboard, который при установке в true скрывает клавиатуру после нажатия кнопки.
Код 1С
ЧатID = "882646417";
ТекстСообщения = "<b>Внимание, опрос</b>
|<i>Как тебе такое, Илон Маск?</i>";
ТекстКнопок = "
|{
| ""keyboard"": [
| [""Кнопка 1""],
| [""Кнопка 2"",""Кнопка 3"",""Кнопка 4""]
| ]}";
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/sendMessage"
+ "?chat_id="
+ ЧатID
+ "&text="
+ ТекстСообщения
+ "&parse_mode=HTML"
+ "&reply_markup="
+ ТекстКнопок;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка отправки сообщения";
КонецПопытки;
ReplyKeyboardHide - Своего рода команда управления видимостью для клавиатуры ReplyKeyboardMarkup
ForceReply - команда инициирующая цитату на отправляемое сообщение
Отправка контактов
GET-метод sendContact позволяет отправить контакт пользователю спец.сообщением.
Метод похож на sendMessage за исключением нескольких обязательных полей:
phone_number - строковое представление телефонного номера
first_name - Имя контакта
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ЧатID = "882646417";
Телефон = "88005555256";
ИмяКонтакта = "Инфостарт";
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/sendContact"
+ "?chat_id="
+ ЧатID
+ "&phone_number="
+ Телефон
+ "&first_name="
+ ИмяКонтакта;
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
Попытка
ОтветHTTP = СоединениеHTTP.Получить(ЗапросHTTP);
Сообщить(ОтветHTTP.ПолучитьТелоКакСтроку());
Исключение
ВызватьИсключение "Ошибка отправки сообщения";
КонецПопытки;
Отправка документов (файлов)
За отправку файлов отвечает POST-метод sendDocument, у которого 2 обязательных поля - chat_id и document.
Поле document может иметь тип строки, это нужно тогда, когда мы переотправляем уже полученный файл и в этом случае указываем идентификатор файла.
Второй тип, который может содержать поле document - это сам отправляемый файл в формате multipart/form-data
Сам формат multipart/form-data достаточно простой, его цель - оправить серверу ряд разнородных данных (файлы, строки и т.д.) в одном сообщении (файле). Это своего рода zip-архив без сжатия, где не только файлы, но и другие данные.
Сервер, получив сообщение, должен понять где заканчиваются/начинаются блоки с данными и что там за данные. Для этого ему необходим разделитель данных - boundary и некая запись о характере данных блока.
Вернемся к нашему методу sendDocument, которому необходимо передать 2 параметра - строковый chat_id и файл document
Шаблон тела запроса будет выглядеть следующим образом:
--%Разделитель%
Content-Disposition: form-data; name="chat_id"
%ЧатID%
--%Разделитель%
Content-Disposition: form-data; name="document"; filename="%ИмяФайла%"
%СодержимоеФайла%
--%Разделитель%--
Со строковыми значениями вопросов не возникает - делаем СтрЗаменить и все, но есть еще и содержимое файла, которое нужно в итоговый запрос подсунуть.
Для решения этой проблемы у 1С есть метод ОбъединитьФайлы, который объединяет переданный в него массив файлов в один.
Разделим шаблон на части - певая это текст до %СодержимоеФайла%, а вторая это текст после %СодержимоеФайла%. Запишем эти 2 текста в файлы и используем ОбъединитьФайлы подсунув между текстовиками отправляемый файл.
МойToken = "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11";
АдресTelegramAPI = "api.telegram.org";
ПроксиАдрес = "159.138.22.170";
ПроксиПорт = 3128;
ЧатID = "882646417";
ПутьКФайлу = "C:\1.pdf";
Boundary = "----"+Строка(Новый УникальныйИдентификатор());
Файл = Новый Файл(ПутьКФайлу);
//Определяем массив для процедуры ОбъединитьФайлы
МассивФайловДляОбъединения = Новый Массив;
МассивФайловДляОбъединения.Добавить(ПолучитьИмяВременногоФайла("txt"));
ФайлОтправкиНачало = Новый ЗаписьТекста(МассивФайловДляОбъединения[0], КодировкаТекста.UTF8);
НачальныеДанные = "--%Разделитель%
|Content-Disposition: form-data; name=""chat_id""
|
|%ЧатID%
|--%Разделитель%
|Content-Disposition: form-data; name=""document""; filename=""%ИмяФайла%""
|";
НачальныеДанные = СтрЗаменить(НачальныеДанные,"%Разделитель%",Boundary);
НачальныеДанные = СтрЗаменить(НачальныеДанные,"%ЧатID%",ЧатID);
НачальныеДанные = СтрЗаменить(НачальныеДанные,"%ИмяФайла%",Файл.Имя);
ФайлОтправкиНачало.ЗаписатьСтроку(НачальныеДанные );
ФайлОтправкиНачало.Закрыть();
МассивФайловДляОбъединения.Добавить(ПутьКФайлу);
МассивФайловДляОбъединения.Добавить(ПолучитьИмяВременногоФайла("txt"));
ФайлаОтправкиКонец = Новый ЗаписьТекста(МассивФайловДляОбъединения[2], КодировкаТекста.UTF8);
КонечныеДанные = "
|--%Разделитель%--";
КонечныеДанные = СтрЗаменить(КонечныеДанные,"%Разделитель%",Boundary);
ФайлаОтправкиКонец.ЗаписатьСтроку(КонечныеДанные);
ФайлаОтправкиКонец.Закрыть();
ИмяИтоговогоФайла = ПолучитьИмяВременногоФайла("txt");
ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяИтоговогоФайла);
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", ПроксиАдрес, ПроксиПорт);
Прокси.Установить("http", ПроксиАдрес, ПроксиПорт);
СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI,443,,,Прокси,,Новый ЗащищенноеСоединениеOpenSSL());
АдресЗапроса = "bot"
+ МойToken
+ "/sendDocument";
ЗапросHTTP = Новый HTTPЗапрос(АдресЗапроса);
ЗапросHTTP.Заголовки.Вставить("Connection", "keep-alive");
ЗапросHTTP.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
ЗапросHTTP.УстановитьИмяФайлаТела(ИмяИтоговогоФайла);
Попытка
ОтветHTTP = СоединениеHTTP.ОтправитьДляОбработки(ЗапросHTTP);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;