diff --git a/src/cf/CommonModules/HttpОбщегоНазначения/Ext/Module.bsl b/src/cf/CommonModules/HttpОбщегоНазначения/Ext/Module.bsl
index d15b7c7..6a3c3db 100644
--- a/src/cf/CommonModules/HttpОбщегоНазначения/Ext/Module.bsl
+++ b/src/cf/CommonModules/HttpОбщегоНазначения/Ext/Module.bsl
@@ -69,6 +69,9 @@
Запрос.УстановитьТелоИзДвоичныхДанных(Данные.ДвоичныеДанные);
Запрос.Заголовки.Вставить("Content-Length", Формат(Данные.ДвоичныеДанные.Размер(), "ЧН=0; ЧГ="));
Запрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Данные.Разделитель);
+ Иначе
+ Запрос.Заголовки.Вставить("Content-Type","application/json");
+ Запрос.УстановитьТелоИзСтроки(HttpОбщегоНазначения.ОбъектВСтрокуJson(Данные));
КонецЕсли;
Иначе
Запрос.Заголовки.Вставить("Content-Type","application/json");
diff --git a/src/cf/CommonModules/ТелеграмМетодыВызовСервера/Ext/Module.bsl b/src/cf/CommonModules/ТелеграмМетодыВызовСервера/Ext/Module.bsl
index 8979916..e607a7c 100644
--- a/src/cf/CommonModules/ТелеграмМетодыВызовСервера/Ext/Module.bsl
+++ b/src/cf/CommonModules/ТелеграмМетодыВызовСервера/Ext/Module.bsl
@@ -1,8 +1,13 @@
#Область ПрограммныйИнтерфейс
-Функция SendMessage(ИдЧата, СообщениеДляОтправки) Экспорт
+Функция SendMessage(ИдЧата, СообщениеДляОтправки, Клавиатура = Неопределено) Экспорт
ТелоЗапроса = Новый Структура("chat_id, text", ИдЧата, СообщениеДляОтправки);
+
+ Если Клавиатура <> Неопределено Тогда
+ ТелоЗапроса.Вставить("reply_markup", Клавиатура);
+ КонецЕсли;
+
АдресРесурса = АдресРесурсаПоИмениМетода("sendMessage");
Возврат HttpОбщегоНазначения.ВыполнитьPostЗапрос(АдресРесурса,, ТелоЗапроса);
@@ -65,6 +70,24 @@
КонецФункции
+Функция SendPhoto(ИдЧата, ФайлДляОтправки, ИмяФайла, Надпись = Неопределено, БезУведомления = Ложь) Экспорт
+
+ АдресРесурса = АдресРесурсаПоИмениМетода("sendPhoto");
+ ПараметрыЗапроса = Новый Структура("chat_id", Формат(ИдЧата, "ЧН=0; ЧГ="));
+ Если Надпись <> Неопределено Тогда
+ ПараметрыЗапроса.Вставить("caption", Надпись);
+ КонецЕсли;
+ Если БезУведомления Тогда
+ ПараметрыЗапроса.Вставить("disable_notification", "true");
+ КонецЕсли;
+
+ Разделитель = СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
+ ДвоичныеДанныеФото = ДвоичныеДанныеФайла(ФайлДляОтправки, ИмяФайла, "image/jpeg", "photo", Разделитель);
+ ДанныеФото = Новый Структура("Разделитель, ДвоичныеДанные", Разделитель, ДвоичныеДанныеФото);
+ Возврат HttpОбщегоНазначения.ВыполнитьPostЗапрос(АдресРесурса, ПараметрыЗапроса, ДанныеФото);
+
+КонецФункции
+
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
@@ -83,6 +106,9 @@
Функция ДвоичныеДанныеДокумента(ИдЧата, Документ, Надпись = Неопределено, БезУведомления = Ложь, Разделитель)
+ //Параметры ИдЧата, Надпись, БезУведомления можно передавать также в параметрах запроса, а не в теле как здесь
+ // Отправка фото сделана именно так. Все значения, кроме непосредственно фото задаются в параметрах запроса.
+
Если Документ = Неопределено ИЛИ Не (Документ.Свойство("ДанныеФайла") И ТипЗнч(Документ.ДанныеФайла) = Тип("ДвоичныеДанные")) Тогда
ВызватьИсключение "Неверный параметр Документ: ожидается непустой объект, содержащий двоичные данные";
КонецЕсли;
@@ -105,7 +131,23 @@
КонецФункции
-Процедура ЗаписатьЭлементаЗапроса(ЗаписьДанных, Разделитель, ИмяПоля, Значение, ИмяФайла = Неопределено, ТипСодержимого = Неопределено)
+Функция ДвоичныеДанныеФайла(Файл, ИмяФайла, ТипСодержимого, ИмяПараметра, Разделитель)
+
+ Если Файл = Неопределено ИЛИ ТипЗнч(Файл) <> Тип("ДвоичныеДанные") Тогда
+ ВызватьИсключение "Неверный параметр Файл: ожидается непустой объект, содержащий двоичные данные";
+ КонецЕсли;
+
+ ТелоЗапроса = Новый ПотокВПамяти();
+ ЗаписьДанных = Новый ЗаписьДанных(ТелоЗапроса, , , Символы.ВК + Символы.ПС, "");
+ ЗаписатьЭлементаЗапроса(ЗаписьДанных, Разделитель, ИмяПараметра, Файл, ИмяФайла, ТипСодержимого);
+ ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--");
+ ЗаписьДанных.Закрыть();
+
+ Возврат ТелоЗапроса.ЗакрытьИПолучитьДвоичныеДанные();
+
+КонецФункции
+
+Процедура ЗаписатьЭлементаЗапроса(ЗаписьДанных, Разделитель, ИмяПараметра, Значение, ИмяФайла = Неопределено, ТипСодержимого = Неопределено)
Если Значение = Неопределено Тогда
Возврат;
@@ -113,9 +155,9 @@
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
Если ИмяФайла <> Неопределено Тогда
- ЗаписьДанных.ЗаписатьСтроку(СтрШаблон("Content-Disposition: form-data; name=%1; filename=%2", ИмяПоля, ИмяФайла));
+ ЗаписьДанных.ЗаписатьСтроку(СтрШаблон("Content-Disposition: form-data; name=%1; filename=%2", ИмяПараметра, ИмяФайла));
Иначе
- ЗаписьДанных.ЗаписатьСтроку(СтрШаблон("Content-Disposition: form-data; name=%1", ИмяПоля));
+ ЗаписьДанных.ЗаписатьСтроку(СтрШаблон("Content-Disposition: form-data; name=%1", ИмяПараметра));
КонецЕсли;
Если ТипСодержимого <> Неопределено Тогда
diff --git a/src/cf/CommonModules/ТелеграмОбщегоНазначения/Ext/Module.bsl b/src/cf/CommonModules/ТелеграмОбщегоНазначения/Ext/Module.bsl
index 5a7d52a..af6f68a 100644
--- a/src/cf/CommonModules/ТелеграмОбщегоНазначения/Ext/Module.bsl
+++ b/src/cf/CommonModules/ТелеграмОбщегоНазначения/Ext/Module.bsl
@@ -45,7 +45,13 @@
Функция ОбновленияТелеграм(ТелоЗапроса) Экспорт
- ДанныеОбновления = HttpОбщегоНазначения.СтрокаJsonВОбъект(ТелоЗапроса);
+ Если ТипЗнч(ТелоЗапроса) = Тип("Соответствие") Тогда
+ ДанныеОбновления = ТелоЗапроса;
+ ИначеЕсли ТипЗнч(ТелоЗапроса) = Тип("Строка") Тогда
+ ДанныеОбновления = HttpОбщегоНазначения.СтрокаJsonВОбъект(ТелоЗапроса);
+ Иначе
+ Возврат Неопределено;
+ КонецЕсли;
МассивСообщенийТелеграм = Новый Массив;
diff --git a/src/cf/CommonModules/ТелеграмРаботаСКлавиатурой.xml b/src/cf/CommonModules/ТелеграмРаботаСКлавиатурой.xml
new file mode 100644
index 0000000..d64fe13
--- /dev/null
+++ b/src/cf/CommonModules/ТелеграмРаботаСКлавиатурой.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ ТелеграмРаботаСКлавиатурой
+
+
+ ru
+ Телеграм работа с клавиатурой
+
+
+
+ false
+ false
+ true
+ true
+ false
+ true
+ false
+ DontUse
+
+
+
\ No newline at end of file
diff --git a/src/cf/CommonModules/ТелеграмРаботаСКлавиатурой/Ext/Module.bsl b/src/cf/CommonModules/ТелеграмРаботаСКлавиатурой/Ext/Module.bsl
new file mode 100644
index 0000000..91fa2f3
--- /dev/null
+++ b/src/cf/CommonModules/ТелеграмРаботаСКлавиатурой/Ext/Module.bsl
@@ -0,0 +1,45 @@
+Функция КлавиатураОтвета(Клавиатура, Компактная = Ложь, Одноразовая = Ложь) Экспорт
+
+ СоответствиеКлавиатуры = Новый Соответствие();
+
+ СоответствиеКлавиатуры.Вставить("keyboard", Клавиатура);
+
+ Если Компактная Тогда
+ СоответствиеКлавиатуры.Вставить("resize_keyboard", Компактная);
+ КонецЕсли;
+
+ Если Одноразовая Тогда
+ СоответствиеКлавиатуры.Вставить("one_time_keyboard", Одноразовая);
+ КонецЕсли;
+
+ Возврат СоответствиеКлавиатуры;
+
+КонецФункции
+
+Функция КнопкаКлавиатуры(Надпись) Экспорт
+
+ СоответствиеКнопка = Новый Соответствие;
+ СоответствиеКнопка.Вставить("text", ?(НЕ ЗначениеЗаполнено(Надпись), ">", Надпись));
+ Возврат СоответствиеКнопка;
+
+КонецФункции
+
+Функция РядКнопок(СписокНаименованийКнопокСтрокой) Экспорт
+
+ Результат = Новый Массив;
+ МассивНаименованийКнопок = СтрРазделить(СписокНаименованийКнопокСтрокой, ";");
+
+ Если МассивНаименованийКнопок.Количество() = 0 Тогда
+ Возврат Результат;
+ КонецЕсли;
+
+ Для каждого НадписьКнопки Из МассивНаименованийКнопок Цикл
+ Результат.Добавить(КнопкаКлавиатуры(НадписьКнопки));
+ КонецЦикла;
+
+ Возврат Результат;
+
+КонецФункции
+
+
+
diff --git a/src/cf/CommonPictures/КартинкаБот.xml b/src/cf/CommonPictures/КартинкаБот.xml
new file mode 100644
index 0000000..bd52136
--- /dev/null
+++ b/src/cf/CommonPictures/КартинкаБот.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ КартинкаБот
+
+
+ ru
+ Картинка бот
+
+
+
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/src/cf/CommonPictures/КартинкаБот/Ext/Picture.xml b/src/cf/CommonPictures/КартинкаБот/Ext/Picture.xml
new file mode 100644
index 0000000..0d1c201
--- /dev/null
+++ b/src/cf/CommonPictures/КартинкаБот/Ext/Picture.xml
@@ -0,0 +1,7 @@
+
+
+
+ Picture.png
+ false
+
+
\ No newline at end of file
diff --git a/src/cf/CommonPictures/КартинкаБот/Ext/Picture/Picture.png b/src/cf/CommonPictures/КартинкаБот/Ext/Picture/Picture.png
new file mode 100644
index 0000000..a3d083e
Binary files /dev/null and b/src/cf/CommonPictures/КартинкаБот/Ext/Picture/Picture.png differ
diff --git a/src/cf/Configuration.xml b/src/cf/Configuration.xml
index b8e1c15..4f2a242 100644
--- a/src/cf/Configuration.xml
+++ b/src/cf/Configuration.xml
@@ -246,12 +246,14 @@
Русский
ТелеграмБот
+ КартинкаБот
HttpОбщегоНазначения
ТелеграмМетодыВызовСервера
ТелеграмОбщегоНазначения
ТелеграмПовторноеИспользование
ТелеграмРегламент
РаботаСФайламиКлиентСервер
+ ТелеграмРаботаСКлавиатурой
HTTPСервис_Telegram
ПроверкаОбновленийТелеграм
ТелеграмТокен
diff --git a/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form.xml b/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form.xml
index 89e8941..31375ae 100644
--- a/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form.xml
+++ b/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form.xml
@@ -116,6 +116,7 @@
Vertical
+ StrongSeparation
@@ -129,10 +130,39 @@
Form.Command.СкачатьФайл
-
+
+
+
+
+ ru
+ Send document
+
+
+
+
+ ru
+ Send document
+
+
+ StrongSeparation
+
+
+
+ ИдЧата
+ true
+
+
+
+
+
@@ -210,6 +240,25 @@
ИдФайла
+
+
+
+ ru
+ Ид чата
+
+
+
+ xs:decimal
+
+ 15
+ 0
+ Any
+
+
+
+ ИдЧата
+
+
@@ -302,20 +351,35 @@
СкачатьФайл
-
+
ru
- Прочитать файл
+ Send document
ru
- Прочитать файл
+ Send document
- ПрочитатьФайл
+ SendDocument
+
+
+
+
+ ru
+ Send photo
+
+
+
+
+ ru
+ Send photo
+
+
+ SendPhoto
\ No newline at end of file
diff --git a/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form/Module.bsl b/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form/Module.bsl
index 6fe9738..eddcbaf 100644
--- a/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form/Module.bsl
+++ b/src/cf/DataProcessors/РаботаССообщениями/Forms/Форма/Ext/Form/Module.bsl
@@ -1,30 +1,34 @@
&НаКлиенте
Процедура ПолучитьСообщения(Команда)
- //Сообщения = "";
- //Ответ = ТелеграмМетодыВызовСервера.GetUpdates();
- //Если НЕ Ответ = Неопределено Тогда
- // Сообщения = HttpОбщегоНазначения.ФорматированныйJson(Ответ);
- //КонецЕсли;
-
- ПолучитьСообщенияНаСервере();
+ Ответ = ПолучитьСообщенияНаСервере();
+ ВывестиОтвет(Ответ);
КонецПроцедуры
-
&НаСервереБезКонтекста
-Процедура ПолучитьСообщенияНаСервере()
+Функция ПолучитьСообщенияНаСервере()
Ответ = ТелеграмМетодыВызовСервера.GetUpdates();
- Если Ответ <> Неопределено Тогда
- МассивСообщенийТелеграм = ТелеграмОбщегоНазначения.ОбновленияТелеграм(Ответ);
+
+ Если Ответ.Успех Тогда
+ МассивРядов = Новый Массив;
+ МассивКнопок = ТелеграмРаботаСКлавиатурой.РядКнопок("один;два;три");
+ МассивРядов.Добавить(МассивКнопок);
+ МассивКнопок = ТелеграмРаботаСКлавиатурой.РядКнопок("Выбрать конфигурацию;Актуальная версия;Калькулятор обновлений");
+ МассивРядов.Добавить(МассивКнопок);
+ Клавиатура = ТелеграмРаботаСКлавиатурой.КлавиатураОтвета(МассивРядов, Истина, Истина);
+
+ МассивСообщенийТелеграм = ТелеграмОбщегоНазначения.ОбновленияТелеграм(Ответ.Тело);
Для каждого СообщениеТелеграм Из МассивСообщенийТелеграм Цикл
ТелеграмОбщегоНазначения.СохранитьСообщениеВБазу(СообщениеТелеграм);
- //ТелеграмМетодыВызовСервера.SendMessage(СообщениеТелеграм.ИдЧата, СообщениеТелеграм.Сообщение.text)
+ ТелеграмМетодыВызовСервера.SendMessage(СообщениеТелеграм.ИдЧата, СообщениеТелеграм.Сообщение.text, Клавиатура);
КонецЦикла;
КонецЕсли;
-КонецПроцедуры
+ Возврат Ответ;
+
+КонецФункции
&НаКлиенте
Процедура getWebhookInfo(Команда)
@@ -66,44 +70,21 @@
КонецПроцедуры
-
&НаКлиенте
Процедура ВывестиОтвет(Ответ)
+ ТекстСообщения = СтрШаблон("Выполнено %1.%2%3", ?(Ответ.Успех, "успешно", "с ошибкой"), Символы.ПС, Ответ.Описание);
+
Сообщение = Новый СообщениеПользователю;
- Сообщение.Текст = HttpОбщегоНазначения.ФорматированныйJson(Ответ);
+ Сообщение.Текст = ТекстСообщения;
Сообщение.Сообщить();
КонецПроцедуры
-
-//&НаСервереБезКонтекста
-//Функция СкачатьФайлНаСервере(ПутьКФайлуНаСервере)
-//
-// АдресРесурса = СтрШаблон("file/bot%1/%2",
-// ТелеграмПовторноеИспользование.ТелеграмТокен(),
-// ПутьКФайлуНаСервере);
-// Ответ = HttpОбщегоНазначения.ВыполнитьGetЗапросДвоичныеДанные(АдресРесурса);
-// МенеджерЗаписи = РегистрыСведений.ТелеграмФайлы.СоздатьМенеджерЗаписи();
-// //МенеджерЗаписи.ИдСообщения = 336;
-// //МенеджерЗаписи.Данные = Новый ХранилищеЗначения(Ответ, Новый СжатиеДанных(0));
-// //МенеджерЗаписи.ИмяФайла = "13_05_2025_09_42_108907060608184446656.json";
-//
-// МенеджерЗаписи.ИдСообщения = 339;
-// МенеджерЗаписи.Данные = Новый ХранилищеЗначения(Ответ, Новый СжатиеДанных(0));
-// МенеджерЗаписи.ИмяФайла = "test.pdf";
-//
-// МенеджерЗаписи.Записать();
-//
-// Возврат Ответ;
-//
-//КонецФункции
-
-
&НаКлиенте
Процедура СкачатьФайл(Команда)
- //ИдФайла = "BQACAgIAAxkBAAIBUmgkRZKtR_4WXvoykjdfXKTFHCvdAAItegACYyUhSQ9mNituwQR1NgQ";
+
СкачатьФайлНаСервере(ИдФайла);
@@ -124,7 +105,6 @@
&НаСервереБезКонтекста
Процедура СкачатьФайлНаСервере(ИдФайла)
-
НовыйДокумент = Справочники.ТелеграмДокумент.СоздатьЭлемент();
НовыйДокумент.Наименование = "Тестовый документ";
НовыйДокумент.id = "AgADLXoAAmMlIUk";
@@ -133,9 +113,9 @@
НовыйДокумент.mime_type = "application/pdf";
НовыйДокумент.file_size = 811482;
- ДанныеДокумента = ТелеграмОбщегоНазначения.ДанныеДокументаПоИд(ИдФайла);
- Если ДанныеДокумента <> Неопределено Тогда
- НовыйДокумент.ДанныеФайла = Новый ХранилищеЗначения(ДанныеДокумента);
+ Ответ = ТелеграмОбщегоНазначения.ДанныеДокументаПоИд(ИдФайла);
+ Если Ответ.Успех Тогда
+ НовыйДокумент.ДанныеФайла = Новый ХранилищеЗначения(Ответ.Тело);
КонецЕсли;
НовыйДокумент.Записать();
@@ -146,60 +126,46 @@
КонецПроцедуры
-
-
&НаКлиенте
-Процедура ПрочитатьФайл(Команда)
+Процедура SendDocument(Команда)
+
+ ДанныеДокумента = ДанныеДокументаСервер();
+ Ответ = ТелеграмМетодыВызовСервера.SendDocument(ИдЧата, ДанныеДокумента, "Отправлен документ");
- ДанныеФайла = ПолучитьДанныеФайла();
- Если ДанныеФайла <> Неопределено Тогда
- Если ДанныеФайла.Свойство("ДвоичныеДанные") И ДанныеФайла.Свойство("ИмяФайла") Тогда
- ИмяВременногоФайла = ПолучитьИмяВременногоФайла(ПолучитьРасширениеИмениФайла(ДанныеФайла.ИмяФайла));
- ДанныеФайла.ДвоичныеДанные.Записать(ИмяВременногоФайла);
- ЗапуститьПриложениеАсинх(ИмяВременногоФайла);
- КонецЕсли;
- КонецЕсли;
-
КонецПроцедуры
&НаСервереБезКонтекста
-Функция ПолучитьДанныеФайла()
-
+Функция ДанныеДокументаСервер()
+
Запрос = Новый Запрос;
Запрос.Текст =
- "ВЫБРАТЬ
- | ТелеграмФайлы.Данные КАК Данные,
- | ТелеграмФайлы.ИмяФайла КАК ИмяФайла
- |ИЗ
- | РегистрСведений.ТелеграмФайлы КАК ТелеграмФайлы
- |ГДЕ
- | ТелеграмФайлы.ИдСообщения = &ИдСообщения";
-
- //Запрос.УстановитьПараметр("ИдСообщения", 336);
- Запрос.УстановитьПараметр("ИдСообщения", 338);
+ "ВЫБРАТЬ
+ | ТелеграмДокумент.ДанныеФайла КАК ДанныеФайла,
+ | ТелеграмДокумент.file_name КАК ИмяФайла
+ |ИЗ
+ | Справочник.ТелеграмДокумент КАК ТелеграмДокумент";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
- ДвоичныеДанные = ВыборкаДетальныеЗаписи.Данные.Получить();
- ИмяФайла = ВыборкаДетальныеЗаписи.ИмяФайла;
- Возврат Новый Структура("ДвоичныеДанные, ИмяФайла", ДвоичныеДанные, ИмяФайла);
+ Возврат Новый Структура("ИмяФайла, ДанныеФайла", ВыборкаДетальныеЗаписи.ИмяФайла, ВыборкаДетальныеЗаписи.ДанныеФайла.Получить());
КонецЕсли;
- Возврат Неопределено;
-
КонецФункции
+&НаКлиенте
+Процедура SendPhoto(Команда)
+
+ ДанныеКартинки = ДанныеКартинки();
+ Ответ = ТелеграмМетодыВызовСервера.SendPhoto(ИдЧата, ДанныеКартинки, "telegram_bot.jpg", "Отправлено фото");
+
+КонецПроцедуры
+
&НаСервереБезКонтекста
-Функция ПолучитьРасширениеИмениФайла(Знач ИмяФайла) Экспорт
+Функция ДанныеКартинки()
- РасширениеФайла = "";
- МассивСтрок = СтрРазделить(ИмяФайла, ".", Ложь);
- Если МассивСтрок.Количество() > 1 Тогда
- РасширениеФайла = МассивСтрок[МассивСтрок.Количество() - 1];
- КонецЕсли;
- Возврат РасширениеФайла;
+ Возврат БиблиотекаКартинок.КартинкаБот.ПолучитьДвоичныеДанные();
-КонецФункции
\ No newline at end of file
+КонецФункции
diff --git a/src/cf/Subsystems/ТелеграмБот.xml b/src/cf/Subsystems/ТелеграмБот.xml
index 97574b8..47928dc 100644
--- a/src/cf/Subsystems/ТелеграмБот.xml
+++ b/src/cf/Subsystems/ТелеграмБот.xml
@@ -27,7 +27,7 @@
Constant.ЛогироватьHttpЗапросы
Document.ЛогHttpЗапроса
Catalog.ТелеграмДокумент
- c3c88554-5bc5-41b7-ae33-7a29b983d784
+ CommonPicture.КартинкаБот
diff --git a/src/cf/VERSION b/src/cf/VERSION
index 253c5c1..5cbcaf5 100644
--- a/src/cf/VERSION
+++ b/src/cf/VERSION
@@ -1,2 +1,2 @@
-3
+4