Используя побликации //infostart.ru/public/387433/ и //infostart.ru/public/419846/ решил создать бота, используя API Telegram
Для разбора JSON использовалась обработка из публикации: //infostart.ru/public/119601/
Регистрируем бот и получаем ТОКЕН, тут: //infostart.ru/public/419846/ есть описание, как это сделать
В текущей версии реализована реакция на тестовые сообщения от пользователя;
«скажи» — бот в ответ посылает сообщение
«отчеты» — показывается клавиатура со списком доступных отчетов
«файлы» — показывается клавиатура со списком доступных файлов
Также бот получает присланные фотографии.
Основные процедуры бота:
&НаСервере
Процедура ПрочитатьСобщенияНаСервере() Экспорт
Сервер = "api.telegram.org";
СтрокаСоединения = "/bot"+Токен+"/getUpdates" + ?(ПоследнийИД = "", "", "?offset=" + ПоследнийИД);
HTTPЗапрос = Новый HTTPЗапрос();
Заголовки = Новый Соответствие;
HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
HTTPЗапрос.АдресРесурса = СтрокаСоединения;
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(Новый СертификатКлиентаWindows, Новый СертификатыУдостоверяющихЦентровWindows);
HTTPСоединение = Новый HTTPСоединение(Сервер,,,,Новый ИнтернетПрокси,, ЗащищенноеСоединение);
Попытка
ОтветHTTP = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ДанныеКакСтрока = ОтветHTTP.ПолучитьТелоКакСтроку();
обОбработка = РеквизитФормыВЗначение("Объект");
Рез = обОбработка.мПрочитатьJSON(ДанныеКакСтрока);
Если Рез["ok"] <> Истина Тогда
Возврат;
КонецЕсли;
Рез = СоответвиеВСтруктуру(Рез);
result = Рез.result;
МаксИД = 0;
Для Каждого mes из result Цикл
ПоследнийИД = Формат(mes.update_id + 1, "ЧГ=");
Попытка
message = mes.message;
Исключение
Продолжить;
КонецПопытки;
Дата = '19700101' + message.date +7*60*60;
Попытка
from = message.from.username;
Исключение
from = message.from.first_name;
КонецПопытки;
chatИД = Формат(message.chat.id, "ЧГ=");
Если message.Свойство("text") Тогда
Ок= истина;
Если Найти(ВРег(message.text), "СКАЖИ")<>0 Тогда
HTTPЗапрос.АдресРесурса = "/bot"+Токен+"/sendMessage?text=Hello I am BOT&chat_id="+chatИД+"&reply_to_message_id=" + message.message_id;
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ИначеЕсли Врег(message.text) = "ОТЧЕТЫ" Тогда
HTTPЗапрос.АдресРесурса = "/bot"+Токен+"/sendMessage?text=Доступные отчеты: &chat_id="+chatИД+"&reply_to_message_id=" + message.message_id +
"&reply_markup="+КлаваОтчеты;
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ИначеЕсли Врег(message.text) = "ФАЙЛЫ" Тогда
HTTPЗапрос.АдресРесурса = "/bot"+Токен+"/sendMessage?text=Доступные файлы: &chat_id="+chatИД+"&reply_to_message_id=" + message.message_id +
"&reply_markup="+КлаваФайлы;
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ИначеЕсли Лев(message.text, 7) = "Отчет: " Тогда
HTTPЗапрос.АдресРесурса = "/bot"+Токен+"/sendMessage?text=Ждите. Отчет формируется&chat_id="+chatИД+"&reply_to_message_id=" + message.message_id;
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ТекстОтчета = ПолучитьТекстОтчета(message.text);
HTTPЗапрос.АдресРесурса = "/bot"+Токен+"/sendMessage?parse_mode=HTML&text="+Кодировать(ТекстОтчета)+"&chat_id="+chatИД+"&reply_to_message_id=" + message.message_id;
HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
ИначеЕсли message.text = "Файл: PDF" Тогда
ОтправитьФайлPDF(chatИД, HTTPСоединение, HTTPЗапрос)
ИначеЕсли message.text = "Файл: XLS" Тогда
ОтправитьФайлXLS(chatИД, HTTPСоединение, HTTPЗапрос)
КонецЕсли;
ИначеЕсли message.Свойство("photo") Тогда
МассивФото = message.photo;
Для Каждого Фото из МассивФото Цикл
HTTPЗапрос.АдресРесурса = "/bot"+Токен+"/getFile?file_id=" + Фото.file_id;
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку();
Путь = СтрЗаменить(Сред(СтрокаОтвета, Найти(СтрокаОтвета,"photo/") + 7) , """}}", "");
СтрФото = Фотографии.Добавить();
СтрФото.Имя = Путь;
СтрФото.Размер = "" + Фото.height +"x" + Фото.width;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаСервере
Функция СоответвиеВСтруктуру(Рез)
мРез = Новый Структура;
Для Каждого Эл из Рез Цикл
Ключ = Эл.Ключ;
мЗнач = Эл.Значение;
Если ТипЗнч(мЗнач) =Тип("Соответствие") Тогда
мЗнач = СоответвиеВСтруктуру(мЗнач);
ИначеЕсли ТипЗнч(мЗнач) =Тип("Массив") Тогда
мЗнач = Новый Массив;
Для Каждого элМ из Эл.Значение Цикл
мЗнач.Добавить(СоответвиеВСтруктуру(элМ));
КонецЦикла;
КонецЕсли;
мРез.Вставить(Ключ, мЗнач);
КонецЦикла;
Возврат мРез;
КонецФункции
&НаСервере
функция Кодировать(Текст)
Возврат ?(Текст = "", "Пусто", КодироватьСтроку(Текст, СпособКодированияСтроки.URLВКодировкеURL));
КонецФункции
&НаСервере
Процедура ОтправитьФайлPDF(chat_id, HTTPСоединение, HTTPЗапрос)
Таб = РеквизитФормыВЗначение("Объект").ПолучитьМакет("МакетОтчета");
ИмяФайла = ПолучитьИмяВременногоФайла("PDF");
Таб.АвтоМасштаб = Истина;
Таб.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF);
СтрокаСоединения = "/bot" + Токен + "/sendDocument";
Boundary = "----"+Строка(Новый УникальныйИдентификатор());
//Определяем массив для процедуры ОбъединитьФайлы
МассивФайловДляОбъединения = Новый Массив;
//Формируем начальный фрагмент файла POST-запроса
ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8);
//Формируем конечный фрагмент файла POST-запроса
ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8);
ТекстДляОтправки = "";
ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""chat_id""" + Символы.ПС + Символы.ПС;
ТекстДляОтправки = ТекстДляОтправки + chat_id + Символы.ПС;
ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary + Символы.ПС;
ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""document""; filename=""report.PDF""" + Символы.ПС;
ФайлОтправкиНачало.ЗаписатьСтроку(ТекстДляОтправки );
ФайлОтправкиНачало.Закрыть();
МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);
МассивФайловДляОбъединения.Добавить(СокрЛП(ИмяФайла));
ТекстДляОтправки = "" + Символы.ПС;
ТекстДляОтправки = ТекстДляОтправки + "--"+Boundary+"--";
ФайлаОтправкиКонец.ЗаписатьСтроку(ТекстДляОтправки);
ФайлаОтправкиКонец.Закрыть();
МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);
ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("txt");
ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);
HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
HTTPЗапрос.АдресРесурса = СтрокаСоединения;
Попытка
ОтветHTTP = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Добавлено:
Что бы клавиатура появлялась прямо в чате необходимо подавать другой текст клавиатуры в обработке он получается так:
Строки = Новый Массив;
Кнопки = Новый Массив;
Кнопки.Добавить(Новый структура("text, callback_data", "Файл: PDF", "1"));
Кнопки.Добавить(Новый структура("text, callback_data", "Файл: XLS", "2"));
Строки.Добавить(Кнопки);
КлавиатураВСообщении = JSON.мЗаписатьJSON(Новый Структура("inline_keyboard", Строки), Ложь);
если текстом:
КлавиатураВСообщении =
"{""inline_keyboard"":[[{""text"":""Файл: PDF"",""callback_data"":""1""},{""text"":""Файл: XLS"",""callback_data"":""2""}]]}"
обработка нажатия на эту кнопку отличается от обработки нажатия на простую клавиатуру, которая впринципе просто отсылает сообщение с нужным текстом:
блок «сallback_query» как раз говорит нам о нажатии на такую кнопку, в нем будет содержаться информации о коде нажатой кноки, в нашем примере это «1» или «2»
КодНажатойКнопки = mes.callback_query.data
далее обратабываем так как нам надо
Баян =(
Желтый у вас заголовок, где же тут процесс создания бота?
(2) ifal, Как понять что он «желтый»?
(3) В заголовке статьи написано: » создаем бота…» -, я ожидал увидеть описание процесса, а что видим внутри? ссылки на другие статьи, где описан процесс, а все что ваше личное упрятано в обработку. Поэтому я делаю такой вывод. Правильней звучало бы «Пример использования бота Telegram».
(4) Добавил тексты основных процедур
Хотел описать, но код вроде настолько простой что вроде и объяснений не надо
Добавил пример inline клавиатуры
Добрый день!
https://developers.facebook.com/ ?
Скажите, а не приходилось ли Вам делать интеграцию с Facebook API
Иными словами, можно ли то же самое прикрутить не к Телеграм, а к Фейсбуку?
Просто в нашей компании никто Телеграм не использует, а интеграцию с каким-нибудь популярным мессенджером хотят, и несмотря на мои уговоры, даже пробовать телеграм не хотят, аргумент такой — вот есть Фейсбук, приложение у всех стоит, АПИ есть, пусть корпоративный бот работает на этой платформе…
Но мне пока не удалось найти ни одного примера реализации бота.. Это потому что на порядок сложней, чем с телеграмом, или просто руки не дошли ни у кого?..
Спасибо!
(7) Я бы попробовал, но не совсем понимаю как это должно работать
Как вы это себе представляете?
(8) аналогично
http://prntscr.com/d4yojf
Пользователь подписывается на бота
И дальше например пишет в чат ОТЧЕТЫ и может выбрать нужный отчёт за нужную дату (sales today — без кнопок для выбора тоже подойдёт, непринципиально)
Либо происходит событие в 1С какое-то, и пользователю в мессенджер приходит уведомление
Но насколько я вчёра смог разобраться — при разработке придётся использовать некую php-прослойку, так как для ФБ обязательно использовать webhook, как я понял.. По крайней мере, именно на этом этапе я споткнулся
Мнение одного специалиста, который делал и для ФБ (на php), и для телеграм (он писал мне в личку, поэтому имя не публикую):
Интересное решение
(7) В общем то несложноhttps://github.com/facebook-csharp-sdk
1C Messenger для отправки сообщений, файлов и обмена данными между пользователями 1С, вэб страницы, мобильными приложениями а ля Skype, WhatsApp
на примере
Сегодня по радио услышал что Viber запустил для всех возможность создания публичного аккаунта
«Представленные паблик аккаунты — это чат-каналы, которые можно использовать для отправки важной (рекламной) информации пользователям, проводить презентации, размещать новости, полезные ссылки, GIF-изображения, всячески общаться и получать обратную реакцию от участников канала. Также создателям каналов доступны CRM-инструменты для управления чатом.»
Коллеги, приветствую! С ботом разобрался, все отлично, но есть одно НО. Почему то иногда мои команды не обрабатываются. Опишу проблему. Отправляю команду — и надеюсь увидеть ее в входящем файле json. Но там остается какой то перечень старых команд…в чем может быть проблема? Вот только что отправил боту команду — пришел ответ, все ок. отправляю следующую команду — и в ответ тишина…Мне не совсем понятна логика формирования json файла
Добрый день, коллеги.
Никак не могу разобраться, как удалить клавиатуру в чате («inline_keyboard»).
Был бы признателен за наглядный пример.
День добрый.
Вроде работает если передать пустую клавиатуру: «{«»keyboard»»:[],»»one_time_keyboard»»:true}»
(15) Спасибо за ответ. Но, к сожалению, ничего не получилось. Насколько я понял, как то нужно использовать ReplyKeyboardRemove.
(13) Внимательно прочитайте описаниеhttps://core.telegram.org/bots/api#getupdates
Наверняка, вы увидели, что параметры не обязательны и юзаете без них. Поэтому получаете первые 100 сообщений по сроку давности. Если вчитаться, то там написано, что этот оффсет — это не смещение, а номер первого непрочитанного сообщения. Т.е. последний полученный ид сообщения + 1.
Получается, чтобы получать свежие сообщения, надо указывать параметр offset.
(14) Передайте пустую клавиатуру.
Показать
(18) Спасибо, получилось!
Автор, как ты решил проблему с BOM кодом? Или веб сервис телеграма самостоятельно его вырезает перед первым boundary?
Может кто сталкивался: отправляю клавиатуру «bot******/sendMessage?chat_id=******&text=Меню&reply_markup={«inline_keyboard»:[[{«text»:»1″,»callback_data»:»1″},{«text»:»2″,»callback_data»:»2″}]]}», она приходит пользователю, тот нажимает на неё, но через «getUpdates» не приходит ответ что он нажал. Куда копать?
(15)Здравствуйте, скажите возможно ли приобрести у вас лично вашу обработку, т.к. купить отдельно стартмани я не могу, а на дорогущий абонемент денег нет. Просто делаю диплом в колледже на похожу тему, вот и хотелось бы посмотреть как это реализовано.
(21) Сообщения из inline_keyboard приходят чуть по другому. Добавьте в цикле
условие
(23) У меня проблема не с поиском, а с тем, что ответ вообще не приходит, чтобы я не нажимал и не делал. Приходит только сообщение о том, что я вызывал меню. А вот апдейт, что я нажал кнопку не приходит.
(24) Странно. А клиент какой? Должно быть так.
(25) Если Вы про клиент телеграмма — пробовал нажимать и на десктопе и на мобилке, результат на скрине в предыдущем моём сообщении.
(26)Конечно, это не совсем то, что вы делаете, попробуйте так сделать меню
(27) Так это обычная кнопка, которая отправляется как текст
(28) Так и есть. Разница, что первая в чате под сообщением, а эта как отдельная клавиатура
(29)Ещё раз повторюсь: возможно я не в том формате формирую строку и данные на сервер телеграмма приходят не совсем корректные (с виду строка с параметрами правильная), по-этому не могут быть возвращены через callback_query.