Версия для печати темы (https://pro1c.org.ua/index.php?s=7f86fbb05e6c32461e3ec02cb9c51c92&showtopic=44207)

Нажмите сюда для просмотра этой темы в обычном формате

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 _ Программирование в 1С Предприятие 8.3 _ Клавиатуры Telegram Bot Api

Автор: kosalex 16.02.18, 16:32

Доброго времени суток!

Есть код

Процедура ОтправитьТекстовоеСообщение(Сообщение,Текст)

    клСтруктура = Новый Структура;
    мСтрок = Новый Массив;
    мКнопок = Новый Массив;

    мКнопок.Добавить(Новый Структура("text, callback_data", "Да", "1"));
    мКнопок.Добавить(Новый Структура("text, callback_data", "Нет", "2"));
    
    мСтрок.Добавить(мКнопок);    
    
    клСтруктура.Вставить("inline_keyboard",мСтрок);
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON,клСтруктура,,);
    
    Клавиатура = ЗаписьJSON.Закрыть();
    
    Ресурс = "/bot" + Константы.Токен.Получить() + "/sendMessage?text=" + КодироватьСтроку(Текст,СпособКодированияСтроки.КодировкаURL) + "&chat_id=" + Формат(Сообщение.from.id,"ЧГ=0") + "&reply_to_message_id=" + Сообщение.message_id + "&reply_markup=" + Клавиатура;
    Результат = ОтправитьЗапросНаОбработкуВTelegram(Ресурс);
    
    Если НЕ Результат.ok Тогда
        Возврат;
    КонецЕсли;
КонецПроцедуры


Отправляю сообщение боту, бот на него отвечает с выводом клавиатуры, после нажатия на кнопку ничего не происходит, кнопка ничего не возвращает.
Помогите разобраться! Все что нашел на форумах не помогает мне :-)

Автор: podcast 16.02.18, 16:42

kosalex @ Сегодня, 16:32 * ,
Что в Результат приходит?

Автор: kosalex 16.02.18, 17:26

podcast @ Сегодня, 16:42 * ,
все норм, затупил немного, код рабочий

Автор: kosalex 25.02.18, 22:26

Задача усложнилась :-) Но все по той же теме, клавиатур в telegram.

Нужно вывести изображение с клавиатурой "inline_keyboard".

Пользуюсь вот таким кодом:

ддКартинка = Блюдо.Ссылка.ОсновноеИзображение.Хранилище.Получить().ПолучитьДвоичныеДанные();
                
                времКаталог = КаталогВременныхФайлов();
                времФайлКартинки = ПолучитьИмяВременногоФайла("jpg");
                имяВремяФайла = СтрЗаменить(времФайлКартинки,времКаталог,"");
                                
                ддКартинка.Записать(времФайлКартинки);
                
                СтрокаСоединения = "/bot" + Константы.Токен.Получить() + "/sendPhoto";
                
                //Определяем массив для процедуры ОбъединитьФайлы
                МассивФайловДляОбъединения = Новый Массив;
                
                //Формируем начальный фрагмент файла POST-запроса
                ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
                ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8);
                
                //Формируем конечный фрагмент файла POST-запроса
                ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
                ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8);
                
                ТекстДляОтправки = "";
                
                Boundary = "----" + Строка(Новый УникальныйИдентификатор());
                
                // ЧАТ
                ТекстДляОтправки = ТекстДляОтправки + "--" + Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""chat_id"""+ Символы.ПС + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + СокрЛП(Формат(Клиент.Код,"ЧГ=0")) + Символы.ПС;
                
                // ПОДПИСЬ  
                Подпись = "Наименование: " + Блюдо.Ссылка.Наименование + Символы.ПС + "Цена: " + Блюдо.Ссылка.Цена;  
                
                ТекстДляОтправки = ТекстДляОтправки + "--" + Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""caption""" + Символы.ПС + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + СокрЛП(Подпись) + Символы.ПС;
                                                                        
                // ФОТО
                ТекстДляОтправки = ТекстДляОтправки + "--" +  Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""photo""; filename=""" + имяВремяФайла + """" + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Type: image/jpg" + Символы.ПС;
                
                //КЛАВИАТУРА
                клСтруктура = Новый Структура;
                Строки = Новый Массив;
                Кнопки = Новый Массив;
                Кнопки.Добавить(Новый Структура("text, callback_data", "В корзину", Блюдо.Ссылка.Код));
                Строки.Добавить(Кнопки);    
                клСтруктура.Вставить("inline_keyboard",Строки);
                ЗаписьJSON = Новый ЗаписьJSON;
                ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет));  //Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет,,,ЭкранированиеСимволовJSON.СимволыВнеASCII)  
                ЗаписатьJSON(ЗаписьJSON,клСтруктура,,);
                Клавиатура = ЗаписьJSON.Закрыть();

                ТекстДляОтправки = ТекстДляОтправки + "--" +  Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""reply_markup""" + Символы.ПС+ Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + СокрЛП(Клавиатура) + Символы.ПС;                 
                
                ФайлОтправкиНачало.ЗаписатьСтроку(ТекстДляОтправки);
                ФайлОтправкиНачало.Закрыть();
                
                МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);
                МассивФайловДляОбъединения.Добавить(времФайлКартинки);
                
                ТекстДляОтправки = "";
                ТекстДляОтправки = ТекстДляОтправки + Символы.ПС  + "--" +  Boundary+"--";
                ФайлаОтправкиКонец.ЗаписатьСтроку(ТекстДляОтправки);
                ФайлаОтправкиКонец.Закрыть();
                МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);
                
                ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("txt");
                
                ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);
                
                HTTPЗапрос = Новый HTTPЗапрос;
                HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
                HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
                HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);    
                HTTPЗапрос.АдресРесурса = СтрокаСоединения;
                
                Результат = ОтправитьЗапросНаОбработкуВTelegramPOST(HTTPЗапрос);


Если убрать раздел с клавиатурой то все ок, картинка отправляется. Если включить, сервер возвращает ""Bad Request: IMAGE_PROCESS_FAILED"".
Помогите пожалуйста! Шел третий день...

Автор: logist 25.02.18, 23:14

Цитата(kosalex @ 25.02.18, 22:26) *
Помогите пожалуйста! Шел третий день...

Поищите на гитхабе по тегам telegram-bot и/или telegram-bot-api + текст ошибки (IMAGE_PROCESS_FAILED), код 1С вы там не найдете, но решения проблем по другим языкам может подсказать куда думать.

Автор: kosalex 26.02.18, 7:41

logist @ Вчера, 23:14 * ,
Дело в том что на гит хабе смотрел) и если отправить картинку уже ту которая есть на сервере то кнопки будут, потому как там запись немного по другому. Просто строкой "Ресурс = "/bot" + Константы.Токен.Получить() + "/sendPhoto?photo=" + АйдиФайла + "&chat_id=" + Формат(Сообщение.from.id,"ЧГ=0") + "&caption=" + КодироватьСтроку(Заголовок,СпособКодированияСтроки.КодировкаURL);"

А вот в мое случае строка запроса собирается немного по другому...

Может я не правильно задаю параметры ?

Автор: kosalex 26.02.18, 10:17

Функция отправки на сервер выглядит так:

Функция ОтправитьЗапросНаОбработкуВTelegramPOST(Запрос)
    Попытка
        Соединение  =  Новый HTTPСоединение(Константы.Сервер.Получить(),443,,,,,Новый ЗащищенноеСоединениеOpenSSL());
        
        Ответ = Соединение.ОтправитьДляОбработки(Запрос);
        ТекстовыеДанныеОтвета = Ответ.ПолучитьТелоКакСтроку();
        
        ДеревоЗн = Новый ДеревоЗначений();
        ЧтениеJSON = Новый ЧтениеJSON();
        ЧтениеJSON.УстановитьСтроку(ТекстовыеДанныеОтвета);
        Результат = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
        
        Возврат Результат;
    Исключение
        ЗаписьЖурналаРегистрации("ОтправитьЗапросНаОбработкуВTelegramPOST",,Метаданные.ОбщиеМодули.TelegramAPI,"Ошибка!" + ИнформацияОбОшибке().Описание,ИнформацияОбОшибке().Причина,);
        Возврат Неопределено;
    КонецПопытки;
КонецФункции




Цитата(logist @ 25.02.18, 23:14) *
решения проблем по другим языкам


таких проблем в других языках нет)) потому как они умеют работать с двоичными данными, отправлять картинку на сервер.

 клСтруктура = Новый Структура;
                Строки = Новый Массив;
                Кнопки = Новый Массив;
                Кнопки.Добавить(Новый Структура("text, callback_data", "В корзину", Блюдо.Ссылка.Код));
                Строки.Добавить(Кнопки);    
                клСтруктура.Вставить("inline_keyboard",Строки);
                ЗаписьJSON = Новый ЗаписьJSON;
                ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет));  //Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет,,,ЭкранированиеСимволовJSON.СимволыВнеASCII)  
                ЗаписатьJSON(ЗаписьJSON,клСтруктура,,);
                Клавиатура = ЗаписьJSON.Закрыть();


В "Клавиатура" после выполнения этого кода будет же строка JSON ?

Автор: logist 26.02.18, 11:11

Цитата(kosalex @ 26.02.18, 10:17) *
таких проблем в других языках нет))

Есть, иначе бы я не писал, полистав вчера немного увидел что чаще всего описывают проблему с именем файла.

Цитата(kosalex @ 26.02.18, 10:17) *
потому как они умеют работать с двоичными данными, отправлять картинку на сервер.

1С это тоже умеет.

Цитата(kosalex @ 26.02.18, 10:17) *
В "Клавиатура" после выполнения этого кода будет же строка JSON ?

По идее да, единственное не понял зачем это:
Цитата(kosalex @ 26.02.18, 10:17) *
ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет)); 


Достаточно так (у меня в REST по крайней мере работает):
    Запись = Новый ЗаписьJSON;
    ЗаписатьJSON(Запись, ТелоЗапроса);
    Запись.Закрыть();


По поводу отправки двоичного файла, у меня есть такой вариант (это не телеграм, но работает), может что-то пригодится:
Код
Function SendJPGImageToServer(FilePath, Connecting, Parametres) Export
    
    FilePost        = New File(FilePath);
    Boundary        = StrReplace(String(New UUID()),"-","");
    FileContents    = Base64Строка(New BinaryData(FilePath));
    TmpFileName        = GetTempFileName();
    
    FileToSend = New TextWriter(TmpFileName, TextEncoding.ANSI, Chars.LF, False);
    FileToSend.WriteLine("--" + Boundary);
    FileToSend.WriteLine("Content-Disposition: form-data; name=""datafile""; filename=""" + FilePost.Name + """");
    FileToSend.WriteLine("Content-Type: image/jpg" + Chars.LF + Chars.LF);
    FileToSend.WriteLine(FileContents);
    FileToSend.WriteLine("--" + Boundary + "--");     
    FileToSend.Close();
    
    Stream            = New File(TmpFileName);
    StreamSize        = XMLString(Stream.Size());
    
    Headers = New Map;
    Headers.Insert("Content-Type", "multipart/form-data; boundary="+Boundary);
    Headers.Insert("Content-Length", StreamSize);
    
    Request = New HTTPRequest;
    Request.ResourceAddress    = Parametres.ServerPath + Parametres.AddParam;
    Request.Headers            = Headers;
    Request.SetBodyFileName(TmpFileName);
    
    Response = SendRequestToServer(Request, Connecting, Parametres.Errors);
    
    Return  Response;

EndFunction

Автор: kosalex 26.02.18, 11:37

Рабочий код! Проблема была в неправильном порядке и заполнении параметров. Определил сначала клавиатуру,а потом уже изображение! И ПОЛУЧИЛОСЬ! :-)

    ддКартинка = Блюдо.Ссылка.ОсновноеИзображение.Хранилище.Получить().ПолучитьДвоичныеДанные();
                
                времКаталог = КаталогВременныхФайлов();
                времФайлКартинки = ПолучитьИмяВременногоФайла("jpg");
                имяВремяФайла = СтрЗаменить(времФайлКартинки,времКаталог,"");
                                
                ддКартинка.Записать(времФайлКартинки);
                
                СтрокаСоединения = "/bot" + Константы.Токен.Получить() + "/sendPhoto";
                
                //Определяем массив для процедуры ОбъединитьФайлы
                МассивФайловДляОбъединения = Новый Массив;
                
                //Формируем начальный фрагмент файла POST-запроса
                ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
                ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.UTF8);
                
                //Формируем конечный фрагмент файла POST-запроса
                ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
                ФайлаОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.UTF8);
                
                ТекстДляОтправки = "";
                
                Boundary = "----" + Строка(Новый УникальныйИдентификатор());
                
                //ЧАТ++
                ТекстДляОтправки = ТекстДляОтправки + "--" + Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""chat_id"""+ Символы.ПС + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + СокрЛП(Формат(Клиент.Код,"ЧГ=0")) + Символы.ПС;
                //ЧАТ++
                
                //ПОДПИСЬ++  
                Подпись = "Наименование: " + Блюдо.Ссылка.Наименование + Символы.ПС + "Цена: " + Блюдо.Ссылка.Цена;  
                
                ТекстДляОтправки = ТекстДляОтправки + "--" + Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""caption""" + Символы.ПС + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + СокрЛП(Подпись) + Символы.ПС;
                //ПОДПИСЬ--
                                                                        
                //КЛАВИАТУРА++
                клСтруктура = Новый Структура;
                Строки = Новый Массив;
                Кнопки = Новый Массив;
                Кнопки.Добавить(Новый Структура("text, callback_data", "В корзину", Блюдо.Ссылка.Код));
                Строки.Добавить(Кнопки);    
                клСтруктура.Вставить("inline_keyboard",Строки);
                
                ЗаписьJSON = Новый ЗаписьJSON;
                ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет,,,ЭкранированиеСимволовJSON.Нет));  //Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет,,,ЭкранированиеСимволовJSON.СимволыВнеASCII)  
                ЗаписатьJSON(ЗаписьJSON,клСтруктура,,);
                Клавиатура = ЗаписьJSON.Закрыть();
                
                ТекстДляОтправки = ТекстДляОтправки + "--" +  Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""reply_markup""" + Символы.ПС+ Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + СокрЛП(Клавиатура) + Символы.ПС;
                //КЛАВИАТУРА--
                
                //ФОТО++
                ТекстДляОтправки = ТекстДляОтправки + "--" +  Boundary + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Disposition: form-data; name=""photo""; filename=""" + имяВремяФайла + """" + Символы.ПС;    
                ТекстДляОтправки = ТекстДляОтправки + "Content-Type: image/jpg" + Символы.ПС;
                //ФОТО--
                
                ФайлОтправкиНачало.ЗаписатьСтроку(ТекстДляОтправки);
                ФайлОтправкиНачало.Закрыть();
                
                МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);
                МассивФайловДляОбъединения.Добавить(времФайлКартинки);
                
                ТекстДляОтправки = "";
                
                ТекстДляОтправки = ТекстДляОтправки + Символы.ПС  + "--" +  Boundary+"--";
                ФайлаОтправкиКонец.ЗаписатьСтроку(ТекстДляОтправки);
                
                ФайлаОтправкиКонец.Закрыть();
                МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);
                
                ИмяФайлаОтправки = ПолучитьИмяВременногоФайла("txt");
                
                ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);
                
                HTTPЗапрос = Новый HTTPЗапрос;
                HTTPЗапрос.Заголовки.Вставить("Connection", "keep-alive");
                HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary="+Boundary);
                HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);    
                HTTPЗапрос.АдресРесурса = СтрокаСоединения;
                
                Результат = ОтправитьЗапросНаОбработкуВTelegramPOST(HTTPЗапрос);
                
                Для Каждого Файл Из МассивФайловДляОбъединения Цикл
                    УдалитьФайлы(Файл);    
                КонецЦикла;

Автор: pbahushevich 01.11.18, 14:38

kosalex @ 26.02.18, 11:37 * ,
отдельное спасибо за рабочий код!!!

Автор: Vofka 01.11.18, 15:21

pbahushevich, для спасибо у нас есть специальная кнопочка.

Автор: qSergey 14.01.21, 8:46

Цитата(kosalex @ 26.02.18, 11:37) *
kosalex

Хорошо написанный, сразу рабочий код, спасибо, добрый человек!

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua