1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-11-25 22:12:29 +02:00

Main build (Jenkins)

This commit is contained in:
Vitaly the Alpaca (bot)
2025-10-21 21:43:05 +03:00
parent 8f5694a5d3
commit cdef2d02ab
1692 changed files with 118757 additions and 12073 deletions

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="457991ad-c2ad-49b8-a26a-9fc83c8a7d11">
<Properties>
<Name>OPI_Airtable</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI airtable</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Airtable (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Airtable из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,695 @@
// OneScript: ./OInt/core/Modules/OPI_Airtable.os
// Lib: Airtable
// CLI: airtable
// Keywords: airtable
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область РаботаСБазами
// Получить список баз
// Получает список доступных баз
//
// Параметры:
// Токен - Строка - Токен - token
// Отступ - Строка - Идентификатор следующей страницы списка баз из перыдудщего запроса - offset
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ПолучитьСписокБаз(Знач Токен, Знач Отступ = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Отступ);
URL = "https://api.airtable.com/v0/meta/bases";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("offset", Отступ, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить таблицы базы
// Получает схему таблиц базы
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы - base
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ПолучитьТаблицыБазы(Знач Токен, Знач База) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
URL = "https://api.airtable.com/v0/meta/bases/" + База + "/tables";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Создать базу
// Создает новую базу данных
//
// Параметры:
// Токен - Строка - Токен - token
// РабочееПространство - Строка - Идентификатор рабочего пространства - ws
// Наименование - Строка - Наименование новой базы - title
// КоллекцияТаблиц - Соответствие Из КлючИЗначение - Описание таблиц: Ключ > имя, Значение > массив полей - tablesdata
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция СоздатьБазу(Знач Токен, Знач РабочееПространство, Знач Наименование, Знач КоллекцияТаблиц) Экспорт
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(КоллекцияТаблиц);
Если Не ТипЗнч(КоллекцияТаблиц) = Тип("Структура")
И Не ТипЗнч(КоллекцияТаблиц) = Тип("Соответствие") Тогда
ВызватьИсключение "Ошибка в данных коллекции таблиц";
КонецЕсли;
URL = "https://api.airtable.com/v0/meta/bases";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
МассивТаблиц = Новый Массив;
Для Каждого Таблица Из КоллекцияТаблиц Цикл
Описание = СформироватьОписаниеТаблицы(Таблица.Ключ, Таблица.Значение);
МассивТаблиц.Добавить(Описание);
КонецЦикла;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("name" , Наименование , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("tables" , МассивТаблиц , "Массив", Параметры);
OPI_Инструменты.ДобавитьПоле("workspaceId", РабочееПространство, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСТаблицами
// Создать таблицу
// Создает новую таблицу в базе
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы - base
// Наименование - Строка - Наименование новой таблицы - title
// МассивПолей - Массив Из Структура - Массив описаний полей - fieldsdata
// Описание - Строка - Описание таблицы - description
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция СоздатьТаблицу(Знач Токен, Знач База, Знач Наименование, Знач МассивПолей, Знач Описание = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
URL = "https://api.airtable.com/v0/meta/bases/" + База + "/tables";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = СформироватьОписаниеТаблицы(Наименование, МассивПолей, Описание);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Изменить таблицу
// Изменяет наименование и|или описание базы
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы - base
// Таблица - Строка - Идентификатор таблицы - table
// Наименование - Строка - Новое наименование - title
// Описание - Строка - Новое описание - description
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ИзменитьТаблицу(Знач Токен, Знач База, Знач Таблица, Знач Наименование = "", Знач Описание = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
URL = "https://api.airtable.com/v0/meta/bases/" + База + "/tables/" + Таблица;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("name" , Наименование, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("description", Описание , "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.PatchСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСПолями
// Создать поле
// Создет новое поле в таблице
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы - base
// Таблица - Строка - Идентификатор таблицы - table
// СтруктураПоля - Структура Из КлючИЗначение - Описание нового поля - fielddata
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция СоздатьПоле(Знач Токен, Знач База, Знач Таблица, Знач СтруктураПоля) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(СтруктураПоля);
Если Не ТипЗнч(СтруктураПоля) = Тип("Структура")
И Не ТипЗнч(СтруктураПоля) = Тип("Соответствие") Тогда
ВызватьИсключение "Ошибка в данных описания поля";
КонецЕсли;
URL = "https://api.airtable.com/v0/meta/bases/" + База + "/tables/" + Таблица + "/fields";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, СтруктураПоля, Заголовки);
Возврат Ответ;
КонецФункции
// Изменить поле
// Изменяет имя и|или описание существующего поля таблицы
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы База - base
// Таблица - Строка - Идентификатор таблицы - table
// Поле - Строка - Идентификатор поля - field
// Наименование - Строка - Новое наименование - title
// Описание - Строка - Новое описание - description
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ИзменитьПоле(Знач Токен, Знач База, Знач Таблица, Знач Поле, Знач Наименование = "", Знач Описание = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Поле);
URL = "https://api.airtable.com/v0/meta/bases/"
+ База
+ "/tables/"
+ Таблица
+ "/fields/"
+ Поле;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура();
OPI_Инструменты.ДобавитьПоле("name" , Наименование, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("description", Описание , "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.PatchСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить поле (строковое)
// Получает описание поля строкового типа
//
// Параметры:
// Наименование - Строка - Наименование нового поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеСтроковое(Знач Наименование) Экспорт
Возврат ОписаниеПримитивногоПоля(Наименование, "richText");
КонецФункции
// Получить поле (числовое)
// Получает описание поля числового типа
//
// Параметры:
// Наименование - Строка - Наименование нового поля - title
// Точность - Число,Строка - Число знаков после запятой - precision
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеНомера(Знач Наименование, Знач Точность = 0) Экспорт
OPI_ПреобразованиеТипов.ПолучитьЧисло(Точность);
СтруктураОпций = Новый Структура("precision", Точность);
Возврат ОписаниеПримитивногоПоля(Наименование, "number", СтруктураОпций);
КонецФункции
// Получить поле (файл)
// Получает описание поля файлового типа
//
// Параметры:
// Наименование - Строка - Наименование поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеВложения(Знач Наименование) Экспорт
Возврат ОписаниеПримитивногоПоля(Наименование, "multipleAttachments");
КонецФункции
// Получить поле (флажок)
// Получает описание поля типа булево
//
// Параметры:
// Наименование - Строка - Наименование поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеФлажка(Знач Наименование) Экспорт
СтруктураОпций = Новый Структура("icon,color", "check", "yellowBright");
Возврат ОписаниеПримитивногоПоля(Наименование, "checkbox", СтруктураОпций);
КонецФункции
// Получить поле (дата)
// Получает описание поля типа дата
//
// Параметры:
// Наименование - Строка - Наименование поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеДаты(Знач Наименование) Экспорт
СтруктураФормата = Новый Структура("format,name", "YYYY-MM-DD", "iso");
СтруктураОпций = Новый Структура("dateFormat", СтруктураФормата);
Возврат ОписаниеПримитивногоПоля(Наименование, "date", СтруктураОпций);
КонецФункции
// Получить поле (email)
// Получает описание поля с электронной почтой
//
// Параметры:
// Наименование - Строка - Наименование поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеПочты(Знач Наименование) Экспорт
Возврат ОписаниеПримитивногоПоля(Наименование, "email");
КонецФункции
// Получить поле (телефон)
// Получает описание поля с номером телефона
//
// Параметры:
// Наименование - Строка - Наименование поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеТелефона(Знач Наименование) Экспорт
Возврат ОписаниеПримитивногоПоля(Наименование, "phoneNumber");
КонецФункции
// Получить поле (url)
// Получает описание поля с URL
//
// Параметры:
// Наименование - Строка - Наименование поля - title
//
// Возвращаемое значение:
// Структура - Описание поля
Функция ПолучитьПолеСсылки(Знач Наименование) Экспорт
Возврат ОписаниеПримитивногоПоля(Наименование, "url");
КонецФункции
#КонецОбласти
#Область РаботаСЗаписями
// Получить список записей
// Получает список записей выбранной таблицы
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Отступ - Строка - Иднтификатор следующей страницы данных из предыдущего запроса - offset
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ПолучитьСписокЗаписей(Знач Токен, Знач База, Знач Таблица, Знач Отступ = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура();
OPI_Инструменты.ДобавитьПоле("offset", Отступ, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить запись
// Получает данные строки таблицы по идентификатору
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Запись - Строка - Идентификатор записи в таблице - record
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ПолучитьЗапись(Знач Токен, Знач База, Знач Таблица, Знач Запись) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Запись);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица + "/" + Запись;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Создать записи
// Создает одну или массив записей по описанию или массиву описаний значений полей
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Данные - Структура, Массив из Структура - Набор или массив наборов пар Ключ : Значение > Поле : Показатель - data
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция СоздатьЗаписи(Знач Токен, Знач База, Знач Таблица, Знач Данные) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Данные);
Параметры = Новый Структура();
ДобавитьОписаниеДанных(Данные, Параметры);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Удалить записи
// Удаляет одну или массив записей по идентификаторам
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Записи - Строка, Массив из Строка - Идентификатор или массив индентификаторов записей - records
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция УдалитьЗаписи(Знач Токен, Знач База, Знач Таблица, Знач Записи) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьМассив(Записи);
СтрокаЗаписей = "";
Для Каждого Запись Из Записи Цикл
СтрокаЗаписей = СтрокаЗаписей
+ ?(ЗначениеЗаполнено(СтрокаЗаписей), "&", "?")
+ "records[]="
+ OPI_Инструменты.ЧислоВСтроку(Запись);
КонецЦикла;
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица + СтрокаЗаписей;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСКомментариями
// Получить комментарии
// Получает список комментариев к записи в таблице
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Запись - Строка - Идентификатор записи в таблице - record
// Отступ - Строка - Иднтификатор следующей страницы данных из предыдущего запроса - offset
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ПолучитьКомментарии(Знач Токен, Знач База, Знач Таблица, Знач Запись, Знач Отступ = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Запись);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица + "/" + Запись + "/comments";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура();
OPI_Инструменты.ДобавитьПоле("offset", Отступ, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Создать комментарий
// Создает комментарий к записи в таблице
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Запись - Строка - Идентификатор записи в таблице - record
// Текст - Строка - Текст комментария - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция СоздатьКомментарий(Знач Токен, Знач База, Знач Таблица, Знач Запись, Знач Текст) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Запись);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица + "/" + Запись + "/comments";
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура();
OPI_Инструменты.ДобавитьПоле("text", Текст, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Изменить комментарий
// Изменяет текст существующего комментария
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Запись - Строка - Идентификатор записи в таблице - record
// Комментарий - Строка - Идентификатор комментария - comment
// Текст - Строка - Новый текст комментария - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция ИзменитьКомментарий(Знач Токен, Знач База, Знач Таблица, Знач Запись, Знач Комментарий, Знач Текст) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Запись);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Комментарий);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица + "/" + Запись + "/comments/" + Комментарий;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура();
OPI_Инструменты.ДобавитьПоле("text", Текст, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.PatchСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Удалить комментарий
// Удаляет комментарий к записи таблицы
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - Идентификатор базы данных - base
// Таблица - Строка - Идентификатор таблицы - table
// Запись - Строка - Идентификатор записи в таблице - record
// Комментарий - Строка - Идентификатор комментария - comment
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Airtable
Функция УдалитьКомментарий(Знач Токен, Знач База, Знач Таблица, Знач Запись, Знач Комментарий) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Таблица);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Запись);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Комментарий);
URL = "https://api.airtable.com/v0/" + База + "/" + Таблица + "/" + Запись + "/comments/" + Комментарий;
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ПолучитьЗаголовокАвторизации(Знач Токен)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + Токен);
Возврат Заголовки;
КонецФункции
Функция СформироватьОписаниеТаблицы(Знач Наименование, Знач МассивПолей, Знач Описание = "")
OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивПолей);
ОписаниеТаблицы = Новый Структура("name,fields", Наименование, МассивПолей);
OPI_Инструменты.ДобавитьПоле("description", Описание, "Строка", ОписаниеТаблицы);
Возврат ОписаниеТаблицы;
КонецФункции
Функция ОписаниеПримитивногоПоля(Знач Наименование, Знач Тип, Знач Опции = "")
СтруктураПоля = Новый Структура();
OPI_Инструменты.ДобавитьПоле("name" , Наименование, "Строка" , СтруктураПоля);
OPI_Инструменты.ДобавитьПоле("type" , Тип , "Строка" , СтруктураПоля);
OPI_Инструменты.ДобавитьПоле("options", Опции , "Коллекция", СтруктураПоля);
Возврат СтруктураПоля;
КонецФункции
Процедура ДобавитьОписаниеДанных(Знач Данные, Параметры)
Если ТипЗнч(Данные) = Тип("Массив") Тогда
МассивОтправки = Новый Массив;
Для Каждого ОписаниеЗаписи Из Данные Цикл
МассивОтправки.Добавить(Новый Структура("fields", ОписаниеЗаписи));
КонецЦикла;
OPI_Инструменты.ДобавитьПоле("records", МассивОтправки, "Массив", Параметры);
Иначе
OPI_Инструменты.ДобавитьПоле("fields", Данные, "Коллекция", Параметры);
КонецЕсли;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="496e68cd-c70d-4c15-aa9e-c2aad28abf8a">
<Properties>
<Name>OPI_Bitrix24</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Bitrix24 (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Bitrix24 из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="6f50b040-6438-4128-b861-8756e188e607">
<Properties>
<Name>OPI_BuildHash</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Build hash (ОПИ</v8:content>
</v8:item>
</Synonym>
<Comment>Служебный модуль, помогающий определить актуальность проекта исходному коду</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,35 @@
// OneScript: ./OInt/tools/Modules/internal/Modules/internal/Modules/OPI_BuildHash.os
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
//@skip-check module-structure-method-in-regions
Function GetHashSum() Export
LastBuildHash = "1BA99EE51AF549BDAC8002EAA5C26D02BC5B240791BE92424CCB3B207E5919F4";
Return LastBuildHash;
EndFunction

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="e5232cd3-87cc-4942-bf6c-d52823affb45">
<Properties>
<Name>OPI_CDEK</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>CDEK (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы со СДЭК из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="66ce7792-41e5-47e4-bfad-2dcff1c96287">
<Properties>
<Name>OPI_Dropbox</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI dropbox</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Dropbox (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Dropbox из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,988 @@
// OneScript: ./OInt/core/Modules/OPI_Dropbox.os
// Lib: Dropbox
// CLI: dropbox
// Keywords: dropbox
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область АккаунтИАвторизация
// Получить ссылку авторизации
// Генерирует ссылку авторизации для перехода в браузере
//
// Параметры:
// КлючПриложения - Строка - Ключ приложения - appkey
//
// Возвращаемое значение:
// Строка - URL для перехода в браузере
Функция ПолучитьСсылкуАвторизации(Знач КлючПриложения) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(КлючПриложения);
Возврат "https://www.dropbox.com/oauth2/authorize?client_id="
+ КлючПриложения
+ "&response_type=code&token_access_type=offline";
КонецФункции
// Получить токен
// Полеучает токен на основе кода со страницы ПолучитьСсылкуАвторизации
//
// Параметры:
// КлючПриложения - Строка - Ключ приложения - appkey
// СекретПриложения - Строка - Секрет приложения - appsecret
// Код - Строка - Код со страницы авторизации - code
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьТокен(Знач КлючПриложения, Знач СекретПриложения, Знач Код) Экспорт
URL = "https://api.dropbox.com/oauth2/token";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("code" , Код , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("grant_type", "authorization_code", "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьFormТело(Параметры)
.ДобавитьBasicАвторизацию(КлючПриложения, СекретПриложения)
.ОбработатьЗапрос("POST")
.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Ответ;
КонецФункции
// Обновить токен
// Получает новый токен на основе рефреш токена
//
// Параметры:
// КлючПриложения - Строка - Ключ приложения - appkey
// СекретПриложения - Строка - Секрет приложения - appsecret
// РефрешТокен - Строка - Рефреш токен - refresh
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ОбновитьТокен(Знач КлючПриложения, Знач СекретПриложения, Знач РефрешТокен) Экспорт
Строка_ = "Строка";
URL = "https://api.dropbox.com/oauth2/token";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("refresh_token", РефрешТокен , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("grant_type" , "refresh_token" , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("client_id" , КлючПриложения , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("client_secret", СекретПриложения, Строка_, Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, , Ложь);
Возврат Ответ;
КонецФункции
// Получить информацию об аккаунте
// Получает информацию об аккаунте
//
// Параметры:
// Токен - Строка - Токен - token
// Аккаунт - Строка - ID аккаунта. Текущий аккаунт токена, если не заполнено - account
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьИнформациюОбАккаунте(Знач Токен, Знач Аккаунт = "") Экспорт
Если ЗначениеЗаполнено(Аккаунт) Тогда
Результат = ПолучитьАккаунт(Токен, Аккаунт);
Иначе
Результат = ПолучитьСвойАккаунт(Токен);
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить данные использования пространства
// Получает информацию о количестве использованного дискового пространства
//
// Параметры:
// Токен - Строка - Токен - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьДанныеИспользованияПространства(Знач Токен) Экспорт
URL = "https://api.dropboxapi.com/2/users/get_space_usage";
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьДвоичноеТело("null")
.УстановитьЗаголовки(Заголовки)
.УстановитьТипДанных("text/plain; charset=dropbox-cors-hack")
.ОбработатьЗапрос("POST")
.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСФайламиИКаталогами
// Получить информацию об объекте
// Получает информацию о файле или каталоге
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту - path
// Подробно - Булево - Добавляет дополнительные поля информации для медиафайлов - detail
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьИнформациюОбОбъекте(Знач Токен, Знач Путь, Знач Подробно = Ложь) Экспорт
URL = "https://api.dropboxapi.com/2/files/get_metadata";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path" , Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("include_media_info", Подробно, "Булево", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить список файлов папки
// Получает список первых файлов каталога или продолжает получение следующих при указании курсора
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к каталогу. Необязателен, если указан курсор - path
// Подробно - Булево - Добавляет дополнительные поля информации для медиафайлов - detail
// Курсор - Строка - Курсор из предыдущего запроса для получения следующего набора файлов - cursor
//
// Возвращаемое значение:
// HTTPОтвет - Получить список файлов папки
Функция ПолучитьСписокФайловПапки(Знач Токен, Знач Путь = "", Знач Подробно = Ложь, Знач Курсор = "") Экспорт
Если Не ЗначениеЗаполнено(Курсор) Тогда
URL = "https://api.dropboxapi.com/2/files/list_folder";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path" , Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("include_media_info", Подробно , "Булево", Параметры);
Иначе
URL = "https://api.dropboxapi.com/2/files/list_folder/continue";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("cursor", Курсор, "Строка", Параметры);
КонецЕсли;
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить превью
// Получает PDF или HTML превью объекта (только для токументов)
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту - path
//
// Возвращаемое значение:
// ДвоичныеДанные - превью документа
Функция ПолучитьПревью(Знач Токен, Знач Путь) Экспорт
URL = "https://content.dropboxapi.com/2/files/get_preview";
Ответ = ОбработатьОбъект(Токен, URL, Путь, Истина);
Возврат Ответ;
КонецФункции
// Загрузить файл
// Загружает файл на облачный диск
//
// Параметры:
// Токен - Строка - Токен - token
// Файл - Строка, ДвоичныеДанные - Данные файл для загрузки - file
// Путь - Строка - Путь сохранения на Dropbox - path
// Перезаписывать - Булево - Перезаписывать файл при конфликте путей - overwrite
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ЗагрузитьФайл(Знач Токен, Знач Файл, Знач Путь, Знач Перезаписывать = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
OPI_ПреобразованиеТипов.ПолучитьБулево(Перезаписывать);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Режим = ?(Перезаписывать, "overwrite", "add");
Размер = Файл.Размер();
Граница = 100000000;
Если Размер > Граница Тогда
Ответ = ЗагрузитьБольшойФайл(Токен, Файл, Путь, Режим);
Иначе
Ответ = ЗагрузитьМалыйФайл(Токен, Файл, Путь, Режим);
КонецЕсли;
Возврат Ответ;
КонецФункции
// Загрузить файл по URL
// Загружает файл на облачный диск, получая его по указанному URL
//
// Параметры:
// Токен - Строка - Токен - token
// URLФайла - Строка - URL источник файла - url
// Путь - Строка - Путь сохранения на Dropbox - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ЗагрузитьФайлПоURL(Знач Токен, Знач URLФайла, Знач Путь) Экспорт
URL = "https://api.dropboxapi.com/2/files/save_url";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("url" , URLФайла , "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить статус загрузки по URL
// Получает статус загрузки файла по URL
//
// Параметры:
// Токен - Строка - Токен - token
// IDРаботы - Строка - ID асинхронной работы из ответа ЗагрузитьФайлПоURL - job
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьСтатусЗагрузкиПоURL(Знач Токен, Знач IDРаботы) Экспорт
URL = "https://api.dropboxapi.com/2/files/save_url/check_job_status";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("async_job_id", IDРаботы, "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Удалить объект
// Удаляет объект с облачного диска
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту удаления - path
// БезВозвратно - Строка - Удалить объект без возможности востановления - permanently
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция УдалитьОбъект(Знач Токен, Знач Путь, Знач Безвозвратно = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Безвозвратно);
Если Безвозвратно Тогда
URL = "https://api.dropboxapi.com/2/files/permanently_delete";
Иначе
URL = "https://api.dropboxapi.com/2/files/delete_v2";
КонецЕсли;
Ответ = ОбработатьОбъект(Токен, URL, Путь);
Возврат Ответ;
КонецФункции
// Копировать объект
// Копирует файл или каталог по выбранному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Откуда - Строка - Путь к объекту оригинала - from
// Куда - Строка - Целевой путь для нового объекта - to
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция КопироватьОбъект(Знач Токен, Знач Откуда, Знач Куда) Экспорт
URL = "https://api.dropboxapi.com/2/files/copy_v2";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("from_path", Откуда, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("to_path" , Куда , "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Переместить объект
// Перемещает объект по выбранному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Откуда - Строка - Путь к объекту оригинала - from
// Куда - Строка - Целевой путь для нового объекта - to
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПереместитьОбъект(Знач Токен, Знач Откуда, Знач Куда) Экспорт
URL = "https://api.dropboxapi.com/2/files/move_v2";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("from_path", Откуда, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("to_path" , Куда , "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Создать папку
// Создает пустой каталог по выбранному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Целевой путь создания каталога - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция СоздатьПапку(Знач Токен, Знач Путь) Экспорт
URL = "https://api.dropboxapi.com/2/files/create_folder_v2";
Ответ = ОбработатьОбъект(Токен, URL, Путь);
Возврат Ответ;
КонецФункции
// Скачать файл
// Скачивает файл по указанному пути или ID
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь или ID файла - path
//
// Возвращаемое значение:
// ДвоичныеДанные - двоичные данные файла
Функция СкачатьФайл(Знач Токен, Знач Путь) Экспорт
URL = "https://content.dropboxapi.com/2/files/download";
Ответ = ОбработатьОбъект(Токен, URL, Путь, Истина);
Возврат Ответ;
КонецФункции
// Скачать папку
// Скачивает zip архив с содержимым указанного каталога
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь или ID каталога - path
//
// Возвращаемое значение:
// ДвоичныеДанные - двоичные данные zip архива с содержимым каталога
Функция СкачатьПапку(Знач Токен, Знач Путь) Экспорт
URL = "https://content.dropboxapi.com/2/files/download_zip";
Ответ = ОбработатьОбъект(Токен, URL, Путь, Истина);
Возврат Ответ;
КонецФункции
// Получить список версий объекта
// Получает список версий (ревизий) объекта
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту - path
// Количество - Строка, Число - Число последних версий объекта для отображения - amount
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьСписокВерсийОбъекта(Знач Токен, Знач Путь, Знач Количество = 10) Экспорт
URL = "https://api.dropboxapi.com/2/files/list_revisions";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path" , Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("limit", Количество, "Число" , Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Восстановить объект к версии
// Восстанавливает состояние объекта к необходимой версии (ревизии)
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту - path
// Версия - Строка - ID версии (ревизии) для востановления - rev
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ВосстановитьОбъектКВерсии(Знач Токен, Знач Путь, Знач Версия) Экспорт
URL = "https://api.dropboxapi.com/2/files/restore";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("rev" , Версия, "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСТегами
// Получить список тегов
// Получает список тегов выбранных файлов
//
// Параметры:
// Токен - Строка - Токен - token
// Пути - Строка, Массив Из Строка - Путь или набору путей к файлам - paths
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьСписокТегов(Знач Токен, Знач Пути) Экспорт
URL = "https://api.dropboxapi.com/2/files/tags/get";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("paths", Пути, "Массив", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Добавить тег
// Добавляет новый текстовый тег к файлу или каталогу
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту, для которого необходимо создать тег - path
// Тег - Строка - Текст тега - tag
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ДобавитьТег(Знач Токен, Знач Путь, Знач Тег) Экспорт
Возврат ОбработатьТег(Токен, Путь, Тег);
КонецФункции
// Удалить тег
// Удаляет текстовый тег файла или каталога
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к объекту, тег которого необходимо удалить - path
// Тег - Строка - Текст тега - tag
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция УдалитьТег(Знач Токен, Знач Путь, Знач Тег) Экспорт
Возврат ОбработатьТег(Токен, Путь, Тег, Истина);
КонецФункции
#КонецОбласти
#Область НастройкиСовместногоДоступа
// Опубликовать папку
// Переводит каталог в режим публичного доступа
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к целевому каталогу - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ОпубликоватьПапку(Знач Токен, Знач Путь) Экспорт
URL = "https://api.dropboxapi.com/2/sharing/share_folder";
Ответ = ОбработатьОбъект(Токен, URL, Путь);
Возврат Ответ;
КонецФункции
// Отменить публикацию папки
// Отменяет режим общего доступа для каталога
//
// Параметры:
// Токен - Строка - Токен - token
// IDПапки - Строка - ID публичного каталога (shared folder ID) - folder
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ОтменитьПубликациюПапки(Знач Токен, Знач IDПапки) Экспорт
URL = "https://api.dropboxapi.com/2/sharing/unshare_folder";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("shared_folder_id", IDПапки, "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Добавить пользователей к файлу
// Определяет доступ к файлу для сторонних пользователей
//
// Параметры:
// Токен - Строка - Токен - token
// IDФайла - Строка - ID файла, к которому предоставляется доступ - fileid
// АдресаПочты - Строка, Массив Из Строка - Список адресов почты добавляемых пользователей - emails
// ТолькоПросмотр - Булево - Запрещает редактирование файла для стороннего пользователя - readonly
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ДобавитьПользователейКФайлу(Знач Токен, Знач IDФайла, Знач АдресаПочты, Знач ТолькоПросмотр = Истина) Экспорт
Строка_ = "Строка";
OPI_ПреобразованиеТипов.ПолучитьМассив(АдресаПочты);
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDФайла);
OPI_ПреобразованиеТипов.ПолучитьБулево(ТолькоПросмотр);
Если Не СтрНачинаетсяС(IDФайла, "id:") Тогда
IDФайла = "id:" + IDФайла;
КонецЕсли;
URL = "https://api.dropboxapi.com/2/sharing/add_file_member";
МассивПользователей = Новый Массив;
Для Каждого Адрес Из АдресаПочты Цикл
ДанныеПользователя = Новый Соответствие;
OPI_Инструменты.ДобавитьПоле(".tag" , "email", Строка_, ДанныеПользователя);
OPI_Инструменты.ДобавитьПоле("email", Адрес , Строка_, ДанныеПользователя);
МассивПользователей.Добавить(ДанныеПользователя);
КонецЦикла;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("file" , IDФайла , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("members", МассивПользователей, "Массив", Параметры);
Режим = ?(ТолькоПросмотр, "viewer", "editor");
OPI_Инструменты.ДобавитьПоле("access_level", Режим , Строка_, Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Добавить пользователей к папке
// Предоставляет стороннии пользователям доступ к каталогу
//
// Параметры:
// Токен - Строка - Токен - token
// IDПапки - Строка - ID публичного каталога (shared folder ID) - folder
// АдресаПочты - Строка, Массив Из Строка - Список адресов почты добавляемых пользователей - emails
// ТолькоПросмотр - Булево - Запрещает редактирование файла для стороннего пользователя - readonly
//
// Возвращаемое значение:
// Неопределено - пустой ответ
Функция ДобавитьПользователейКПапке(Знач Токен, Знач IDПапки, Знач АдресаПочты, Знач ТолькоПросмотр = Истина) Экспорт
Строка_ = "Строка";
OPI_ПреобразованиеТипов.ПолучитьМассив(АдресаПочты);
OPI_ПреобразованиеТипов.ПолучитьБулево(ТолькоПросмотр);
Режим = ?(ТолькоПросмотр, "viewer", "editor");
URL = "https://api.dropboxapi.com/2/sharing/add_folder_member";
МассивПользователей = Новый Массив;
Для Каждого Адрес Из АдресаПочты Цикл
ДанныеПользователя = Новый Соответствие;
OPI_Инструменты.ДобавитьПоле(".tag" , "email", Строка_, ДанныеПользователя);
OPI_Инструменты.ДобавитьПоле("email", Адрес , Строка_, ДанныеПользователя);
СтруктураПользователя = Новый Структура("member,access_level", ДанныеПользователя, Режим);
МассивПользователей.Добавить(СтруктураПользователя);
КонецЦикла;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("shared_folder_id", IDПапки , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("members" , МассивПользователей , "Массив", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить статус асинхронного изменения
// Получает статус асинхронной работы по изменению доступов
//
// Параметры:
// Токен - Строка - Токен - token
// IDРаботы - Строка - ID асинхронной работы - job
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ПолучитьСтатусАсинхронногоИзменения(Знач Токен, Знач IDРаботы) Экспорт
URL = "https://api.dropboxapi.com/2/sharing/check_job_status";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("async_job_id", IDРаботы, "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Отменить публикацию файла
// Запрещает доступ к файлу для внешних пользователей
//
// Параметры:
// Токен - Строка - Токен - token
// IDФайла - Строка - ID файла, к которому предоставляется доступ - fileid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Dropbox
Функция ОтменитьПубликациюФайла(Знач Токен, Знач IDФайла) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDФайла);
Если Не СтрНачинаетсяС(IDФайла, "id:") Тогда
IDФайла = "id:" + IDФайла;
КонецЕсли;
URL = "https://api.dropboxapi.com/2/sharing/unshare_file";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("file", IDФайла, "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция PostBinary(Знач URL, Знач Данные, Знач Заголовки) Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные);
HttpКлиент = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьТипДанных("application/octet-stream")
.УстановитьЗаголовки(Заголовки);
Если Данные.Размер() > 0 Тогда
HttpКлиент.УстановитьДвоичноеТело(Данные);
КонецЕсли;
Возврат HttpКлиент.ОбработатьЗапрос("POST").ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецФункции
Функция ОбработатьОбъект(Знач Токен, Знач URL, Знач Путь, Знач ВЗаголовках = Ложь)
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь, "Строка", Параметры);
Если ВЗаголовках Тогда
Заголовки = ПолучитьЗаголовкиЗапроса(Токен, Параметры);
Ответ = PostBinary(URL, ПолучитьДвоичныеДанныеИзСтроки(""), Заголовки);
Иначе
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
КонецЕсли;
Возврат Ответ;
КонецФункции
Функция ОбработатьТег(Знач Токен, Знач Путь, Знач Тег, Знач ЭтоУдаление = Ложь)
Если ЭтоУдаление Тогда
URL = "https://api.dropboxapi.com/2/files/tags/remove";
Иначе
URL = "https://api.dropboxapi.com/2/files/tags/add";
КонецЕсли;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path" , Путь, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("tag_text" , Тег , "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
Функция ПолучитьЗаголовкиЗапроса(Знач Токен, Знач Параметры = "")
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization" , "Bearer " + Токен);
Если ЗначениеЗаполнено(Параметры) Тогда
JSON = OPI_Инструменты.JSONСтрокой(Параметры, "Нет");
JSON = СтрЗаменить(JSON, Символы.ВК + Символы.ПС, "");
Заголовки.Вставить("Dropbox-API-Arg", JSON);
КонецЕсли;
Возврат Заголовки;
КонецФункции
Функция ЗагрузитьБольшойФайл(Знач Токен, Знач Файл, Знач Путь, Знач Режим)
URL = "https://content.dropboxapi.com/2/files/upload_session/append_v2";
РазмерЧасти = 100000000;
ТекущаяПозиция = 0;
ПрочитаноБайт = 0;
ОбщийРазмер = Файл.Размер();
Сессия = ОткрытьСессию(Токен);
Если OPI_Инструменты.ЭтоКоллекция(Сессия) Тогда
Возврат Сессия;
КонецЕсли;
Пока ПрочитаноБайт < ОбщийРазмер Цикл
Отступ = ТекущаяПозиция;
Курсор = Новый Структура("offset,session_id", Отступ, Сессия);
Параметры = Новый Структура("cursor", Курсор);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен, Параметры);
ЧтениеДанных = Новый ЧтениеДанных(Файл);
ПрочитаноБайт = ЧтениеДанных.Пропустить(ТекущаяПозиция);
Результат = ЧтениеДанных.Прочитать(РазмерЧасти);
ТекущиеДанные = Результат.ПолучитьДвоичныеДанные();
РазмерТекущих = ТекущиеДанные.Размер();
СледующаяПозиция = ТекущаяПозиция + РазмерТекущих;
Если РазмерТекущих = 0 Тогда
Прервать;
КонецЕсли;
Ответ = PostBinary(URL, ТекущиеДанные, Заголовки);
ТекущаяПозиция = СледующаяПозиция;
КБайт = 1024;
МБайт = КБайт * КБайт;
OPI_Инструменты.ИнформацияОПрогрессе(ТекущаяПозиция, ОбщийРазмер, "МБ", МБайт);
// !OInt ВыполнитьСборкуМусора();
// !OInt ОсвободитьОбъект(ТекущиеДанные);
КонецЦикла;
Ответ = ЗакрытьСессию(Токен, Путь, Режим, ОбщийРазмер, Сессия);
Возврат Ответ;
КонецФункции
Функция ЗагрузитьМалыйФайл(Знач Токен, Знач Файл, Знач Путь, Знач Режим)
Булево_ = "Булево";
Строка_ = "Строка";
URL = "https://content.dropboxapi.com/2/files/upload";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("autorename" , Ложь , Булево_, Параметры);
OPI_Инструменты.ДобавитьПоле("mode" , Режим, Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("mute" , Ложь , Булево_, Параметры);
OPI_Инструменты.ДобавитьПоле("path" , Путь , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("strict_conflict", Ложь , Булево_, Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен, Параметры);
Ответ = PostBinary(URL, Файл, Заголовки);
Возврат Ответ;
КонецФункции
Функция ОткрытьСессию(Знач Токен)
SessionId = "session_id";
URL = "https://content.dropboxapi.com/2/files/upload_session/start";
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = PostBinary(URL, ПолучитьДвоичныеДанныеИзСтроки(""), Заголовки);
Сессия = Ответ[SessionId];
Если Сессия = Неопределено Тогда
Сессия = Ответ;
КонецЕсли;
Возврат Сессия;
КонецФункции
Функция ЗакрытьСессию(Знач Токен, Знач Путь, Знач Режим, Знач ОбщийРазмер, Знач Сессия)
URL = "https://content.dropboxapi.com/2/files/upload_session/finish";
Коммит = Новый Структура();
OPI_Инструменты.ДобавитьПоле("mode", Режим, "Строка", Коммит);
OPI_Инструменты.ДобавитьПоле("path", Путь , "Строка", Коммит);
Курсор = Новый Структура("offset,session_id", ОбщийРазмер, Сессия);
Параметры = Новый Структура("commit,cursor", Коммит, Курсор);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен, Параметры);
Ответ = PostBinary(URL, ПолучитьДвоичныеДанныеИзСтроки(""), Заголовки);
Возврат Ответ;
КонецФункции
Функция ПолучитьАккаунт(Знач Токен, Знач Аккаунт)
URL = "https://api.dropboxapi.com/2/users/get_account";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("account_id", Аккаунт, "Строка", Параметры);
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
Функция ПолучитьСвойАккаунт(Знач Токен)
URL = "https://api.dropboxapi.com/2/users/get_current_account";
Заголовки = ПолучитьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьДвоичноеТело("null")
.УстановитьЗаголовки(Заголовки)
.УстановитьТипДанных("text/plain; charset=dropbox-cors-hack")
.ОбработатьЗапрос("POST")
.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Ответ;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="4b20914a-129a-449b-b361-8d62ca43ffd8">
<Properties>
<Name>OPI_FTP</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>FTP (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с FTP из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="d27d4ffb-31c2-4362-bd6d-d785ce171b49">
<Properties>
<Name>OPI_GoogleCalendar</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI google calendar</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Google Calendar (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Google Calendar из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,656 @@
// OneScript: ./OInt/core/Modules/OPI_GoogleCalendar.os
// Lib: Google Calendar
// CLI: gcalendar
// Keywords: google calendar, googlecalendar, gcalendar
// Depends: OPI_GoogleWorkspace
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область РаботаСМетаданнымиКалендарей
// Создать календарь
// Создает пустой календарь
//
// Параметры:
// Токен - Строка - Токен - token
// Наименование - Строка - Наименование создаваемого календаря - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция СоздатьКалендарь(Знач Токен, Знач Наименование) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars";
Параметры = Новый Структура;
Параметры.Вставить("summary" , Наименование);
Параметры.Вставить("timeZone", "Europe/Moscow");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить календарь
// Получает информацию о календаре по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьМетаданныеКалендаря(Знач Токен, Знач Календарь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/" + Календарь;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Изменить календарь
// Изменяет свойства существуещего календаря
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
// Наименование - Строка - Новое наименование - title
// Описание - Строка - Новое описание календаря - description
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ИзменитьМетаданныеКалендаря(Знач Токен
, Знач Календарь
, Знач Наименование = ""
, Знач Описание = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Описание);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/" + Календарь;
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Наименование) Тогда
Параметры.Вставить("summary", Наименование);
КонецЕсли;
Если ЗначениеЗаполнено(Описание) Тогда
Параметры.Вставить("description", Описание);
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.PatchСТелом(URL, Параметры, Заголовки, Истина);
Возврат Ответ;
КонецФункции
// Очистить основной календарь
// Очищает список событий основного календаря
//
// Параметры:
// Токен - Строка - Токен - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ОчиститьОсновнойКалендарь(Знач Токен) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/primary/clear";
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, , Заголовки, Ложь);
Возврат Ответ;
КонецФункции
// Удалить календарь
// Удаляет календарь по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьКалендарь(Знач Токен, Знач Календарь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/" + Календарь;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСоСпискомКалендарей
// Получить список календарей
// Получает массив календарей аккаунта
//
// Параметры:
// Токен - Строка - Токен - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Массив соответствий данных календарей
Функция ПолучитьСписокКалендарей(Знач Токен) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
МассивКалендарей = Новый Массив;
ПолучитьСписокКалендарейРекурсивно(Заголовки, МассивКалендарей);
Возврат МассивКалендарей;
КонецФункции
// Добавить календарь в список
// Добавляет существующий календарь в список пользователя
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ДобавитьКалендарьВСписок(Знач Токен, Знач Календарь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
Параметры = Новый Структура;
Параметры.Вставить("id", Календарь);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить календарь списка
// Получает календарь из списка пользователя по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьКалендарьСписка(Знач Токен, Знач Календарь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/users/me/calendarList/" + Календарь;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Удалить календарь из списка
// Удаляет календарь из списка пользователя
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьКалендарьИзСписка(Знач Токен, Знач Календарь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/users/me/calendarList/" + Календарь;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Изменить календарь списка
// Изменяет свойства календаря из списка пользователей
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
// ОсновнойЦвет - Строка - HEX основного цвета (#ffffff) - primary
// ДополнительныйЦвет - Строка - HEX дополнительного цвета (#ffffff) - secondary
// Скрытый - Булево - Скрытый календарь - hidden
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ИзменитьКалендарьСписка(Знач Токен
, Знач Календарь
, Знач ОсновнойЦвет
, Знач ДополнительныйЦвет
, Знач Скрытый = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ОсновнойЦвет);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ДополнительныйЦвет);
OPI_ПреобразованиеТипов.ПолучитьБулево(Скрытый);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/users/me/calendarList/" + Календарь + "?colorRgbFormat=true";
Параметры = Новый Соответствие;
Параметры.Вставить("hidden" , Скрытый);
Параметры.Вставить("foregroundColor", ОсновнойЦвет);
Параметры.Вставить("backgroundColor", ДополнительныйЦвет);
Ответ = OPI_ЗапросыHTTP.PutСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаССобытиями
// Получить описание события
// Получает пустой макет для создания события
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Пустой макет события
Функция ПолучитьОписаниеСобытия(Знач Пустая = Ложь) Экспорт
ТекущаяДата = OPI_Инструменты.ПолучитьТекущуюДату();
Час = 3600;
Событие = Новый Соответствие;
Событие.Вставить("Описание" , ""); // Описание события
Событие.Вставить("Заголовок" , "Новое событие"); // Заголовок события
Событие.Вставить("МестоПроведения" , ""); // Строка описание места проведения
Событие.Вставить("ДатаНачала" , ТекущаяДата); // Дата начала события
Событие.Вставить("ДатаОкончания" , ТекущаяДата + Час); // Дата окончания события
Событие.Вставить("МассивURLФайловВложений", Новый Соответствие); // Ключ - название, Значение - URL к файлу
Событие.Вставить("ОтправлятьУведомления" , Истина); // Признак отправки уведомлений участникам
Если Пустая Тогда
Событие_ = Новый Соответствие;
Для Каждого Поле Из Событие Цикл
Событие_.Вставить(Поле.Ключ, "");
КонецЦикла;
Событие = Событие_;
КонецЕсли;
Возврат Событие;
КонецФункции
// Получить список событий
// Получает список всех событий календаря
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Массив соответствий событий
Функция ПолучитьСписокСобытий(Знач Токен, Знач Календарь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
МассивСобытий = Новый Массив;
ПолучитьСписокСобытийРекурсивно(Заголовки, Календарь, МассивСобытий);
Возврат МассивСобытий;
КонецФункции
// Получить событие
// Получает событие по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
// Событие - Строка - ID события - event
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьСобытие(Знач Токен, Знач Календарь, Знач Событие) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Событие);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/"
+ Календарь
+ "/events/"
+ Событие;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Создать событие
// Создает новое событие
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
// ОписаниеСобытия - Соответствие Из КлючИЗначение - Описание события - props
//
// Возвращаемое значение:
// Строка, Произвольный, HTTPОтвет, ДвоичныеДанные, Неопределено - ответ сервера Google
Функция СоздатьСобытие(Знач Токен, Знач Календарь, Знач ОписаниеСобытия) Экспорт
Возврат УправлениеСобытием(Токен, Календарь, ОписаниеСобытия);
КонецФункции
// Переместить событие
// Перемещает событие в другой календарь
//
// Параметры:
// Токен - Строка - Токен - token
// КалендарьИсточник - Строка - ID календаря источника - from
// КалендарьПриемник - Строка - ID календаря приемника - to
// Событие - Строка - ID события календаря источника - event
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПереместитьСобытие(Знач Токен, Знач КалендарьИсточник, Знач КалендарьПриемник, Знач Событие) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(КалендарьИсточник);
OPI_ПреобразованиеТипов.ПолучитьСтроку(КалендарьПриемник);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Событие);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/"
+ КалендарьИсточник
+ "/events/"
+ Событие
+ "/move?destination="
+ КалендарьПриемник;
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Изменить событие
// Изменяет существующее событие
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
// ОписаниеСобытия - Строка - Новое описание события - props
// Событие - Строка - ID события - event
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ИзменитьСобытие(Знач Токен, Знач Календарь, Знач ОписаниеСобытия, Знач Событие) Экспорт
Возврат УправлениеСобытием(Токен, Календарь, ОписаниеСобытия, Событие);
КонецФункции
// Удалить событие
// Удаляет событие по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Календарь - Строка - ID календаря - calendar
// Событие - Строка - ID события - event
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьСобытие(Знач Токен, Знач Календарь, Знач Событие) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Событие);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/calendar/v3/calendars/"
+ Календарь
+ "/events/"
+ Событие;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ПреобразоватьДату(Знач Дата)
OPI_ПреобразованиеТипов.ПолучитьДату(Дата);
СтруктураДаты = Новый Структура;
Если Не ТипЗнч(Дата) = Тип("Дата") Тогда
Возврат Неопределено;
КонецЕсли;
Если Дата = НачалоДня(Дата) Тогда
ФорматДаты = "ДФ=yyyy-MM-dd";
Поле = "date";
Иначе
ФорматДаты = "ДФ=yyyy-MM-ddTHH:mm:ssZ";
Поле = "dateTime";
КонецЕсли;
Дата = Формат(Дата, ФорматДаты);
СтруктураДаты.Вставить(Поле , Дата);
СтруктураДаты.Вставить("timeZone", "Europe/Moscow");
Возврат СтруктураДаты;
КонецФункции
Функция ПреобразоватьВложения(Знач Вложения)
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Вложения);
МассивВложений = Новый Массив;
Если ТипЗнч(Вложения) = Тип("Соответствие") Или ТипЗнч(Вложения) = Тип("Структура") Тогда
Для Каждого Вложение Из Вложения Цикл
ТекущеВложение = Новый Структура;
ТекущеВложение.Вставить("title" , Вложение.Ключ);
ТекущеВложение.Вставить("fileUrl", Вложение.Значение);
МассивВложений.Добавить(ТекущеВложение);
КонецЦикла;
КонецЕсли;
Если МассивВложений.Количество() > 0 Тогда
Возврат МассивВложений;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Функция УправлениеСобытием(Знач Токен, Знач Календарь, Знач ОписаниеСобытия, Знач Событие = "")
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Календарь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Событие);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(ОписаниеСобытия);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
Существующее = ЗначениеЗаполнено(Событие);
URL = "https://www.googleapis.com/calendar/v3/calendars/"
+ Календарь
+ "/events"
+ ?(Существующее, "/" + Событие, "");
Дата0 = ОписаниеСобытия["ДатаНачала"];
Дата1 = ОписаниеСобытия["ДатаОкончания"];
Вложения = ОписаниеСобытия["МассивURLФайловВложений"];
Вложения = ПреобразоватьВложения(Вложения);
Уведомления = ?(ОписаниеСобытия["ОтправлятьУведомления"] = Неопределено
, Ложь
, ОписаниеСобытия["ОтправлятьУведомления"]);
Параметры = Новый Структура;
Параметры.Вставить("summary" , ОписаниеСобытия["Заголовок"]);
Параметры.Вставить("description", ОписаниеСобытия["Описание"]);
Параметры.Вставить("location" , ОписаниеСобытия["МестоПроведения"]);
Параметры.Вставить("start" , ПреобразоватьДату(Дата0));
Параметры.Вставить("end" , ПреобразоватьДату(Дата1));
Параметры.Вставить("attachments", Вложения);
ПараметрыURL = Новый Структура;
ПараметрыURL.Вставить("sendUpdates" , ?(Уведомления , "all" , "none"));
ПараметрыURL.Вставить("supportsAttachments" , ?(ЗначениеЗаполнено(Вложения), "true", "false"));
URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL);
OPI_Инструменты.УдалитьПустыеПоляКоллекции(Параметры);
Если Существующее Тогда
Ответ = OPI_ЗапросыHTTP.PatchСТелом(URL, Параметры, Заголовки, Истина);
Иначе
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки, Истина);
КонецЕсли;
Возврат Ответ;
КонецФункции
Процедура ПолучитьСписокКалендарейРекурсивно(Знач Заголовки, МассивКалендарей, Страница = "")
Items = "items";
NPT = "nextPageToken";
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Страница) Тогда
Параметры.Вставить("pageToken", Страница);
КонецЕсли;
Результат = OPI_ЗапросыHTTP.Get("https://www.googleapis.com/calendar/v3/users/me/calendarList"
, Параметры
, Заголовки);
Календари = Результат[Items];
Страница = Результат[NPT];
Для Каждого Календарь Из Календари Цикл
МассивКалендарей.Добавить(Календарь);
КонецЦикла;
Если Календари.Количество() > 0 И ЗначениеЗаполнено(Страница) Тогда
ПолучитьСписокКалендарейРекурсивно(Заголовки, МассивКалендарей, Страница);
КонецЕсли;
КонецПроцедуры
Процедура ПолучитьСписокСобытийРекурсивно(Знач Заголовки, Знач Календарь, МассивСобытий, Страница = "")
Items = "items";
NPT = "nextPageToken";
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Страница) Тогда
Параметры.Вставить("pageToken", Страница);
КонецЕсли;
Результат = OPI_ЗапросыHTTP.Get("https://www.googleapis.com/calendar/v3/calendars/" + Календарь + "/events"
, Параметры
, Заголовки);
События = Результат[Items];
Страница = Результат[NPT];
Для Каждого Событие Из События Цикл
МассивСобытий.Добавить(Событие);
КонецЦикла;
Если События.Количество() > 0 И ЗначениеЗаполнено(Страница) Тогда
ПолучитьСписокСобытийРекурсивно(Заголовки, МассивСобытий, Страница);
КонецЕсли;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="3bf39c90-a263-4300-b800-7fd85f7c6d40">
<Properties>
<Name>OPI_GoogleDrive</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI google drive</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Google Drive (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Google Drive из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,778 @@
// OneScript: ./OInt/core/Modules/OPI_GoogleDrive.os
// Lib: Google Drive
// CLI: gdrive
// Keywords: google drive, googledrive, gdrive, google disk
// Depends: OPI_GoogleWorkspace
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область РаботаСФайламиИКаталогами
// Получить информацию об объекте
// Получает информацию о папке или файле по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор файла или каталога - object
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьИнформациюОбОбъекте(Знач Токен, Знач Идентификатор) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + Идентификатор;
Параметры = Новый Структура;
Параметры.Вставить("fields", "*");
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить список каталогов
// Получает список каталогов диска
//
// Параметры:
// Токен - Строка - Токен - token
// ИмяСодержит - Строка - Отбор по имени - querry
// Подробно - Булево - Добавляет список файлов к полям каталога - depth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Массив соответствий каталогов
Функция ПолучитьСписокКаталогов(Знач Токен, Знач ИмяСодержит = "", Знач Подробно = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИмяСодержит);
OPI_ПреобразованиеТипов.ПолучитьБулево(Подробно);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
МассивОбъектов = Новый Массив;
Отбор = Новый Массив;
Отбор.Добавить("mimeType = 'application/vnd.google-apps.folder'");
Если ЗначениеЗаполнено(ИмяСодержит) Тогда
Отбор.Добавить("name contains '" + ИмяСодержит + "'");
КонецЕсли;
ПолучитьСписокОбъектовРекурсивно(Заголовки, МассивОбъектов, Подробно, Отбор);
Если Подробно Тогда
РазложитьОбъектыПодробно(Токен, МассивОбъектов);
КонецЕсли;
Возврат МассивОбъектов;
КонецФункции
// Получить список файлов
// Получает список файлов
//
// Параметры:
// Токен - Строка - Токен - token
// ИмяСодержит - Строка - Отбор по имени - querry
// Каталог - Строка - Отбор по ID каталога родителя - catalog
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Массив соответствий файлов
Функция ПолучитьСписокФайлов(Знач Токен, Знач ИмяСодержит = "", Знач Каталог = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИмяСодержит);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Каталог);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
МассивОбъектов = Новый Массив;
Отбор = Новый Массив;
Отбор.Добавить("mimeType != 'application/vnd.google-apps.folder'");
Если ЗначениеЗаполнено(ИмяСодержит) Тогда
Отбор.Добавить("name contains '" + ИмяСодержит + "'");
КонецЕсли;
Если ЗначениеЗаполнено(Каталог) Тогда
Отбор.Добавить("'" + Каталог + "' in parents");
КонецЕсли;
ПолучитьСписокОбъектовРекурсивно(Заголовки, МассивОбъектов, , Отбор);
Возврат МассивОбъектов;
КонецФункции
// Загрузить файл
// Загружает файл на диск
//
// Параметры:
// Токен - Строка - Токен - token
// Файл - ДвоичныеДанные,Строка - Загружаемый файл - file
// Описание - Соответствие Из КлючИЗначение - См. ПолучитьОписаниеФайла - props
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ЗагрузитьФайл(Знач Токен, Знач Файл, Знач Описание) Экспорт
Возврат УправлениеФайлом(Токен, Файл, Описание);
КонецФункции
// Создать папку
// Создает пустой каталог на диске
//
// Параметры:
// Токен - Строка - Токен - token
// Имя - Строка - Имя папки - title
// Родитель - Строка - Родитель - catalog
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция СоздатьПапку(Знач Токен, Знач Имя, Знач Родитель = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Имя);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Родитель);
Описание = Новый Соответствие;
Описание.Вставить("MIME" , "application/vnd.google-apps.folder");
Описание.Вставить("Имя" , Имя);
Описание.Вставить("Описание", "");
Описание.Вставить("Родитель", ?(ЗначениеЗаполнено(Родитель), Родитель, "root"));
Возврат УправлениеФайлом(Токен, , Описание);
КонецФункции
// Скачать файл
// Получает файл по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор файла - object
// ПутьСохранения - Строка - Путь сохранения файла - out
//
// Возвращаемое значение:
// ДвоичныеДанные,Строка - Двоичные данные или путь к файлу при указании параметра ПутьСохранения
Функция СкачатьФайл(Знач Токен, Знач Идентификатор, Знач ПутьСохранения = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + Идентификатор;
Параметры = Новый Соответствие;
Параметры.Вставить("alt", "media");
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры , Заголовки, ПутьСохранения);
Возврат Ответ;
КонецФункции
// Скоприровать объект
// Копирует файл или каталог
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор объекта - object
// НовоеИмя - Строка - Новое имя объекта - title
// НовыйРодитель - Строка - Новый каталог размещения - catalog
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция СкопироватьОбъект(Знач Токен, Знач Идентификатор, Знач НовоеИмя = "", Знач НовыйРодитель = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(НовоеИмя);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
OPI_ПреобразованиеТипов.ПолучитьСтроку(НовыйРодитель);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + Идентификатор + "/copy";
Параметры = Новый Структура;
Если ЗначениеЗаполнено(НовоеИмя) Тогда
Параметры.Вставить("name", НовоеИмя);
КонецЕсли;
Если ЗначениеЗаполнено(НовыйРодитель) Тогда
МассивРодителей = Новый Массив;
МассивРодителей.Добавить(НовыйРодитель);
Параметры.Вставить("parents", МассивРодителей);
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры , Заголовки, Истина);
Возврат Ответ;
КонецФункции
// Обновить файл
// Обновляет двоичные данные файла
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор обновляемого объекта - object
// Файл - ДвоичныеДанные,Строка - Файл источник обновления - file
// НовоеИмя - Строка - Новое имя файла (если необходимо) - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ОбновитьФайл(Знач Токен, Знач Идентификатор, Знач Файл, Знач НовоеИмя = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
OPI_ПреобразованиеТипов.ПолучитьСтроку(НовоеИмя);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
Если ЗначениеЗаполнено(НовоеИмя) Тогда
Описание = Новый Соответствие;
Описание.Вставить("Имя", НовоеИмя);
Иначе
Описание = "";
КонецЕсли;
Возврат УправлениеФайлом(Токен, Файл, Описание, Идентификатор);
КонецФункции
// Удалить объект
// Удаляет файл или каталог по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор объекта для удаления - object
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьОбъект(Знач Токен, Знач Идентификатор) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + Идентификатор;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить описание файла
// Получает шаблон пустого описания для загрузки файла
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Описание файла
Функция ПолучитьОписаниеФайла(Знач Пустая = Ложь) Экспорт
Описание = Новый Соответствие;
Описание.Вставить("MIME" , "image/jpeg"); // MIME-тип загружаемого файла
Описание.Вставить("Имя" , "Новый файл.jpg"); // Имя файла с расширением
Описание.Вставить("Описание" , "Это новый файл"); // Описание файла
Описание.Вставить("Родитель" , "root"); // ID каталога загрузки или "root" для загрузки в корень
Если Пустая Тогда
Описание_ = Новый Соответствие;
Для Каждого Поле Из Описание Цикл
Описание_.Вставить(Поле.Ключ, "");
КонецЦикла;
Описание = Описание_;
КонецЕсли;
Возврат Описание;
КонецФункции
#КонецОбласти
#Область РаботаСКомментариями
// Создать комментарий
// Создает комментарий к файлу или каталогу
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор объекта, для которого необходим комментарий - object
// Комментарий - Строка - Текст комментария - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция СоздатьКомментарий(Знач Токен, Знач Идентификатор, Знач Комментарий) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Комментарий);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + Идентификатор + "/comments?fields=*";
Параметры = Новый Структура;
Параметры.Вставить("content", Комментарий);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить комментарий
// Получает комментарий по ID
//
// Параметры:
// Токен - Строка - Токен - token
// ИДОбъекта - Строка - Идентификатор файла или каталога размещения комментария - object
// ИДКомментария - Строка - Идентификатор комментария - comment
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьКомментарий(Знач Токен, Знач ИДОбъекта, Знач ИДКомментария) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДОбъекта);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДКомментария);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + ИДОбъекта + "/comments/" + ИДКомментария;
Параметры = Новый Структура;
Параметры.Вставить("fields", "*");
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить список комментариев
// Получает список всех комментариев объекта
//
// Параметры:
// Токен - Строка - Токен - token
// ИДОбъекта - Строка - Идентификатор объекта - object
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьСписокКомментариев(Знач Токен, Знач ИДОбъекта) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДОбъекта);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + ИДОбъекта + "/comments";
Параметры = Новый Структура;
Параметры.Вставить("fields", "*");
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Удалить комментарий
// Удаляет комментарий по ID
//
// Параметры:
// Токен - Строка - Токен - token
// ИДОбъекта - Строка - Идентификатор файла или каталога размещения комментария - object
// ИДКомментария - Строка - Идентификатор комментария - comment
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьКомментарий(Знач Токен, Знач ИДОбъекта, Знач ИДКомментария) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДОбъекта);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДКомментария);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://www.googleapis.com/drive/v3/files/" + ИДОбъекта + "/comments/" + ИДКомментария;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ПолучитьСписокОбъектовРекурсивно(Знач Заголовки, МассивОбъектов, Подробно = Ложь, Отбор = "", Страница = "")
URL = "https://www.googleapis.com/drive/v3/files";
Files = "files";
NPT = "nextPageToken";
Параметры = Новый Структура;
Параметры.Вставить("fields", "*");
Если ЗначениеЗаполнено(Страница) Тогда
Параметры.Вставить("pageToken", Страница);
КонецЕсли;
Если ЗначениеЗаполнено(Отбор) И ТипЗнч(Отбор) = Тип("Массив") Тогда
ОтборСтрока = СтрСоединить(Отбор, " and ");
Параметры.Вставить("q", ОтборСтрока);
КонецЕсли;
Результат = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Объекты = Результат[Files];
Страница = Результат[NPT];
Для Каждого ТекущийОбъект Из Объекты Цикл
МассивОбъектов.Добавить(ТекущийОбъект);
КонецЦикла;
Если Объекты.Количество() > 0 И ЗначениеЗаполнено(Страница) Тогда
ПолучитьСписокОбъектовРекурсивно(Заголовки, МассивОбъектов, Подробно, Отбор, Страница);
КонецЕсли;
КонецПроцедуры
Процедура РазложитьОбъектыПодробно(Знач Токен, МассивОбъектов)
Для Каждого ТекущийОбъект Из МассивОбъектов Цикл
МассивФайлов = Новый Массив;
ТекущийИД = ТекущийОбъект["id"];
Результат = ПолучитьСписокФайлов(Токен, , ТекущийИД);
Для Каждого Файл Из Результат Цикл
МассивФайлов.Добавить(Файл);
КонецЦикла;
ТекущийОбъект.Вставить("files", МассивФайлов);
КонецЦикла;
КонецПроцедуры
Процедура СформироватьПараметрыЗагрузкиФайла(Описание)
СформированноеОписание = Новый Соответствие;
OPI_Инструменты.УдалитьПустыеПоляКоллекции(Описание);
СоответствиеПолей = Новый Соответствие;
СоответствиеПолей.Вставить("MIME" , "mimeType");
СоответствиеПолей.Вставить("Имя" , "name");
СоответствиеПолей.Вставить("Описание" , "description");
СоответствиеПолей.Вставить("Родитель" , "parents");
СоответствиеПолей.Вставить("Расширение", "fileExtension");
Для Каждого Элемент Из Описание Цикл
Если Элемент.Ключ = "Родитель" Тогда
ТекущееЗначение = Новый Массив;
ТекущееЗначение.Добавить(Элемент.Значение);
Иначе
ТекущееЗначение = Элемент.Значение;
КонецЕсли;
ИмяПоля = СоответствиеПолей.Получить(Элемент.Ключ);
СформированноеОписание.Вставить(ИмяПоля, ТекущееЗначение);
КонецЦикла;
Описание = СформированноеОписание;
КонецПроцедуры
Функция УправлениеФайлом(Знач Токен, Знач Файл = "", Знач Описание = "", Знач Идентификатор = "")
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
Если ЗначениеЗаполнено(Описание) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Описание);
КонецЕсли;
MimeType = "mimeType";
Если ЗначениеЗаполнено(Идентификатор) Тогда
MIME = ПолучитьИнформациюОбОбъекте(Токен, Идентификатор)[MimeType];
Иначе
MIME = Описание["MIME"];
КонецЕсли;
Если Не ЗначениеЗаполнено(Описание) Тогда
Описание = Новый Соответствие;
КонецЕсли;
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
СформироватьПараметрыЗагрузкиФайла(Описание);
ОписаниеJSON = OPI_Инструменты.JSONСтрокой(Описание);
СоответствиеФайла = Новый Соответствие;
Если ЗначениеЗаполнено(Файл) Тогда
РазмерЧасти = 268435457;
Размер = OPI_Инструменты.ПреобразоватьДанныеСПолучениемРазмера(Файл, РазмерЧасти);
СоответствиеФайла.Вставить(Файл, MIME);
Если Размер < РазмерЧасти И ТипЗнч(Файл) = Тип("ДвоичныеДанные") Тогда
Ответ = ЗагрузитьМалыйФайл(ОписаниеJSON, СоответствиеФайла, Заголовки, Идентификатор);
Иначе
Ответ = ЗагрузитьБольшойФайл(Описание, СоответствиеФайла, Заголовки, Идентификатор);
КонецЕсли;
Иначе
Ответ = ЗагрузитьМалыйФайл(ОписаниеJSON, СоответствиеФайла, Заголовки, Идентификатор);
КонецЕсли;
Возврат Ответ;
КонецФункции
Функция ЗагрузитьМалыйФайл(Знач Описание, Знач СоответствиеФайла, Знач Заголовки, Знач Идентификатор = "")
URL = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
URL = СтрЗаменить(URL, "/files", "/files/" + Идентификатор);
Если ЗначениеЗаполнено(Идентификатор) Тогда
Метод = "PATCH";
Иначе
Метод = "POST";
КонецЕсли;
HTTPКлиент = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьЗаголовки(Заголовки)
.НачатьЗаписьТелаMultipart(Истина, "related")
.ДобавитьДанныеRelated(Описание, "application/json; charset=UTF-8");
Для Каждого Файл Из СоответствиеФайла Цикл
HTTPКлиент.ДобавитьДанныеRelated(Файл.Ключ, Файл.Значение);
КонецЦикла;
Ответ = HTTPКлиент.ОбработатьЗапрос(Метод).ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Ответ;
КонецФункции
Функция ЗагрузитьБольшойФайл(Знач Описание, Знач СоответствиеФайла, Знач Заголовки, Знач Идентификатор = "")
Для Каждого Файл Из СоответствиеФайла Цикл
Двоичные = Файл.Ключ;
Прервать;
КонецЦикла;
URL = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable";
Если ЗначениеЗаполнено(Идентификатор) Тогда
URL = СтрЗаменить(URL, "/files", "/files/" + Идентификатор);
Метод = "PATCH";
Иначе
Метод = "POST";
КонецЕсли;
HttpКлиент = OPI_ЗапросыHTTP.НовыйЗапрос().Инициализировать(URL);
Ответ = HttpКлиент.УстановитьЗаголовки(Заголовки)
.УстановитьJsonТело(Описание)
.ОбработатьЗапрос(Метод)
.ВернутьОтвет(Ложь, Истина);
АдресЗагрузки = Ответ.Заголовки["Location"];
Если Не ЗначениеЗаполнено(АдресЗагрузки) Тогда
Возврат HttpКлиент.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецЕсли;
HttpКлиентЗагрузки = ЗагрузитьФайлЧастями(Двоичные, АдресЗагрузки);
Если HttpКлиентЗагрузки <> Неопределено Тогда
Ответ = HttpКлиентЗагрузки.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Иначе
Ответ = HttpКлиент.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецЕсли;
Возврат Ответ;
КонецФункции
Функция ЗагрузитьФайлЧастями(Знач Двоичные, Знач АдресЗагрузки)
HttpКлиент = Неопределено;
РазмерЧасти = 268435456;
ПрочитаноБайт = 0;
ТекущаяПозиция = 0;
ОбщийРазмер = Двоичные.Размер();
СтрОбщийРазмер = OPI_Инструменты.ЧислоВСтроку(ОбщийРазмер);
ЧтениеДанных = Новый ЧтениеДанных(Двоичные);
ИсходныйПоток = ЧтениеДанных.ИсходныйПоток();
КБайт = 1024;
МБайт = КБайт * КБайт;
Пока ПрочитаноБайт < ОбщийРазмер Цикл
ПрочитаноБайт = ИсходныйПоток.ТекущаяПозиция();
Результат = ЧтениеДанных.Прочитать(РазмерЧасти);
ТекущиеДанные = Результат.ПолучитьДвоичныеДанные();
РазмерТекущих = ТекущиеДанные.Размер();
СледующаяПозиция = ТекущаяПозиция + РазмерТекущих - 1;
Если Не ЗначениеЗаполнено(ТекущиеДанные) Тогда
Прервать;
КонецЕсли;
ЗаголовокПотока = "bytes "
+ OPI_Инструменты.ЧислоВСтроку(ТекущаяПозиция)
+ "-"
+ OPI_Инструменты.ЧислоВСтроку(СледующаяПозиция)
+ "/"
+ СтрОбщийРазмер;
ДопЗаголовки = Новый Соответствие;
ДопЗаголовки.Вставить("Content-Length", OPI_Инструменты.ЧислоВСтроку(РазмерТекущих));
ДопЗаголовки.Вставить("Content-Range" , ЗаголовокПотока);
ДопЗаголовки.Вставить("Content-Type" , "application/octet-stream");
HttpКлиент = OPI_ЗапросыHTTP
.НовыйЗапрос()
.Инициализировать(АдресЗагрузки)
.УстановитьЗаголовки(ДопЗаголовки)
.УстановитьДвоичноеТело(ТекущиеДанные)
.ОбработатьЗапрос("PUT");
РезультатПроверки = ПроверитьЗагрузкуЧасти(HttpКлиент
, СтрОбщийРазмер
, ДопЗаголовки
, АдресЗагрузки
, ТекущаяПозиция);
Если РезультатПроверки <> Неопределено Тогда
Возврат РезультатПроверки;
КонецЕсли;
OPI_Инструменты.ИнформацияОПрогрессе(ТекущаяПозиция, ОбщийРазмер, "МБ", МБайт);
// !OInt ВыполнитьСборкуМусора();
// !OInt ОсвободитьОбъект(ТекущиеДанные);
КонецЦикла;
OPI_Инструменты.ИнформацияОПрогрессе(ОбщийРазмер, ОбщийРазмер, "МБ", МБайт);
Возврат HttpКлиент;
КонецФункции
Функция ПроверитьЗагрузкуЧасти(HttpКлиент, СтрОбщийРазмер, ДопЗаголовки, АдресЗагрузки, ТекущаяПозиция)
НачалоКодовОшибок = 400;
КонецКодовПадений = 600;
НачалоКодовУспеха = 200;
КонецКодовУспеха = 300;
Перенаправление = 308;
Ответ = HttpКлиент.ВернутьОтвет(Ложь, Истина);
Если Ответ.КодСостояния >= НачалоКодовОшибок И Ответ.КодСостояния < КонецКодовПадений Тогда
ЗаголовокПотока = "bytes */" + СтрОбщийРазмер;
ДопЗаголовки.Вставить("Content-Range" , ЗаголовокПотока);
HttpКлиентПроверки = OPI_ЗапросыHTTP.НовыйЗапрос().Инициализировать(АдресЗагрузки);
ОтветПроверки = HttpКлиентПроверки.УстановитьЗаголовки(ДопЗаголовки)
.ОбработатьЗапрос("PUT")
.ВернутьОтвет(Ложь, Истина);
Если ОтветПроверки.КодСостояния >= НачалоКодовУспеха И ОтветПроверки.КодСостояния < КонецКодовУспеха Тогда
Возврат HttpКлиентПроверки;
ИначеЕсли ОтветПроверки.КодСостояния = Перенаправление Тогда
ЗагруженныеДанные = Ответ.Заголовки["Range"];
Иначе
Возврат HttpКлиент;
КонецЕсли;
Иначе
ЗагруженныеДанные = Ответ.Заголовки["Range"];
КонецЕсли;
Если Не ЗначениеЗаполнено(ЗагруженныеДанные) Тогда
Возврат HttpКлиент;
КонецЕсли;
ЗагруженныеДанные = СтрЗаменить(ЗагруженныеДанные, "bytes=", "");
МассивИнформации = СтрРазделить(ЗагруженныеДанные, "-", Ложь);
НеобходимоЧастей = 2;
Если Не МассивИнформации.Количество() = НеобходимоЧастей Тогда
Возврат HttpКлиент;
КонецЕсли;
ТекущаяПозиция = Число(МассивИнформации[1]) + 1;
Возврат Неопределено;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="3890523a-552f-495c-ae7d-2991df8bb175">
<Properties>
<Name>OPI_GoogleSheets</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI google sheets</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Google Sheets (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Google Sheets из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,420 @@
// OneScript: ./OInt/core/Modules/OPI_GoogleSheets.os
// Lib: Google Sheets
// CLI: gsheets
// Keywords: googlesheets, google sheets, spreadsheets
// Depends: OPI_GoogleWorkspace
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область РаботаСКнигами
// Создать книгу
// Создает новую книгу
//
// Параметры:
// Токен - Строка - Токен - token
// Наименование - Строка - Наименование - title
// МассивИменЛистов - Массив из Строка - Массив имен для добавления новых листов в книгу - sheets
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция СоздатьКнигу(Знач Токен, Знач Наименование, Знач МассивИменЛистов) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивИменЛистов);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets";
Свойства = Новый Структура("title" , Наименование);
Листы = Новый Массив;
ЗаполнитьМассивЛистов(МассивИменЛистов, Листы);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("properties", Свойства, "Коллекция", Параметры);
OPI_Инструменты.ДобавитьПоле("sheets" , Листы , "Коллекция", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить книгу
// Получает информацию о книге по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Идентификатор - Строка - Идентификатор книги - spreadsheet
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьКнигу(Знач Токен, Знач Идентификатор) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Идентификатор;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Изменить наименование книги
// Изменяет наименование существующей книги
//
// Параметры:
// Токен - Строка - Токен - token
// Книга - Строка - ID книги - spreadsheet
// Наименование - Строка - Новое наименование - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ИзменитьНаименованиеКниги(Знач Токен, Знач Книга, Знач Наименование) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + ":batchUpdate";
Изменение = Новый Структура("title", Наименование);
ЗапросИзменения = Новый Структура("properties,fields", Изменение, "title");
Запрос = Новый Структура("updateSpreadsheetProperties", ЗапросИзменения);
МассивЗапросов = Новый Массив;
МассивЗапросов.Добавить(Запрос);
Параметры = Новый Структура("requests", МассивЗапросов);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСЛистами
// Добавить лист
// Добавляет новый лист в книгу
//
//
// Параметры:
// Токен - Строка - Токен - token
// Книга - Строка - Идентификатор книги - spreadsheet
// Наименование - Строка - Наименование нового листа - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ДобавитьЛист(Знач Токен, Знач Книга, Знач Наименование) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + ":batchUpdate";
Лист = СоздатьЛист(Наименование);
Запросы = Новый Массив;
Изменение = Новый Структура("addSheet", Лист);
Запросы.Добавить(Изменение);
Параметры = Новый Структура("requests", Запросы);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Удалить лист
// Удаляет лист из книги
//
// Параметры:
// Токен - Строка - Токен - token
// Книга - Строка - Идентификатор книги - spreadsheet
// Лист - Строка - Идентификатор удаляемого листа - sheet
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УдалитьЛист(Знач Токен, Знач Книга, Знач Лист) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + ":batchUpdate";
Запросы = Новый Массив;
Лист = Новый Структура("sheetId" , Лист);
Изменение = Новый Структура("deleteSheet", Лист);
Запросы.Добавить(Изменение);
Параметры = Новый Структура("requests", Запросы);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Копировать лист
// Копирует лист из одной книги в другую
//
// Параметры:
// Токен - Строка - Токен - token
// Откуда - Строка - ID книги источника - from
// Куда - Строка - ID книги приемника - to
// Лист - Строка - ID копируемого листа - sheet
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция КопироватьЛист(Знач Токен, Знач Откуда, Знач Куда, Знач Лист) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Откуда);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Куда);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/"
+ Откуда
+ "/sheets/"
+ Лист
+ ":copyTo";
Параметры = Новый Структура("destinationSpreadsheetId", Куда);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСДанными
// Установить значения ячеек
// Устанавливает значения ячеек листа
//
// Параметры:
// Токен - Строка - Токен - token
// Книга - Строка - ID книги - spreadsheet
// СоответствиеЗначений - Соответствие Из КлючИЗначение - Данные заполнения, где ключ это имя ячейки вида A1 - data
// Лист - Строка - Имя листа (первый лист по умолчанию) - sheetname
// ОсновноеИзмерение - Строка - Основное измерение при заполнении диапазона массивом - dim
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция УстановитьЗначенияЯчеек(Знач Токен
, Знач Книга
, Знач СоответствиеЗначений
, Знач Лист = ""
, Знач ОсновноеИзмерение = "COLUMNS") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(СоответствиеЗначений);
Если Не ТипЗнч(СоответствиеЗначений) = Тип("Структура")
И Не ТипЗнч(СоответствиеЗначений) = Тип("Соответствие") Тогда
Возврат "Не удалось привести структуру значений к коллекции";
КонецЕсли;
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + "/values:batchUpdate";
МассивДанных = СформироватьМассивДанныхЯчеек(СоответствиеЗначений, ОсновноеИзмерение, Лист);
Параметры = Новый Структура("data,valueInputOption", МассивДанных, "USER_ENTERED");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Очистить ячейки
// Очищает значение в ячейках
//
// Параметры:
// Токен - Строка - Токен - token
// Книга - Строка - ID книги - spreadsheet
// МассивЯчеек - Массив из Строка - Массив ячеек вида А1 для очистки - cells
// Лист - Строка - Имя листа (первый лист по умолчанию) - sheetname
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ОчиститьЯчейки(Знач Токен, Знач Книга, Знач МассивЯчеек, Знач Лист = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивЯчеек);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + "/values:batchClear";
СформироватьМассивИменЯчеек(МассивЯчеек, Лист);
Параметры = Новый Структура("ranges", МассивЯчеек);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить значения ячеек
// Получает значения ячеек таблицы
//
// Параметры:
// Токен - Строка - Токен - token
// Книга - Строка - ID книги - spreadsheet
// МассивЯчеек - Массив из Строка - Массив ячеек вида А1 для получения (весь лист, если не заполнено) - cells
// Лист - Строка - Имя листа (первый лист по умолчанию) - sheetname
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьЗначенияЯчеек(Знач Токен, Знач Книга, Знач МассивЯчеек = "", Знач Лист = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Книга);
Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://sheets.googleapis.com/v4/spreadsheets/" + Книга + "/values:batchGet";
Если ЗначениеЗаполнено(МассивЯчеек) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивЯчеек);
СформироватьМассивИменЯчеек(МассивЯчеек, Лист);
Первый = Истина;
Для Каждого Ячейка Из МассивЯчеек Цикл
Разделитель = ?(Первый, "?", "&");
URL = URL + Разделитель + "ranges=" + Ячейка;
Первый = Ложь;
КонецЦикла;
Иначе
URL = URL + "?ranges='" + Лист + "'";
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ЗаполнитьМассивЛистов(Знач МассивИмен, МассивЛистов)
Для Каждого ИмяЛиста Из МассивИмен Цикл
Лист = СоздатьЛист(ИмяЛиста);
МассивЛистов.Добавить(Лист);
КонецЦикла;
КонецПроцедуры
Процедура ДобавитьИмяЛиста(Ячейка, Знач Лист)
Если ЗначениеЗаполнено(Лист) Тогда
Ячейка = "'" + Лист + "'!" + Ячейка;
КонецЕсли;
КонецПроцедуры
Функция СоздатьЛист(Знач Наименование)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование);
СвойстваЛиста = Новый Структура("title" , Наименование);
Лист = Новый Структура("properties", СвойстваЛиста);
Возврат Лист;
КонецФункции
Функция СформироватьМассивДанныхЯчеек(Знач СтруктураЗначений, Знач ОсновноеИзмерение, Знач Лист)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
МассивДанных = Новый Массив;
Для Каждого ДанныеЯчейки Из СтруктураЗначений Цикл
ТекущееЗначение = ДанныеЯчейки.Значение;
ТекущийКлюч = ДанныеЯчейки.Ключ;
ДобавитьИмяЛиста(ТекущийКлюч, Лист);
OPI_ПреобразованиеТипов.ПолучитьМассив(ТекущееЗначение);
ТекущиеДанные = Новый Соответствие;
ТекущийМассив = Новый Массив;
ТекущийМассив.Добавить(ТекущееЗначение);
OPI_Инструменты.ДобавитьПоле("range" , ТекущийКлюч , "Строка", ТекущиеДанные);
OPI_Инструменты.ДобавитьПоле("values" , ТекущийМассив , "Массив", ТекущиеДанные);
OPI_Инструменты.ДобавитьПоле("majorDimension", ОсновноеИзмерение, "Строка", ТекущиеДанные);
МассивДанных.Добавить(ТекущиеДанные);
КонецЦикла;
Возврат МассивДанных;
КонецФункции
Процедура СформироватьМассивИменЯчеек(Знач МассивИмен, Знач Лист)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Лист);
Для Н = 0 По МассивИмен.ВГраница() Цикл
ДобавитьИмяЛиста(МассивИмен[Н], Лист);
КонецЦикла;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="e5bf1867-4c83-4724-91f2-931150325ea0">
<Properties>
<Name>OPI_GoogleWorkspace</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI google workspace</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Google Workspace (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Google Workspace из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,245 @@
// OneScript: ./OInt/core/Modules/OPI_GoogleWorkspace.os
// Lib: Google Workspace
// CLI: google
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
// Сформировать ссылку получения кода
// Возвращает URL для авторизации в браузере
//
// Параметры:
// ClientID - Строка - Client ID - id
// Calendar - Булево - разрешение на методы Calendar - calendar
// Drive - Булево - разрешение на методы Drive - drive
// Sheets - Булево - разрешение на методы Sheets - sheets
//
// Возвращаемое значение:
// Строка - Ссылка получения кода
Функция СформироватьСсылкуПолученияКода(Знач ClientID
, Знач Calendar = Истина
, Знач Drive = Истина
, Знач Sheets = Истина) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientID);
OPI_ПреобразованиеТипов.ПолучитьБулево(Calendar);
OPI_ПреобразованиеТипов.ПолучитьБулево(Sheets);
OPI_ПреобразованиеТипов.ПолучитьБулево(Drive);
URL = "https://accounts.google.com/o/oauth2/auth";
ПараметрыURL = Новый Структура;
ПараметрыURL.Вставить("response_type", "code");
ПараметрыURL.Вставить("client_id" , ClientID);
ПараметрыURL.Вставить("redirect_uri" , "http://localhost");
ПараметрыURL.Вставить("access_type" , "offline");
ПараметрыURL.Вставить("scope" , ПолучитьСписокРазрешений(Calendar, Drive, Sheets));
URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL);
Возврат URL;
КонецФункции
// Получить токен по коду
// Получает токен по коду из авторизации в бразуере
//
// Параметры:
// ClientID - Строка - Client ID - id
// ClientSecret - Строка - Client secret - secret
// Code - Строка - Code из браузера - code
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьТокенПоКоду(Знач ClientID, Знач ClientSecret, Знач Code) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientID);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientSecret);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Code);
URL = "https://accounts.google.com/o/oauth2/token";
ПараметрыURL = Новый Структура;
ПараметрыURL.Вставить("grant_type" , "authorization_code");
ПараметрыURL.Вставить("client_id" , ClientID);
ПараметрыURL.Вставить("client_secret", ClientSecret);
ПараметрыURL.Вставить("redirect_uri" , "http://localhost");
ПараметрыURL.Вставить("code" , Code);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, ПараметрыURL, , Ложь);
Возврат Ответ;
КонецФункции
// Обновить токен
// Обновляет токен по Refresh token
//
// Параметры:
// ClientID - Строка - Client ID - id
// ClientSecret - Строка - Client secret - secret
// RefreshToken - Строка - Refresh token - refresh
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ОбновитьТокен(Знач ClientID, Знач ClientSecret, Знач RefreshToken) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientID);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientSecret);
OPI_ПреобразованиеТипов.ПолучитьСтроку(RefreshToken);
URL = "https://accounts.google.com/o/oauth2/token";
ПараметрыURL = Новый Структура;
ПараметрыURL.Вставить("grant_type" , "refresh_token");
ПараметрыURL.Вставить("client_id" , ClientID);
ПараметрыURL.Вставить("client_secret", ClientSecret);
ПараметрыURL.Вставить("refresh_token", RefreshToken);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, ПараметрыURL, , Ложь);
Возврат Ответ;
КонецФункции
// Получить токен service аккаунта
// Получает токен авторизации по данным service аккаунта
//
// Примечание:
// Список доступных областей действия: [developers.google.com](https://developers.google.com/identity/protocols/oauth2/scopes)
//
// Параметры:
// Данные - Произвольный - JSON данные авторизации как файл, коллекция или двоичные данные - auth
// ОбластиДействия - Массив Из Строка - Область действия (scope) или массив областей - scope
// ВремяЖизни - Число - Время жизни токена в секундах - exp
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Google
Функция ПолучитьТокенServiceАккаунта(Знач Данные, Знач ОбластиДействия, Знач ВремяЖизни = 3600) Экспорт
ТекстОшибки = "Переданные данные service аккаунта не являются валидным JSON";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Данные, ТекстОшибки);
OPI_ПреобразованиеТипов.ПолучитьЧисло(ВремяЖизни);
OPI_ПреобразованиеТипов.ПолучитьМассив(ОбластиДействия);
МассивОбязательныхПолей = Новый Массив;
МассивОбязательныхПолей.Добавить("token_uri");
МассивОбязательныхПолей.Добавить("client_email");
МассивОбязательныхПолей.Добавить("private_key");
МассивОбязательныхПолей.Добавить("private_key_id");
ОтсутствующиеПоля = OPI_Инструменты.НайтиОтсутствующиеПоляКоллекции(Данные, МассивОбязательныхПолей);
Если ЗначениеЗаполнено(ОтсутствующиеПоля) Тогда
ШаблонОшибкиПолей = "В данных service аккаунта отсутствуют обязательные поля: %1";
ТекстОшибкиПолей = СтрШаблон(ШаблонОшибкиПолей, СтрСоединить(ОтсутствующиеПоля, ", "));
ВызватьИсключение ТекстОшибкиПолей;
КонецЕсли;
ОбластиДействияСтрокой = СтрСоединить(ОбластиДействия, " ");
КлючПодписи = Данные["private_key"];
URL = Данные["token_uri"];
ТекущаяДата = ТекущаяУниверсальнаяДата();
ДатаСгорания = ТекущаяДата + ВремяЖизни;
UnixTime = OPI_Инструменты.UnixTime(ТекущаяДата);
ExpTime = OPI_Инструменты.UnixTime(ДатаСгорания);
Payload = Новый Структура;
Payload.Вставить("iss" , Данные["client_email"]);
Payload.Вставить("scope", ОбластиДействияСтрокой);
Payload.Вставить("aud" , URL);
Payload.Вставить("exp" , Число(ExpTime));
Payload.Вставить("iat" , Число(UnixTime));
ДопЗаголовки = Новый Структура("kid", Данные["private_key_id"]);
JWT = OPI_Криптография.JWT(Payload, КлючПодписи, "RS256", ДопЗаголовки);
Грант = "urn:ietf:params:oauth:grant-type:jwt-bearer";
СтруктураТела = Новый Структура("grant_type,assertion", Грант, JWT);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, СтруктураТела, , Ложь);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьЗаголовокАвторизации(Знач Токен) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + Токен);
Возврат Заголовки;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИфункции
Функция ПолучитьСписокРазрешений(Calendar, Drive, Sheets)
МассивРазрешений = Новый Массив;
Если Calendar Тогда
МассивРазрешений.Добавить("https://www.googleapis.com/auth/calendar");
КонецЕсли;
Если Drive Тогда
МассивРазрешений.Добавить("https://www.googleapis.com/auth/drive");
КонецЕсли;
Если Sheets Тогда
МассивРазрешений.Добавить("https://www.googleapis.com/auth/spreadsheets");
КонецЕсли;
Возврат СтрСоединить(МассивРазрешений, " ");
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="9a796a27-ce46-4b3f-b763-7b3acd9edd0d">
<Properties>
<Name>OPI_GreenAPI</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Green API (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с WhatsApp через GreenAPI из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="4e5775cb-c0c2-4b37-9ccf-4efaed1bb8e8">
<Properties>
<Name>OPI_GreenMax</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>GreenAPI Max (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Max через GreenAPI из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,384 @@
// OneScript: ./OInt/core/Modules/OPI_GreenMax.os
// Lib: Green Max
// CLI: greenmax
// Keywords: greenapi, max
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check bsl-legacy-check-string-literal
#Область ПрограммныйИнтерфейс
#Область Аккаунт
// Сформировать параметры доступа
// Формирует структуру основных авторизационных данных
//
// Примечание:
// Подробнее в документации API: [Получить параметры доступа к инстансу](@green-api.com/v3/docs/before-start/#parameters)
//
// Параметры:
// ApiUrl - Строка - Ссылка на хост API - api
// MediaUrl - Строка - Ссылка на хост API для отправки файлов - media
// IdInstance - Строка - Уникальный номер инстанса - id
// ApiTokenInstance - Строка - Ключ доступа инстанса - token
//
// Возвращаемое значение:
// Структура - Структура параметров доступа
Функция СформироватьПараметрыДоступа(Знач ApiUrl, Знач MediaUrl, Знач IdInstance, Знач ApiTokenInstance) Экспорт
Строка_ = "Строка";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("apiUrl" , ApiUrl , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("mediaUrl" , MediaUrl , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("idInstance" , IdInstance , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("apiTokenInstance", ApiTokenInstance, Строка_, Параметры);
Возврат Параметры;
КонецФункции
// Получить информацию об аккаунте
// Получает информацию об аккаунте
//
// Примечание:
// Метод в документации API: [GetWaSettings](@green-api.com/v3/docs/api/account/GetAccountSettings/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ПолучитьИнформациюОбАккаунте(Знач ПараметрыДоступа) Экспорт
URL = СформироватьОсновнойURL(ПараметрыДоступа, "getAccountSettings");
Ответ = OPI_ЗапросыHTTP.Get(URL);
Возврат Ответ;
КонецФункции
// Получить настройки инстанса
// Получает текущие настройки инстанса
//
// Примечание:
// Метод в документации API: [GetSettings](@green-api.com/v3/docs/api/account/GetSettings/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ПолучитьНастройкиИнстанса(Знач ПараметрыДоступа) Экспорт
URL = СформироватьОсновнойURL(ПараметрыДоступа, "getSettings");
Ответ = OPI_ЗапросыHTTP.Get(URL);
Возврат Ответ;
КонецФункции
// Установить настройки инстанса
// Устанавливает настройки инстанса
//
// Примечание
// Метод в документации API: [SetSettings](@green-api.com/v3/docs/api/account/SetSettings/)
//
// Параметры:
// Настройки - Структура Из КлючИЗначение - Настройки инстанса. См. ПолучитьСтруктуруНастроекИнстанса - settings
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция УстановитьНастройкиИнстанса(Знач Настройки, Знач ПараметрыДоступа) Экспорт
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Настройки);
URL = СформироватьОсновнойURL(ПараметрыДоступа, "setSettings");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Настройки);
Возврат Ответ;
КонецФункции
// Получить код авторизации
// Отправляет SMS по указанному номеру для получения кода подтверждения
//
// Примечание:
// Метод в документации API: [StartAuthorization](@green-api.com/v3/docs/api/account/StartAuthorization/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
// НомерТелефона - Строка, Число - Номер телефона без знака + - phone
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ПолучитьКодАвторизации(Знач ПараметрыДоступа, Знач НомерТелефона) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(НомерТелефона);
НомерТелефона = СтрЗаменить(НомерТелефона, "+", "");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("phoneNumber", НомерТелефона, "Число", Параметры);
URL = СформироватьОсновнойURL(ПараметрыДоступа, "startAuthorization");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры);
Возврат Ответ;
КонецФункции
// Отправить код авторизации
// Авторизует инстанс по коду доступа из SMS
//
// Примечание:
// Метод в документации API: [SendAuthorizationCode](@green-api.com/v3/docs/api/account/SendAuthorizationCode/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
// КодАвторизации - Строка - Код авторизации - code
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ОтправитьКодАвторизации(Знач ПараметрыДоступа, Знач КодАвторизации) Экспорт
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("code", КодАвторизации, "Строка", Параметры);
URL = СформироватьОсновнойURL(ПараметрыДоступа, "sendAuthorizationCode");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры);
Возврат Ответ;
КонецФункции
// Получить состояние инстанса
// Получает состояние инстанса
//
// Примечание:
// Метод в документации API: [GetStateInstance](@green-api.com/v3/docs/api/account/GetStateInstance/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ПолучитьСостояниеИнстанса(Знач ПараметрыДоступа) Экспорт
URL = СформироватьОсновнойURL(ПараметрыДоступа, "getStateInstance");
Ответ = OPI_ЗапросыHTTP.Get(URL);
Возврат Ответ;
КонецФункции
// Установить картинку профиля
// Устанавливает новую картинку профиля
//
// Примечание:
// Метод в документации API: [SetProfilePicture](@green-api.com/v3/docs/api/account/SetProfilePicture/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
// Картинка - ДвоичныеДанные, Строка - Картинка профиля - picture
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция УстановитьКартинкуПрофиля(Знач ПараметрыДоступа, Знач Картинка) Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Картинка);
СоответствиеКартинки = Новый Соответствие();
СоответствиеКартинки.Вставить("file|file.jpg", Картинка);
URL = СформироватьОсновнойURL(ПараметрыДоступа, "setProfilePicture");
Ответ = OPI_ЗапросыHTTP.PostMultipart(URL, , СоответствиеКартинки);
Возврат Ответ;
КонецФункции
// Разлогинить инстанс
// Разлогинивает инстанс
//
// Примечание:
// Метод в документации API: [Logout](@green-api.com/v3/docs/api/account/Logout/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция РазлогинитьИнстанс(Знач ПараметрыДоступа) Экспорт
URL = СформироватьОсновнойURL(ПараметрыДоступа, "logout");
Ответ = OPI_ЗапросыHTTP.Get(URL);
Возврат Ответ;
КонецФункции
// Перезапустить инстанс
// Перезапускает инстанс
//
// Примечание:
// Метод в документации API: [Reboot](@green-api.com/v3/docs/api/account/Reboot/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ПерезапуститьИнстанс(Знач ПараметрыДоступа) Экспорт
URL = СформироватьОсновнойURL(ПараметрыДоступа, "reboot");
Ответ = OPI_ЗапросыHTTP.Get(URL);
Возврат Ответ;
КонецФункции
// Проверить аккаунт
// Проверяет существование аккаунта Max по номеру телефона
//
// Примечание:
// Метод в документации API: [CheckAccount](@green-api.com/v3/docs/api/account/CheckAccount/)
//
// Параметры:
// ПараметрыДоступа - Структура Из КлючИЗначение - Параметры доступа. См. СформироватьПараметрыДоступа - access
// НомерТелефона - Строка, Число - Номер телефона для проверки без знака + - phone
// ИгнорироватьКэш - Булево - Игнорировать кэш при повторном запросе проверки - force
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Green API
Функция ПроверитьАккаунт(Знач ПараметрыДоступа, Знач НомерТелефона, Знач ИгнорироватьКэш = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(НомерТелефона);
НомерТелефона = СтрЗаменить(НомерТелефона, "+", "");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("phoneNumber", НомерТелефона , "Число" , Параметры);
OPI_Инструменты.ДобавитьПоле("force" , ИгнорироватьКэш, "Булево", Параметры);
URL = СформироватьОсновнойURL(ПараметрыДоступа, "checkAccount");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры);
Возврат Ответ;
КонецФункции
// Получить структуру настроек инстанса
// Получает шаблон структуры для установки настроек инстанса
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек инстанса
Функция ПолучитьСтруктуруНастроекИнстанса(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
СтруктураНастроек = Новый Структура;
СтруктураНастроек.Вставить("webhookUrl" , "<URL для отправки уведомлений>");
СтруктураНастроек.Вставить("webhookUrlToken" , "<токен для доступа к вашему серверу уведомлений, если требуется>");
СтруктураНастроек.Вставить("delaySendMessagesMilliseconds" , "<интервал отправки сообщений в миллисекундах>");
СтруктураНастроек.Вставить("markIncomingMessagesReaded" , "<отмечать входящие сообщения прочитанными: yes, no>");
СтруктураНастроек.Вставить("markIncomingMessagesReadedOnReply", "<отмечать входящие сообщения прочитанными при отправке сообщения в чат: yes, no>");
СтруктураНастроек.Вставить("outgoingWebhook" , "<получать уведомления о статусах отправки/доставки/прочтении исходящих сообщений: yes, no>");
СтруктураНастроек.Вставить("outgoingMessageWebhook" , "<получать уведомления о сообщениях, отправленных с телефона: yes, no>");
СтруктураНастроек.Вставить("outgoingAPIMessageWebhook" , "<получать уведомления о сообщениях, отправленных через API: yes, no>");
СтруктураНастроек.Вставить("stateWebhook" , "<получать уведомления об изменении состояния авторизации инстанса: yes, no>");
СтруктураНастроек.Вставить("incomingWebhook" , "<получать уведомления о входящих сообщениях и файлах: yes, no>");
Если Пустая Тогда
СтруктураНастроек = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураНастроек);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураНастроек;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция СформироватьОсновнойURL(Знач ПараметрыДоступа, Знач Метод)
Возврат СформироватьURL(ПараметрыДоступа, Метод, "apiUrl");
КонецФункции
Функция СформироватьМедиаURL(Знач ПараметрыДоступа, Знач Метод)
Возврат СформироватьURL(ПараметрыДоступа, Метод, "mediaUrl");
КонецФункции
Функция СформироватьURL(ПараметрыДоступа, Метод, ПолеURL)
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ПараметрыДоступа);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Метод);
ОбязательныеПоля = СтрРазделить(ПолеURL + ",idInstance,apiTokenInstance", ",");
ОтсутствующиеПоля = OPI_Инструменты.НайтиОтсутствующиеПоляКоллекции(ПараметрыДоступа, ОбязательныеПоля);
Если ОтсутствующиеПоля.Количество() > 0 Тогда
ВызватьИсключение "Отсутствуют обязательные поля в параметрах доступа!";
КонецЕсли;
Url = ПараметрыДоступа[ПолеURL];
IdInstance = ПараметрыДоступа["idInstance"];
ApiTokenInstance = ПараметрыДоступа["apiTokenInstance"];
URL = СтрШаблон("%1/waInstance%2/%3/%4", Url, IdInstance, Метод, ApiTokenInstance);
Возврат URL;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="67786f17-aa45-45d1-afc3-4314e97a8621">
<Properties>
<Name>OPI_MSSQL</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>MS SQL (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с базами MSSQL из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,591 @@
// OneScript: ./OInt/core/Modules/OPI_MSSQL.os
// Lib: MSSQL
// CLI: mssql
// Keywords: mssql, ms sql
// Depends: OPI_MSSQL
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-collection-item-type
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает подключение к указанной базе
//
// Параметры:
// СтрокаПодключения - Строка - Строка подключения. См. СформироватьСтрокуПодключения - string
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или структура с информацией об ошибке
Функция ОткрытьСоединение(Знач СтрокаПодключения = "", Знач Tls = "") Экспорт
Если ЭтоКоннектор(СтрокаПодключения) Тогда
Возврат СтрокаПодключения;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(СтрокаПодключения);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(СтрокаПодключения);
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("MSSQL");
Tls = OPI_Компоненты.УстановитьTls(Коннектор, Tls);
Если Не OPI_Инструменты.ПолучитьИли(Tls, "result", Ложь) Тогда
Возврат Tls;
КонецЕсли;
Коннектор.ConnectionString = СтрокаПодключения;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Возврат ?(Результат["result"], Коннектор, Результат);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - dbc
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
Результат = Соединение.Close();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Иначе
Результат = Новый Структура("result,error", Ложь, "It's not a connection");
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты MSSQL
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_MSSQL.Main";
КонецФункции
// Выполнить запрос SQL
// Выполняет произвольный SQL запрос
//
// Примечание:
// Параметры запроса указываются как массив структур вида `{'Тип данных': 'Значение'}`.^^
// Список доступных типов описан на начальной странице документации библиотеки MSSQL
// Без указания флага `ФорсироватьРезультат`, чтение результата осуществляется только для запросов, начинающихся с `SELECT`^^
// Для остальных запросов возвращается `result:true` или `false` с текстом ошибки
//
// Параметры:
// ТекстЗапроса - Строка - Текст запроса к базе - sql
// Параметры - Массив Из Произвольный - Массив позиционных параметров запроса - params
// ФорсироватьРезультат - Булево - Включает попытку получения результата, даже для не SELECT запросов - force
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ВыполнитьЗапросSQL(Знач ТекстЗапроса
, Знач Параметры = ""
, Знач ФорсироватьРезультат = Ложь
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Если ЭтоКоннектор(Соединение) Тогда
ЗакрыватьСоединение = Ложь;
Коннектор = Соединение;
Иначе
ЗакрыватьСоединение = Истина;
Коннектор = ОткрытьСоединение(Соединение, Tls);
КонецЕсли;
Если Не ЭтоКоннектор(Коннектор) Тогда
Возврат Коннектор;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
Параметры_ = OPI_ЗапросыSQL.ОбработатьПараметры(Параметры, ПолучитьСтруктуруТипов());
Результат = OPI_ЗапросыSQL.ВыполнитьЗапросСОбработкой(Коннектор, ТекстЗапроса, ФорсироватьРезультат, Параметры_);
Если ЗакрыватьСоединение Тогда
ЗакрытьСоединение(Коннектор);
КонецЕсли;
Возврат Результат;
КонецФункции
// Сформировать строку подключения
// Формирует строку подключения из переданных данных
//
// Примечание:
// Данная функция позволяет быстро собрать базовую строку подключения.^^
// В случае необходимости более гибкой настройки, вы также можете сформировать (получить) данную строку самостоятельно (формат ADO)
//
// Параметры:
// Адрес - Строка - Адрес и экземпляр сервера СУБД - addr
// База - Строка - Имя базы данных для подключения - db
// Логин - Строка - Логин пользователя mssql - login
// Пароль - Строка - Пароль пользователя mssql - pass
// Порт - Число - Порт сервера - port
// АутентификацияWindows - Булево - Использовать аутентификацию Windows. Логин и пароль будут проигнорированы - trust
//
// Возвращаемое значение:
// Строка - Строка подключения к базе MSSQL
Функция СформироватьСтрокуПодключения(Знач Адрес
, Знач База = ""
, Знач Логин = ""
, Знач Пароль = ""
, Знач Порт = ""
, Знач АутентификацияWindows = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Адрес);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Порт);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
OPI_ПреобразованиеТипов.ПолучитьБулево(АутентификацияWindows);
Если ЗначениеЗаполнено(База) Тогда
БлокБД = СтрШаблон("Database=%1;", База);
Иначе
БлокБД = "";
КонецЕсли;
Если ЗначениеЗаполнено(Порт) Тогда
БлокПорта = СтрШаблон(",%1", Порт);
Иначе
БлокПорта = "";
КонецЕсли;
Если АутентификацияWindows Тогда
ШаблонСтроки = "Server=%1%2;%3IntegratedSecurity=True;";
СтрокаПодключения = СтрШаблон(ШаблонСтроки, Адрес, БлокПорта, БлокБД);
Иначе
ШаблонСтроки = "Server=%1%2;%3User Id=%4;Password=%5;";
СтрокаПодключения = СтрШаблон(ШаблонСтроки, Адрес, БлокПорта, БлокБД, Логин, Пароль);
КонецЕсли;
Возврат СтрокаПодключения;
КонецФункции
// Получить настройки TLS
// Формирует настройки для использования TLS при выполнении запросов
//
// Примечание:
// Настройки Tls могут быть установлены только в момент создания соединения: явного, при использовании функции `ОткрытьСоединение`^^
// или неявного, при передаче строки подключения в методы ORM.
// Передача настроек Tls совместно с передачей уже созданного соединения в параметр `Соединение` будет проигнорирована
// Настройки Tls могут быть также переданы в строке подключения
//
// Параметры:
// ОтключитьПроверкуСертификатов - Булево - Позволяет работать с некорретными сертификатами, в т.ч. самоподписанными - trust
// ПутьКСертификату - Строка - Путь к корневому PEM файлу сертификата, если его нет в системном хранилище - cert
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек TLS соединения
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату);
КонецФункции
#КонецОбласти
#Область ORM
// Создать базу данных
// Создает базу данных с указанным именем
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьБазуДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьБазуДанных(OPI_MSSQL, База, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить базу данных
// Удаляет базу данных
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьБазуДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
ШаблонЗапроса = "USE master;
|ALTER DATABASE [%1]
|SET SINGLE_USER
|WITH ROLLBACK IMMEDIATE;
|DROP DATABASE [%1];";
ТекстЗапроса = СтрШаблон(ШаблонЗапроса, База);
Результат = ВыполнитьЗапросSQL(ТекстЗапроса, , , Соединение, Tls);
Возврат Результат;
КонецФункции
// Создать таблицу
// Создает пустую таблицу в базе
//
// Примечание:
// Список доступных типов описан на начальной странице документации библиотеки MSSQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьТаблицу(OPI_MSSQL, Таблица, СтруктураКолонок, Соединение, Tls);
Возврат Результат;
КонецФункции
// Добавить колонку таблицы
// Добавляет новую колонку в существующую таблицу
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// ТипДанных - Строка - Тип данных колонки - type
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач ТипДанных, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьКолонкуТаблицы(OPI_MSSQL, Таблица, Имя, ТипДанных, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить колонку таблицы
// Удаляет колонку из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьКолонкуТаблицы(OPI_MSSQL, Таблица, Имя, Соединение, Tls);
Возврат Результат;
КонецФункции
// Гарантировать таблицу
// Создает новую таблицу в случае отсутствия или обновляет состав колонок существующей таблицы
//
// Примечание:
// В результате изменения структуры таблицы данные могут быть утеряны!^^
// Рекомендуется предварительно опробовать данный метод на тестовых данных
// Данная функция не обновляет тип данных существующих колонок
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ГарантироватьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ГарантироватьТаблицу(OPI_MSSQL, Таблица, СтруктураКолонок, Соединение, Tls);
Возврат Результат;
КонецФункции
// Очистить таблицу
// Очищает таблицу базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОчиститьТаблицу(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_MSSQL, Таблица, , Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить таблицу
// Удаляет таблицу из базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьТаблицу(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьТаблицу(OPI_MSSQL, Таблица, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить информацию о таблице
// Получает информацию о таблице
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьИнформациюОТаблице(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьСтруктуруТаблицы(OPI_MSSQL, Таблица, Соединение, Tls);
Возврат Результат;
КонецФункции
// Добавить записи
// Добавляет записи в таблицу
//
// Примечание:
// Данные записей указываются как массив структур вида:^
// `{'Имя поля 1': {'Тип данных': 'Значение'}, 'Имя поля 2': {'Тип данных': 'Значение'},...}`
// Список доступных типов описан на начальной странице документации библиотеки MSSQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// МассивДанных - Массив Из Структура - Массив структур данных строк: Ключ > поле, Значение > значение поля - rows
// Транзакция - Булево - Истина > добавление записей в транзакции с откатом при ошибке - trn
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьЗаписи(Знач Таблица, Знач МассивДанных, Знач Транзакция = Истина, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьЗаписи(OPI_MSSQL, Таблица, МассивДанных, Транзакция, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить записи
// Получает записи из выбранной таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Поля - Массив Из Строка - Поля для выборки - fields
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Сортировка - Структура Из КлючИЗначение - Сортировка: Ключ > поле, Значение > направление (ASC, DESC) - order
// Количество - Число - Ограничение количества получаемых строк - limit
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьЗаписи(Знач Таблица
, Знач Поля = "*"
, Знач Фильтры = ""
, Знач Сортировка = ""
, Знач Количество = ""
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьЗаписи(OPI_MSSQL
, Таблица
, Поля
, Фильтры
, Сортировка
, Количество
, Соединение
, Tls);
Возврат Результат;
КонецФункции
// Обновить записи
// Обновляет значение записей по выбранным критериям
//
// Примечание:
// Данные записей указываются как массив структур вида:^
// `{'Имя поля 1': {'Тип данных': 'Значение'}, 'Имя поля 2': {'Тип данных': 'Значение'},...}`
// Список доступных типов описан на начальной странице документации библиотеки MSSQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураЗначений - Структура Из КлючИЗначение - Структура значений: Ключ > поле, Значение > значение поля - values
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОбновитьЗаписи(Знач Таблица
, Знач СтруктураЗначений
, Знач Фильтры = ""
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ОбновитьЗаписи(OPI_MSSQL, Таблица, СтруктураЗначений, Фильтры, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить записи
// Удаляет записи из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьЗаписи(Знач Таблица, Знач Фильтры = "", Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_MSSQL, Таблица, Фильтры, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить структуру фильтра записей
// Получает структуру шаблон для фильтрации записей в запросах ORM
//
// Примечание:
// Использование признака `raw` необходимо для составных конструкций, вроде `BEETWEEN`.^^
// Например: при `raw:false` фильтр `type:BETWEEN` `value:10 AND 20` будет интерпритирован как `BETWEEN ?1 `^^
// где `?1 = "10 AND 20"`, что приведет к ошибке.^^
// В таком случае необходимо использовать `raw:true` для установки условия напрямую в текст запроса
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Элемент фильтра записей
Функция ПолучитьСтруктуруФильтраЗаписей(Знач Пустая = Ложь) Экспорт
Возврат OPI_ЗапросыSQL.ПолучитьСтруктуруФильтраЗаписей(Пустая);
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьОсобенности() Экспорт
Особенности = Новый Соответствие;
Особенности.Вставить("НумерацияПараметров", Истина);
Особенности.Вставить("МаркерПараметров" , "@P");
Особенности.Вставить("СУБД" , "mssql");
Особенности.Вставить("ПолеКолонки" , "column_name");
Особенности.Вставить("НачалоТранзакции" , "BEGIN TRAN");
Возврат Особенности;
КонецФункции
Функция ПолучитьСтруктуруТипов() Экспорт
СтруктураТипов = Новый Соответствие;
СтруктураТипов.Вставить("ДвоичныеДанные" , "BYTES");
СтруктураТипов.Вставить("УникальныйИдентификатор", "UUID");
СтруктураТипов.Вставить("Булево" , "BIT");
СтруктураТипов.Вставить("Дробное" , "DECIMAL");
СтруктураТипов.Вставить("Целое" , "INT");
СтруктураТипов.Вставить("Дата" , "DATETIMEOFFSET");
СтруктураТипов.Вставить("Строка" , "NVARCHAR");
СтруктураТипов.Вставить("Коллекции" , Новый СписокЗначений);
СтруктураТипов.Вставить("БулевоКакЧисло" , Ложь);
Возврат СтруктураТипов;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="03ab9cfa-2ef2-447c-8222-219dbe07d53f">
<Properties>
<Name>OPI_MongoDB</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>MongoDB (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с базами MongoDB из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,118 @@
// OneScript: ./OInt/core/Modules/OPI_MongoDB.os
// Lib: MongoDB
// CLI: mongodb
// Keywords: mongodb, mongo, nosql
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-collection-item-type
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает подключение к указанной базе
//
// Параметры:
// СтрокаПодключения - Строка - Строка подключения - string
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или структура с информацией об ошибке
Функция ОткрытьСоединение(Знач СтрокаПодключения = "") Экспорт
Если ЭтоКоннектор(СтрокаПодключения) Тогда
Возврат СтрокаПодключения;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(СтрокаПодключения);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(СтрокаПодключения);
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("MongoDB");
Коннектор.ConnectionString = СтрокаПодключения;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Возврат ?(Результат["result"], Коннектор, Результат);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - dbc
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
Результат = Соединение.Close();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Иначе
Результат = Новый Структура("result,error", Ложь, "It's not a connection");
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты MSSQL
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_MongoDB.Main";
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="080b004e-2bff-48bc-a034-c69937b69323">
<Properties>
<Name>OPI_MySQL</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>MySQL (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с базами MySQL из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,554 @@
// OneScript: ./OInt/core/Modules/OPI_MySQL.os
// Lib: MySQL
// CLI: mysql
// Keywords: mysql, my sql
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-collection-item-type
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает подключение к указанной базе
//
// Параметры:
// СтрокаПодключения - Строка - Строка подключения. См. СформироватьСтрокуПодключения - string
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или структура с информацией об ошибке
Функция ОткрытьСоединение(Знач СтрокаПодключения = "", Знач Tls = "") Экспорт
Если ЭтоКоннектор(СтрокаПодключения) Тогда
Возврат СтрокаПодключения;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(СтрокаПодключения);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(СтрокаПодключения);
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("MySQL");
Tls = OPI_Компоненты.УстановитьTls(Коннектор, Tls);
Если Не OPI_Инструменты.ПолучитьИли(Tls, "result", Ложь) Тогда
Возврат Tls;
КонецЕсли;
Коннектор.ConnectionString = СтрокаПодключения;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Возврат ?(Результат["result"], Коннектор, Результат);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - dbc
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
Результат = Соединение.Close();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Иначе
Результат = Новый Структура("result,error", Ложь, "It's not a connection");
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты MySQL
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_MySQL.Main";
КонецФункции
// Выполнить запрос SQL
// Выполняет произвольный SQL запрос
//
// Примечание:
// Параметры запроса указываются как массив структур вида `{'Тип данных': 'Значение'}`.^^
// Список доступных типов описан на начальной странице документации библиотеки MySQL
// Без указания флага `ФорсироватьРезультат`, чтение результата осуществляется только для запросов, начинающихся с `SELECT`^^
// Для остальных запросов возвращается `result:true` или `false` с текстом ошибки
//
// Параметры:
// ТекстЗапроса - Строка - Текст запроса к базе - sql
// Параметры - Массив Из Произвольный - Массив позиционных параметров запроса - params
// ФорсироватьРезультат - Булево - Включает попытку получения результата, даже для не SELECT запросов - force
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ВыполнитьЗапросSQL(Знач ТекстЗапроса
, Знач Параметры = ""
, Знач ФорсироватьРезультат = Ложь
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Если ЭтоКоннектор(Соединение) Тогда
ЗакрыватьСоединение = Ложь;
Коннектор = Соединение;
Иначе
ЗакрыватьСоединение = Истина;
Коннектор = ОткрытьСоединение(Соединение, Tls);
КонецЕсли;
Если Не ЭтоКоннектор(Коннектор) Тогда
Возврат Коннектор;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
Параметры_ = OPI_ЗапросыSQL.ОбработатьПараметры(Параметры, ПолучитьСтруктуруТипов());
Результат = OPI_ЗапросыSQL.ВыполнитьЗапросСОбработкой(Коннектор, ТекстЗапроса, ФорсироватьРезультат, Параметры_);
Если ЗакрыватьСоединение Тогда
ЗакрытьСоединение(Коннектор);
КонецЕсли;
Возврат Результат;
КонецФункции
// Сформировать строку подключения
// Формирует строку подключения из переданных данных
//
// Параметры:
// Адрес - Строка - IP адрес или доменное имя сервера - addr
// База - Строка - Имя базы данных для подключения - db
// Логин - Строка - Логин пользователя mysql - login
// Пароль - Строка - Пароль пользователя mysql - pass
// Порт - Строка - Порт подключения - port
//
// Возвращаемое значение:
// Строка - Строка подключения к базе MySQL
Функция СформироватьСтрокуПодключения(Знач Адрес, Знач База = "", Знач Логин = "", Знач Пароль = "", Знач Порт = "3306") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Адрес);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Порт);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
Порт = ?(ЗначениеЗаполнено(Порт), ":" + Порт, Порт);
Пароль = ?(ЗначениеЗаполнено(Пароль), ":" + Пароль, Пароль);
ШаблонСтроки = "mysql://%1%2@%3%4/%5";
СтрокаПодключения = СтрШаблон(ШаблонСтроки, Логин, Пароль, Адрес, Порт, База);
Возврат СтрокаПодключения;
КонецФункции
// Получить настройки TLS
// Формирует настройки для использования TLS при выполнении запросов
//
// Примечание:
// Настройки Tls могут быть установлены только в момент создания соединения: явного, при использовании функции `ОткрытьСоединение`^^
// или неявного, при передаче строки подключения в методы ORM.
// Передача настроек Tls совместно с передачей уже созданного соединения в параметр `Соединение` будет проигнорирована
//
// Параметры:
// ОтключитьПроверкуСертификатов - Булево - Позволяет работать с некорретными сертификатами, в т.ч. самоподписанными - trust
// ПутьКСертификату - Строка - Путь к корневому PEM файлу сертификата, если его нет в системном хранилище - cert
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек TLS соединения
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату);
КонецФункции
#КонецОбласти
#Область ORM
// Создать базу данных
// Создает базу данных с указанным именем
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьБазуДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьБазуДанных(OPI_MySQL, База, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить базу данных
// Удаляет базу данных
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьБазуДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьБазуДанных(OPI_MySQL, База, Соединение, Tls);
Возврат Результат;
КонецФункции
// Создать таблицу
// Создает пустую таблицу в базе
//
// Примечание:
// Список доступных типов описан на начальной странице документации библиотеки MySQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьТаблицу(OPI_MySQL, Таблица, СтруктураКолонок, Соединение, Tls);
Возврат Результат;
КонецФункции
// Добавить колонку таблицы
// Добавляет новую колонку в существующую таблицу
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// ТипДанных - Строка - Тип данных колонки - type
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач ТипДанных, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьКолонкуТаблицы(OPI_MySQL, Таблица, Имя, ТипДанных, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить колонку таблицы
// Удаляет колонку из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьКолонкуТаблицы(OPI_MySQL, Таблица, Имя, Соединение, Tls);
Возврат Результат;
КонецФункции
// Гарантировать таблицу
// Создает новую таблицу в случае отсутствия или обновляет состав колонок существующей таблицы
//
// Примечание:
// В результате изменения структуры таблицы данные могут быть утеряны!^^
// Рекомендуется предварительно опробовать данный метод на тестовых данных
// Данная функция не обновляет тип данных существующих колонок
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ГарантироватьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ГарантироватьТаблицу(OPI_MySQL, Таблица, СтруктураКолонок, Соединение, Tls);
Возврат Результат;
КонецФункции
// Очистить таблицу
// Очищает таблицу базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОчиститьТаблицу(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_MySQL, Таблица, , Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить таблицу
// Удаляет таблицу из базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьТаблицу(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьТаблицу(OPI_MySQL, Таблица, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить информацию о таблице
// Получает информацию о таблице
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьИнформациюОТаблице(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьСтруктуруТаблицы(OPI_MySQL, Таблица, Соединение, Tls);
Возврат Результат;
КонецФункции
// Добавить записи
// Добавляет записи в таблицу
//
// Примечание:
// Данные записей указываются как массив структур вида:^
// `{'Имя поля 1': {'Тип данных': 'Значение'}, 'Имя поля 2': {'Тип данных': 'Значение'},...}`
// Список доступных типов описан на начальной странице документации библиотеки MySQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// МассивДанных - Массив Из Структура - Массив структур данных строк: Ключ > поле, Значение > значение поля - rows
// Транзакция - Булево - Истина > добавление записей в транзакции с откатом при ошибке - trn
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьЗаписи(Знач Таблица, Знач МассивДанных, Знач Транзакция = Истина, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьЗаписи(OPI_MySQL, Таблица, МассивДанных, Транзакция, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить записи
// Получает записи из выбранной таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Поля - Массив Из Строка - Поля для выборки - fields
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Сортировка - Структура Из КлючИЗначение - Сортировка: Ключ > поле, Значение > направление (ASC, DESC) - order
// Количество - Число - Ограничение количества получаемых строк - limit
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьЗаписи(Знач Таблица
, Знач Поля = "*"
, Знач Фильтры = ""
, Знач Сортировка = ""
, Знач Количество = ""
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьЗаписи(OPI_MySQL
, Таблица
, Поля
, Фильтры
, Сортировка
, Количество
, Соединение
, Tls);
Возврат Результат;
КонецФункции
// Обновить записи
// Обновляет значение записей по выбранным критериям
//
// Примечание:
// Данные записей указываются как массив структур вида:^
// `{'Имя поля 1': {'Тип данных': 'Значение'}, 'Имя поля 2': {'Тип данных': 'Значение'},...}`
// Список доступных типов описан на начальной странице документации библиотеки MySQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураЗначений - Структура Из КлючИЗначение - Структура значений: Ключ > поле, Значение > значение поля - values
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОбновитьЗаписи(Знач Таблица
, Знач СтруктураЗначений
, Знач Фильтры = ""
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ОбновитьЗаписи(OPI_MySQL, Таблица, СтруктураЗначений, Фильтры, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить записи
// Удаляет записи из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьЗаписи(Знач Таблица, Знач Фильтры = "", Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_MySQL, Таблица, Фильтры, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить структуру фильтра записей
// Получает структуру шаблон для фильтрации записей в запросах ORM
//
// Примечание:
// Использование признака `raw` необходимо для составных конструкций, вроде `BEETWEEN`.^^
// Например: при `raw:false` фильтр `type:BETWEEN` `value:10 AND 20` будет интерпритирован как `BETWEEN ?1 `^^
// где `?1 = "10 AND 20"`, что приведет к ошибке.^^
// В таком случае необходимо использовать `raw:true` для установки условия напрямую в текст запроса
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Элемент фильтра записей
Функция ПолучитьСтруктуруФильтраЗаписей(Знач Пустая = Ложь) Экспорт
Возврат OPI_ЗапросыSQL.ПолучитьСтруктуруФильтраЗаписей(Пустая);
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьОсобенности() Экспорт
Особенности = Новый Соответствие;
Особенности.Вставить("НумерацияПараметров", Ложь);
Особенности.Вставить("МаркерПараметров" , "?");
Особенности.Вставить("СУБД" , "mysql");
Особенности.Вставить("ПолеКолонки" , "COLUMN_NAME");
Особенности.Вставить("НачалоТранзакции" , "BEGIN");
Возврат Особенности;
КонецФункции
Функция ПолучитьСтруктуруТипов() Экспорт
СтруктураТипов = Новый Соответствие;
СтруктураТипов.Вставить("ДвоичныеДанные" , "BYTES");
СтруктураТипов.Вставить("УникальныйИдентификатор", "TEXT");
СтруктураТипов.Вставить("Булево" , "INT");
СтруктураТипов.Вставить("Дробное" , "DOUBLE");
СтруктураТипов.Вставить("Целое" , "DOUBLE");
СтруктураТипов.Вставить("Дата" , "DATE");
СтруктураТипов.Вставить("Строка" , "TEXT");
СтруктураТипов.Вставить("Коллекции" , Новый СписокЗначений);
СтруктураТипов.Вставить("БулевоКакЧисло" , Истина);
Возврат СтруктураТипов;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="5128c6b7-5449-4a95-954d-4bb73e6b1c7d">
<Properties>
<Name>OPI_Neocities</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Neocities (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Neocities из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,449 @@
// OneScript: ./OInt/core/Modules/OPI_Neocities.os
// Lib: Neocities
// CLI: neocities
// Keywords: neocities
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область ПолучениеДанных
// Получить данные о сайте
// Получает информацию о сайте по его имени или токену
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// Сайт - Строка - Имя сайта (логин) для получения информации. Текущий, если не заполнено - sitename
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Neocities
Функция ПолучитьДанныеОСайте(Знач Токен, Знач Сайт = "") Экспорт
URL = "https://neocities.org/api/info";
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("sitename", Сайт, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить токен
// Получает токен авторизации по логину и паролю
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
//
// Параметры:
// Логин - Строка - Логин пользователя - login
// Пароль - Строка - Пароль пользователя - password
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Neocities
Функция ПолучитьТокен(Знач Логин, Знач Пароль) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
URL = "neocities.org";
Таймаут = 120;
Попытка
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
БезопасноеСоединение = Новый HTTPСоединение(URL, 443, Логин, Пароль, , Таймаут, ЗащищенноеСоединение);
Исключение
URL = "https://" + URL;
БезопасноеСоединение = Новый HTTPСоединение(URL, 443, Логин, Пароль, , Таймаут);
КонецПопытки;
Ответ = БезопасноеСоединение.Получить(Новый HTTPЗапрос("/api/key"));
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Ответ = ПрочитатьJSON(ЧтениеJSON);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСФайлами
// Загрузить файл
// Загружает одиночный файл на сервер Neocities
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// Путь - Строка - Целевой путь файла на Neocities - path
// Данные - Строка, ДвоичныеДанные - URL, путь или данные файла для загрузки - file
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Neocities
Функция ЗагрузитьФайл(Знач Токен, Знач Путь, Знач Данные) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные);
URL = "https://neocities.org/api/upload";
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
СоответствиеФайла = Новый Соответствие;
СоответствиеФайла.Вставить(Путь + "|" + Путь, Данные);
Ответ = OPI_ЗапросыHTTP.PostMultipart(URL, , СоответствиеФайла, "multipart/form-data", Заголовки);
Возврат Ответ;
КонецФункции
// Загрузить файлы
// Загружает несколько файлов на сервер Neocities
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// СоответствиеФайлов - Соответствие Из КлючИЗначение - Файлы для загрузки: Ключ > путь на NC, Значение > Файл - files
// ПоОдному - Булево - Истина > отправляет файлы отдельными запросами - singly
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Neocities
Функция ЗагрузитьФайлы(Знач Токен, Знач СоответствиеФайлов, Знач ПоОдному = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(ПоОдному);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(СоответствиеФайлов);
КонечныйОтвет = Новый Массив;
ОбработанноеСоответствие = Новый Соответствие;
Для Каждого ФайлОтправки Из СоответствиеФайлов Цикл
Если ПоОдному Тогда
Ответ = ЗагрузитьФайл(Токен, ФайлОтправки.Ключ, ФайлОтправки.Значение);
КонечныйОтвет.Добавить(Ответ);
Иначе
ТекущийПуть = ФайлОтправки.Ключ;
ТекущиеДанные = ФайлОтправки.Значение;
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекущийПуть);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(ТекущиеДанные);
ОбработанноеСоответствие.Вставить(ТекущийПуть + "|" + ТекущийПуть, ТекущиеДанные);
КонецЕсли;
КонецЦикла;
Если Не ПоОдному Тогда
URL = "https://neocities.org/api/upload";
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
КонечныйОтвет = OPI_ЗапросыHTTP.PostMultipart(URL
,
, ОбработанноеСоответствие
, "multipart/form-data"
, Заголовки);
КонецЕсли;
Возврат КонечныйОтвет;
КонецФункции
// Удалить выбранные файлы
// Удаляет файл или несколько файлов с сервера Neocities
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// Пути - Строка, Массив Из Строка - Путь или несколько путей удаляемых файлов - paths
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Neocities
Функция УдалитьВыбранныеФайлы(Знач Токен, Знач Пути) Экспорт
OPI_ПреобразованиеТипов.ПолучитьМассив(Пути);
URL = "https://neocities.org/api/delete";
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Для Н = 0 По Пути.ВГраница() Цикл
ТекущееЗначение = Пути[Н];
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекущееЗначение);
Пути.Установить(Н, "filenames[]=" + ТекущееЗначение);
КонецЦикла;
ПутиСтрокой = СтрСоединить(Пути, "&");
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, ПутиСтрокой, Заголовки, Ложь);
Возврат Ответ;
КонецФункции
// Получить список файлов
// Получает список файлов с отбором каталога или без
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// Путь - Строка - Отбор файлов по каталогу. Все, если не заполнено - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Neocities
Функция ПолучитьСписокФайлов(Знач Токен, Знач Путь = "") Экспорт
URL = "https://neocities.org/api/list";
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Синхронизировать каталоги
// Создает копию локального каталога по выбранному пути на сервере
//
// Примечание:
// Документация Neocities API: [neocities.org/api](@neocities.org/api)
// Метод удаляет файлы на сервере, если они отсутствуют в локальном каталоге
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// ЛокальныйКаталог - Строка - Локальный каталог источник - local
// УдаленныйКаталог - Строка - Удаленный каталог приемника. Корень, если не заполнено - remote
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - информация об ошибках синхронизации
Функция СинхронизироватьКаталоги(Знач Токен, Знач ЛокальныйКаталог, Знач УдаленныйКаталог = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ЛокальныйКаталог);
OPI_ПреобразованиеТипов.ПолучитьСтроку(УдаленныйКаталог);
// !OInt Сообщить("Начало синхронизации...");
Если ЗначениеЗаполнено(УдаленныйКаталог) Тогда
УдаленныйКаталог = ?(СтрЗаканчиваетсяНа(УдаленныйКаталог, "/"), УдаленныйКаталог, УдаленныйКаталог + "/");
КонецЕсли;
УдаленныеФайлы = ПолучитьСписокФайлов(Токен, УдаленныйКаталог);
Если Не УдаленныеФайлы["result"] = "success" Тогда
//@skip-check constructor-function-return-section
Возврат УдаленныеФайлы;
КонецЕсли;
ЛокальныеПути = Новый Соответствие;
ЛокальныеПодкаталоги = Новый Соответствие;
ПолучитьНаборыЛокальныхПутей(ЛокальныйКаталог, УдаленныйКаталог, ЛокальныеПути, ЛокальныеПодкаталоги);
МассивУдаляемых = ПолучитьУдаляемыеФайлы(УдаленныеФайлы, ЛокальныеПути, ЛокальныеПодкаталоги);
Результат = ВыполнитьСинхронизацию(Токен, МассивУдаляемых, ЛокальныеПути);
//@skip-check constructor-function-return-section
Возврат Результат;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция СоздатьЗаголовкиЗапроса(Знач Токен)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + Токен);
Возврат Заголовки;
КонецФункции
Функция ПолучитьУдаляемыеФайлы(УдаленныеФайлы, ЛокальныеПути, ЛокальныеПодкаталоги)
МассивУдаляемых = Новый Массив;
Для Каждого УдаленныйФайл Из УдаленныеФайлы["files"] Цикл
ПутьУдаленногоОсновной = УдаленныйФайл["path"];
ПутьУдаленногоДополнительный = "/" + УдаленныйФайл["path"];
Если УдаленныйФайл["is_directory"] Тогда
СуществующийУдаленный = ЛокальныеПодкаталоги[ПутьУдаленногоОсновной];
СуществующийУдаленный = ?(ЗначениеЗаполнено(СуществующийУдаленный)
, СуществующийУдаленный
, ЛокальныеПодкаталоги[ПутьУдаленногоДополнительный]);
Иначе
СуществующийУдаленный = ЛокальныеПути[ПутьУдаленногоОсновной];
СуществующийУдаленный = ?(ЗначениеЗаполнено(СуществующийУдаленный)
, СуществующийУдаленный
, ЛокальныеПути[ПутьУдаленногоДополнительный]);
КонецЕсли;
Если СуществующийУдаленный = Неопределено Тогда
МассивУдаляемых.Добавить(ПутьУдаленногоОсновной);
КонецЕсли;
КонецЦикла;
Возврат МассивУдаляемых;
КонецФункции
Функция ВыполнитьСинхронизацию(Токен, МассивУдаляемых, ЛокальныеПути)
МассивОшибок = Новый Массив;
Если Не МассивУдаляемых.Количество() = 0 Тогда
Ответ = УдалитьВыбранныеФайлы(Токен, МассивУдаляемых);
Если Не Ответ["result"] = "success" Тогда
МассивОшибок.Добавить(Ответ);
Иначе
// BSLLS:UnusedLocalVariable-off
//@skip-check module-unused-local-variable
СообщениеУдаления = СтрШаблон("Удалено %1 лишних файлов", Строка(МассивУдаляемых.Количество()));
// !OInt Сообщить(СообщениеУдаления);
// BSLLS:UnusedLocalVariable-on
КонецЕсли;
КонецЕсли;
Всего = OPI_Инструменты.ЧислоВСтроку(ЛокальныеПути.Количество());
Счетчик = 0;
Для Каждого ЛокальныйПуть Из ЛокальныеПути Цикл
Ответ = ЗагрузитьФайл(Токен, ЛокальныйПуть.Ключ, ЛокальныйПуть.Значение);
Если Не Ответ["result"] = "success" Тогда
МассивОшибок.Добавить(Ответ);
Иначе
// BSLLS:UnusedLocalVariable-off
//@skip-check module-unused-local-variable
Прогресс = "[" + OPI_Инструменты.ЧислоВСтроку(Счетчик) + "/" + Всего + "] ";
// !OInt Сообщить(Прогресс + ЛокальныйПуть.Ключ + Символы.ПС + Ответ["message"] + Символы.ПС);
// BSLLS:UnusedLocalVariable-on
КонецЕсли;
Счетчик = Счетчик + 1;
КонецЦикла;
Возврат Новый Структура("errors,items", МассивОшибок.Количество(), МассивОшибок);
КонецФункции
Процедура ПолучитьНаборыЛокальныхПутей(ЛокальныйКаталог, УдаленныйКаталог, ЛокальныеПути, ЛокальныеПодкаталоги)
ЛокальныйКаталог = СтрЗаменить(ЛокальныйКаталог, "\", "/");
ЛокальныйКаталог = ?(СтрЗаканчиваетсяНа(ЛокальныйКаталог, "/"), ЛокальныйКаталог, ЛокальныйКаталог + "/");
ЛокальныеФайлы = НайтиФайлы(ЛокальныйКаталог, "*", Истина);
Для Каждого ЛокальныйФайл Из ЛокальныеФайлы Цикл
ТекущийАбсПуть = ЛокальныйФайл.ПолноеИмя;
ТекущийОтнПуть = Прав(ТекущийАбсПуть, СтрДлина(ТекущийАбсПуть) - СтрДлина(ЛокальныйКаталог));
ТекущийОтнПуть = УдаленныйКаталог + ТекущийОтнПуть;
ТекущийОтнПуть = СтрЗаменить(ТекущийОтнПуть, "\", "/");
Если ЛокальныйФайл.ЭтоКаталог() Тогда
ЛокальныеПодкаталоги.Вставить(ТекущийОтнПуть, ТекущийАбсПуть);
Иначе
ЛокальныеПути.Вставить(ТекущийОтнПуть, ТекущийАбсПуть);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="1bef723b-a2a4-4547-b29f-63cf9c78d813">
<Properties>
<Name>OPI_Notion</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Notion (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Notion из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,893 @@
// OneScript: ./OInt/core/Modules/OPI_Notion.os
// Lib: Notion
// CLI: notion
// Keywords: notion
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check method-too-many-params
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область РаботаСоСтраницами
// Создать страницу
// Создает дочернюю страницу над другой страницей-родителем
//
// Параметры:
// Токен - Строка - Токен - token
// Родитель - Строка - ID Родителя - page
// Заголовок - Строка - Заголовок страницы - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция СоздатьСтраницу(Знач Токен, Знач Родитель, Знач Заголовок) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Родитель);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Заголовок);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Свойства = Новый Структура;
Параметры = Новый Структура;
ДобавитьЗаголовокСтраницы(Заголовок, Свойства);
ДобавитьРодителяСтраницы(Родитель, Ложь, Параметры);
Параметры.Вставить("properties", Свойства);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.notion.com/v1/pages", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Создать страницу в базу
// Создает страницу в базе-родителе
//
// Параметры:
// Токен - Строка - Токен - token
// Родитель - Строка - ID родительской базы - base
// Данные - Соответствие Из КлючИЗначение - Соответствие свойств - data
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция СоздатьСтраницуВБазу(Знач Токен, Знач Родитель, Знач Данные) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Родитель);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Данные);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Параметры = Новый Структура;
ДобавитьРодителяСтраницы(Родитель, Истина, Параметры);
Свойства = ЗаполнитьДанныеПоСхеме(Родитель, Данные, Токен);
Параметры.Вставить("properties", Свойства);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.notion.com/v1/pages", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить страницу
// Получает информацию о странице по ID
//
// Параметры:
// Токен - Строка - Токен - token
// Страница - Строка - ID страницы - page
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ПолучитьСтраницу(Знач Токен, Знач Страница) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Страница);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
ПреобразоватьИД(Страница);
Ответ = OPI_ЗапросыHTTP.Get("https://api.notion.com/v1/pages/" + Страница, , Заголовки);
Возврат Ответ;
КонецФункции
// Изменить свойства страницы
// Изменяет свойства существующей страницы
//
// Параметры:
// Токен - Строка - Токен - token
// Страница - Строка - ID изменяемой страницы - page
// Данные - Соответствие Из КлючИЗначение - Соответствие изменяемых параметров - data
// Иконка - Строка - URL картинки иконки страницы - icon
// Обложка - Строка - URL картинки обложки страницы - cover
// Архивирована - Булево - Архивировать страницу или нет (булево) - archive
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ИзменитьСвойстваСтраницы(Знач Токен
, Знач Страница
, Знач Данные = ""
, Знач Иконка = ""
, Знач Обложка = ""
, Знач Архивирована = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Страница);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Иконка);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Обложка);
OPI_ПреобразованиеТипов.ПолучитьБулево(Архивирована);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Данные);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Параметры = Новый Структура;
Files = "files";
Если ЗначениеЗаполнено(Данные)
И (ТипЗнч(Данные) = Тип("Соответствие") Или ТипЗнч(Данные) = Тип("Структура")) Тогда
Свойства = ЗаполнитьДанныеПоСхеме(Страница, Данные, Токен, Ложь);
Иначе
Свойства = Новый Соответствие;
КонецЕсли;
Если ЗначениеЗаполнено(Иконка) Тогда
СоответствиеИконки = Новый Соответствие;
СоответствиеИконки.Вставить("Icon", Иконка);
ОбъектИконка = ПреобразоватьЗначениеПоТипу(Files, СоответствиеИконки);
ОбъектИконка = ОбъектИконка[Files][0];
ОбъектИконка.Удалить("name");
Параметры.Вставить("icon", ОбъектИконка);
КонецЕсли;
Если ЗначениеЗаполнено(Обложка) Тогда
СоответствиеОбложки = Новый Соответствие;
СоответствиеОбложки.Вставить("Cover", Обложка);
ОбъектОбложка = ПреобразоватьЗначениеПоТипу(Files, СоответствиеОбложки);
ОбъектОбложка = ОбъектОбложка[Files][0];
ОбъектОбложка.Удалить("name");
Параметры.Вставить("cover", ОбъектОбложка);
КонецЕсли;
Параметры.Вставить("properties", Свойства);
Параметры.Вставить("archived" , Архивирована);
ПреобразоватьИД(Страница);
Ответ = OPI_ЗапросыHTTP.PatchСТелом("https://api.notion.com/v1/pages/" + Страница, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСБазамиДанных
// Создать базу данных
// Создает базу данных
//
// Параметры:
// Токен - Строка - Токен - token
// Родитель - Строка - ID страницы родителя - page
// Заголовок - Строка - Заголовок базы данных - title
// Свойства - Структура Из Строка - Свойства базы данных - props
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция СоздатьБазуДанных(Знач Токен, Знач Родитель, Знач Заголовок, Знач Свойства = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Родитель);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Заголовок);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Свойства);
// Пример структуры/соответствия свойств
// Имя : title
// Описание : rich_text
// В работе : checkbox
// Количество : number
// Дата : date
// Статус : Соответствие
// Активный : green
// Неактивный : red
// Архив : yellow
// Все страницы, которые будут созданы как дочерние, должны иметь свойства базы-родителя
Если Не ТипЗнч(Свойства) = Тип("Структура") И Не ТипЗнч(Свойства) = Тип("Соответствие") Тогда
Свойства = Новый Структура("Наименование", "title");
КонецЕсли;
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Параметры = Новый Структура;
ДобавитьРодителяБазы(Родитель, Ложь, Параметры);
ДобавитьЗаголовокБазы(Заголовок, Параметры);
ДобавитьСвойстваБазы(Свойства, Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.notion.com/v1/databases", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить базу данных
// Получить данные о базе данных
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - ID базы данных - base
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ПолучитьБазуДанных(Знач Токен, Знач База) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
ПреобразоватьИД(База);
Ответ = OPI_ЗапросыHTTP.Get("https://api.notion.com/v1/databases/" + База, , Заголовки);
Возврат Ответ;
КонецФункции
// Изменить свойства базы
// Изменяет свойства существующей базы
//
// Параметры:
// Токен - Строка - Токен - token
// База - Строка - ID целевой базы - base
// Свойства - Соответствие из КлючИЗначение - Новые или изменяемые свойства базы данных - props
// Заголовок - Строка - Новый заголовок базы - title
// Описание - Строка - Новое описание базы - description
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ИзменитьСвойстваБазы(Знач Токен, Знач База, Знач Свойства = "", Знач Заголовок = "", Знач Описание = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Заголовок);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Описание);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Свойства);
Параметры = Новый Структура;
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
ПреобразоватьИД(База);
Если ЗначениеЗаполнено(Заголовок) Тогда
ДобавитьЗаголовокБазы(Заголовок, Параметры);
КонецЕсли;
Если ЗначениеЗаполнено(Описание) Тогда
ДобавитьОписаниеБазы(Описание, Параметры);
КонецЕсли;
Если ТипЗнч(Свойства) = Тип("Структура") Или ТипЗнч(Свойства) = Тип("Соответствие") Тогда
ДобавитьСвойстваБазы(Свойства, Параметры);
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.PatchСТелом("https://api.notion.com/v1/databases/" + База, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСБлоками
// Создать блок
// Создает новый блок на основе существующего блока
//
// Параметры:
// Токен - Строка - Токен - token
// Родитель - Строка - ID родительского блока или страницы - page
// Блок - Строка,Соответствие Из КлючИЗначение - ID блока или сам блок образец - block
// ВставитьПосле - Строка - ID блока, после которого необходимо встаивть новый - prev
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция СоздатьБлок(Знач Токен, Знач Родитель, Знач Блок, Знач ВставитьПосле = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Родитель);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ВставитьПосле);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Блок);
Если ТипЗнч(Блок) = Тип("Массив") Тогда
Блок = Блок[0];
КонецЕсли;
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
ПреобразоватьИД(Родитель);
Если ТипЗнч(Блок) = Тип("Строка") Тогда
ПреобразоватьИД(Блок);
Блок = ВернутьБлок(Токен, Блок);
КонецЕсли;
МассивБлоков = Новый Массив;
МассивБлоков.Добавить(Блок);
Параметры = Новый Соответствие;
Параметры.Вставить("children", МассивБлоков);
Если ЗначениеЗаполнено(ВставитьПосле) Тогда
Параметры.Вставить("after", ВставитьПосле);
КонецЕсли;
URL = "https://api.notion.com/v1/blocks/" + Родитель + "/children";
Ответ = OPI_ЗапросыHTTP.PatchСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Вернуть блок
// Возвращает структуру блока по ID
//
// Параметры:
// Токен - Строка - Токен - token
// ИДБлока - Строка - ID блока - block
// ТолькоОснова - Булево - Истина > служебные поля удаляются, остается только сам блок - core
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ВернутьБлок(Знач Токен, Знач ИДБлока, Знач ТолькоОснова = Истина) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДБлока);
OPI_ПреобразованиеТипов.ПолучитьБулево(ТолькоОснова);
ПреобразоватьИД(ИДБлока);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Get("https://api.notion.com/v1/blocks/" + ИДБлока, , Заголовки);
Если ТолькоОснова Тогда
УдалитьЛишниеПоляБлока(Ответ);
КонецЕсли;
Возврат Ответ;
КонецФункции
// Вернуть дочерние блоки
// Созвращает список дочерних блоков блока-родителя
//
// Параметры:
// Токен - Строка - Токен - token
// ИДБлока - Строка - ID блока родителя - block
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ВернутьДочерниеБлоки(Знач Токен, Знач ИДБлока) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДБлока);
ПреобразоватьИД(ИДБлока);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Get("https://api.notion.com/v1/blocks/" + ИДБлока + "/children", , Заголовки);
Возврат Ответ;
КонецФункции
// Удалить блок
// Удаляет блок по ID
//
// Параметры:
// Токен - Строка - Токен - token
// ИДБлока - Строка - ID блока - block
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция УдалитьБлок(Знач Токен, Знач ИДБлока) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДБлока);
ПреобразоватьИД(ИДБлока);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Delete("https://api.notion.com/v1/blocks/" + ИДБлока, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область Пользователи
// Список пользователей
// Возвращает список пользователей рабочего пространства
//
// Параметры:
// Токен - Строка - Токен - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция СписокПользователей(Знач Токен) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Get("https://api.notion.com/v1/users", , Заголовки);
Возврат Ответ;
КонецФункции
// Получить данные пользователя
// Получает данные пользователя по ID
//
// Параметры:
// Токен - Строка - Токен - token
// ИДПользователя - Строка - ID целевого пользователя - user
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Notion
Функция ПолучитьДанныеПользователя(Знач Токен, Знач ИДПользователя) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИДПользователя);
ПреобразоватьИД(ИДПользователя);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Get("https://api.notion.com/v1/users/" + ИДПользователя, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция СоздатьЗаголовкиЗапроса(Знач Токен)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization" , "Bearer " + Токен);
Заголовки.Вставить("Notion-Version", "2022-06-28");
Возврат Заголовки;
КонецФункции
Процедура ПреобразоватьИД(Идентификатор)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Идентификатор);
Идентификатор = СтрЗаменить(Идентификатор, "-", "");
КонецПроцедуры
Процедура ДобавитьРодителяСтраницы(Знач Родитель, Знач РодительБаза, ОсновнаяСтруктура)
OPI_ПреобразованиеТипов.ПолучитьСтроку(РодительБаза);
ПреобразоватьИД(Родитель);
ПолеИдентификатора = ?(РодительБаза, "database_id", "page_id");
СтруктураРодителя = Новый Структура(ПолеИдентификатора, Родитель);
ОсновнаяСтруктура.Вставить("parent", СтруктураРодителя);
КонецПроцедуры
Процедура ДобавитьРодителяБазы(Знач Родитель, Знач РодительБаза, ОсновнаяСтруктура)
OPI_ПреобразованиеТипов.ПолучитьСтроку(РодительБаза);
ПреобразоватьИД(Родитель);
ПолеИдентификатора = ?(РодительБаза, "database_id", "page_id");
СтруктураРодителя = Новый Структура();
СтруктураРодителя.Вставить("type" , ПолеИдентификатора);
СтруктураРодителя.Вставить(ПолеИдентификатора, Родитель);
ОсновнаяСтруктура.Вставить("parent", СтруктураРодителя);
КонецПроцедуры
Процедура ДобавитьЗаголовокСтраницы(Знач Заголовок, ОсновнаяСтруктура)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Заголовок);
ПодчиненнаяСтруктура = Новый Структура;
СтруктураДанных = Новый Структура;
СтруктураТекста = Новый Структура;
МассивДанных = Новый Массив;
Title = "title";
СтруктураТекста.Вставить("content", Заголовок);
СтруктураТекста.Вставить("link" , Неопределено);
СтруктураДанных.Вставить("text", СтруктураТекста);
СтруктураДанных.Вставить("type", "text");
МассивДанных.Добавить(СтруктураДанных);
ПодчиненнаяСтруктура.Вставить("id" , Title);
ПодчиненнаяСтруктура.Вставить("type" , Title);
ПодчиненнаяСтруктура.Вставить(Title , МассивДанных);
ОсновнаяСтруктура.Вставить(Title, ПодчиненнаяСтруктура);
КонецПроцедуры
Процедура ДобавитьЗаголовокБазы(Знач Заголовок, ОсновнаяСтруктура)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Заголовок);
Заголовок = ПреобразоватьЗаголовок(Заголовок);
ОсновнаяСтруктура.Вставить("title", Заголовок["title"]);
КонецПроцедуры
Процедура ДобавитьОписаниеБазы(Знач Описание, ОсновнаяСтруктура)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Описание);
Заголовок = ПреобразоватьЗаголовок(Описание);
ОсновнаяСтруктура.Вставить("description", Заголовок["title"]);
КонецПроцедуры
Процедура ДобавитьСвойстваБазы(Знач Свойства, ОсновнаяСтруктура)
Если Свойства.Количество() = 0 Тогда
ОсновнаяСтруктура.Вставить("properties", Новый Структура);
Возврат;
КонецЕсли;
СоответствиеПараметров = Новый Соответствие;
Для Каждого Свойство Из Свойства Цикл
Если ТипЗнч(Свойство.Значение) = Тип("Строка") Тогда
СоответствиеПараметров.Вставить(Свойство.Ключ, Новый Структура(Свойство.Значение, Новый Структура));
ИначеЕсли ТипЗнч(Свойство.Значение) = Тип("Структура")
Или ТипЗнч(Свойство.Значение) = Тип("Соответствие") Тогда
ВыборЗначения = СформироватьЗначенияВыбора(Свойство.Значение);
СоответствиеПараметров.Вставить(Свойство.Ключ, Новый Структура("select", ВыборЗначения));
Иначе
СоответствиеПараметров.Вставить(Свойство.Ключ, Свойство.Значение);
КонецЕсли;
КонецЦикла;
ОсновнаяСтруктура.Вставить("properties", СоответствиеПараметров);
КонецПроцедуры
Функция СформироватьЗначенияВыбора(Знач СтруктураВариантов)
МассивВариантов = Новый Массив;
Для Каждого Вариант Из СтруктураВариантов Цикл
СоответствиеВарианта = Новый Соответствие;
СоответствиеВарианта.Вставить("name" , Вариант.Ключ);
СоответствиеВарианта.Вставить("color", Вариант.Значение);
МассивВариантов.Добавить(СоответствиеВарианта);
КонецЦикла;
Возврат Новый Структура("options", МассивВариантов);
КонецФункции
Функция ЗаполнитьДанныеПоСхеме(Знач Схема, Знач Данные, Знач Токен, Знач ЭтоБаза = Истина)
Если ЭтоБаза Тогда
ДанныеСхемы = ПолучитьБазуДанных(Токен, Схема);
Иначе
ДанныеСхемы = ПолучитьСтраницу(Токен, Схема);
КонецЕсли;
ПоляБазы = ДанныеСхемы["properties"];
Свойства = Новый Соответствие;
Если ЗначениеЗаполнено(ПоляБазы) Тогда
Для Каждого Поле Из ПоляБазы Цикл
ДанныеПоля = Поле.Значение;
ТипПоля = ДанныеПоля["type"];
ЗаполняемыеДанные = Данные.Получить(Поле.Ключ);
Если ЗаполняемыеДанные = Неопределено Тогда
Продолжить;
КонецЕсли;
ПреобразованныеДанные = ПреобразоватьЗначениеПоТипу(ТипПоля, ЗаполняемыеДанные);
Если ПреобразованныеДанные = Неопределено Тогда
Продолжить;
КонецЕсли;
Свойства.Вставить(ДанныеПоля["id"], ПреобразованныеДанные);
КонецЦикла;
КонецЕсли;
Возврат Свойства;
КонецФункции
Процедура УдалитьЛишниеПоляБлока(Знач Блок)
МассивЛишних = Новый Массив;
МассивЛишних.Добавить("request_id");
МассивЛишних.Добавить("archived");
МассивЛишних.Добавить("created_by");
МассивЛишних.Добавить("last_edited_time");
МассивЛишних.Добавить("created_time");
МассивЛишних.Добавить("has_children");
МассивЛишних.Добавить("parrent");
МассивЛишних.Добавить("last_edited_by");
МассивЛишних.Добавить("id");
Для Каждого Поле Из МассивЛишних Цикл
Если Не Блок.Получить(Поле) = Неопределено Тогда
Блок.Удалить(Поле);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
#Область ПреобразованиеТипов
Функция ПреобразоватьЗначениеПоТипу(Знач Тип, Знач Значение)
Если Тип = "title" Тогда
Возврат ПреобразоватьЗаголовок(Значение);
ИначеЕсли Тип = "rich_text" Тогда
Возврат ПреобразоватьТекст(Значение);
ИначеЕсли Тип = "number" Тогда
Возврат ПреобразоватьЧисло(Значение);
ИначеЕсли Тип = "select" Тогда
Возврат ПреобразоватьВариантВыбора(Значение);
ИначеЕсли Тип = "multi_select" Тогда
Возврат ПреобразоватьМножественныйВыбор(Значение);
ИначеЕсли Тип = "status" Тогда
Возврат ПреобразоватьСтатус(Значение);
ИначеЕсли Тип = "date" Тогда
Возврат ПреобразоватьДату(Значение);
ИначеЕсли Тип = "relation" Тогда
Возврат ПреобразоватьСвязь(Значение);
ИначеЕсли Тип = "people" Тогда
Возврат ПреобразоватьПользователей(Значение);
ИначеЕсли Тип = "files" Тогда
Возврат ПреобразоватьФайлы(Значение);
ИначеЕсли Тип = "checkbox" Тогда
Возврат ПреобразоватьБулево(Значение);
ИначеЕсли Тип = "url" Тогда
Возврат ПреобразоватьСсылку(Значение);
ИначеЕсли Тип = "email" Тогда
Возврат ПреобразоватьПочту(Значение);
ИначеЕсли Тип = "phone_number" Тогда
Возврат ПреобразоватьТелефон(Значение);
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Функция ПреобразоватьЗаголовок(Знач Заголовок)
СтруктураДанных = Новый Структура;
СтруктураТекста = Новый Структура;
МассивДанных = Новый Массив;
СтруктураТекста.Вставить("content", Заголовок);
СтруктураТекста.Вставить("link" , Неопределено);
СтруктураДанных.Вставить("type", "text");
СтруктураДанных.Вставить("text", СтруктураТекста);
МассивДанных.Добавить(СтруктураДанных);
Возврат Новый Структура("title", МассивДанных);
КонецФункции
Функция ПреобразоватьТекст(Знач Текст)
МассивТекста = Новый Массив;
СтруктураТекста = Новый Структура;
СтруктураТекста.Вставить("type", "text");
СтруктураТекста.Вставить("text", Новый Структура("content", Текст));
МассивТекста.Добавить(СтруктураТекста);
Возврат Новый Структура("rich_text", МассивТекста);
КонецФункции
Функция ПреобразоватьЧисло(Знач Число)
Возврат Новый Структура("number", Число);
КонецФункции
Функция ПреобразоватьВариантВыбора(Знач Вариант)
СтруктураВыбора = Новый Структура;
СтруктураВыбора.Вставить("select", Новый Структура("name", Вариант));
Возврат СтруктураВыбора;
КонецФункции
Функция ПреобразоватьСтатус(Знач Статус)
СтруктураСтатуса = Новый Структура;
СтруктураСтатуса.Вставить("status", Новый Структура("name", Статус));
Возврат СтруктураСтатуса;
КонецФункции
Функция ПреобразоватьМножественныйВыбор(Знач МассивВариантов)
МассивВариантовВыбора = Новый Массив;
Для Каждого Вариант Из МассивВариантов Цикл
МассивВариантовВыбора.Добавить(Новый Структура("name", Вариант));
КонецЦикла;
Возврат Новый Структура("multi_select", МассивВариантовВыбора);
КонецФункции
Функция ПреобразоватьДату(Знач Дата)
СтруктураДаты = Новый Структура;
Если Дата = НачалоДня(Дата) Тогда
ФорматДаты = "ДФ=yyyy-MM-dd";
Иначе
ФорматДаты = "ДФ=yyyy-MM-ddThh:mm:ssZ";
КонецЕсли;
Дата = Формат(Дата, ФорматДаты);
СтруктураДаты.Вставить("start", Дата);
Возврат Новый Структура("date", СтруктураДаты);
КонецФункции
Функция ПреобразоватьСвязь(Знач Идентификатор)
МассивСвязи = Новый Массив;
МассивСвязи.Добавить(Новый Структура("id", Идентификатор));
Возврат Новый Структура("relation", МассивСвязи);
КонецФункции
Функция ПреобразоватьПользователей(Знач МассивИД)
Если Не ТипЗнч(МассивИД) = Тип("Массив") Тогда
МассивИД_ = Новый Массив;
МассивИД_.Добавить(МассивИД);
МассивИД = МассивИД_;
КонецЕсли;
МассивПользователей = Новый Массив;
Для Каждого Идентификатор Из МассивИД Цикл
СтруктураПользователя = Новый Структура;
СтруктураПользователя.Вставить("object", "user");
СтруктураПользователя.Вставить("id" , Идентификатор);
МассивПользователей.Добавить(СтруктураПользователя);
КонецЦикла;
Возврат Новый Структура("people", МассивПользователей);
КонецФункции
Функция ПреобразоватьФайлы(Знач СоответствиеФайлов)
МассивФайлов = Новый Массив;
Для Каждого Файл Из СоответствиеФайлов Цикл
СтруктураФайла = Новый Структура;
СтруктураФайла.Вставить("type" , "external");
СтруктураФайла.Вставить("name" , Файл.Ключ);
СтруктураФайла.Вставить("external", Новый Структура("url", Файл.Значение));
МассивФайлов.Добавить(СтруктураФайла);
КонецЦикла;
Возврат Новый Структура("files", МассивФайлов);
КонецФункции
Функция ПреобразоватьБулево(Знач Булево)
Возврат Новый Структура("checkbox", Булево);
КонецФункции
Функция ПреобразоватьСсылку(Знач URL)
Возврат Новый Структура("url", URL);
КонецФункции
Функция ПреобразоватьПочту(Знач Почта)
Возврат Новый Структура("email", Почта);
КонецФункции
Функция ПреобразоватьТелефон(Знач Телефон)
Возврат Новый Структура("phone_number", Телефон);
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="bb0d07ea-7a4b-4200-a8fa-f6e8cafca6f5">
<Properties>
<Name>OPI_Ollama</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Ollama (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Ollama из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,731 @@
// OneScript: ./OInt/core/Modules/OPI_Ollama.os
// Lib: Ollama
// CLI: ollama
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-collection-item-type
#Область ПрограммныйИнтерфейс
#Область ОбработкаЗапросов
// Получить версию
// Получает версию Ollama
//
// Примечание:
// Метод в документации API: [Version](@github.com/ollama/ollama/blob/main/docs/api.md#version)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьВерсию(Знач URL, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/version");
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить ответ
// Генерирует ответ по заданному текстовому запросу
//
// Примечание:
// Метод в документации API: [Generate a completion](@github.com/ollama/ollama/blob/main/docs/api.md#generate-a-completion)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Вопрос - Строка - Текст запроса - prompt
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры. См. ПолучитьСтруктуруПараметровЗапроса - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьОтвет(Знач URL, Знач Модель, Знач Вопрос, Знач ДопПараметры = "", Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/generate");
Параметры = Новый Структура;
Параметры.Вставить("suffix", "");
OPI_Инструменты.ДобавитьПоле("model" , Модель, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("prompt", Вопрос, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("stream", Ложь , "Булево", Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить ответ в контексте
// Получает очередной ответ от модели в соответствии с историей сообщений
//
// Примечание:
// Метод в документации API: [Generate a chat completion](@github.com/ollama/ollama/blob/main/docs/api.md#generate-a-chat-completion)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Сообщения - Массив Из Структура - История сообщений. См. ПолучитьСтруктуруСообщенияКонтекста - msgs
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры. См. ПолучитьСтруктуруПараметровЗапроса - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьОтветВКонтексте(Знач URL, Знач Модель, Знач Сообщения, Знач ДопПараметры = "", Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/chat");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель , "Строка" , Параметры);
OPI_Инструменты.ДобавитьПоле("messages", Сообщения, "Коллекция", Параметры);
OPI_Инструменты.ДобавитьПоле("stream" , Ложь , "Булево" , Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить представления
// Получает представления (embeddings) для заданных вводных
//
// Примечание:
// Метод в документации API: [Generate Embeddings](@github.com/ollama/ollama/blob/main/docs/api.md#generate-embeddings)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Вопрос - Массив Из Строка - Строка или массив строк запросов - input
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры. См. ПолучитьСтруктуруПараметровПредставлений - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьПредставления(Знач URL, Знач Модель, Знач Вопрос, Знач ДопПараметры = "", Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/embed");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model", Модель, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("input", Вопрос, "Строка", Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить структуру параметров запроса
// Получает структуру дополнительных параметров для обработки запроса
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруПараметровЗапроса(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
СтруктураПолей = Новый Структура;
СтруктураПолей.Вставить("format" , "<формат, в котором возвращается ответ: json или схема JSON>");
СтруктураПолей.Вставить("options" , "<дополнительные параметры модели, перечисленные в документации к Modelfile>");
СтруктураПолей.Вставить("system" , "<системное сообщение (переопределяет то, что определено в Modelfile)>");
СтруктураПолей.Вставить("template" , "<шаблон промпта (переопределяет то, что определено в Modelfile)>");
СтруктураПолей.Вставить("raw" , "<истина > откюлчить форматирование промпта>");
СтруктураПолей.Вставить("keep_alive", "<как долго модель будет оставаться загруженной в память после запроса>");
СтруктураПолей.Вставить("suffix" , "<текст после ответа модели>");
СтруктураПолей.Вставить("images" , "<список картинок в формате Base64 (для многомодальных моделей, вроде llava)>");
Если Пустая Тогда
СтруктураПолей = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураПолей);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураПолей;
КонецФункции
// Получить структуру параметров представлений
// Получает структуру дополнительных параметров для обработки запросов получения представлений
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруПараметровПредставлений(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
СтруктураПолей = Новый Структура;
СтруктураПолей.Вставить("options" , "<дополнительные параметры модели, перечисленные в документации к Modelfile>");
СтруктураПолей.Вставить("keep_alive", "<как долго модель будет оставаться загруженной в память после запроса>");
СтруктураПолей.Вставить("truncate" , "<обрезает конец каждого ответа, чтобы уложиться в длину контекста. Возвращает ошибку, если false и длина превышена>");
Если Пустая Тогда
СтруктураПолей = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураПолей);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураПолей;
КонецФункции
// Получить структуру параметров в контексте
// Получает структуру дополнительных параметров для обработки запроса в контексте
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруПараметровВКонтексте(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
СтруктураПолей = Новый Структура;
СтруктураПолей.Вставить("format" , "<формат, в котором возвращается ответ: json или схема JSON>");
СтруктураПолей.Вставить("options" , "<дополнительные параметры модели, перечисленные в документации к Modelfile>");
СтруктураПолей.Вставить("keep_alive", "<как долго модель будет оставаться загруженной в память после запроса>");
СтруктураПолей.Вставить("tools" , "<список инструментов в формате JSON (для моделей, которые это поддерживают)>");
Если Пустая Тогда
СтруктураПолей = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураПолей);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураПолей;
КонецФункции
// Получить структуру сообщения контекста
// Получает структуру сообщения для списка сообщений запроса в контексте
//
// Параметры:
// Роль - Строка - Источник сообщения: system, user, assistant, tool - role
// Текст - Строка - Текст сообщения - text
// Картинки - Массив Из Строка - Список картинок в формате Base64 (для многомодальных моделей, вроде llava) - images
// Инструменты - Массив Из Строка - Список инструментов в формате JSON, которые модель должна использовать - tools
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруСообщенияКонтекста(Знач Роль, Знач Текст, Знач Картинки = "", Знач Инструменты = "") Экспорт
СтруктураПолей = Новый Структура;
OPI_Инструменты.ДобавитьПоле("role" , Роль , "Строка" , СтруктураПолей);
OPI_Инструменты.ДобавитьПоле("content" , Текст , "Строка" , СтруктураПолей);
OPI_Инструменты.ДобавитьПоле("images" , Картинки , "Коллекция", СтруктураПолей);
OPI_Инструменты.ДобавитьПоле("tool_calls", Инструменты, "Коллекция", СтруктураПолей);
Возврат СтруктураПолей;
КонецФункции
#КонецОбласти
#Область РаботаСМоделями
// Получить список моделей
// Получает список локальных моделей
//
// Примечание:
// Метод в документации API: [List Local Models](@github.com/ollama/ollama/blob/main/docs/api.md#list-local-models)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокМоделей(Знач URL, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/tags");
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить список запущенных моделей
// Получает список запущенных моделей
//
// Примечание:
// Метод в документации API: [List Running Models](@github.com/ollama/ollama/blob/main/docs/api.md#list-running-models)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокЗапущенныхМоделей(Знач URL, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/ps");
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить информацию о модели
// Получает информацию о выбранной модели
//
// Примечание:
// Метод в документации API: [Show Model Information](@github.com/ollama/ollama/blob/main/docs/api.md#show-model-information)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Подробно - Булево - Возврат полной информации о модели - verbose
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьИнформациюОМодели(Знач URL, Знач Модель, Знач Подробно = Истина, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/show");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("verbose", Подробно, "Булево", Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Создать модель
// Создает новую модель с заданными настройками
//
// Примечание:
// Метод в документации API: [Create a Model](@github.com/ollama/ollama/blob/main/docs/api.md#create-a-model)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Настройки - Структура Из КлючИЗначение - Настройки модели. См. ПолучитьСтруктуруНастроекМодели - settings
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СоздатьМодель(Знач URL, Знач Модель, Знач Настройки, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/create");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель, "Строка" , Параметры);
OPI_Инструменты.ДобавитьПоле("stream", Ложь , "Булево" , Параметры);
ОбработатьПараметры(Параметры, Настройки);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Копировать модель
// Копирует существующую модель
//
// Примечание:
// Метод в документации API: [Copy a Model](@github.com/ollama/ollama/blob/main/docs/api.md#copy-a-model)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя существующей модели - model
// Имя - Строка - Имя новой модели - name
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция КопироватьМодель(Знач URL, Знач Модель, Знач Имя, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/copy");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("source" , Модель, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("destination", Имя , "Строка", Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки, , Истина);
Ответ = Новый Структура("status_code", Ответ.КодСостояния);
Возврат Ответ;
КонецФункции
// Удалить модель
// Удаляет существующую модель
//
// Примечание:
// Метод в документации API: [Delete a Model](@github.com/ollama/ollama/blob/main/docs/api.md#delete-a-model)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьМодель(Знач URL, Знач Модель, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/delete");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель, "Строка", Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.DeleteСТелом(URL, Параметры, ДопЗаголовки, , Истина);
Ответ = Новый Структура("status_code", Ответ.КодСостояния);
Возврат Ответ;
КонецФункции
// Загрузить модель в память
// Загружает выбранную модель в оперативную память
//
// Примечание:
// Метод в документации API: [Load a model](@github.com/ollama/ollama/blob/main/docs/api.md#load-a-model)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Период - Число - Время удержания модели в памяти в секундах - keep
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ЗагрузитьМодельВПамять(Знач URL, Знач Модель, Знач Период = 300, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/generate");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("keep_alive", Период, "Число" , Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Выгрузить модель из памяти
// Выгружает выбранную модель из памяти
//
// Примечание:
// Метод в документации API: [Unload a model](@github.com/ollama/ollama/blob/main/docs/api.md#unload-a-model)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ВыгрузитьМодельИзПамяти(Знач URL, Знач Модель, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/generate");
Параметры = Новый Структура;
Параметры.Вставить("keep_alive", 0);
OPI_Инструменты.ДобавитьПоле("model", Модель, "Строка", Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Отправить модель
// Загружает модель в библиотеку моделей
//
// Примечание:
// Метод в документации API: [Push a Model](@github.com/ollama/ollama/blob/main/docs/api.md#push-a-model)
// Имя модели должно быть в формате <namespace>/<model>:<tag>^
// Требуется регистрация на ollama.ai и добавление открытого ключа.
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Небезопасно - Булево - Разрешает незащищенное соединение с библиотекой - insecure
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ОтправитьМодель(Знач URL, Знач Модель, Знач Небезопасно = Ложь, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/push");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("insecure", Небезопасно, "Булево", Параметры);
OPI_Инструменты.ДобавитьПоле("stream" , Ложь , "Булево", Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Скачать модель
// Скачивает модель из библиотеки
//
// Примечание:
// Метод в документации API: [Pull a Model](@github.com/ollama/ollama/blob/main/docs/api.md#pull-a-model)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Модель - Строка - Имя модели - model
// Небезопасно - Булево - Разрешает незащищенное соединение с библиотекой - insecure
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СкачатьМодель(Знач URL, Знач Модель, Знач Небезопасно = Ложь, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "api/pull");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("insecure", Небезопасно, "Булево", Параметры);
OPI_Инструменты.ДобавитьПоле("stream" , Ложь , "Булево", Параметры);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Получить структуру настроек модели
// Получает структуру настроек для создания новой модели
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруНастроекМодели(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
СтруктураПолей = Новый Структура;
СтруктураПолей.Вставить("from" , "<имя существующей модели, из которой будет создана новая>");
СтруктураПолей.Вставить("files" , "<список имен файлов или SHA256 блобов, из которых будет создана модель>");
СтруктураПолей.Вставить("adapters" , "<список имен файлов или SHA256 блобов для LORA адаптеров>");
СтруктураПолей.Вставить("template" , "<шаблон промптов новой модели>");
СтруктураПолей.Вставить("license" , "<строка или список строк текста лицензий для модели>");
СтруктураПолей.Вставить("system" , "<строка с системным промптом для модели>");
СтруктураПолей.Вставить("parameters", "<список параметров модели>");
СтруктураПолей.Вставить("messages" , "<список объектов сообщений контекста>");
СтруктураПолей.Вставить("quantize" , "<квантовать неквантованную (например, float16) модель>");
Если Пустая Тогда
СтруктураПолей = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураПолей);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураПолей;
КонецФункции
#КонецОбласти
#Область РаботаСBlob
// Отправить BLOB
// Отправляет двоичные данные на сервер Ollama
//
// Примечание:
// Метод в документации API: [Push a Blob](@github.com/ollama/ollama/blob/main/docs/api.md#push-a-blob)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// Данные - Строка, ДвоичныеДанные - Данные или путь к файлу - data
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ОтправитьBlob(Знач URL, Знач Данные, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные, Истина);
ДополнитьURL(URL, "api/blobs/sha256:%1");
Хеш = OPI_Криптография.Хеш(Данные, ХешФункция.SHA256);
Хеш = нРег(ПолучитьHexСтрокуИзДвоичныхДанных(Хеш));
URL = СтрШаблон(URL, Хеш);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьДвоичноеТело(Данные)
.УстановитьЗаголовки(ДопЗаголовки)
.ОбработатьЗапрос("POST")
.ВернутьОтвет(Ложь, Истина);
Ответ = Новый Структура("status_code,digest", Ответ.КодСостояния, Хеш);
Возврат Ответ;
КонецФункции
// Проверить BLOB
// Проверяет существование BLOB по его SHA256 дайджесту
//
// Примечание:
// Метод в документации API: [Check if a Blob Exists](@github.com/ollama/ollama/blob/main/docs/api.md#check-if-a-blob-exists)
//
// Параметры:
// URL - Строка - URL сервера Ollama - url
// SHA256 - Строка - SHA256 дайджест нужного BLOB - digest
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПроверитьBlob(Знач URL, Знач SHA256, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(SHA256);
ДополнитьURL(URL, "api/blobs/sha256:%1");
URL = СтрШаблон(URL, SHA256);
ОбработатьЗаголовки(ДопЗаголовки);
Ответ = OPI_ЗапросыHTTP.Head(URL, , ДопЗаголовки, , Истина);
Ответ = Новый Структура("status_code", Ответ.КодСостояния);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ДополнитьURL(URL, Знач Путь)
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
URL = ?(СтрЗаканчиваетсяНа(URL, "/"), URL, URL + "/");
URL = URL + Путь;
КонецПроцедуры
Процедура ОбработатьПараметры(Параметры, Знач ДопПараметры)
Если Не ЗначениеЗаполнено(ДопПараметры) Тогда
Возврат;
КонецЕсли;
ТекстОшибки = "Передана некорректная коллекция доп. параметров!";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ДопПараметры, ТекстОшибки);
Для Каждого ДопПараметр Из ДопПараметры Цикл
Параметры.Вставить(ДопПараметр.Ключ, ДопПараметр.Значение);
КонецЦикла;
КонецПроцедуры
Процедура ОбработатьЗаголовки(ДопЗаголовки)
Если Не ЗначениеЗаполнено(ДопЗаголовки) Тогда
ДопЗаголовки = Новый Соответствие;
Иначе
ТекстОшибки = "Передана некорректная коллекция доп. заголовков!";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ДопЗаголовки, ТекстОшибки);
КонецЕсли;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="37e51d81-2e33-4735-bc32-fae8d3e6e1d5">
<Properties>
<Name>OPI_OpenAI</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Open AI (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с OpenAI API из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,772 @@
// OneScript: ./OInt/core/Modules/OPI_OpenAI.os
// Lib: OpenAI
// CLI: openai
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-collection-item-type
#Область ПрограммныйИнтерфейс
#Область ОбработкаЗапросов
// Получить ответ
// Генерирует ответ по заданному текстовому запросу
//
// Примечание:
// Метод в документации API: [Create chat completion](@platform.openai.com/docs/api-reference/chat/create)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Модель - Строка - Имя модели - model
// Сообщения - Строка, Массив Из Строка - Сообщения разговора. См. ПолучитьСтруктуруСообщения - msgs
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьОтвет(Знач URL, Знач Токен, Знач Модель, Знач Сообщения, Знач ДопПараметры = "", Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/chat/completions");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("messages", Сообщения, "Массив", Параметры);
OPI_Инструменты.ДобавитьПоле("stream" , Ложь , "Булево", Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Получить картинки
// Генерирует картинки по указанному описанию
//
// Примечание:
// Метод в документации API: [Create image](@platform.openai.com/docs/api-reference/images/create)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Модель - Строка - Имя модели - model
// Описание - Структура Из КлючИЗначение - Параметры генерации. См. ПолучитьСтруктуруОписанияКартинок - descr
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьКартинки(Знач URL, Знач Токен, Знач Модель, Знач Описание, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Описание);
ДополнитьURL(URL, "v1/images/generations");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model", Модель, "Строка", Параметры);
Для Каждого Поле Из Описание Цикл
Параметры.Вставить(Поле.Ключ, Поле.Значение);
КонецЦикла;
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Получить представления
// Получает представления (embeddings) для заданных вводных
//
// Примечание:
// Метод в документации API: [Create embeddings](@platform.openai.com/docs/api-reference/embeddings/create)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Модель - Строка - Имя модели - model
// Текст - Массив Из Строка - Строка или массив строк запросов - input
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьПредставления(Знач URL, Знач Токен, Знач Модель, Знач Текст, Знач ДопПараметры = "", Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/embeddings");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model", Модель, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("input", Текст , "Массив", Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Получить структуру сообщения
// Получает структуру произвольного сообщения для списка сообщений запроса
//
// Параметры:
// Роль - Строка - Источник сообщения: system, user, assistant и др. - role
// Текст - Строка - Текст сообщения - text
// Имя - Строка - Имя участника разговора - name
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруСообщения(Знач Роль, Знач Текст, Знач Имя = "") Экспорт
Строка_ = "Строка";
СтруктураПолей = Новый Структура;
OPI_Инструменты.ДобавитьПоле("role" , Роль , Строка_, СтруктураПолей);
OPI_Инструменты.ДобавитьПоле("content", Текст, Строка_, СтруктураПолей);
OPI_Инструменты.ДобавитьПоле("name" , Имя , Строка_, СтруктураПолей);
Возврат СтруктураПолей;
КонецФункции
// Получить сообщение пользователя
// Получает структуру сообщения от лица пользователя для использования в запросе
//
// Примечание:
// Является краткой формой функции `ПолучитьСтруктуруСообщения`
//
// Параметры:
// Текст - Строка - Текст сообщения - text
// Имя - Строка - Имя участника разговора - name
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСообщениеПользователя(Знач Текст, Знач Имя = "") Экспорт
Возврат ПолучитьСтруктуруСообщения("user", Текст, Имя);
КонецФункции
// Получить сообщение ассистента
// Получает структуру сообщения от лица ассистента для использования в запросе
//
// Примечание:
// Является краткой формой функции `ПолучитьСтруктуруСообщения`
//
// Параметры:
// Текст - Строка - Текст сообщения - text
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСообщениеАссистента(Знач Текст) Экспорт
Возврат ПолучитьСтруктуруСообщения("assistant", Текст);
КонецФункции
// Получить сообщение системы
// Получает структуру системного сообщения для использования в запросе
//
// Примечание:
// Является краткой формой функции `ПолучитьСтруктуруСообщения`
//
// Параметры:
// Текст - Строка - Текст сообщения - text
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСообщениеСистемы(Знач Текст) Экспорт
Возврат ПолучитьСтруктуруСообщения("system", Текст);
КонецФункции
// Получить структуру сообщения картинки
// Получает структура сообщения на основе изображения для списка сообщений запроса
//
// Параметры:
// Роль - Строка - Источник сообщения: system, user, developer - role
// IDФайла - Строка - ID файла картинки. См. ЗагрузитьФайл - file
// Текст - Строка - Вводный текст запроса для обработки картинки - prompt
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруСообщенияКартинки(Знач Роль, Знач IDФайла, Знач Текст = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDФайла);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Текст);
СтруктураПолей = Новый Структура;
МассивКонтента = Новый Массив;
МассивКонтента.Добавить(Новый Структура("type,file_id", "input_image", IDФайла));
Если ЗначениеЗаполнено(Текст) Тогда
МассивКонтента.Добавить(Новый Структура("type,text", "input_text", Текст));
КонецЕсли;
OPI_Инструменты.ДобавитьПоле("role" , Роль , "Строка", СтруктураПолей);
OPI_Инструменты.ДобавитьПоле("content", МассивКонтента, "Массив", СтруктураПолей);
Возврат СтруктураПолей;
КонецФункции
// Получить структуру описания картинок
// Получить структуру описания картинок для генерации
//
// Примечание:
// Набор полей и их интерпретация может отличаться в зависимости от используемой модели
//
// Параметры:
// Промпт - Строка - Текстовое описание картинки для генерации - prompt
// Количество - Число - Количество изображений для генерации - amount
// Фон - Строка - Вариант генерации фона: transparent, opaque, auto - bg
// Размер - Строка - Вариант размера сгенерированных изображений - size
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
//
// Возвращаемое значение:
// Структура - Структура полей
Функция ПолучитьСтруктуруОписанияКартинок(Знач Промпт
, Знач Количество
, Знач Фон = ""
, Знач Размер = ""
, Знач ДопПараметры = "") Экспорт
Строка_ = "Строка";
Описание = Новый Структура;
OPI_Инструменты.ДобавитьПоле("prompt" , Промпт , Строка_, Описание);
OPI_Инструменты.ДобавитьПоле("n" , Количество, "Число", Описание);
OPI_Инструменты.ДобавитьПоле("background", Фон , Строка_, Описание);
OPI_Инструменты.ДобавитьПоле("size" , Размер , Строка_, Описание);
ОбработатьПараметры(Описание, ДопПараметры);
Возврат Описание;
КонецФункции
#КонецОбласти
#Область Ассистенты
// Получить список ассистентов
// Получает список ассистентов с отбором или без
//
// Примечание:
// Метод в документации API: [List assistants](@platform.openai.com/docs/api-reference/assistants/listAssistants)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Количество - Число - Максимальное число возвращаемых ассистентов - limit
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокАссистентов(Знач URL
, Знач Токен
, Знач Количество = 20
, Знач ДопПараметры = ""
, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/assistants");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("limit", Количество, "Число", Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, ДопЗаголовки);
Если ТипЗнч(Ответ) = Тип("Массив") Тогда
Ответ = Новый Структура("object,data", "list", Ответ);
КонецЕсли;
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Создать ассистента
// Создает ассистента по модели и инструкции
//
// Примечание:
// Метод в документации API: [Create assistant](@platform.openai.com/docs/api-reference/assistants/createAssistant)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Модель - Строка - Имя модели - model
// Имя - Строка - Имя ассистента - name
// Инструкция - Строка - Системная инструкция для ассистента - inst
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СоздатьАссистента(Знач URL
, Знач Токен
, Знач Модель
, Знач Имя = ""
, Знач Инструкция = ""
, Знач ДопПараметры = ""
, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/assistants");
Строка_ = "Строка";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model" , Модель , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("name" , Имя , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("instructions", Инструкция , Строка_, Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Получить ассистента
// Получает информацию об ассистенте по ID
//
// Примечание:
// Метод в документации API: [Retrieve assistant](@platform.openai.com/docs/api-reference/assistants/getAssistant)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// IDАссистента - Строка - ID ассистента - id
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьАссистента(Знач URL, Знач Токен, Знач IDАссистента, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDАссистента);
ДополнитьURL(URL, СтрШаблон("v1/assistants/%1", IDАссистента));
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Удалить ассистента
// Удаляет ранее созданного ассистента
//
// Примечание:
// Метод в документации API: [Delete assistant](@platform.openai.com/docs/api-reference/assistants/deleteAssistant)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// IDАссистента - Строка - ID ассистента - id
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьАссистента(Знач URL, Знач Токен, Знач IDАссистента, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDАссистента);
ДополнитьURL(URL, СтрШаблон("v1/assistants/%1", IDАссистента));
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Delete(URL, , ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
#КонецОбласти
#Область РаботаСФайлами
// Получить список файлов
// Получает список файлов с отбором или без
//
// Примечание:
// Метод в документации API: [List files](@platform.openai.com/docs/api-reference/files/list)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Количество - Число - Максимальное число возвращаемых ассистентов - limit
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокФайлов(Знач URL
, Знач Токен
, Знач Количество = 10000
, Знач ДопПараметры = ""
, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/files");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("limit", Количество, "Число", Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, ДопЗаголовки);
Если ТипЗнч(Ответ) = Тип("Массив") Тогда
Ответ = Новый Структура("object,data", "list", Ответ);
КонецЕсли;
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Загрузить файл
// Загружает файл для дальнейшего использования в других запросах
//
// Примечание:
// Метод в документации API: [Upload file](@platform.openai.com/docs/api-reference/files/create)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// ИмяФайла - Строка - Имя файла с раширением - name
// Данные - Строка, ДвоичныеДанные - Путь к файлу или данные - data
// Назначение - Строка - Назначение файла: assistants, batch, vision, user_data, evals - purpose
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ЗагрузитьФайл(Знач URL, Знач Токен, Знач ИмяФайла, Знач Данные, Знач Назначение, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/files");
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.НачатьЗаписьТелаMultipart()
.ДобавитьФайлMultipartFormData("file", ИмяФайла, Данные)
.ДобавитьПолеMultipartFormData("purpose", Назначение)
.УстановитьЗаголовки(ДопЗаголовки)
.ОбработатьЗапрос("POST")
.ВернутьОтветКакJSONКоллекцию();
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Получить информацию о файле
// Получает информацию о файле
//
// Примечание:
// Метод в документации API: [Retrieve file](@platform.openai.com/docs/api-reference/files/retrieve)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// IDФайла - Строка - ID файла - id
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьИнформациюОФайле(Знач URL, Знач Токен, Знач IDФайла, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDФайла);
ДополнитьURL(URL, СтрШаблон("v1/files/%1", IDФайла));
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
// Скачать файл
// Получает данные файла с сервера
//
// Примечание:
// Метод в документации API: [Retrieve file content](@platform.openai.com/docs/api-reference/files/retrieve-contents)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// IDФайла - Строка - ID файла - id
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// ДвоичныеДанные - Данные файла
Функция СкачатьФайл(Знач URL, Знач Токен, Знач IDФайла, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDФайла);
ДополнитьURL(URL, СтрШаблон("v1/files/%1/content", IDФайла));
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Удалить файл
// Удаляет ранее загруженный файл
//
// Примечание:
// Метод в документации API: [Delete file](@platform.openai.com/docs/api-reference/files/delete)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// IDФайла - Строка - ID файла - id
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьФайл(Знач URL, Знач Токен, Знач IDФайла, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDФайла);
ДополнитьURL(URL, СтрШаблон("v1/files/%1", IDФайла));
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Delete(URL, , ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
#КонецОбласти
#Область РаботаСАудио
// Сгенерировать речь
// Генерирует аудио с озвучиванием указанного текста
//
// Примечание:
// Метод в документации API: [Create speech](@platform.openai.com/docs/api-reference/audio/createSpeech)
// Доступные голоса могут отличаться в зависимости от выбранной модели
// Формат аудиофайла ответа можно изменить при помощи добавления `response_format` в доп. параметры.^^
// Доступные форматы: mp3 (по умолчанию), opus, aac, flac, wav, pcm
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Модель - Строка - Имя модели - model
// Текст - Строка - Текст для озвучивания - input
// Голос - Строка - Вид голоса: alloy, ash, ballad, coral, echo и др. - voice
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// ДвоичныеДанные - Результат обработки
Функция СгенерироватьРечь(Знач URL
, Знач Токен
, Знач Модель
, Знач Текст
, Знач Голос = "alloy"
, Знач ДопПараметры = ""
, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/audio/speech");
Строка_ = "Строка";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("model", Модель, Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("input", Текст , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("voice", Голос , Строка_, Параметры);
ОбработатьПараметры(Параметры, ДопПараметры);
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ДопЗаголовки);
Возврат Ответ;
КонецФункции
// Создать транскрипцию
// Создает текстовую транскрипцию для выбранного аудио файла
//
// Примечание:
// Метод в документации API: [Create transcription](@platform.openai.com/docs/api-reference/audio/createTranscription)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// Модель - Строка - Имя модели - model
// Аудио - Строка, ДвоичныеДанные - Аудио файл - audio
// MIME - Строка - MIME тип аудио файла - type
// ДопПараметры - Структура Из КлючИЗначение - Доп. параметры запроса, если необходимо - options
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СоздатьТранскрипцию(Знач URL
, Знач Токен
, Знач Модель
, Знач Аудио
, Знач MIME = "audio/mpeg"
, Знач ДопПараметры = ""
, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(MIME);
ДополнитьURL(URL, "v1/audio/transcriptions");
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.НачатьЗаписьТелаMultipart()
.ДобавитьФайлMultipartFormData("file", "audio.bin", Аудио, MIME)
.ДобавитьПолеMultipartFormData("model", Модель)
.УстановитьЗаголовки(ДопЗаголовки)
.ОбработатьЗапрос("POST")
.ВернутьОтветКакJSONКоллекцию();
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
#КонецОбласти
#Область РаботаСМоделями
// Получить список моделей
// Получает список доступных моделей
//
// Примечание:
// Метод в документации API: [List models](@platform.openai.com/docs/api-reference/models/list)
//
// Параметры:
// URL - Строка - URL сервера OpenAI - url
// Токен - Строка - Токен авторизации OpenAI - token
// ДопЗаголовки - Соответствие Из КлючИЗначение - Доп. заголовки запроса, если необходимо - headers
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокМоделей(Знач URL, Знач Токен, Знач ДопЗаголовки = "") Экспорт
ДополнитьURL(URL, "v1/models");
ОбработатьЗаголовки(ДопЗаголовки, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , ДопЗаголовки);
Возврат ПривестиКлючиКНижнемуРегистру(Ответ);
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ДополнитьURL(URL, Знач Путь)
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
URL = ?(СтрЗаканчиваетсяНа(URL, "/"), URL, URL + "/");
URL = URL + Путь;
КонецПроцедуры
Процедура ОбработатьПараметры(Параметры, Знач ДопПараметры)
Если Не ЗначениеЗаполнено(ДопПараметры) Тогда
Возврат;
КонецЕсли;
ТекстОшибки = "Передана некорректная коллекция доп. параметров!";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ДопПараметры, ТекстОшибки);
Для Каждого ДопПараметр Из ДопПараметры Цикл
Параметры.Вставить(ДопПараметр.Ключ, ДопПараметр.Значение);
КонецЦикла;
КонецПроцедуры
Процедура ОбработатьЗаголовки(ДопЗаголовки, Знач Токен)
Если Не ЗначениеЗаполнено(ДопЗаголовки) Тогда
ДопЗаголовки = Новый Соответствие;
Иначе
ТекстОшибки = "Передана некорректная коллекция доп. заголовков!";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ДопЗаголовки, ТекстОшибки);
КонецЕсли;
Если ЗначениеЗаполнено(Токен) Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
ДопЗаголовки.Вставить("Authorization", СтрШаблон("Bearer %1", Токен));
КонецЕсли;
КонецПроцедуры
Функция ПривестиКлючиКНижнемуРегистру(Знач Коллекция)
Попытка
Коллекция_ = Новый(ТипЗнч(Коллекция));
Для Каждого КлючЗначение Из Коллекция Цикл
Коллекция_.Вставить(нРег(КлючЗначение.Ключ), КлючЗначение.Значение);
КонецЦикла;
Возврат Коллекция_;
Исключение
Возврат Коллекция;
КонецПопытки;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="80366dfb-0340-4cbf-b9b5-18489bd1643f">
<Properties>
<Name>OPI_PostgreSQL</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>PostgreSQL (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с базами PostgreSQL из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,586 @@
// OneScript: ./OInt/core/Modules/OPI_PostgreSQL.os
// Lib: PostgreSQL
// CLI: postgres
// Keywords: postgresql, postgre sql, postgres
// Depends: OPI_PostgreSQL
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-collection-item-type
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает подключение к указанной базе
//
// Параметры:
// СтрокаПодключения - Строка - Строка подключения. См. СформироватьСтрокуПодключения - string
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или структура с информацией об ошибке
Функция ОткрытьСоединение(Знач СтрокаПодключения = "", Знач Tls = "") Экспорт
Если ЭтоКоннектор(СтрокаПодключения) Тогда
Возврат СтрокаПодключения;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(СтрокаПодключения);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(СтрокаПодключения);
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("PostgreSQL");
Tls = OPI_Компоненты.УстановитьTls(Коннектор, Tls);
Если Не OPI_Инструменты.ПолучитьИли(Tls, "result", Ложь) Тогда
Возврат Tls;
КонецЕсли;
Коннектор.ConnectionString = СтрокаПодключения;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Возврат ?(Результат["result"], Коннектор, Результат);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - dbc
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
Результат = Соединение.Close();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Иначе
Результат = Новый Структура("result,error", Ложь, "It's not a connection");
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты PostgreSQL
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_PostgreSQL.Main";
КонецФункции
// Выполнить запрос SQL
// Выполняет произвольный SQL запрос
//
// Примечание:
// Параметры запроса указываются как массив структур вида `{'Тип данных': 'Значение'}`.^^
// Список доступных типов описан на начальной странице документации библиотеки PostgreSQL
// Без указания флага `ФорсироватьРезультат`, чтение результата осуществляется только для запросов, начинающихся с `SELECT`^^
// Для остальных запросов возвращается `result:true` или `false` с текстом ошибки
//
// Параметры:
// ТекстЗапроса - Строка - Текст запроса к базе - sql
// Параметры - Массив Из Произвольный - Массив позиционных параметров запроса - params
// ФорсироватьРезультат - Булево - Включает попытку получения результата, даже для не SELECT запросов - force
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ВыполнитьЗапросSQL(Знач ТекстЗапроса
, Знач Параметры = ""
, Знач ФорсироватьРезультат = Ложь
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Если ЭтоКоннектор(Соединение) Тогда
ЗакрыватьСоединение = Ложь;
Коннектор = Соединение;
Иначе
ЗакрыватьСоединение = Истина;
Коннектор = ОткрытьСоединение(Соединение, Tls);
КонецЕсли;
Если Не ЭтоКоннектор(Коннектор) Тогда
Возврат Коннектор;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
Параметры_ = OPI_ЗапросыSQL.ОбработатьПараметры(Параметры, ПолучитьСтруктуруТипов());
Результат = OPI_ЗапросыSQL.ВыполнитьЗапросСОбработкой(Коннектор, ТекстЗапроса, ФорсироватьРезультат, Параметры_);
Если ЗакрыватьСоединение Тогда
ЗакрытьСоединение(Коннектор);
КонецЕсли;
Возврат Результат;
КонецФункции
// Сформировать строку подключения
// Формирует строку подключения из переданных данных
//
// Параметры:
// Адрес - Строка - IP адрес или доменное имя сервера - addr
// База - Строка - Имя базы данных для подключения - db
// Логин - Строка - Логин пользователя postgres - login
// Пароль - Строка - Пароль пользователя postgres - pass
// Порт - Строка - Порт подключения - port
//
// Возвращаемое значение:
// Строка - Строка подключения к базе PostgreSQL
Функция СформироватьСтрокуПодключения(Знач Адрес, Знач База, Знач Логин, Знач Пароль = "", Знач Порт = "5432") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Адрес);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Порт);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
Порт = ?(ЗначениеЗаполнено(Порт), ":" + Порт, Порт);
Пароль = ?(ЗначениеЗаполнено(Пароль), ":" + Пароль, Пароль);
ШаблонСтроки = "postgresql://%1%2@%3%4/%5";
СтрокаПодключения = СтрШаблон(ШаблонСтроки, Логин, Пароль, Адрес, Порт, База);
Возврат СтрокаПодключения;
КонецФункции
// Получить настройки TLS
// Формирует настройки для использования TLS при выполнении запросов
//
// Примечание:
// Настройки Tls могут быть установлены только в момент создания соединения: явного, при использовании функции `ОткрытьСоединение`^^
// или неявного, при передаче строки подключения в методы ORM.
// Передача настроек Tls совместно с передачей уже созданного соединения в параметр `Соединение` будет проигнорирована
//
// Параметры:
// ОтключитьПроверкуСертификатов - Булево - Позволяет работать с некорретными сертификатами, в т.ч. самоподписанными - trust
// ПутьКСертификату - Строка - Путь к корневому PEM файлу сертификата, если его нет в системном хранилище - cert
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек TLS соединения
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату);
КонецФункции
#КонецОбласти
#Область ORM
// Создать базу данных
// Создает базу данных с указанным именем
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьБазуДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьБазуДанных(OPI_PostgreSQL, База, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить базу данных
// Удаляет базу данных
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьБазуДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьБазуДанных(OPI_PostgreSQL, База, Соединение, Tls);
Возврат Результат;
КонецФункции
// Отключить все соединения базы данных
// Завершает все соединения к базе данных кроме текущего
//
// Параметры:
// База - Строка - Имя базы - base
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОтключитьВсеСоединенияБазыДанных(Знач База, Знач Соединение = "", Знач Tls = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
ТекстSQL = "SELECT pg_terminate_backend(pid)
|FROM pg_stat_activity
|WHERE datname = '%1' AND pid <> pg_backend_pid();";
ТекстSQL = СтрШаблон(ТекстSQL, База);
Результат = ВыполнитьЗапросSQL(ТекстSQL, , , Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить информацию о таблице
// Получает информацию о таблице
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьИнформациюОТаблице(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьСтруктуруТаблицы(OPI_PostgreSQL, Таблица, Соединение, Tls);
Возврат Результат;
КонецФункции
// Создать таблицу
// Создает пустую таблицу в базе
//
// Примечание:
// Список доступных типов описан на начальной странице документации библиотеки PostgreSQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьТаблицу(OPI_PostgreSQL, Таблица, СтруктураКолонок, Соединение, Tls);
Возврат Результат;
КонецФункции
// Добавить колонку таблицы
// Добавляет новую колонку в существующую таблицу
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// ТипДанных - Строка - Тип данных колонки - type
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач ТипДанных, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьКолонкуТаблицы(OPI_PostgreSQL, Таблица, Имя, ТипДанных, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить колонку таблицы
// Удаляет колонку из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьКолонкуТаблицы(OPI_PostgreSQL, Таблица, Имя, Соединение, Tls);
Возврат Результат;
КонецФункции
// Гарантировать таблицу
// Создает новую таблицу в случае отсутствия или обновляет состав колонок существующей таблицы
//
// Примечание:
// В результате изменения структуры таблицы данные могут быть утеряны!^^
// Рекомендуется предварительно опробовать данный метод на тестовых данных
// Данная функция не обновляет тип данных существующих колонок
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ГарантироватьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ГарантироватьТаблицу(OPI_PostgreSQL, Таблица, СтруктураКолонок, Соединение, Tls);
Возврат Результат;
КонецФункции
// Очистить таблицу
// Очищает таблицу базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОчиститьТаблицу(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_PostgreSQL, Таблица, , Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить таблицу
// Удаляет таблицу из базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьТаблицу(Знач Таблица, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьТаблицу(OPI_PostgreSQL, Таблица, Соединение, Tls);
Возврат Результат;
КонецФункции
// Добавить записи
// Добавляет записи в таблицу
//
// Примечание:
// Данные записей указываются как массив структур вида:^
// `{'Имя поля 1': {'Тип данных': 'Значение'}, 'Имя поля 2': {'Тип данных': 'Значение'},...}`
// Список доступных типов описан на начальной странице документации библиотеки PostgreSQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// МассивДанных - Массив Из Структура - Массив структур данных строк: Ключ > поле, Значение > значение поля - rows
// Транзакция - Булево - Истина > добавление записей в транзакции с откатом при ошибке - trn
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьЗаписи(Знач Таблица, Знач МассивДанных, Знач Транзакция = Истина, Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьЗаписи(OPI_PostgreSQL, Таблица, МассивДанных, Транзакция, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить записи
// Получает записи из выбранной таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Поля - Массив Из Строка - Поля для выборки - fields
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Сортировка - Структура Из КлючИЗначение - Сортировка: Ключ > поле, Значение > направление (ASC, DESC) - order
// Количество - Число - Ограничение количества получаемых строк - limit
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьЗаписи(Знач Таблица
, Знач Поля = "*"
, Знач Фильтры = ""
, Знач Сортировка = ""
, Знач Количество = ""
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьЗаписи(OPI_PostgreSQL
, Таблица
, Поля
, Фильтры
, Сортировка
, Количество
, Соединение
, Tls);
Возврат Результат;
КонецФункции
// Обновить записи
// Обновляет значение записей по выбранным критериям
//
// Примечание:
// Данные записей указываются как массив структур вида:^
// `{'Имя поля 1': {'Тип данных': 'Значение'}, 'Имя поля 2': {'Тип данных': 'Значение'},...}`
// Список доступных типов описан на начальной странице документации библиотеки PostgreSQL
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураЗначений - Структура Из КлючИЗначение - Структура значений: Ключ > поле, Значение > значение поля - values
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОбновитьЗаписи(Знач Таблица
, Знач СтруктураЗначений
, Знач Фильтры = ""
, Знач Соединение = ""
, Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.ОбновитьЗаписи(OPI_PostgreSQL, Таблица, СтруктураЗначений, Фильтры, Соединение, Tls);
Возврат Результат;
КонецФункции
// Удалить записи
// Удаляет записи из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Соединение или строка подключения - dbc
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьЗаписи(Знач Таблица, Знач Фильтры = "", Знач Соединение = "", Знач Tls = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_PostgreSQL, Таблица, Фильтры, Соединение, Tls);
Возврат Результат;
КонецФункции
// Получить структуру фильтра записей
// Получает структуру шаблон для фильтрации записей в запросах ORM
//
// Примечание:
// Использование признака `raw` необходимо для составных конструкций, вроде `BEETWEEN`.^^
// Например: при `raw:false` фильтр `type:BETWEEN` `value:10 AND 20` будет интерпритирован как `BETWEEN ?1 `^^
// где `?1 = "10 AND 20"`, что приведет к ошибке.^^
// В таком случае необходимо использовать `raw:true` для установки условия напрямую в текст запроса
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Элемент фильтра записей
Функция ПолучитьСтруктуруФильтраЗаписей(Знач Пустая = Ложь) Экспорт
Возврат OPI_ЗапросыSQL.ПолучитьСтруктуруФильтраЗаписей(Пустая);
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьОсобенности() Экспорт
Особенности = Новый Соответствие;
Особенности.Вставить("НумерацияПараметров", Истина);
Особенности.Вставить("МаркерПараметров" , "$");
Особенности.Вставить("СУБД" , "postgres");
Особенности.Вставить("ПолеКолонки" , "column_name");
Особенности.Вставить("НачалоТранзакции" , "BEGIN");
Возврат Особенности;
КонецФункции
Функция ПолучитьСтруктуруТипов() Экспорт
ТипыКоллекции = Новый СписокЗначений();
ТипыКоллекции.Добавить("JSONB");
ТипыКоллекции.Добавить("JSON");
ТипыКоллекции.Добавить("HSTORE");
СтруктураТипов = Новый Соответствие;
СтруктураТипов.Вставить("ДвоичныеДанные" , "BYTEA");
СтруктураТипов.Вставить("УникальныйИдентификатор", "UUID");
СтруктураТипов.Вставить("Булево" , "BOOL");
СтруктураТипов.Вставить("Дробное" , "REAL");
СтруктураТипов.Вставить("Целое" , "INT");
СтруктураТипов.Вставить("Дата" , "TIMESTAMP");
СтруктураТипов.Вставить("Строка" , "VARCHAR");
СтруктураТипов.Вставить("Коллекции" , ТипыКоллекции);
СтруктураТипов.Вставить("БулевоКакЧисло" , Ложь);
Возврат СтруктураТипов;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="4ed55122-2475-453b-85cf-882e3d62efe1">
<Properties>
<Name>OPI_RCON</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>RCON (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с RCON из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,163 @@
// OneScript: ./OInt/core/Modules/OPI_RCON.os
// Lib: RCON
// CLI: rcon
// Keywords: rcon, remote console
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область ВыполнениеКоманд
// Открыть соединение !NOCLI
// Открывает новое соединения RCON
//
// Параметры:
// ПараметрыСоединения - Структура Из КлючИЗначение - Параметры соединения. См. СформироватьПараметрыСоединения - params
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или структура с информацией об ошибке
Функция ОткрытьСоединение(Знач ПараметрыСоединения) Экспорт
Если ЭтоКоннектор(ПараметрыСоединения) Тогда
Возврат ПараметрыСоединения;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ПараметрыСоединения);
МассивОбязательных = СтрРазделить("url,password,read_timeout,write_timeout", ",");
МассивНедостающих = OPI_Инструменты.НайтиОтсутствующиеПоляКоллекции(ПараметрыСоединения, МассивОбязательных);
Если ЗначениеЗаполнено(МассивНедостающих) Тогда
ВызватьИсключение СтрШаблон("Отсутствуют параметры подключения: %1", СтрСоединить(МассивНедостающих, ", "));
КонецЕсли;
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("RCON");
URL = ПараметрыСоединения["url"];
Пароль = ПараметрыСоединения["password"];
ТаймаутЧтения = ПараметрыСоединения["read_timeout"];
ТаймаутЗаписи = ПараметрыСоединения["write_timeout"];
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
OPI_ПреобразованиеТипов.ПолучитьЧисло(ТаймаутЧтения);
OPI_ПреобразованиеТипов.ПолучитьЧисло(ТаймаутЗаписи);
Результат = Коннектор.Connect(URL, Пароль, ТаймаутЧтения, ТаймаутЗаписи);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Возврат ?(Результат["result"], Коннектор, Результат);
КонецФункции
// Выполнить команду
// Выполняет команду на сервере
//
// Примечание:
// При передаче параметров соединения, новое соединение будет создано и закрыто в рамках выполнения одной команды.^^
// Для выполнения нескольких команд (в версиях для OS и 1С) рекомендуется использовать заранее созданное соединение (см. ОткрытьСоединение)
//
// Параметры:
// Команда - Строка - Текст команды - exec
// Соединение - Произвольный, Структура Из КлючИЗначение - Соединение или параметры соединения - conn
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения команды
Функция ВыполнитьКоманду(Знач Команда, Знач Соединение) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
Коннектор = Соединение;
Иначе
Коннектор = ОткрытьСоединение(Соединение);
КонецЕсли;
Если Не ЭтоКоннектор(Коннектор) Тогда
Возврат Коннектор;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(Команда);
Результат = Коннектор.Command(Команда);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Возврат Результат;
КонецФункции
// Сформировать параметры соединения
// Формирует коллекцию параметров соединения
//
// Параметры:
// URL - Строка - URL сервера - url
// Пароль - Строка - Пароль для подключения - pass
// ТаймаутЧтения - Число - Таймаут ожидания ответа (в секундах) - rtout
// ТаймаутЗаписи - Число - Таймаут ожидания отправки запроса (в секундах) - wtout
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура параметров соединения
Функция СформироватьПараметрыСоединения(Знач URL, Знач Пароль, Знач ТаймаутЧтения = 30, Знач ТаймаутЗаписи = 30) Экспорт
ПараметрыСоединения = Новый Структура;
OPI_Инструменты.ДобавитьПоле("url" , URL , "Строка", ПараметрыСоединения);
OPI_Инструменты.ДобавитьПоле("password" , Пароль , "Строка", ПараметрыСоединения);
OPI_Инструменты.ДобавитьПоле("read_timeout" , ТаймаутЧтения, "Число" , ПараметрыСоединения);
OPI_Инструменты.ДобавитьПоле("write_timeout", ТаймаутЗаписи, "Число" , ПараметрыСоединения);
Возврат ПараметрыСоединения;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты RCON
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_RCON.Main";
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="d9f83304-554e-4d40-a7bd-692d75467497">
<Properties>
<Name>OPI_ReportPortal</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>ReportPortal (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с ReportPortal из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,480 @@
// OneScript: ./OInt/core/Modules/OPI_ReportPortal.os
// Lib: ReportPortal
// CLI: rportal
// Keywords: reportportal
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UnreachableCode-off
// BSLLS:CommentedCode-off
// BSLLS:UsingServiceTag-off
// BSLLS:NumberOfParams-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область Авторизация
// Получить временный токен
// Получает временный токен на основе логина и пароля
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Логин - Строка - Логин пользователя - login
// Пароль - Строка - Пароль пользователя - pass
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция ПолучитьВременныйТокен(Знач URL, Знач Логин, Знач Пароль) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
ДополнитьURL(URL, "uat/sso/oauth/token");
Результат = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать()
.УстановитьURL(URL)
.ДобавитьBasicАвторизацию("ui", "uiman")
.УстановитьFormТело(Новый Структура("grant_type,username,password", "password", Логин, Пароль))
.ОбработатьЗапрос("POST")
.ВернутьОтветКакJSONКоллекцию();
Возврат Результат;
КонецФункции
// Получить постоянный токен
// Создает постоянный токен пользователя ReportPortal
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// IDПользователя - Строка - ID пользователя - user
// ИмяКлюча - Строка - Имя токена - name
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция ПолучитьПостоянныйТокен(Знач URL, Знач Токен, Знач IDПользователя, Знач ИмяКлюча) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПользователя);
ДополнитьURL(URL, СтрШаблон("api/users/%1/api-keys", IDПользователя));
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("name", ИмяКлюча, "Строка", Параметры);
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Результат;
КонецФункции
// Удалить постоянный токен
// Удаляет ранее созданный токен пользователя
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// IDПользователя - Строка - ID пользователя - user
// IDКлюча - Строка - ID токена - id
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция УдалитьПостоянныйТокен(Знач URL, Знач Токен, Знач IDПользователя, Знач IDКлюча) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПользователя);
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDКлюча);
ДополнитьURL(URL, СтрШаблон("api/users/%1/api-keys/%2", IDПользователя, IDКлюча));
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Результат;
КонецФункции
#КонецОбласти
#Область УправлениеРезультатами
// Создать запуск
// Запускает новый сеанс выполнения тестов
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// Проект - Строка - ID проекта - proj
// СтруктураЗапуска - Структура Из КлючИЗначение - Параметры запуска. См. ПолучитьСтруктуруЗапуска - params
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция СоздатьЗапуск(Знач URL, Знач Токен, Знач Проект, Знач СтруктураЗапуска) Экспорт
ТекстОшибки = "Структура запуска не является корректной коллекцией КлючИЗначение";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураЗапуска, ТекстОшибки);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Проект);
ДополнитьURL(URL, СтрШаблон("api/v1/%1/launch", Проект));
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.PostСТелом(URL, СтруктураЗапуска, Заголовки);
Возврат Результат;
КонецФункции
// Создать элемент
// Создает новый тестовый элемент
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// Проект - Строка - ID проекта - proj
// СтруктураЭлемента - Структура Из КлючИЗначение - Параметры элемента. См. ПолучитьСтруктуруЭлемента - params
// Родитель - Строка - ID родительского элемента, если необходимо - parent
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция СоздатьЭлемент(Знач URL, Знач Токен, Знач Проект, Знач СтруктураЭлемента, Знач Родитель = "") Экспорт
ТекстОшибки = "Структура элемента не является корректной коллекцией КлючИЗначение";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураЭлемента, ТекстОшибки);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Проект);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Родитель);
Родитель = ?(ЗначениеЗаполнено(Родитель), "/" + Родитель, "");
ДополнитьURL(URL, СтрШаблон("api/v1/%1/item%2", Проект, Родитель));
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.PostСТелом(URL, СтруктураЭлемента, Заголовки);
Возврат Результат;
КонецФункции
// Завершить запуск
// Завершает запущенный ранее сеанс выполнения тестов
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// Проект - Строка - ID проекта - proj
// IDЗапуска - Строка - ID запуска - id
// СтруктураЗавершения - Структура Из КлючИЗначение - Параметры завершения. См. ПолучитьСтруктуруЗавершенияЗапуска - params
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция ЗавершитьЗапуск(Знач URL, Знач Токен, Знач Проект, Знач IDЗапуска, Знач СтруктураЗавершения) Экспорт
ТекстОшибки = "Структура завершения не является корректной коллекцией КлючИЗначение";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураЗавершения, ТекстОшибки);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Проект);
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDЗапуска);
ДополнитьURL(URL, СтрШаблон("api/v1/%1/launch/%2/finish", Проект, IDЗапуска));
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.PutСТелом(URL, СтруктураЗавершения, Заголовки);
Возврат Результат;
КонецФункции
// Завершить элемент
// Завершает работу созданного ранее тестового элемента
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// Проект - Строка - ID проекта - proj
// IDЭлемента - Строка - ID элемента - id
// СтруктураЗавершения - Структура Из КлючИЗначение - Параметры завершения. См. ПолучитьСтруктуруЗавершенияЭлемента - params
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция ЗавершитьЭлемент(Знач URL, Знач Токен, Знач Проект, Знач IDЭлемента, Знач СтруктураЗавершения) Экспорт
ТекстОшибки = "Структура завершения не является корректной коллекцией КлючИЗначение";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураЗавершения, ТекстОшибки);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Проект);
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDЭлемента);
ДополнитьURL(URL, СтрШаблон("api/v1/%1/item/%2", Проект, IDЭлемента));
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.PutСТелом(URL, СтруктураЗавершения, Заголовки);
Возврат Результат;
КонецФункции
// Получить структуру запуска
// Получает структуру параметров запуска
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
// КакСоответствие - Булево - Истина > возвращает поля фильтра как соответствие - map
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруЗапуска(Знач Пустая = Ложь, Знач КакСоответствие = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
OPI_ПреобразованиеТипов.ПолучитьБулево(КакСоответствие);
Если КакСоответствие Тогда
СтруктураЗапуска = Новый Соответствие;
Иначе
СтруктураЗапуска = Новый Структура;
КонецЕсли;
СтруктураЗапуска.Вставить("name" , "<название запуска>");
СтруктураЗапуска.Вставить("startTime" , "<время начала запуска>");
СтруктураЗапуска.Вставить("description", "<описание запуска>");
СтруктураЗапуска.Вставить("uuid" , "<UUID запуска. Будет сгенерирован автоматически, если не заполнено>");
СтруктураЗапуска.Вставить("attributes" , "<атрибуты запуска в виде ключ1:значение1, ключ2:значение2>");
СтруктураЗапуска.Вставить("mode" , "<режим: default или debug>");
СтруктураЗапуска.Вставить("rerun" , "<признак перезапуска>");
СтруктураЗапуска.Вставить("rerunOf" , "<UUID уже существующего запуска, если rerun = Истина>");
Если Пустая Тогда
СтруктураЗапуска = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураЗапуска);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураЗапуска;
КонецФункции
// Получить структуру элемента
// Получает структуру параметров тестового элемента
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
// КакСоответствие - Булево - Истина > возвращает поля фильтра как соответствие - map
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруЭлемента(Знач Пустая = Ложь, Знач КакСоответствие = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
OPI_ПреобразованиеТипов.ПолучитьБулево(КакСоответствие);
Если КакСоответствие Тогда
СтруктураЭлемента = Новый Соответствие;
Иначе
СтруктураЭлемента = Новый Структура;
КонецЕсли;
СтруктураЭлемента.Вставить("name" , "<название элемента>");
СтруктураЭлемента.Вставить("startTime" , "<время начала>");
СтруктураЭлемента.Вставить("type" , "<тип элемента: suite, story, test, scenario, step, before_class, before_groups, before_method, before_suite, before_test, after_class, after_groups, after_method, after_suite, after_test>");
СтруктураЭлемента.Вставить("launchUuid" , "<UUID запуска>");
СтруктураЭлемента.Вставить("description", "<описание элемента>");
СтруктураЭлемента.Вставить("attributes" , "<атрибуты элемента в виде ключ1:значение1, ключ2:значение2>");
СтруктураЭлемента.Вставить("uuid" , "<UUID элемента. Будет сгенерирован автоматически, если не заполнено>");
СтруктураЭлемента.Вставить("codeRef" , "<физическое расположение тестов>");
СтруктураЭлемента.Вставить("parameters" , "<параметры для параметризированных тестов>");
СтруктураЭлемента.Вставить("retry" , "<является перезапуском>");
Если Пустая Тогда
СтруктураЭлемента = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураЭлемента);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураЭлемента;
КонецФункции
// Получить структуру завершения элемента
// Получает структуру параметров завершения выполнения тестового элемента
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
// КакСоответствие - Булево - Истина > возвращает поля фильтра как соответствие - map
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруЗавершенияЭлемента(Знач Пустая = Ложь, Знач КакСоответствие = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
OPI_ПреобразованиеТипов.ПолучитьБулево(КакСоответствие);
Если КакСоответствие Тогда
СтруктураЭлемента = Новый Соответствие;
Иначе
СтруктураЭлемента = Новый Структура;
КонецЕсли;
СтруктураЭлемента.Вставить("endTime" , "<время окончания>");
СтруктураЭлемента.Вставить("launchUuid" , "<UUID запуска>");
СтруктураЭлемента.Вставить("status" , "<статус завершения: passed, failed, stopped, skipped, interrupted, cancelled>");
СтруктураЭлемента.Вставить("description", "<описание элемента. Перезаписывает указанное при создании>");
СтруктураЭлемента.Вставить("attributes" , "<атрибуты элемента. Перезаписывает указанное при создании>");
СтруктураЭлемента.Вставить("retry" , "<флаг завершения повторной попытки>");
СтруктураЭлемента.Вставить("issue" , "<информация о проблеме>");
Если Пустая Тогда
СтруктураЭлемента = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураЭлемента);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураЭлемента;
КонецФункции
// Получить структуру завершения запуска
// Получает структуру параметров завершения тестового сеанса
//
// Параметры:
// Время - Дата - Дата и время завершения запуска - end
// Статус - Строка - Статус заверщения: passed, failed, stopped, skipped, interrupted, cancelled - status
// Описание - Строка - Описание запуска. Перезаписывает указанное при создании - descr
// Артибуты - Строка - Атрибуты запуска. Перезаписывает указанное при создании - attr
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруЗавершенияЗапуска(Знач Время, Знач Статус = "", Знач Описание = "", Знач Артибуты = "") Экспорт
Строка_ = "Строка";
СтруктураЗавершения = Новый Структура;
OPI_Инструменты.ДобавитьПоле("endTime" , Время , "ДатаISO", СтруктураЗавершения);
OPI_Инструменты.ДобавитьПоле("status" , Статус , Строка_ , СтруктураЗавершения);
OPI_Инструменты.ДобавитьПоле("description", Описание, Строка_ , СтруктураЗавершения);
OPI_Инструменты.ДобавитьПоле("attributes" , Артибуты, Строка_ , СтруктураЗавершения);
Возврат СтруктураЗавершения;
КонецФункции
#КонецОбласти
#Область ЗаписьЛогов
// Записать лог
// Добавляет информацию о выполнении для тестового элемента
//
// Параметры:
// URL - Строка - URL сервера ReportPortal - url
// Токен - Строка - Токен доступа - token
// Проект - Строка - ID проекта - proj
// СтруктураЛога - Структура Из КлючИЗначение - Информация о выполнении. См. ПолучитьСтруктуруЛога - params
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от ReportPortal
Функция ЗаписатьЛог(Знач URL, Знач Токен, Знач Проект, Знач СтруктураЛога) Экспорт
ТекстОшибки = "Структура лога не является корректной коллекцией КлючИЗначение";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураЛога, ТекстОшибки);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Проект);
ДополнитьURL(URL, СтрШаблон("api/v1/%1/log", Проект));
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
Результат = OPI_ЗапросыHTTP.PostСТелом(URL, СтруктураЛога, Заголовки);
Возврат Результат;
КонецФункции
// Получить структуру лога
// Получает структуру параметров для записи лога
//
// Параметры:
// IDЗапуска - Строка - ID запуска, к которому принадлежит тестовый элемент - launch
// IDЭлемента - Строка - ID тестового элемента - id
// Время - Дата - Дата и время записи лога - time
// Текст - Строка - Текстовая информация лога - text
// Уровень - Строка - Уровень информации: error, warn, info, debug, trace, fatal, unknown - level
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей
Функция ПолучитьСтруктуруЛога(Знач IDЗапуска, Знач IDЭлемента, Знач Время, Знач Текст = "", Знач Уровень = "info") Экспорт
Строка_ = "Строка";
СтруктураЛога = Новый Структура;
OPI_Инструменты.ДобавитьПоле("launchUuid", IDЗапуска , Строка_ , СтруктураЛога);
OPI_Инструменты.ДобавитьПоле("itemUuid" , IDЭлемента, Строка_ , СтруктураЛога);
OPI_Инструменты.ДобавитьПоле("time" , Время , "Дата" , СтруктураЛога);
OPI_Инструменты.ДобавитьПоле("message" , Текст , Строка_ , СтруктураЛога);
OPI_Инструменты.ДобавитьПоле("level" , Уровень , Строка_ , СтруктураЛога);
Возврат СтруктураЛога;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ДополнитьURL(URL, Знач Путь)
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
URL = ?(СтрЗаканчиваетсяНа(URL, "/"), URL, URL + "/");
URL = URL + Путь;
КонецПроцедуры
Функция ПолучитьЗаголовокАвторизации(Знач Токен)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
OPI_Инструменты.ДобавитьПоле("Authorization", СтрШаблон("Bearer %1", Токен), "Строка", Заголовки);
Возврат Заголовки;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="bf7a006c-94c1-4208-a8be-cbc7ae68489e">
<Properties>
<Name>OPI_S3</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>S3 (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с S3 хранилищами из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="72aa8b08-1537-461e-954d-0b657275c31d">
<Properties>
<Name>OPI_SFTP</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SFTP (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с SFTP из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,740 @@
// OneScript: ./OInt/core/Modules/OPI_SFTP.os
// Lib: SFTP
// CLI: sftp
// Keywords: sftp
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает новый сеанс SFTP
//
// Примечание:
// Получить конфигурацию соединения можно при помощи функций `ПолучитьНастройкиЛогинПароль`,^^
// `ПолучитьНастройкиПриватныйКлюч`, `ПолучитьНастройкиЧерезАгента`
//
// Параметры:
// НастройкиSSH - Структура Из КлючИЗначение - Структура настроек соединения - set
// Прокси - Структура Из КлючИЗначение - Структура настроек прокси, если необходимо - proxy
//
// Возвращаемое значение:
// Произвольный, Соответствие Из КлючИЗначение - Открыть соединение
Функция ОткрытьСоединение(Знач НастройкиSSH, Знач Прокси = "") Экспорт
СоединениеSSH = OPI_ЗапросыSSH.ОткрытьСоединение(НастройкиSSH, Прокси);
Если ЭтоКоннектор(СоединениеSSH) Тогда
Результат = СоединениеSSH.ToSFTP();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Иначе
Возврат СоединениеSSH;
КонецЕсли;
Возврат ?(Результат["result"], СоединениеSSH, Результат);
КонецФункции
// Получить конфигурацию соединения
// Формирует полную структуру настроек соединения, которая может быть использована вместо самого соединения при вызове других функций
//
// Примечание:
// Может быть передана в качестве параметра `Соединение` в других функциях вместо настоящего соединения из функции `ОткрытьСоединение`.^^
// При этом новое соединение будет открыто и закрыто в рамках вызываемой функции
// Не рекомендуется использовать конфигурацию соединения при множественных обращениях к серверу SSH.^^
// Данный функционал предназначен, в первую очередь для CLI версии ОПИ, где хранение соединения между вызовами невозможно
//
// Параметры:
// НастройкиSSH - Структура Из КлючИЗначение - Настройки SSH - set
// Прокси - Структура Из КлючИЗначение - Настройки прокси, если необходимо. См. ПолучитьНастройкиПрокси - proxy
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек соединения
Функция ПолучитьКонфигурациюСоединения(Знач НастройкиSSH, Знач Прокси = Неопределено) Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьКонфигурациюСоединения(НастройкиSSH, Прокси);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - conn
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Возврат OPI_ЗапросыSSH.ЗакрытьСоединение(Соединение);
КонецФункции
// Изменить путь
// Изменяет путь объекта на указанный
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Текущий путь к объекту - old
// НовыйПуть - Строка - Новый путь к объекту - new
// Перезаписывать - Булево - Перезаписывать, если объект по целевому пути уже существует - rw
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ИзменитьПуть(Знач Соединение, Знач Путь, Знач НовыйПуть, Знач Перезаписывать = Ложь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(НовыйПуть);
OPI_ПреобразованиеТипов.ПолучитьБулево(Перезаписывать);
Результат = Соединение.RenameObject(Путь, НовыйПуть, Перезаписывать);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты для работы с SFTP
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат OPI_ЗапросыSSH.ЭтоКоннектор(Значение);
КонецФункции
// Получить настройки (логин/пароль)
// Получает настройки соединения с авторизацией через логин и пароль
//
// Параметры:
// Хост - Строка - Хост SSH - host
// Порт - Число - Порт SSH - port
// Логин - Строка - Имя пользователя SSH - user
// Пароль - Строка - Пароль пользователя SSH - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Конфигурация соединения
Функция ПолучитьНастройкиЛогинПароль(Знач Хост, Знач Порт, Знач Логин, Знач Пароль = "") Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиЛогинПароль(Хост, Порт, Логин, Пароль);
КонецФункции
// Получить настройки (приватный ключ)
// Получает настройки соединения с авторизацией через приватный ключ
//
// Параметры:
// Хост - Строка - Хост SSH - host
// Порт - Число - Порт SSH - port
// Логин - Строка - Имя пользователя SSH - user
// Приватный - Строка - Путь к файлу приватного ключа - key
// Публичный - Строка - Путь к файлу публичного ключ - pub
// Пароль - Строка - Пароль (passphrase) приватного ключа - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Конфигурация соединения
Функция ПолучитьНастройкиПриватныйКлюч(Знач Хост
, Знач Порт
, Знач Логин
, Знач Приватный
, Знач Публичный = ""
, Знач Пароль = "") Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиПриватныйКлюч(Хост, Порт, Логин, Приватный, Публичный, Пароль);
КонецФункции
// Получить настройки (через агента)
// Получает настройки соединения с авторизацией через SSH Agent
//
// Параметры:
// Хост - Строка - Хост SSH - host
// Порт - Число - Порт SSH - port
// Логин - Строка - Имя пользователя SSH - user
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Конфигурация соединения
Функция ПолучитьНастройкиЧерезАгента(Знач Хост, Знач Порт, Знач Логин) Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиЧерезАгента(Хост, Порт, Логин);
КонецФункции
// Получить настройки прокси
// Формирует структуру настроек прокси-сервера для соединения
//
// Параметры:
// Адрес - Строка - Адрес прокси - addr
// Порт - Число - Порт прокси - port
// Вид - Строка - Вид прокси: socks5, socks4, http - type
// Логин - Строка, Неопределено - Логин авторизации, если необходимо - login
// Пароль - Строка, Неопределено - Пароль для авторизации, если необходимо - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек прокси
Функция ПолучитьНастройкиПрокси(Знач Адрес
, Знач Порт
, Знач Вид = "socks5"
, Знач Логин = Неопределено
, Знач Пароль = Неопределено) Экспорт
//@skip-check constructor-function-return-section
Возврат OPI_Компоненты.ПолучитьНастройкиПрокси(Адрес, Порт, Вид, Логин, Пароль);
КонецФункции
#КонецОбласти
#Область РаботаСДиректориями
// Получить список объектов
// Получает информацию о содержимом директории по выбранному пути
//
// Примечание:
// Команда FTP: `LIST`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к директории поиска - path
// Рекурсивно - Булево - Получать информацию об объектах во вложенных директориях - rcv
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокОбъектов(Знач Соединение, Знач Путь = "", Знач Рекурсивно = Ложь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьБулево(Рекурсивно);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.ListDirectory(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
ОбработатьРезультатПолученияСписка(Результат, Соединение, Рекурсивно);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// BSLLS:MagicNumber-off
// Создать новую директорию
// Создает директорию по указанному пути
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к новой директории - path
// Права - Строка - Режим доступа к каталогу в числовом формате POSIX (как в chmod) - mode
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СоздатьНовуюДиректорию(Знач Соединение, Знач Путь, Знач Права = 700) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.MakeDirectory(Путь, Права);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// BSLLS:MagicNumber-on
// Удалить директорию
// Удаляет существующую директорию
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к удаляемой директории - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьДиректорию(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.RemoveDirectory(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить текущий каталог
// Получает текущий каталог, от которого вычисляются относительные пути
//
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьТекущийКаталог(Знач Соединение) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
Результат = OPI_ЗапросыSSH.ВыполнитьКоманду(Соединение, "pwd");
ОбработатьВыполнениеКомандыSSH(Результат, "path");
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область РаботаСФайлами
// Загрузить файл
// Загружает файл с диска или двоичные данные на сервер
//
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Файл - Строка, ДвоичныеДанные - Файл на диске или данные файла - file
// Путь - Строка - Путь сохранения файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ЗагрузитьФайл(Знач Соединение, Знач Файл, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
Если ТипЗнч(Файл) = Тип("Строка") Тогда
ФайлНаДиске = Новый Файл(Файл);
ЭтоФайлНаДиске = ФайлНаДиске.Существует();
Иначе
ЭтоФайлНаДиске = Ложь;
КонецЕсли;
Если Не ЭтоФайлНаДиске Тогда
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
Если OPI_Компоненты.ТребуетсяПередачаЧерезФайл() Тогда
// BSLLS:MissingTemporaryFileDeletion-off
//@skip-check missing-temporary-file-deletion
ИВФ = ПолучитьИмяВременногоФайла();
// BSLLS:MissingTemporaryFileDeletion-on
Файл.Записать(ИВФ);
Результат = Соединение.UploadFile(ИВФ, Путь);
OPI_Инструменты.УдалитьФайлВПопытке(ИВФ, "Не удалось удалить временный файл после загрузки");
Иначе
Результат = Соединение.UploadData(Файл, Путь);
КонецЕсли;
Иначе
Результат = Соединение.UploadFile(Файл, Путь);
КонецЕсли;
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Удалить файл
// Удаляет файл с сервера
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьФайл(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.RemoveFile(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Сохранить файл
// Сохраняет файл с сервера по указанному пути
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
// ИмяФайла - Строка - Путь для сохранения файла на диске - file
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СохранитьФайл(Знач Соединение, Знач Путь, Знач ИмяФайла) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИмяФайла);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ИмяФайла);
Результат = Соединение.DownloadToFile(Путь, ИмяФайла);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить данные файла !NOCLI
// Получает файл с сервера как двоичные данные
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение, ДвоичныеДанные - Данные файла или информация об ошибке
Функция ПолучитьДанныеФайла(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Если OPI_Компоненты.ТребуетсяПередачаЧерезФайл() Тогда
// BSLLS:MissingTemporaryFileDeletion-off
//@skip-check missing-temporary-file-deletion
ИВФ = ПолучитьИмяВременногоФайла();
// BSLLS:MissingTemporaryFileDeletion-on
Результат = Соединение.DownloadToFile(Путь, ИВФ);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Если Результат["result"] Тогда
Данные = Новый ДвоичныеДанные(ИВФ);
OPI_Инструменты.УдалитьФайлВПопытке(ИВФ, "Не удалось удалить временный файл после загрузки");
Возврат Данные;
КонецЕсли;
Иначе
Данные = Соединение.DownloadToBuffer(Путь);
Если ТипЗнч(Данные) = Тип("Строка") Тогда
Результат = OPI_Инструменты.JsonВСтруктуру(Данные);
Иначе
Возврат Данные;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить информацию о файле
// Получает информацию о файле по указанному пути
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьИнформациюОФайле(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.GetFileInfo(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ПроверитьСоздатьСоединение(Соединение)
Если Не ЭтоКоннектор(Соединение) Тогда
ЗакрыватьСоединение = Истина;
Соединение = ОткрытьСоединениеПоКонфигурации(Соединение);
Иначе
ЗакрыватьСоединение = Ложь;
КонецЕсли;
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
КонецЕсли;
ЭтоSFTP = Соединение.IsSFTP();
Если Не ЭтоSFTP Тогда
Результат = Соединение.ToSFTP();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Соединение = ?(Результат["result"], Соединение, Результат);
КонецЕсли;
Возврат ЗакрыватьСоединение;
КонецФункции
Функция ОткрытьСоединениеПоКонфигурации(Знач СтруктураКонфигурации)
Если ЭтоКоннектор(СтруктураКонфигурации) Тогда
Возврат СтруктураКонфигурации;
КонецЕсли;
ШаблонОшибки = "Передана некорректная конфигурация соединения: %1";
Попытка
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураКонфигурации);
Исключение
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, ОписаниеОшибки()));
Возврат Результат;
КонецПопытки;
Если Не OPI_Инструменты.ПолеКоллекцииСуществует(СтруктураКонфигурации, "set") Тогда
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, "отсутствуют основные параметры соединения"));
Возврат Результат;
КонецЕсли;
НастройкиSSH = СтруктураКонфигурации["set"];
Прокси = OPI_Инструменты.ПолучитьИли(СтруктураКонфигурации, "proxy", Неопределено);
Возврат ОткрытьСоединение(НастройкиSSH, Прокси);
КонецФункции
Процедура ОбработатьВыполнениеКомандыSSH(Результат, ПолеРезультата = "data")
Result_ = "result";
Если Результат[Result_] Тогда
РезультатОбработки = Новый Соответствие;
Если Не ЗначениеЗаполнено(Результат["stderr"]) Тогда
РезультатОбработки.Вставить(Result_, Истина);
StdOut = Результат["stdout"];
Если ЗначениеЗаполнено(StdOut) Тогда
РезультатОбработки.Вставить(ПолеРезультата, StdOut);
КонецЕсли;
Иначе
РезультатОбработки.Вставить(Result_, Ложь);
РезультатОбработки.Вставить("error", Результат["stderr"]);
КонецЕсли;
Результат = РезультатОбработки;
КонецЕсли;
КонецПроцедуры
Процедура ОбработатьРезультатПолученияСписка(Результат, Соединение, Знач Рекурсивно)
Если Результат["result"] И Рекурсивно Тогда
Для Каждого ОбъектКаталога Из Результат["data"] Цикл
Если Не ОбъектКаталога["is_directory"] Тогда
Продолжить;
КонецЕсли;
Дочерние = ПолучитьСписокОбъектов(Соединение, ОбъектКаталога["path"], Истина);
Если Дочерние["result"] Тогда
ОбъектКаталога.Вставить("objects", Дочерние["data"]);
Иначе
ОбъектКаталога.Вставить("objects", Дочерние["error"]);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="2d373a84-c3c2-40ee-baa8-e759487fef4a">
<Properties>
<Name>OPI_SQLite</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI SQLite</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SQLite (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с базами SQLite из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,501 @@
// OneScript: ./OInt/core/Modules/OPI_SQLite.os
// Lib: SQLite
// CLI: sqlite
// Keywords: sqlite
// Depends: OPI_SQLite
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает подключение к указанной базе
//
// Параметры:
// База - Строка - Путь к базе. In memory, если не заполнено - db
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или структура с информацией об ошибке
Функция ОткрытьСоединение(Знач База = "") Экспорт
Если ЭтоКоннектор(База) Тогда
Возврат База;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(База);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(База);
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("SQLite");
Коннектор.Database = База;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Возврат ?(Результат["result"], Коннектор, Результат);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - db
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
Результат = Соединение.Close();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат, Ложь);
Иначе
Результат = Новый Структура("result,error", Ложь, "It's not a connection");
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты SQLite
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_SQLite.Main";
КонецФункции
// Выполнить запрос SQL
// Выполняет произвольный SQL запрос
//
// Примечание:
// Доступные типы параметров: Cтрока, Число, Дата, Булево, ДвоичныеДанные.^^
// Двоичные данные могут также быть переданы как структура `{'blob':Путь к файлу}`. Возвращаются значения двоичных данных (BLOB)^^
// в виде `{'blob':Base64 строка}`
// Без указания флага `ФорсироватьРезультат`, чтение результата осуществляется только для запросов, начинающихся с `SELECT`^^
// Для остальных запросов возвращается `result:true` или `false` с текстом ошибки
// При выполнении нескольких запросов в рамках одного соединения, расширения лучше подключить один раз при помощи функции `ПодключитьРасширение`
//
// Параметры:
// ТекстЗапроса - Строка - Текст запроса к базе - sql
// Параметры - Массив Из Произвольный - Массив позиционных параметров запроса - params
// ФорсироватьРезультат - Булево - Включает попытку получения результата, даже для не SELECT запросов - force
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе. In memory, если не заполнено - db
// Расширения - Соответствие Из КлючИЗначение - Расширения: Ключ > путь или данные расширения, Значение > точка входа - exts
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ВыполнитьЗапросSQL(Знач ТекстЗапроса
, Знач Параметры = ""
, Знач ФорсироватьРезультат = Ложь
, Знач Соединение = ""
, Знач Расширения = Неопределено) Экспорт
Если ЭтоКоннектор(Соединение) Тогда
ЗакрыватьСоединение = Ложь;
Коннектор = Соединение;
Иначе
ЗакрыватьСоединение = Истина;
Коннектор = ОткрытьСоединение(Соединение);
КонецЕсли;
Если Не ЭтоКоннектор(Коннектор) Тогда
Возврат Коннектор;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстЗапроса, Истина);
OPI_ПреобразованиеТипов.ПолучитьБулево(ФорсироватьРезультат);
Если ЗначениеЗаполнено(Расширения) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Расширения, "Некорректная коллекция расширений!");
Для Каждого Расширение Из Расширения Цикл
ПодключениеРасширения = ПодключитьРасширение(Расширение.Ключ, Расширение.Значение, Коннектор);
Если Не ПодключениеРасширения["result"] Тогда
Возврат ПодключениеРасширения;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Параметры_ = OPI_ЗапросыSQL.ОбработатьПараметры(Параметры, ПолучитьСтруктуруТипов());
Результат = OPI_ЗапросыSQL.ВыполнитьЗапросСОбработкой(Коннектор, ТекстЗапроса, ФорсироватьРезультат, Параметры_);
Если ЗакрыватьСоединение Тогда
ЗакрытьСоединение(Коннектор);
КонецЕсли;
Возврат Результат;
КонецФункции
// Подключить расширение !NOCLI
// Подключает расширение SQLite для указанного соединения
//
// Примечание:
// Расширение активно только в рамках соединения. При каждом новом соединении его необходимо подключать заново
// Аналогично использованию параметра `Расширения` (`exts` в CLI) функции `ВыполнитьЗапросSQL`
//
// Параметры:
// Расширение - Строка, ДвоичныеДанные - Данные или путь к расширению - ext
// ТочкаВхода - Строка - Точка входа расширения, если необходима - point
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе. In memory, если не заполнено - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат подключения расширения
Функция ПодключитьРасширение(Знач Расширение, Знач ТочкаВхода = "", Знач Соединение = "") Экспорт
Расширение_ = Расширение;
РасширениеФайла = ?(OPI_Инструменты.ЭтоWindows(), "dll", "so");
OPI_ПреобразованиеТипов.ПолучитьФайлНаДиске(Расширение_, РасширениеФайла);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТочкаВхода);
Временный = Расширение_["Временный"];
ПутьКФайлу = Расширение_["Путь"];
Коннектор = ОткрытьСоединение(Соединение);
ТипКомпоненты = "AddIn.OPI_SQLite.Main";
Если ТипЗнч(Коннектор) <> Тип(ТипКомпоненты) Тогда
Возврат Коннектор;
КонецЕсли;
Результат = Коннектор.LoadExtension(ПутьКФайлу, ТочкаВхода);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Если Временный Тогда
Попытка
УдалитьФайлы(ПутьКФайлу);
Исключение
Возврат Результат;
КонецПопытки;
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ORM
// Получить информацию о таблице
// Получает информацию о таблице
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьИнформациюОТаблице(Знач Таблица, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьСтруктуруТаблицы(OPI_SQLite, Таблица, Соединение);
Возврат Результат;
КонецФункции
// Создать таблицу
// Создает пустую таблицу в базе
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция СоздатьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.СоздатьТаблицу(OPI_SQLite, Таблица, СтруктураКолонок, Соединение);
Возврат Результат;
КонецФункции
// Добавить колонку таблицы
// Добавляет новую колонку в существующую таблицу
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// ТипДанных - Строка - Тип данных колонки - type
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач ТипДанных, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьКолонкуТаблицы(OPI_SQLite, Таблица, Имя, ТипДанных, Соединение);
Возврат Результат;
КонецФункции
// Удалить колонку таблицы
// Удаляет колонку из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Имя - Строка - Имя колонки - name
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьКолонкуТаблицы(Знач Таблица, Знач Имя, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьКолонкуТаблицы(OPI_SQLite, Таблица, Имя, Соединение);
Возврат Результат;
КонецФункции
// Гарантировать таблицу
// Создает новую таблицу в случае отсутствия или обновляет состав колонок существующей таблицы
//
// Примечание:
// В результате изменения структуры таблицы данные могут быть утеряны!^^
// Рекомендуется предварительно опробовать данный метод на тестовых данных
// Данная функция не обновляет тип данных существующих колонок
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураКолонок - Структура Из КлючИЗначение - Структура колонок: Ключ > имя, Значение > Тип данных - cols
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ГарантироватьТаблицу(Знач Таблица, Знач СтруктураКолонок, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.ГарантироватьТаблицу(OPI_SQLite, Таблица, СтруктураКолонок, Соединение);
Возврат Результат;
КонецФункции
// Добавить записи
// Добавляет записи в таблицу
//
// Примечание:
// Двоичные данные могут также быть переданы как структура `{'blob':Путь к файлу}`
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// МассивДанных - Массив Из Структура - Массив структур данных строк: Ключ > поле, Значение > значение поля - rows
// Транзакция - Булево - Истина > добавление записей в транзакции с откатом при ошибке - trn
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ДобавитьЗаписи(Знач Таблица, Знач МассивДанных, Знач Транзакция = Истина, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.ДобавитьЗаписи(OPI_SQLite, Таблица, МассивДанных, Транзакция, Соединение);
Возврат Результат;
КонецФункции
// Получить записи
// Получает записи из выбранной таблицы
//
// Примечание:
// Значения типа Двоичные данные (BLOB) возвращаются в виде `{'blob':Base64 строка}`
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Поля - Массив Из Строка - Поля для выборки - fields
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Сортировка - Структура Из КлючИЗначение - Сортировка: Ключ > поле, Значение > направление (ASC, DESC) - order
// Количество - Число - Ограничение количества получаемых строк - limit
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ПолучитьЗаписи(Знач Таблица
, Знач Поля = "*"
, Знач Фильтры = ""
, Знач Сортировка = ""
, Знач Количество = ""
, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.ПолучитьЗаписи(OPI_SQLite, Таблица, Поля, Фильтры, Сортировка, Количество, Соединение);
Возврат Результат;
КонецФункции
// Обновить записи
// Обновляет значение записей по выбранным критериям
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// СтруктураЗначений - Структура Из КлючИЗначение - Структура значений: Ключ > поле, Значение > значение поля - values
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОбновитьЗаписи(Знач Таблица, Знач СтруктураЗначений, Знач Фильтры = "", Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.ОбновитьЗаписи(OPI_SQLite, Таблица, СтруктураЗначений, Фильтры, Соединение);
Возврат Результат;
КонецФункции
// Удалить записи
// Удаляет записи из таблицы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Фильтры - Массив Из Структура - Массив фильтров. См. ПолучитьСтруктуруФильтраЗаписей - filter
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьЗаписи(Знач Таблица, Знач Фильтры = "", Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_SQLite, Таблица, Фильтры, Соединение);
Возврат Результат;
КонецФункции
// Удалить таблицу
// Удаляет таблицу из базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция УдалитьТаблицу(Знач Таблица, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьТаблицу(OPI_SQLite, Таблица, Соединение);
Возврат Результат;
КонецФункции
// Очистить таблицу
// Очищает таблицу базы
//
// Параметры:
// Таблица - Строка - Имя таблицы - table
// Соединение - Строка, Произвольный - Существующее соединение или путь к базе - db
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат выполнения запроса
Функция ОчиститьТаблицу(Знач Таблица, Знач Соединение = "") Экспорт
Результат = OPI_ЗапросыSQL.УдалитьЗаписи(OPI_SQLite, Таблица, , Соединение);
Возврат Результат;
КонецФункции
// Получить структуру фильтра записей
// Получает структуру шаблон для фильтрации записей в запросах ORM
//
// Примечание:
// Использование признака `raw` необходимо для составных конструкций, вроде `BEETWEEN`.^^
// Например: при `raw:false` фильтр `type:BETWEEN` `value:10 AND 20` будет интерпритирован как `BETWEEN ?1 `^^
// где `?1 = "10 AND 20"`, что приведет к ошибке.^^
// В таком случае необходимо использовать `raw:true` для установки условия напрямую в текст запроса
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Элемент фильтра записей
Функция ПолучитьСтруктуруФильтраЗаписей(Знач Пустая = Ложь) Экспорт
Возврат OPI_ЗапросыSQL.ПолучитьСтруктуруФильтраЗаписей(Пустая);
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьОсобенности() Экспорт
Особенности = Новый Соответствие;
Особенности.Вставить("НумерацияПараметров", Истина);
Особенности.Вставить("МаркерПараметров" , "?");
Особенности.Вставить("СУБД" , "sqlite");
Особенности.Вставить("ПолеКолонки" , "name");
Особенности.Вставить("НачалоТранзакции" , "BEGIN");
Возврат Особенности;
КонецФункции
Функция ПолучитьСтруктуруТипов() Экспорт
Text_ = "TEXT";
СтруктураТипов = Новый Соответствие;
СтруктураТипов.Вставить("ДвоичныеДанные" , "BLOB");
СтруктураТипов.Вставить("УникальныйИдентификатор", Text_);
СтруктураТипов.Вставить("Булево" , "BOOL");
СтруктураТипов.Вставить("Дробное" , "REAL");
СтруктураТипов.Вставить("Целое" , "INTEGER");
СтруктураТипов.Вставить("Дата" , Text_);
СтруктураТипов.Вставить("Строка" , Text_);
СтруктураТипов.Вставить("Коллекции" , Новый СписокЗначений);
СтруктураТипов.Вставить("БулевоКакЧисло" , Ложь);
Возврат СтруктураТипов;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="cae67566-59cb-430c-a927-828bb12fcdf1">
<Properties>
<Name>OPI_SSH</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SSH (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с SSH из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,212 @@
// OneScript: ./OInt/core/Modules/OPI_SSH.os
// Lib: SSH
// CLI: ssh
// Keywords: ssh, shell
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Создает новый сеанс SSH
//
// Примечание:
// Получить конфигурацию соединения можно при помощи функций `ПолучитьНастройкиЛогинПароль`,^^
// `ПолучитьНастройкиПриватныйКлюч`, `ПолучитьНастройкиЧерезАгента`
//
// Параметры:
// НастройкиSSH - Структура Из КлючИЗначение - Структура настроек соединения - set
// Прокси - Структура Из КлючИЗначение - Структура настроек прокси, если необходимо - proxy
//
// Возвращаемое значение:
// Произвольный, Соответствие Из КлючИЗначение - Открыть соединение
Функция ОткрытьСоединение(Знач НастройкиSSH, Знач Прокси = "") Экспорт
Возврат OPI_ЗапросыSSH.ОткрытьСоединение(НастройкиSSH, Прокси);
КонецФункции
// Получить конфигурацию соединения
// Формирует полную структуру настроек соединения, которая может быть использована вместо самого соединения при вызове других функций
//
// Примечание:
// Может быть передана в качестве параметра `Соединение` в других функциях вместо настоящего соединения из функции `ОткрытьСоединение`.^^
// При этом новое соединение будет открыто и закрыто в рамках вызываемой функции
// Не рекомендуется использовать конфигурацию соединения при множественных обращениях к серверу SSH.^^
// Данный функционал предназначен, в первую очередь для CLI версии ОПИ, где хранение соединения между вызовами невозможно
//
// Параметры:
// НастройкиSSH - Структура Из КлючИЗначение - Настройки SSH - set
// Прокси - Структура Из КлючИЗначение - Настройки прокси, если необходимо. См. ПолучитьНастройкиПрокси - proxy
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек соединения
Функция ПолучитьКонфигурациюСоединения(Знач НастройкиSSH, Знач Прокси = Неопределено) Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьКонфигурациюСоединения(НастройкиSSH, Прокси);
КонецФункции
// Выполнить команду
// Выполняет указанную команду
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Команда - Строка - Текст команды - comm
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ВыполнитьКоманду(Знач Соединение, Знач Команда) Экспорт
Возврат OPI_ЗапросыSSH.ВыполнитьКоманду(Соединение, Команда);
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - conn
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Возврат OPI_ЗапросыSSH.ЗакрытьСоединение(Соединение);
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты для работы с SSH
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат OPI_ЗапросыSSH.ЭтоКоннектор(Значение);
КонецФункции
// Получить настройки (логин/пароль)
// Получает настройки соединения с авторизацией через логин и пароль
//
// Параметры:
// Хост - Строка - Хост SSH - host
// Порт - Число - Порт SSH - port
// Логин - Строка - Имя пользователя SSH - user
// Пароль - Строка - Пароль пользователя SSH - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Конфигурация соединения
Функция ПолучитьНастройкиЛогинПароль(Знач Хост, Знач Порт, Знач Логин, Знач Пароль = "") Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиЛогинПароль(Хост, Порт, Логин, Пароль);
КонецФункции
// Получить настройки (приватный ключ)
// Получает настройки соединения с авторизацией через приватный ключ
//
// Параметры:
// Хост - Строка - Хост SSH - host
// Порт - Число - Порт SSH - port
// Логин - Строка - Имя пользователя SSH - user
// Приватный - Строка - Путь к файлу приватного ключа - key
// Публичный - Строка - Путь к файлу публичного ключ - pub
// Пароль - Строка - Пароль (passphrase) приватного ключа - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Конфигурация соединения
Функция ПолучитьНастройкиПриватныйКлюч(Знач Хост
, Знач Порт
, Знач Логин
, Знач Приватный
, Знач Публичный = ""
, Знач Пароль = "") Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиПриватныйКлюч(Хост, Порт, Логин, Приватный, Публичный, Пароль);
КонецФункции
// Получить настройки (через агента)
// Получает настройки соединения с авторизацией через SSH Agent
//
// Параметры:
// Хост - Строка - Хост SSH - host
// Порт - Число - Порт SSH - port
// Логин - Строка - Имя пользователя SSH - user
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Конфигурация соединения
Функция ПолучитьНастройкиЧерезАгента(Знач Хост, Знач Порт, Знач Логин) Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиЧерезАгента(Хост, Порт, Логин);
КонецФункции
// Получить настройки прокси
// Формирует структуру настроек прокси-сервера для соединения
//
// Параметры:
// Адрес - Строка - Адрес прокси - addr
// Порт - Число - Порт прокси - port
// Вид - Строка - Вид прокси: socks5, socks4, http - type
// Логин - Строка, Неопределено - Логин авторизации, если необходимо - login
// Пароль - Строка, Неопределено - Пароль для авторизации, если необходимо - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек прокси
Функция ПолучитьНастройкиПрокси(Знач Адрес
, Знач Порт
, Знач Вид = "socks5"
, Знач Логин = Неопределено
, Знач Пароль = Неопределено) Экспорт
Возврат OPI_ЗапросыSSH.ПолучитьНастройкиПрокси(Адрес, Порт, Вид, Логин, Пароль);
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="21b89e7a-e792-4a4c-9d01-c630225fe48a">
<Properties>
<Name>OPI_Slack</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Slack (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы со Slack из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="ed305045-7f7e-4dae-b254-e1e1bdb32293">
<Properties>
<Name>OPI_TCP</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>TCP (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с TCP из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,309 @@
// OneScript: ./OInt/core/Modules/OPI_TCP.os
// Lib: TCP
// CLI: tcp
// Keywords: tcp
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область МетодыКлиента
// Открыть соединение !NOCLI
// Создает TCP соединение
//
// Параметры:
// Адрес - Строка - Адрес и порт для подключения - address
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение, Произвольный - Возвращает объект TCP клиента при успешном подключении или информацию об ошибке
Функция ОткрытьСоединение(Знач Адрес, Знач Tls = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Адрес);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(Адрес);
Домен = OPI_Инструменты.ПолучитьДомен(Адрес);
TCPКлиент = OPI_Компоненты.ПолучитьКомпоненту("TCPClient");
Успех = TCPКлиент.SetAddress(Адрес, Домен);
Если Не Успех Тогда
Возврат ПолучитьПоследнююОшибку(TCPКлиент);
КонецЕсли;
Tls = OPI_Компоненты.УстановитьTls(TCPКлиент, Tls);
Если Не OPI_Инструменты.ПолучитьИли(Tls, "result", Ложь) Тогда
Возврат Tls;
КонецЕсли;
Успех = TCPКлиент.Connect();
Если Не Успех Тогда
Возврат ПолучитьПоследнююОшибку(TCPКлиент);
КонецЕсли;
Возврат TCPКлиент;
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает созданное ранее соединение
//
// Параметры:
// Соединение - Произвольный - Соединение, см. ОткрытьСоединение - tcp
//
// Возвращаемое значение:
// Булево - всегда возвращает Истина
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
Возврат Соединение.Disconnect();
КонецФункции
// Прочитать двоичные данные !NOCLI
// Читает данные из указанного соединения
//
// Примечание:
// При работе с бесконечным потоком входящих данных обязательно указание параметра МаксимальныйРазмер, так как^^
// бесконечное получение данных может привести к зависанию
// При закрытии соединения, ошибке или обнаружении EOF чтение завершается в любом случае
//
// Параметры:
// Соединение - Произвольный - Соединение, см. ОткрытьСоединение - tcp
// МаксимальныйРазмер - Число - Максимальный размер данных (байт). 0 > без ограничений - size
// Маркер - Строка, ДвоичныеДанные - Маркер конца сообщения. Пусто > без маркера - marker
// Таймаут - Число - Таймаут ожидания данных (мс). 0 > без ограничений - timeout
//
// Возвращаемое значение:
// ДвоичныеДанные - Полученные данные
Функция ПрочитатьДвоичныеДанные(Знач Соединение
, Знач МаксимальныйРазмер = 0
, Знач Маркер = ""
, Знач Таймаут = 5000) Экспорт
OPI_ПреобразованиеТипов.ПолучитьЧисло(Таймаут);
OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер);
Если ТипЗнч(Маркер) = Тип("Строка") Тогда
Маркер = ПолучитьДвоичныеДанныеИзСтроки(Маркер);
Иначе
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Маркер);
КонецЕсли;
Данные = Соединение.Read(МаксимальныйРазмер, Маркер, Таймаут);
Возврат Данные;
КонецФункции
// Прочитать строку !NOCLI
// Читает данные из указанного соединения в виде строки
//
// Примечание:
// При закрытии соединения, ошибке или обнаружении EOF чтение завершается в любом случае
//
// Параметры:
// Соединение - Произвольный - Соединение, см. ОткрытьСоединение - tcp
// Кодировка - Строка - Кодировка преобразования данных в строку - enc
// Маркер - Строка, ДвоичныеДанные - Маркер конца сообщения. Пусто > без маркера - marker
// Таймаут - Число - Таймаут ожидания данных (мс). 0 > без ограничений - timeout
//
// Возвращаемое значение:
// Строка - Полученные данные в виде строки
Функция ПрочитатьСтроку(Знач Соединение
, Знач Кодировка = "UTF-8"
, Знач Маркер = ""
, Знач Таймаут = 5000) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Кодировка);
Данные = ПрочитатьДвоичныеДанные(Соединение, , Маркер, Таймаут);
Данные = ПолучитьСтрокуИзДвоичныхДанных(Данные, Кодировка);
Возврат Данные;
КонецФункции
// Отправить двоичные данные !NOCLI
// Отправляет двоичные данные через указанное соединение
//
// Параметры:
// Соединение - Произвольный - Соединение, см. ОткрытьСоединение - tcp
// Данные - ДвоичныеДанные - Данные для отправки - data
// Таймаут - Число - Таймаут ожидания записи (мс). 0 > без ограничений - timeout
//
// Возвращаемое значение:
// Булево - Признак успешного выполнения
Функция ОтправитьДвоичныеДанные(Знач Соединение, Знач Данные, Знач Таймаут = 5000) Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные);
OPI_ПреобразованиеТипов.ПолучитьЧисло(Таймаут);
Результат = Соединение.Send(Данные, Таймаут);
Возврат Результат;
КонецФункции
// Отправить строку !NOCLI
// Отправляет данные в виде строки через указанное соединение
//
// Параметры:
// Соединение - Произвольный - Соединение, см. ОткрытьСоединение - tcp
// Данные - Строка - Данные для отправки в виде строки - data
// Кодировка - Строка - Кодировка для записи исходящей строки в поток - enc
// Таймаут - Число - Таймаут ожидания записи (мс). 0 > без ограничений - timeout
//
// Возвращаемое значение:
// Булево - Признак успешного выполнения
Функция ОтправитьСтроку(Знач Соединение, Знач Данные, Знач Кодировка = "UTF-8", Знач Таймаут = 5000) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Данные);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Кодировка);
ДанныеДД = ПолучитьДвоичныеДанныеИзСтроки(Данные, Кодировка);
Результат = ОтправитьДвоичныеДанные(Соединение, ДанныеДД, Таймаут);
Возврат Результат;
КонецФункции
// Обработать запрос
// Отправляет одиночный запрос на указанный адрес и получает ответ, используя стандартные настройки
//
// Параметры:
// Адрес - Строка - Адрес и порт для подключения - address
// Данные - Строка, ДвоичныеДанные - Данные или текст для отправки - data
// ОтветСтрокой - Булево - Признак получения ответа как строки - string
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// ДвоичныеДанные, Строка - Ответ на запрос или информация об ошибке
Функция ОбработатьЗапрос(Знач Адрес, Знач Данные = "", Знач ОтветСтрокой = Истина, Знач Tls = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные, Истина, Ложь);
OPI_ПреобразованиеТипов.ПолучитьБулево(ОтветСтрокой);
Соединение = ОткрытьСоединение(Адрес, Tls);
Если Не OPI_Компоненты.ЭтоКомпонента(Соединение) Тогда
Возврат Соединение;
КонецЕсли;
Результат = ОтправитьДвоичныеДанные(Соединение, Данные);
Если Результат Тогда
Ответ = ПрочитатьДвоичныеДанные(Соединение, , Символы.ПС);
Если Не ЗначениеЗаполнено(Ответ) Тогда
Ошибка = ПолучитьПоследнююОшибку(Соединение);
Если ЗначениеЗаполнено(Ошибка) Тогда
Ответ = OPI_Инструменты.JSONСтрокой(Ошибка);
Ответ = ПолучитьДвоичныеДанныеИзСтроки(Ответ);
КонецЕсли;
КонецЕсли;
Ответ = ?(ОтветСтрокой, ПолучитьСтрокуИзДвоичныхДанных(Ответ), Ответ);
Иначе
Ответ = ПолучитьПоследнююОшибку(Соединение);
Ответ = ?(ЗначениеЗаполнено(Ответ), OPI_Инструменты.JSONСтрокой(Ответ), "OPI: Не удалось отправить сообщение");
Ответ = ?(ОтветСтрокой, Ответ, ПолучитьДвоичныеДанныеИзСтроки(Ответ));
КонецЕсли;
ЗакрытьСоединение(Соединение);
Возврат Ответ;
КонецФункции
// Получить последнюю ошибку !NOCLI
// Получает информацию о последней ошибке в соединении
//
// Параметры:
// Соединение - Произвольный - Соединение, см. ОткрытьСоединение - tcp
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение, Неопределено - Информация об ошибке или неопределено, если ошибки нет
Функция ПолучитьПоследнююОшибку(Знач Соединение) Экспорт
Результат = Соединение.GetLastError();
Если ЗначениеЗаполнено(Результат) Тогда
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Иначе
Результат = Неопределено;
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить настройки TLS
// Формирует настройки для использования TLS при выполнении запросов
//
// Примечание:
// Настройки Tls могут быть установлены только в момент создания соединения: явного, при использовании функции `ОткрытьСоединение`^^
// или неявного, при передаче строки подключения в метод `ОбработатьЗапрос`
//
// Параметры:
// ОтключитьПроверкуСертификатов - Булево - Позволяет работать с некорретными сертификатами, в т.ч. самоподписанными - trust
// ПутьКСертификату - Строка - Путь к корневому PEM файлу сертификата, если его нет в системном хранилище - cert
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек TLS соединения
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату);
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="fe603e76-e34a-40fd-977d-ee3c2dbc6620">
<Properties>
<Name>OPI_Telegram</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Telegram (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Telegram Bot API из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="748f90c6-8251-482b-a249-b0372df0c72e">
<Properties>
<Name>OPI_Twitter</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Twitter (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Twitter из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,661 @@
// OneScript: ./OInt/core/Modules/OPI_Twitter.os
// Lib: Twitter
// CLI: twitter
// Keywords: twitter, x
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// Если в не знаете с чего начать, то стоит найти метод ПолучитьСтандартныеПараметры()
// и почитать комментарии
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check method-too-many-params
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область ДанныеИНастройка
// Получить ссылку для авторизации
// Формирует ссылку для авторизации через браузер
//
// Параметры:
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Строка - URL для перехода в браузере
Функция ПолучитьСсылкуАвторизации(Параметры = "") Экспорт
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
ПараметрыURL = Новый Структура;
ПараметрыURL.Вставить("response_type" , "code");
ПараметрыURL.Вставить("client_id" , Параметры_["client_id"]);
ПараметрыURL.Вставить("redirect_uri" , Параметры_["redirect_uri"]);
ПараметрыURL.Вставить("scope" , Параметры_["scope"]);
ПараметрыURL.Вставить("state" , "state");
ПараметрыURL.Вставить("code_challenge" , "challenge");
ПараметрыURL.Вставить("code_challenge_method", "plain");
ПараметрыURL = OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL);
Линк = "https://twitter.com/i/oauth2/authorize" + ПараметрыURL;
Возврат Линк;
КонецФункции
// Получить токен
// Получает токен по коду, полученному при авторизации по ссылке из ПолучитьСсылкуАвторизации
//
// Параметры:
// Код - Строка - Код, полученный из авторизации См.ПолучитьСсылкуАвторизации - code
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция ПолучитьТокен(Знач Код, Знач Параметры = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Код);
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("code" , Код);
ПараметрыЗапроса.Вставить("grant_type" , "authorization_code");
ПараметрыЗапроса.Вставить("client_id" , Параметры_["client_id"]);
ПараметрыЗапроса.Вставить("redirect_uri" , Параметры_["redirect_uri"]);
ПараметрыЗапроса.Вставить("code_verifier", "challenge");
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.twitter.com/2/oauth2/token"
, ПараметрыЗапроса
,
, Ложь);
Возврат Ответ;
КонецФункции
// Обновить токен
// Обновляет v2 токен при помощи refresh_token
//
// Параметры:
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция ОбновитьТокен(Знач Параметры = "") Экспорт
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
Refresh = "refresh_token";
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить(Refresh , Параметры_[Refresh]);
ПараметрыЗапроса.Вставить("grant_type" , Refresh);
ПараметрыЗапроса.Вставить("client_id" , Параметры_["client_id"]);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://api.twitter.com/2/oauth2/token"
, ПараметрыЗапроса
,
, Ложь);
Возврат Ответ;
КонецФункции
// Обработка входящего запроса после авторизации !NOCLI
// Метод для вставки в http-сервис, адрес которого указывается в redirect_uri
//
// Примечание:
// Вызывает метод получения токена, так как для получения токена из кода, приходящего^^
// на redirect_uri после авторизации через браузер есть всего 30 секунд
//
// Параметры:
// Запрос - HTTPСервисЗапрос - Запрос, приходящий на http-сервис
//
// Возвращаемое значение:
// HTTPОтвет, Произвольный, ДвоичныеДанные - Результат чтения JSON ответа сервера
Функция ОбработкаВходящегоЗапросаПослеАвторизации(Запрос) Экспорт
Код = Запрос.ПараметрыЗапроса["code"];
ОтветТокен = ПолучитьТокен(Код);
// BSLLS:CommentedCode-off
// Предпочтительное хранение токенов
// Константы.TwitterRefresh.Установить(ОтветТокен["refresh_token"]);
// Константы.TwitterToken.Установить(ОтветТокен["access_token"]);
// BSLLS:CommentedCode-on
Возврат ОтветТокен;
КонецФункции
#КонецОбласти
#Область Твиты
// Создать произвольный твит
// Создает твит с произвольным содержимым
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивМедиа - Массив из Строка,ДвоичныеДанные - Массив двоичных данных или путей к файлам - media
// МассивВариантовОпроса - Массив из Строка - Массив вариантов опроса, если необходимо - options
// ДлительностьОпроса - Строка,Число - Длительность опроса, если необходимо (опрос без длительности не создается) - dur
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьПроизвольныйТвит(Знач Текст = ""
, Знач МассивМедиа = ""
, Знач МассивВариантовОпроса = ""
, Знач ДлительностьОпроса = ""
, Знач Параметры = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Текст);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ДлительностьОпроса);
Если ЗначениеЗаполнено(МассивМедиа) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивМедиа);
КонецЕсли;
Если ЗначениеЗаполнено(МассивВариантовОпроса) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивВариантовОпроса);
КонецЕсли;
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
URL = "https://api.twitter.com/2/tweets";
Массив = "Массив";
Поля = Новый Соответствие;
Если ЗначениеЗаполнено(Текст) Тогда
Поля.Вставить("text", Текст);
КонецЕсли;
Если ТипЗнч(МассивВариантовОпроса) = Тип(Массив) И ЗначениеЗаполнено(ДлительностьОпроса) Тогда
ДлительностьОпроса = Число(ДлительностьОпроса);
Если МассивВариантовОпроса.Количество() > 0 Тогда
СтруктураВарианта = Новый Структура("options,duration_minutes", МассивВариантовОпроса, ДлительностьОпроса);
Поля.Вставить("poll", СтруктураВарианта);
КонецЕсли;
КонецЕсли;
Если ТипЗнч(МассивМедиа) = Тип(Массив) Тогда
Если МассивМедиа.Количество() > 0 Тогда
Поля.Вставить("media", Новый Структура("media_ids", МассивМедиа));
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(Поля["media"]) Тогда
ЭтоV2 = Ложь;
Иначе
ЭтоV2 = Истина;
КонецЕсли;
Ответ = Post(URL, Поля, Параметры_, Истина, ЭтоV2);
Возврат Ответ;
КонецФункции
// Создать текстовый твит
// Создает твит без вложений
//
// Параметры:
// Текст - Строка - Текст твита - text
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТекстовыйТвит(Знач Текст, Знач Параметры = "") Экспорт
Возврат СоздатьПроизвольныйТвит(Текст, , , , Параметры);
КонецФункции
// Создать твит картинки
// Создает твит с картинкой вложением
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивКартинок - Массив из Строка,ДвоичныеДанные - Массив файлов картинок - pictures
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитКартинки(Знач Текст, Знач МассивКартинок, Знач Параметры = "") Экспорт
МассивМедиа = ЗагрузитьМассивВложений(МассивКартинок, "tweet_image", Параметры);
Если ТипЗнч(МассивМедиа) = Тип("Массив") Тогда
Результат = СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
Иначе
Результат = МассивМедиа;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать твит гифки
// Создает твит с вложением-гифкой
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивГифок - Массив из Строка,ДвоичныеДанные - Массив файлов гифок - gifs
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитГифки(Знач Текст, Знач МассивГифок, Знач Параметры = "") Экспорт
МассивМедиа = ЗагрузитьМассивВложений(МассивГифок, "tweet_gif", Параметры);
Если ТипЗнч(МассивМедиа) = Тип("Массив") Тогда
Результат = СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
Иначе
Результат = МассивМедиа;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать твит видео
// Создает твит с видеовложением
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивВидео - Массив из Строка,ДвоичныеДанные - Массив файлов видео - videos
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитВидео(Знач Текст, Знач МассивВидео, Знач Параметры = "") Экспорт
МассивМедиа = ЗагрузитьМассивВложений(МассивВидео, "tweet_video", Параметры);
Если ТипЗнч(МассивМедиа) = Тип("Массив") Тогда
Результат = СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
Иначе
Результат = МассивМедиа;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать твит опрос
// Создает твит с опросом
//
// Параметры:
// Текст - Строка - Текст твита - text
// МассивВариантов - Массив из Строка - Массив вариантов опроса - options
// Длительность - Строка,Число - Длительность опроса - duration
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитОпрос(Знач Текст, Знач МассивВариантов, Знач Длительность, Знач Параметры = "") Экспорт
Возврат СоздатьПроизвольныйТвит(Текст, , МассивВариантов, Длительность, Параметры);
КонецФункции
// Загрузить массив вложений
// Загружает файлы на сервер и возвращает их ID
//
// Параметры:
// МассивФайлов - Массив из Строка, ДвоичныеДанные - Массив файлов для загрузки - files
// ТипВложений - Строка - Тип вложений: tweet_video, tweet_image, tweet_gif - type
// Параметры - Структура из Строка - Данные авторизации. См.ПолучитьСтандартныеПараметры - auth
//
// Возвращаемое значение:
// Массив Из Строка - Массив ID медиа
Функция ЗагрузитьМассивВложений(Знач МассивФайлов, Знач ТипВложений, Знач Параметры = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТипВложений);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивФайлов);
МассивМедиа = Новый Массив;
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
MIS = "media_id_string";
Если ЗначениеЗаполнено(МассивФайлов) Тогда
Для Каждого ФайлОтправки Из МассивФайлов Цикл
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(ФайлОтправки);
Ответ = ЗагрузитьМедиафайл(ФайлОтправки, ТипВложений, Параметры_);
IDМедиа = Ответ[MIS];
Если Не ЗначениеЗаполнено(IDМедиа) Тогда
Возврат Ответ;
КонецЕсли;
МассивМедиа.Добавить(IDМедиа);
КонецЦикла;
КонецЕсли;
Возврат МассивМедиа;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ЗагрузитьМедиафайл(Знач Файл, Знач Тип, Знач Параметры)
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
ВидЗапроса = "POST";
Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
URL = "https://upload.twitter.com/1.1/media/upload.json";
Ответ = ЗагрузитьМедиаЧастями(Файл, Тип, ВидЗапроса, URL, Параметры_);
Возврат Ответ;
КонецФункции
Функция ЗагрузитьМедиаЧастями(Знач Файл, Знач Тип, Знач ВидЗапроса, Знач URL, Параметры)
Единица = 1024;
Количество = 4;
MID = "media_id";
MIS = "media_id_string";
Command = "command";
Размер = Файл.Размер();
РазмерЧасти = Количество * Единица * Единица;
МассивЧтения = РазделитьДвоичныеДанные(Файл, РазмерЧасти);
Поля = Новый Структура;
Поля.Вставить(Command , "INIT");
Поля.Вставить("total_bytes" , OPI_Инструменты.ЧислоВСтроку(Размер));
Поля.Вставить("media_category", Тип);
ОтветИнициализации = Post(URL, Поля, Параметры);
IDИнициализации = ОтветИнициализации[MID];
IDSИнициализации = ОтветИнициализации[MIS];
Если Не ЗначениеЗаполнено(IDSИнициализации) Или Не ЗначениеЗаполнено(IDИнициализации) Тогда
Возврат ОтветИнициализации;
КонецЕсли;
Счетчик = 0;
Для Каждого Часть Из МассивЧтения Цикл
Поля = Новый Структура;
Поля.Вставить(Command , "APPEND");
Поля.Вставить(MID , IDSИнициализации);
Поля.Вставить("segment_index", OPI_Инструменты.ЧислоВСтроку(Счетчик));
Поля.Вставить("media" , Часть);
Ответ = PostMultipart(URL, Поля, Параметры);
Счетчик = Счетчик + 1;
КонецЦикла;
Поля = Новый Структура;
Поля.Вставить(Command, "FINALIZE");
Поля.Вставить(MID , IDSИнициализации);
СтатусОбработки = ПолучитьСтатусОбработки(Параметры, Поля, URL);
Если Не ТипЗнч(СтатусОбработки) = Тип("Строка") Тогда
Возврат СтатусОбработки;
КонецЕсли;
Ответ = ОжидатьЗавершенияОбработки(СтатусОбработки, IDSИнициализации, URL, Параметры);
Возврат Ответ;
КонецФункции
Функция ОжидатьЗавершенияОбработки(Знач СтатусОбработки, Знач IDИнициализации, Знач URL, Знач Параметры)
ProcessingInfo = "processing_info";
Command = "command";
Поля = Новый Структура;
Поля.Вставить(Command , "STATUS");
Поля.Вставить("media_id", IDИнициализации);
Пока Строка(СтатусОбработки) = "pending" Или Строка(СтатусОбработки) = "in_progress" Цикл
Ответ = Get(URL, Поля, Параметры);
Информация = Ответ[ProcessingInfo];
Если Не ЗначениеЗаполнено(Информация) Тогда
Возврат Ответ;
КонецЕсли;
СтатусОбработки = Информация["state"];
Если Не ЗначениеЗаполнено(СтатусОбработки) Тогда
Возврат Ответ;
КонецЕсли;
КонецЦикла;
Если СтатусОбработки = "failed" Тогда
ВызватьИсключение "Твиттер не смог обработать загруженное вами видео";
КонецЕсли;
Возврат Ответ;
КонецФункции
Функция ПолучитьСтандартныеПараметры(Знач Параметры = "")
// Здесь собрано определение данных, необходимых для работы.
// Для Twitter это довольно значительный набор, что обсуловлено наличием сразу 2-х API,
// которые, при этом, созданы не для разныз задач, но просто являются версиями друг друга.
// Актуальной версией API является v2 и она требует получения временных токенов. Несмотря на то,
// что Twitter настаивает на использовании этой актуальной версии, они как-то умудрились не перенести
// механизм загрузки файлов и некоторые другие из старой версии - v1.1. Поэтому что-то нужно делать
// на версии 1.1, а что-то на 2: вплоть до того что они убрали возможность постить твиты из v1.1,
// но только через нее в твит можно добавить картинку. При этом способы авторизации и токены у них разные
// Мировая гигокорпорация Илона Маска, кстати, напоминаю ;)
// P.S Далее часто упоминается "страница настроек Twitter Developer" - это
// https://developer.twitter.com/en/portal/dashboard и выбор конкретного проекта из списка (значек c ключем)
Параметры_ = Новый Соответствие;
Разрешения = "tweet.read tweet.write tweet.moderate.write users.read "
+ "follows.read follows.write offline.access space.read mute.read "
+ "mute.write like.read like.write list.read list.write block.read "
+ "block.write bookmark.read bookmark.write";
// Данные для API v2
// redirect_uri - URL вашего http-сервиса (или другого обработчика запросов) для авторизации
// scope - набор разрешений для получаемого ключа. Может быть любой, но offline.access обязателен
// client_id - Из OAuth 2.0 Client ID and Client Secret страницы настроек Twitter Developer
// client_secret - Из OAuth 2.0 Client ID and Client Secret страницы настроек Twitter Developer
// access_token - ПолучитьСсылкуАвторизации() -> Браузер -> code придет на redirect_uri -> ПолучитьТокен(code)
// refresh_token - Приходит вместе с access_token и используется для его обновления (время жизни access_token - 2 ч)
// Обновление происходит методом ОбновитьТокен с новыми access_token и refresh_token.
// При следующем обновлении нужно использовать уже новый refresh_token, так что захардкодить
// не получится (access_token тоже не получится)
// |--> ОбновитьТокен() ->|access_token --> Используется в т-нии 2-х часов для запросов
// | |refresh_token --|
// |--------[через 2 ч.]-------------------|
// Данные для API v1.1
// oauth_token - Из Authentication Tokens -> Access Token and Secret страницы настроек Twitter Developer
// oauth_token_secret - Из Authentication Tokens -> Access Token and Secret страницы настроек Twitter Developer
// oauth_consumer_key - Из Consumer Keys -> Access Token and Secret страницы настроек Twitter Developer
// oauth_consumer_secret - Из Consumer Keys -> Access Token and Secret страницы настроек Twitter Developer
// Эти токены обновлять не надо
Параметры_.Вставить("redirect_uri" , "");
Параметры_.Вставить("scope" , Разрешения);
Параметры_.Вставить("client_id" , "");
Параметры_.Вставить("client_secret" , "");
Параметры_.Вставить("access_token" , ""); // Должно быть нечто вроде Константы.TwitterToken.Получить()
Параметры_.Вставить("refresh_token" , ""); // Должно быть нечто вроде Константы.TwitterRefresh.Получить()
Параметры_.Вставить("oauth_token" , "");
Параметры_.Вставить("oauth_token_secret" , "");
Параметры_.Вставить("oauth_consumer_key" , "");
Параметры_.Вставить("oauth_consumer_secret", "");
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Параметры);
Если ТипЗнч(Параметры) = Тип("Структура") Или ТипЗнч(Параметры) = Тип("Соответствие") Тогда
Для Каждого ПереданныйПараметр Из Параметры Цикл
Параметры_.Вставить(ПереданныйПараметр.Ключ, OPI_Инструменты.ЧислоВСтроку(ПереданныйПараметр.Значение));
КонецЦикла;
КонецЕсли;
Возврат Параметры_;
КонецФункции
Функция ПолучитьСтатусОбработки(Знач Параметры, Знач Поля, Знач URL)
ProcessingInfo = "processing_info";
Ответ = Post(URL, Поля, Параметры);
Информация = Ответ[ProcessingInfo];
Если Не ЗначениеЗаполнено(Информация) Тогда
Возврат Ответ;
КонецЕсли;
СтатусОбработки = Информация["state"];
Если Не ЗначениеЗаполнено(СтатусОбработки) Тогда
Возврат Ответ;
Иначе
Возврат СтатусОбработки;
КонецЕсли;
КонецФункции
Функция Get(Знач URL, Знач Поля, Знач УчетныеДанные)
Токен = УчетныеДанные["oauth_token"];
Секрет = УчетныеДанные["oauth_token_secret"];
КлючПользователя = УчетныеДанные["oauth_consumer_key"];
СекретПользователя = УчетныеДанные["oauth_consumer_secret"];
Версия = "1.0";
Результат = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.УстановитьПараметрыURL(Поля)
.ДобавитьOauthV1Авторизацию(Токен, Секрет, КлючПользователя, СекретПользователя, Версия)
.УстановитьАлгоритмOAuthV1("HMAC", "SHA1")
.ОбработатьЗапрос("GET")
.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Результат;
КонецФункции
Функция Post(Знач URL, Знач Поля, Знач УчетныеДанные, Знач JSON = Ложь, Знач ЭтоV2 = Ложь)
Токен = УчетныеДанные["oauth_token"];
Секрет = УчетныеДанные["oauth_token_secret"];
КлючПользователя = УчетныеДанные["oauth_consumer_key"];
СекретПользователя = УчетныеДанные["oauth_consumer_secret"];
Версия = "1.0";
HttpКлиент = OPI_ЗапросыHTTP.НовыйЗапрос().Инициализировать(URL);
Если ЭтоV2 Тогда
HttpКлиент.ДобавитьЗаголовок("Authorization", "Bearer " + УчетныеДанные["access_token"]);
Иначе
ДействиеСВложениями = OPI_Инструменты.ПолеКоллекцииСуществует(Поля, "media");
HttpКлиент.ДобавитьOauthV1Авторизацию(Токен, Секрет, КлючПользователя, СекретПользователя, Версия)
.УстановитьАлгоритмOAuthV1("HMAC", "SHA1")
.ИспользоватьПоляТелаВOAuth(Не ДействиеСВложениями);
КонецЕсли;
Если JSON Тогда
HttpКлиент.УстановитьJsonТело(Поля);
Иначе
HttpКлиент.УстановитьFormТело(Поля);
КонецЕсли;
Возврат HttpКлиент.ОбработатьЗапрос("POST").ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецФункции
Функция PostMultipart(Знач URL, Знач Поля, Знач УчетныеДанные)
Токен = УчетныеДанные["oauth_token"];
Секрет = УчетныеДанные["oauth_token_secret"];
КлючПользователя = УчетныеДанные["oauth_consumer_key"];
СекретПользователя = УчетныеДанные["oauth_consumer_secret"];
Версия = "1.0";
HttpКлиент = OPI_ЗапросыHTTP.НовыйЗапрос()
.Инициализировать(URL)
.НачатьЗаписьТелаMultipart()
.ДобавитьOauthV1Авторизацию(Токен, Секрет, КлючПользователя, СекретПользователя, Версия)
.УстановитьАлгоритмOAuthV1("HMAC", "SHA1")
.ИспользоватьПоляТелаВOAuth(Ложь);
Для Каждого Параметр Из Поля Цикл
HttpКлиент.ДобавитьПолеMultipartFormData(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
Результат = HttpКлиент.ОбработатьЗапрос("POST").ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Результат;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="1ab0a76a-246d-4037-97c3-212d680aa589">
<Properties>
<Name>OPI_VK</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>VK (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с VK из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="cba61dc6-38eb-4bff-83cd-34dbc233f294">
<Properties>
<Name>OPI_VKTeams</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>VK Teams (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с VK Teams из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,976 @@
// OneScript: ./OInt/core/Modules/OPI_VKTeams.os
// Lib: VKTeams
// CLI: vkteams
// Keywords: vkteams, vk teams
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область ОбщиеМетоды
// Проверить токен
// Проверяет работоспособность токена бота
//
// Примечание:
// Метод в документации API: [GET /self/get](@teams.vk.com/botapi/#/self/get_self_get)
//
// Параметры:
// Токен - Строка - Токен бота - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПроверитьТокен(Знач Токен) Экспорт
URL = "/self/get";
Параметры = НормализоватьОснову(URL, Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Получить события
// Получает события бота в Polling режиме
//
// Примечание:
// Метод в документации API: [GET /events/get](@teams.vk.com/botapi/#/events/get_events_get)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDПоследнего - Строка, Число - ID последнего обработанного до этого события - last
// Таймаут - Строка, Число - Время удержания соединения для Long Polling - timeout
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьСобытия(Знач Токен, Знач IDПоследнего, Знач Таймаут = 0) Экспорт
URL = "/events/get";
Параметры = НормализоватьОснову(URL, Токен);
IDПоследнего = OPI_Инструменты.ЧислоВСтроку(IDПоследнего);
OPI_Инструменты.ДобавитьПоле("lastEventId", IDПоследнего, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("pollTime" , Таймаут , "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Получить информацию о файле
// Получает информацию о файле по его ID
//
// Примечание:
// Метод в документации API: [GET /files/getInfo](@teams.vk.com/botapi/#/files/get_files_getInfo)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDФайла - Строка, Число - ID Файла - fileid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьИнформациюОФайле(Знач Токен, Знач IDФайла) Экспорт
URL = "/files/getInfo";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("fileId", IDФайла , "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область ОтправкаСообщений
// Отправить текстовое сообщение
// Отправляет текстовое сообщение в чат
//
// Примечание:
// Можно упомянуть пользователя, добавив в текст его userId в следующем формате @[userId]
// Метод в документации API: [GET /messages/sendText](@teams.vk.com/botapi/#/messages/get_messages_sendText)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки сообщения - chatid
// Текст - Строка - Текст сообщения - text
// IDЦитируемого - Строка, Число - ID цитируемого сообщения, если необходимо - reply
// Клавиатура - Массив Из Строка - Кнопки к сообщению, если необходимо - keyboard
// Разметка - Строка - Вид разметки для текста сообщения: MarkdownV2 или HTML - parsemod
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОтправитьТекстовоеСообщение(Знач Токен
, Знач IDЧата
, Знач Текст
, Знач IDЦитируемого = 0
, Знач Клавиатура = ""
, Знач Разметка = "MarkdownV2") Экспорт
Строка_ = "Строка";
URL = "/messages/sendText";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("text" , Текст , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("replyMsgId" , IDЦитируемого, Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("inlineKeyboardMarkup", Клавиатура , "Коллекция", Параметры);
OPI_Инструменты.ДобавитьПоле("parseMode" , Разметка , Строка_ , Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Отправить файл
// Отправляет файл в чат
//
// Примечание:
// Метод в документации API: [POST /messages/sendFile](@teams.vk.com/botapi/#/messages/post_messages_sendFile)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки файла - chatid
// Файл - ДвоичныеДанные, Строка - Файл для отправки - file
// Текст - Строка - Подпись к файлу - text
// ИмяФайла - Строка - Отображаемое имя файла - filename
// Разметка - Строка - Вид разметки для текста сообщения: MarkdownV2 или HTML - parsemod
// ТипКонтента - Строка - Тип файла для отправки - type
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОтправитьФайл(Знач Токен
, Знач IDЧата
, Знач Файл
, Знач Текст = ""
, Знач ИмяФайла = ""
, Знач Разметка = "MarkdownV2"
, Знач ТипКонтента = "image/jpeg") Экспорт
Строка_ = "Строка";
URL = "/messages/sendFile";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("caption" , Текст , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("parseMode", Разметка, Строка_, Параметры);
Если ТипЗнч(Файл) = Тип(Строка_) Тогда
ФайлОбъект = Новый Файл(Файл);
ИспользуемоеИмя = ФайлОбъект.Имя;
Иначе
ИспользуемоеИмя = "file";
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
ИспользуемоеИмя = ?(ЗначениеЗаполнено(ИмяФайла), ИмяФайла, ИспользуемоеИмя);
Файлы = Новый Соответствие;
Файлы.Вставить("file|" + ИспользуемоеИмя, Файл);
Ответ = OPI_ЗапросыHTTP.PostMultipart(URL, Параметры, Файлы, ТипКонтента);
Возврат Ответ;
КонецФункции
// Отправить голосовое сообщение
// Отправляет аудиофайл в качестве голосового сообщения
//
// Примечание:
// Если вы хотите, чтобы клиент отображал этот файл как воспроизводимое голосовое сообщение, он должен быть в формате aac, ogg или m4a
// Метод в документации API: [POST /messages/sendVoice](@teams.vk.com/botapi/#/messages/post_messages_sendVoice)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки файла - chatid
// Файл - ДвоичныеДанные, Строка - Файл для отправки - file
// ТипФайла - Строка - Тип аудиофайла: aac, ogg или m4a - type
// IDЦитируемого - Строка, Число - ID цитируемого сообщения, если необходимо - reply
// Клавиатура - Массив Из Строка - Кнопки к сообщению, если необходимо - keyboard
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОтправитьГолосовоеСообщение(Знач Токен
, Знач IDЧата
, Знач Файл
, Знач ТипФайла = "m4a"
, Знач IDЦитируемого = 0
, Знач Клавиатура = "") Экспорт
URL = "/messages/sendVoice";
Параметры = НормализоватьОснову(URL, Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТипФайла);
СоответствиеMIME = Новый Соответствие;
СоответствиеMIME.Вставить("m4a", "audio/mp4");
СоответствиеMIME.Вставить("ogg", "audio/ogg");
СоответствиеMIME.Вставить("aac", "audio/aac");
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , "Строка" , Параметры);
OPI_Инструменты.ДобавитьПоле("inlineKeyboardMarkup", Клавиатура , "Коллекция", Параметры);
OPI_Инструменты.ДобавитьПоле("replyMsgId" , IDЦитируемого, "Строка" , Параметры);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
Файлы = Новый Соответствие;
Файлы.Вставить("file|voice", Файл);
Ответ = OPI_ЗапросыHTTP.PostMultipart(URL, Параметры, Файлы, СоответствиеMIME[ТипФайла]);
Возврат Ответ;
КонецФункции
// Изменить текст сообщения
// Изменяет текст сущесствующего сообщения
//
// Примечание:
// Можно упомянуть пользователя, добавив в текст его userId в следующем формате @[userId]
// Метод в документации API: [GET /messages/editText](@teams.vk.com/botapi/#/messages/get_messages_editText)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки сообщения - chatid
// IDСообщения - Строка, Число - ID сообщения для редактирования - messageid
// Текст - Строка - Новый текст сообщения - text
// Разметка - Строка - Вид разметки для текста сообщения: MarkdownV2 или HTML - parsemod
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ИзменитьТекстСообщения(Знач Токен
, Знач IDЧата
, Знач IDСообщения
, Знач Текст
, Знач Разметка = "MarkdownV2") Экспорт
Строка_ = "Строка";
URL = "/messages/editText";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("text" , Текст , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("msgId" , IDСообщения, Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("parseMode", Разметка , Строка_, Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Удалить сообщение
// Удаляет сообщение по ID
//
// Примечание:
// Метод в документации API: [GET /messages/deleteMessages](@teams.vk.com/botapi/#/messages/get_messages_deleteMessages)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки сообщения - chatid
// IDСообщения - Строка, Число - ID сообщения для редактирования - messageid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция УдалитьСообщение(Знач Токен, Знач IDЧата, Знач IDСообщения) Экспорт
URL = "/messages/deleteMessages";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("msgId" , IDСообщения, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Переслать файл
// Отправляет ранее загруженный файл по его ID
//
// Примечание:
// Метод в документации API: [GET /messages/sendFile](@teams.vk.com/botapi/#/messages/get_messages_sendFile)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки файла - chatid
// IDФайла - Строка, Число - ID Файла для отправки - fileid
// Текст - Строка - Подпись к файлу - text
// Разметка - Строка - Вид разметки для текста сообщения: MarkdownV2 или HTML - parsemod
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПереслатьФайл(Знач Токен
, Знач IDЧата
, Знач IDФайла
, Знач Текст = ""
, Знач Разметка = "MarkdownV2") Экспорт
Строка_ = "Строка";
URL = "/messages/sendFile";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("caption" , Текст , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("parseMode" , Разметка, Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("fileId" , IDФайла , Строка_, Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Переслать голосовое сообщение
// Отправляет ранее загруженное голосовое сообщение по ID
//
// Примечание:
// Метод в документации API: [GET /messages/sendVoice](@teams.vk.com/botapi/#/messages/get_messages_sendVoice)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата для отправки файла - chatid
// IDФайла - Строка, Число - ID Файла голосового сообщения - fileid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПереслатьГолосовоеСообщение(Знач Токен, Знач IDЧата, Знач IDФайла) Экспорт
URL = "/messages/sendVoice";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("fileId", IDФайла , "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Переслать сообщение
// Переслыает существующее сообщение в текущий диалог
//
// Примечание:
// В IDЧатаИсточника можно передавать только chatId из событий (код из ссылки на чат не подходит)
// Метод в документации API: [GET /messages/sendText](@teams.vk.com/botapi/#/messages/get_messages_sendText)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDСообщения - Строка, Число - ID оригинального сообщения - messageid
// IDЧатаИсточника - Строка, Число - ID чата источника оригинального сообщения - fromid
// IDЧата - Строка, Число - ID чата для отправки сообщения - chatid
// Текст - Строка - Дополнительный текст сообщения - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПереслатьСообщение(Знач Токен, Знач IDСообщения, Знач IDЧатаИсточника, Знач IDЧата, Знач Текст = "") Экспорт
Строка_ = "Строка";
URL = "/messages/sendText";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("text" , Текст , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("forwardChatId", IDЧатаИсточника, Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("forwardMsgId" , IDСообщения , Строка_, Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Закрепить сообщение
// Закрепляет выбранное сообщение в чате
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате
// Метод в документации API: [GET /chats/pinMessage](@teams.vk.com/botapi/#/chats/get_chats_pinMessage)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// IDСообщения - Строка, Число - ID сообщения для закрепления - messageid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ЗакрепитьСообщение(Знач Токен, Знач IDЧата, Знач IDСообщения) Экспорт
URL = "/chats/pinMessage";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("msgId" , IDСообщения, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Открепить сообщение
// Открепляет ранее закрепленное сообщение в чате
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате
// Метод в документации API: [GET /chats/unpinMessage](@teams.vk.com/botapi/#/chats/get_chats_unpinMessage)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// IDСообщения - Строка, Число - ID сообщения для открепления - messageid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОткрепитьСообщение(Знач Токен, Знач IDЧата, Знач IDСообщения) Экспорт
URL = "/chats/unpinMessage";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("msgId" , IDСообщения, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Ответить на событие клавиатуры
// Возвращает ответ пользователю при нажатии на кнопку клавиатуры
//
// Примечание:
// Вызов данного метода должен использоваться в ответ на получение события callbackQuery
// Метод в документации API: [GET /messages/answerCallbackQuery](@teams.vk.com/botapi/#/messages/get_messages_answerCallbackQuery)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDСобытия - Строка - Идентификатор callback query полученного ботом - queryid
// Текст - Строка - Текст ответа - text
// URL - Строка - URL, который будет открыт клиентским приложением - url
// ЭтоПредупреждение - Булево - Отображать ответ как предупреждение (alert) - showalert
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОтветитьНаСобытиеКлавиатуры(Знач Токен
, Знач IDСобытия
, Знач Текст = ""
, Знач URL = ""
, Знач ЭтоПредупреждение = Ложь) Экспорт
Строка_ = "Строка";
URLЗапроса = "/messages/answerCallbackQuery";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("queryId" , IDСобытия , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("text" , Текст , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("url" , URL , Строка_ , Параметры);
OPI_Инструменты.ДобавитьПоле("showAlert", ЭтоПредупреждение , "Булево", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URLЗапроса, Параметры);
Возврат Ответ;
КонецФункции
// Сформировать кнопку действия
// Формирует кнопку действия для клавиатуры сообщения
//
// Примечание:
// Используется при вызове функции `ОтправитьТекстовоеСообщение`
//
// Параметры:
// Текст - Строка - Текст кнопки - text
// Значение - Строка - Значение, возвращаемое в событии нажатия. Только если не заполнено URL - data
// URL - Строка - URL для создания кнопки открытия страницы. Только если не заполнено Значение - url
// Стиль - Строка - Стиль кнопки: primary, attention или base - style
//
// Возвращаемое значение:
// Структура - Кнопка для клавиатуры
Функция СформироватьКнопкуДействия(Знач Текст, Знач Значение = "", Знач URL = "", Знач Стиль = "base") Экспорт
Строка_ = "Строка";
СтруктураКнопки = Новый Структура;
OPI_Инструменты.ДобавитьПоле("text" , Текст , Строка_, СтруктураКнопки);
OPI_Инструменты.ДобавитьПоле("callbackData", Значение, Строка_, СтруктураКнопки);
OPI_Инструменты.ДобавитьПоле("url" , URL , Строка_, СтруктураКнопки);
OPI_Инструменты.ДобавитьПоле("style" , Стиль , Строка_, СтруктураКнопки);
Возврат СтруктураКнопки;
КонецФункции
#КонецОбласти
#Область УправлениеЧатами
// Исключить пользователей чата
// Исключает пользователей из чата
//
// Примечание:
// Метод в документации API: [GET /chats/members/delete](@teams.vk.com/botapi/#/chats/get_chats_members_delete)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// Пользователи - Строка, Число, Массив Из Строка, Число - Пользователь или пользователи чата для удаления - members
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ИсключитьПользователейЧата(Знач Токен, Знач IDЧата, Знач Пользователи) Экспорт
OPI_ПреобразованиеТипов.ПолучитьМассив(Пользователи);
URL = "/chats/members/delete";
Параметры = НормализоватьОснову(URL, Токен);
СтрокаПользователей = "";
Для Каждого ПользовательЧата Из Пользователи Цикл
ТекущийПользователь = OPI_Инструменты.ЧислоВСтроку(ПользовательЧата);
СтрокаПользователей = ?(ЗначениеЗаполнено(СтрокаПользователей), СтрокаПользователей + ",", "[");
СтрокаПользователей = СтрокаПользователей
+ "{""sn"":"""
+ ТекущийПользователь
+ """}";
КонецЦикла;
СтрокаПользователей = СтрокаПользователей + "]";
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("members", СтрокаПользователей, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Изменить аватар чата
// Изменяет картинку аватар чата
//
// Примечание:
// Метод в документации API: [POST ​/chats​/avatar​/set](@teams.vk.com/botapi/#/chats/post_chats_avatar_set)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// Файл - ДвоичныеДанные, Строка - Файл картинки - file
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ИзменитьАватарЧата(Знач Токен, Знач IDЧата, Знач Файл) Экспорт
URL = "/chats/avatar/set";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата, "Строка", Параметры);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
Файлы = Новый Соответствие;
Файлы.Вставить("image|image", Файл);
Ответ = OPI_ЗапросыHTTP.PostMultipart(URL, Параметры, Файлы, "image/xyz");
Возврат Ответ;
КонецФункции
// Получить информацию о чате
// Получает основную информацию о чате
//
// Примечание:
// Метод в документации API: [GET /chats/getInfo](@teams.vk.com/botapi/#/chats/get_chats_getInfo)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьИнформациюОЧате(Знач Токен, Знач IDЧата) Экспорт
Метод = "/chats/getInfo";
Ответ = ПолучитьДанныеЧата(Токен, IDЧата, Метод);
Возврат Ответ;
КонецФункции
// Получить администраторов чата
// Получает список администраторов чата
//
// Примечание:
// Метод в документации API: [GET /chats/getAdmins](@teams.vk.com/botapi/#/chats/get_chats_getAdmins)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьАдминистраторовЧата(Знач Токен, Знач IDЧата) Экспорт
Метод = "/chats/getAdmins";
Ответ = ПолучитьДанныеЧата(Токен, IDЧата, Метод);
Возврат Ответ;
КонецФункции
// Получить пользователей чата
// Получает список пользователей чата
//
// Примечание:
// Метод в документации API: [GET /chats/getMembers](@teams.vk.com/botapi/#/chats/get_chats_getMembers)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// Курсор - Строка - Маркер продолжения списка из предыдущего запроса - cursor
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьПользователейЧата(Знач Токен, Знач IDЧата, Знач Курсор = "") Экспорт
Метод = "/chats/getMembers";
Ответ = ПолучитьДанныеЧата(Токен, IDЧата, Метод, Курсор);
Возврат Ответ;
КонецФункции
// Получить заблокированных пользователей чата
// Получает список заблокированных пользователей чата
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​/chats​/getBlockedUsers](@teams.vk.com/botapi/#/chats/get_chats_getBlockedUsers)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьЗаблокированныхПользователейЧата(Знач Токен, Знач IDЧата) Экспорт
Метод = "/chats/getBlockedUsers";
Ответ = ПолучитьДанныеЧата(Токен, IDЧата, Метод);
Возврат Ответ;
КонецФункции
// Получить запросы вступления чата
// Получает список запросов на вступление в чат
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats​/getPendingUsers](@teams.vk.com/botapi/#/chats/get_chats_getPendingUsers)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ПолучитьЗапросыВступленияЧата(Знач Токен, Знач IDЧата) Экспорт
Метод = "/chats/getPendingUsers";
Ответ = ПолучитьДанныеЧата(Токен, IDЧата, Метод);
Возврат Ответ;
КонецФункции
// Заблокировать пользователя чата
// Блокирует выбранного пользователя в чате
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats​/blockUser](@teams.vk.com/botapi/#/chats/get_chats_blockUser)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// IDПользователя - Строка, Число - ID пользователя для блокировки - userid
// УдалитьПоследниеСообщения - Булево - Удалить последние сообщения перед блокировкой - dellast
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ЗаблокироватьПользователяЧата(Знач Токен
, Знач IDЧата
, Знач IDПользователя
, Знач УдалитьПоследниеСообщения = Ложь) Экспорт
URL = "/chats/blockUser";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("userId" , IDПользователя , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("delLastMessages", УдалитьПоследниеСообщения, "Булево", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Разблокировать пользователя чата
// Разблокирует ранее заблокированного пользователя в чате
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats/unblockUser](@teams.vk.com/botapi/#/chats/get_chats_unblockUser)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// IDПользователя - Строка, Число - ID пользователя - userid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция РазблокироватьПользователяЧата(Знач Токен, Знач IDЧата, Знач IDПользователя) Экспорт
URL = "/chats/unblockUser";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("userId", IDПользователя, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
// Одобрить заявку на вступление
// Подтверждает вступление пользователя в закрытый чат
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats/resolvePending](@teams.vk.com/botapi/#/chats/get_chats_resolvePending)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// IDПользователя - Строка, Число - ID пользователя. Ответ на все заявки, если не заполнено - userid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОдобритьЗаявкуНаВступление(Знач Токен, Знач IDЧата, Знач IDПользователя = "") Экспорт
Ответ = ОтветитьНаЗаявкуНаВступление(Токен, IDЧата, Истина, IDПользователя);
Возврат Ответ;
КонецФункции
// Отклонить заявку на вступление
// Отклоняет вступление пользователя в закрытый чат
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats/resolvePending](@teams.vk.com/botapi/#/chats/get_chats_resolvePending)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// IDПользователя - Строка, Число - ID пользователя. Ответ на все заявки, если не заполнено - userid
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция ОтклонитьЗаявкуНаВступление(Знач Токен, Знач IDЧата, Знач IDПользователя = "") Экспорт
Ответ = ОтветитьНаЗаявкуНаВступление(Токен, IDЧата, Ложь, IDПользователя);
Возврат Ответ;
КонецФункции
// Установить заголовок чата
// Устанавливает новый заголовок чата
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats/setTitle](@teams.vk.com/botapi/#/chats/get_chats_setTitle)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// Текст - Строка - Текст заголовка - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция УстановитьЗаголовокЧата(Знач Токен, Знач IDЧата, Знач Текст) Экспорт
Ответ = ИзменитьПараметрыЧата(Токен, IDЧата, "title", Текст);
Возврат Ответ;
КонецФункции
// Установить описание чата
// Устанавливает новое описание чата
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET ​​/chats/setAbout](@teams.vk.com/botapi/#/chats/get_chats_setAbout)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// Текст - Строка - Текст описания - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция УстановитьОписаниеЧата(Знач Токен, Знач IDЧата, Знач Текст) Экспорт
Ответ = ИзменитьПараметрыЧата(Токен, IDЧата, "about", Текст);
Возврат Ответ;
КонецФункции
// Установить правила чата
// Устанавливает новые правила чата
//
// Примечание:
// Для вызова этого метода бот должен быть администратором в чате.
// Метод в документации API: [GET /chats/setRules](@teams.vk.com/botapi/#/chats/get_chats_setRules)
//
// Параметры:
// Токен - Строка - Токен бота - token
// IDЧата - Строка, Число - ID чата - chatid
// Текст - Строка - Текст правил - text
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от VK Teams
Функция УстановитьПравилаЧата(Знач Токен, Знач IDЧата, Знач Текст) Экспорт
Ответ = ИзменитьПараметрыЧата(Токен, IDЧата, "rules", Текст);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция НормализоватьОснову(URL, Знач Токен)
URL = "https://myteam.mail.ru/bot/v1" + URL;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("token", Токен, "Строка", Параметры);
Возврат Параметры;
КонецФункции
Функция ПолучитьДанныеЧата(Знач Токен, Знач IDЧата, Знач Метод, Знач Курсор = "")
URL = Метод;
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("cursor", Курсор, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
Функция ОтветитьНаЗаявкуНаВступление(Знач Токен, Знач IDЧата, Знач Ответ, Знач IDПользователя = "")
URL = "/chats/resolvePending";
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId" , IDЧата, "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("approve", Ответ , "Булево", Параметры);
Если ЗначениеЗаполнено(IDПользователя) Тогда
OPI_Инструменты.ДобавитьПоле("userId" , IDПользователя, "Строка", Параметры);
Иначе
OPI_Инструменты.ДобавитьПоле("everyone", Истина , "Булево", Параметры);
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
Функция ИзменитьПараметрыЧата(Знач Токен, Знач IDЧата, Знач Параметр, Знач Значение)
URL = "/chats/set" + ТРег(Параметр);
Параметры = НормализоватьОснову(URL, Токен);
OPI_Инструменты.ДобавитьПоле("chatId", IDЧата , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле(Параметр, Значение, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры);
Возврат Ответ;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="ece78a60-71c0-4443-a6e4-63dd8a7b10d0">
<Properties>
<Name>OPI_Viber</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Viber (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Viber из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,405 @@
// OneScript: ./OInt/core/Modules/OPI_Viber.os
// Lib: Viber
// CLI: viber
// Keywords: viber
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область НастройкиИИнформация
// Установить Webhook
// ВАЖНО: Установка Webhook обязательна по правилам Viber. Для этого надо иметь свободный URL,
// который будет возвращать 200 и подлинный SSL сертификат. Если есть сертификат и база опубликована
// на сервере - можно использовать http-сервис. Туда же будет приходить и информация о новых сообщениях
// Viber периодически стучит по адресу Webhook, так что если он будет неактивен, то все перестанет работать
//
// Параметры:
// Токен - Строка - Токен Viber - token
// URL - Строка - URL для установки Webhook - url
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция УстановитьWebhook(Знач Токен, Знач URL) Экспорт
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("url" , URL , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("auth_token" , Токен, "Строка", Параметры);
Возврат OPI_ЗапросыHTTP.PostСТелом("https://chatapi.viber.com/pa/set_webhook", Параметры);
КонецФункции
// Получить информацию о канале
// Тут можно получить ID пользователей канала. ID для бота необходимо получать из прилетов на Webhook
// ID пользователя из информации о канале не подойдет для отправки сообщений через бота - они разные
//
// Параметры:
// Токен - Строка - Токен - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ПолучитьИнформациюОКанале(Знач Токен) Экспорт
URL = "https://chatapi.viber.com/pa/get_account_info";
Возврат OPI_ЗапросыHTTP.Get(URL, , ТокенВЗаголовки(Токен));
КонецФункции
// Получить данные пользователя
// Получает информацию о пользователе по ID
//
// Параметры:
// Токен - Строка - Токен - token
// IDПользователя - Строка, Число - ID пользователя Viber - user
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ПолучитьДанныеПользователя(Знач Токен, Знач IDПользователя) Экспорт
URL = "https://chatapi.viber.com/pa/get_user_details";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("id", IDПользователя, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ТокенВЗаголовки(Токен));
Возврат Ответ;
КонецФункции
// Получить онлайн пользователей
// Получает статус пользователя или нескольких пользователей по ID
//
// Параметры:
// Токен - Строка - Токен Viber - token
// IDПользователей - Строка,Число,Массив из Строка,Число - ID пользователей(я) Viber - users
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ПолучитьОнлайнПользователей(Знач Токен, Знач IDПользователей) Экспорт
URL = "https://chatapi.viber.com/pa/get_online";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("ids", IDПользователей, "Коллекция", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, ТокенВЗаголовки(Токен));
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область ОтправкаСообщений
// Отправить текстовое сообщение
// Отправляет текстовое сообщение в чат или канал
//
// Параметры:
// Токен - Строка - Токен - token
// Текст - Строка - Текст сообщения - text
// IDПользователя - Строка,Число - ID пользователя. Для канала > администратора, для бота > получателя - user
// ОтправкаВКанал - Булево - Отправка в канал или в чат бота - ischannel
// Клавиатура - Структура из Строка - См. СформироватьКлавиатуруИзМассиваКнопок - keyboard
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ОтправитьТекстовоеСообщение(Знач Токен
, Знач Текст
, Знач IDПользователя
, Знач ОтправкаВКанал
, Знач Клавиатура = "") Экспорт
Возврат ОтправитьСообщение(Токен, "text", IDПользователя, ОтправкаВКанал, , Текст, Клавиатура);
КонецФункции
// Отправить картинку
// Отправляет картинку в чат или канал
//
// Параметры:
// Токен - Строка - Токен - token
// URL - Строка - URL картинки - picture
// IDПользователя - Строка,Число - ID пользователя. Для канала > администратора, для бота > получателя - user
// ОтправкаВКанал - булево - Отправка в канал или в чат бота - ischannel
// Описание - Строка - Аннотация к картинке - description
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ОтправитьКартинку(Знач Токен, Знач URL, Знач IDПользователя, Знач ОтправкаВКанал, Знач Описание = "") Экспорт
Возврат ОтправитьСообщение(Токен, "picture", IDПользователя, ОтправкаВКанал, URL, Описание);
КонецФункции
// Отправить файл
// Отправляет файл (документ) в чат или канал
//
// Параметры:
// Токен - Строка - Токен - token
// URL - Строка - URL файла - file
// IDПользователя - Строка,Число - ID пользователя. Для канала > администратора, для бота > получателя - user
// ОтправкаВКанал - Булево - Отправка в канал или в чат бота - ischannel
// Расширение - Строка - Расширение файла - ext
// Размер - Число - Размер файла. Если не заполнен > определяется автоматически скачиванием файла - size
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ОтправитьФайл(Знач Токен
, Знач URL
, Знач IDПользователя
, Знач ОтправкаВКанал
, Знач Расширение
, Знач Размер = "") Экспорт
Если Не ЗначениеЗаполнено(Размер) Тогда
Ответ = OPI_ЗапросыHTTP.Get(URL);
Размер = Ответ.Размер();
КонецЕсли;
Строка_ = "Строка";
Расширение = СтрЗаменить(Расширение, ".", "");
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("URL" , URL , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("Размер" , Размер , Строка_, Параметры);
OPI_Инструменты.ДобавитьПоле("Расширение", Расширение, Строка_, Параметры);
Возврат ОтправитьСообщение(Токен, "file", IDПользователя, ОтправкаВКанал, Параметры);
КонецФункции
// Отправить контакт
// Отправляет контакт с номером телефона в чат или канал
//
// Параметры:
// Токен - Строка - Токен - token
// ИмяКонтакта - Строка - Имя контакта - name
// НомерТелефона - Строка - Номер телефона - phone
// IDПользователя - Строка,Число - ID пользователя. Для канала > администратора, для бота > получателя - user
// ОтправкаВКанал - Булево - Отправка в канал или в чат бота - ischannel
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ОтправитьКонтакт(Знач Токен
, Знач ИмяКонтакта
, Знач НомерТелефона
, Знач IDПользователя
, Знач ОтправкаВКанал) Экспорт
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("name" , ИмяКонтакта , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("phone_number", НомерТелефона, "Строка", Параметры);
Возврат ОтправитьСообщение(Токен, "contact", IDПользователя, ОтправкаВКанал, Параметры);
КонецФункции
// Отправить локацию
// Отправляет географические координаты в чат или канал
//
// Параметры:
// Токен - Строка - Токен - token
// Широта - Строка,Число - Географическая широта - lat
// Долгота - Строка,Число - Географическая долгота - long
// IDПользователя - Строка,Число - ID пользователя. Для канала > администратора, для бота > получателя - user
// ОтправкаВКанал - Булево - Отправка в канал или в чат бота - ischannel
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ОтправитьЛокацию(Знач Токен, Знач Широта, Знач Долгота, Знач IDПользователя, Знач ОтправкаВКанал) Экспорт
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("lat", Широта , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("lon", Долгота, "Строка", Параметры);
Возврат ОтправитьСообщение(Токен, "location", IDПользователя, ОтправкаВКанал, Параметры);
КонецФункции
// Отправить ссылку
// Отправляет URL с предпросмотром в чат или канал
//
// Параметры:
// Токен - Строка - Токен - token
// URL - Строка - Отправляемая ссылка - url
// IDПользователя - Строка,Число - ID пользователя. Для канала > администратора, для бота > получателя - user
// ОтправкаВКанал - Булево - Отправка в канал или в чат бота - ischannel
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Viber
Функция ОтправитьСсылку(Знач Токен, Знач URL, Знач IDПользователя, Знач ОтправкаВКанал) Экспорт
Возврат ОтправитьСообщение(Токен, "url", IDПользователя, ОтправкаВКанал, URL);
КонецФункции
// Сформировать клавиатуру из массива кнопок
// Возвращает структура клавиатуры для сообщений
//
// Параметры:
// МассивКнопок - Массив из Строка - Массив кнопок - buttons
// ЦветКнопок - Строка - HEX цвет кнопок с # в начале - color
//
// Возвращаемое значение:
// Структура - Сформировать клавиатуру из массива кнопок:
// * Buttons - Массив из Структура - Массив сформированных кнопок
// * Type - Строка - Тип клавиатуры
Функция СформироватьКлавиатуруИзМассиваКнопок(Знач МассивКнопок, Знач ЦветКнопок = "#2db9b9") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ЦветКнопок);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивКнопок);
МассивСтруктурКнопок = Новый Массив;
СтруктураКлавиатуры = Новый Структура;
Для Каждого ТекстКнопки Из МассивКнопок Цикл
СтруктураКнопки = Новый Структура;
СтруктураКнопки.Вставить("ActionType", "reply");
СтруктураКнопки.Вставить("ActionBody", ТекстКнопки);
СтруктураКнопки.Вставить("Text" , ТекстКнопки);
СтруктураКнопки.Вставить("BgColor" , ЦветКнопок);
СтруктураКнопки.Вставить("Coloumns" , 3);
МассивСтруктурКнопок.Добавить(СтруктураКнопки);
КонецЦикла;
СтруктураКлавиатуры.Вставить("Buttons", МассивСтруктурКнопок);
СтруктураКлавиатуры.Вставить("Type" , "keyboard");
Возврат СтруктураКлавиатуры;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ОтправитьСообщение(Знач Токен
, Знач Тип
, Знач IDПользователя
, Знач ЭтоКанал
, Знач Значение = ""
, Знач Текст = ""
, Знач Клавиатура = "")
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Тип);
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПользователя);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Текст);
OPI_ПреобразованиеТипов.ПолучитьБулево(ЭтоКанал);
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Клавиатура);
СтруктураПараметров = ВернутьСтандартныеПараметры();
СтруктураПараметров.Вставить("type", Тип);
Если (Тип = "text" Или Тип = "picture") И ЗначениеЗаполнено(Текст) Тогда
СтруктураПараметров.Вставить("text", Текст);
КонецЕсли;
Если ТипЗнч(Клавиатура) = Тип("Структура") Тогда
СтруктураПараметров.Вставить("keyboard", Клавиатура);
КонецЕсли;
Если ЗначениеЗаполнено(Значение) Тогда
Если Тип = "file" Тогда
СтруктураПараметров.Вставить("media" , Значение.URL);
СтруктураПараметров.Вставить("size" , Значение.Размер);
СтруктураПараметров.Вставить("file_name", "Файл." + Значение.Расширение);
ИначеЕсли Тип = "contact" Тогда
СтруктураПараметров.Вставить("contact" , Значение);
ИначеЕсли Тип = "location" Тогда
СтруктураПараметров.Вставить("location" , Значение);
Иначе
СтруктураПараметров.Вставить("media" , Значение);
КонецЕсли;
КонецЕсли;
Если ЭтоКанал Тогда
СтруктураПараметров.Вставить("from" , IDПользователя);
URL = "https://chatapi.viber.com/pa/post";
Иначе
СтруктураПараметров.Вставить("receiver", IDПользователя);
URL = "https://chatapi.viber.com/pa/send_message";
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, СтруктураПараметров, ТокенВЗаголовки(Токен));
Попытка
Возврат OPI_Инструменты.JsonВСтруктуру(Ответ.ПолучитьТелоКакДвоичныеДанные());
Исключение
Возврат Ответ;
КонецПопытки;
КонецФункции
Функция ВернутьСтандартныеПараметры()
СтруктураОтправителя = Новый Структура;
СтруктураОтправителя.Вставить("name" , "Bot");
СтруктураОтправителя.Вставить("avatar", "");
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("sender" , СтруктураОтправителя);
СтруктураПараметров.Вставить("min_api_version", 1);
Возврат СтруктураПараметров;
КонецФункции
Функция ТокенВЗаголовки(Знач Токен)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
СтруктураЗаголовков = Новый Соответствие;
СтруктураЗаголовков.Вставить("X-Viber-Auth-Token", Токен);
Возврат СтруктураЗаголовков;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="af0b34e8-10fa-414f-a643-915210c6289a">
<Properties>
<Name>OPI_YandexDisk</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Yandex.Disk (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Yandex.Disk из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,608 @@
// OneScript: ./OInt/core/Modules/OPI_YandexDisk.os
// Lib: Yandex Disk
// CLI: yadisk
// Keywords: yandexdisk, yandex.disk, yandex disk, yandex drive, yadisk, ya disk
// Depends: OPI_YandexID
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check method-too-many-params
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
#Область РаботаСФайламиИПапками
// Получить информацию о диске
// Получает информацию о текущем диске
//
// Параметры:
// Токен - Строка - Токен - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьИнформациюОДиске(Знач Токен) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk", , Заголовки);
Возврат Ответ;
КонецФункции
// Создать папку
// Создает каталог на диске
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к созаваемой папке - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция СоздатьПапку(Знач Токен, Знач Путь) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://cloud-api.yandex.net/v1/disk/resources";
Href = "href";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь, "Строка", Параметры);
Параметры = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры);
Ответ = OPI_ЗапросыHTTP.PutСТелом(URL + Параметры, , Заголовки, Ложь);
URLОтвета = Ответ[Href];
Если Не ЗначениеЗаполнено(URLОтвета) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URLОтвета, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить объект
// Получает информацию об объекте диска по заданному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к папке или файлу - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьОбъект(Знач Токен, Знач Путь) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/resources", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Удалить объект
// Удаляет объект по заданному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к удаляемой папке или файлу - path
// ВКорзину - Булево - В корзину - can
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция УдалитьОбъект(Знач Токен, Знач Путь, Знач ВКорзину = Истина) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(ВКорзину);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path" , Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("permanently", Не ВКорзину, "Булево", Параметры);
Ответ = OPI_ЗапросыHTTP.Delete("https://cloud-api.yandex.net/v1/disk/resources", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Создать копию объекта
// Создает копию объекта по заданному пути и пути к оригиналу
//
// Параметры:
// Токен - Строка - Токен - token
// Оригинал - Строка - Путь к оригинальному файлу или каталогу - from
// Путь - Строка - Путь назначения для копии - to
// Перезаписывать - Булево - Перезаписывать если файл с таким именем уже существует - rewrite
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция СоздатьКопиюОбъекта(Знач Токен, Знач Оригинал, Знач Путь, Знач Перезаписывать = Ложь) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://cloud-api.yandex.net/v1/disk/resources/copy";
Href = "href";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("from" , Оригинал , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("path" , Путь , "Строка", Параметры);
OPI_Инструменты.ДобавитьПоле("overwrite", Перезаписывать, "Булево", Параметры);
Параметры = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL + Параметры, , Заголовки, Ложь);
URLОтвета = Ответ[Href];
Если Не ЗначениеЗаполнено(URLОтвета) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URLОтвета, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить ссылку для скачивания
// Получает ссылку для скачивания файла
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к файлу для скачивания - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСсылкуДляСкачивания(Знач Токен, Знач Путь) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("path", Путь, "Строка", Параметры);
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/resources/download", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Скачать файл
// Скачивает файл по указанному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к файлу для скачивания - path
// ПутьСохранения - Строка - Путь сохранения файла - out
//
// Возвращаемое значение:
// ДвоичныеДанные,Строка - Двоичные данные или путь к файлу при указании параметра ПутьСохранения
Функция СкачатьФайл(Знач Токен, Знач Путь, Знач ПутьСохранения = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(ПутьСохранения);
Ответ = ПолучитьСсылкуДляСкачивания(Токен, Путь);
URL = Ответ["href"];
Если Не ЗначениеЗаполнено(URL) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URL, , , ПутьСохранения);
Возврат Ответ;
КонецФункции
// Получить список файлов
// Получает список файлов с или без отбора по типу
// Список доступных типов: audio, backup, book, compressed, data, development,
// diskimage, document, encoded, executable, flash, font,
// mage, settings, spreadsheet, text, unknown, video, web
//
// Параметры:
// Токен - Строка - Токен - token
// Количество - Число,Строка - Количество возвращаемых объектов - amount
// СмещениеОтНачала - Число - Смещение для получение объектов не из начала списка - offset
// ОтборПоТипу - Строка - Отбор по типу файла - type
// СортироватьПоДате - Булево - Истина > сортировать по дате, Ложь > по алфавиту - datesort
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСписокФайлов(Знач Токен
, Знач Количество = 0
, Знач СмещениеОтНачала = 0
, Знач ОтборПоТипу = ""
, Знач СортироватьПоДате = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Количество);
OPI_ПреобразованиеТипов.ПолучитьСтроку(СмещениеОтНачала);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ОтборПоТипу);
OPI_ПреобразованиеТипов.ПолучитьБулево(СортироватьПоДате);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Количество) Тогда
Параметры.Вставить("limit", OPI_Инструменты.ЧислоВСтроку(Количество));
КонецЕсли;
Если ЗначениеЗаполнено(СмещениеОтНачала) Тогда
Параметры.Вставить("offset", OPI_Инструменты.ЧислоВСтроку(СмещениеОтНачала));
КонецЕсли;
Если ЗначениеЗаполнено(ОтборПоТипу) Тогда
Параметры.Вставить("media_type", ОтборПоТипу);
КонецЕсли;
Если СортироватьПоДате Тогда
Назначение = "last-uploaded";
Иначе
Назначение = "files";
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/resources/" + Назначение, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Переместить объект
// Перемещает объект по заданному пути и пути к оригиналу
//
// Параметры:
// Токен - Строка - Токен - token
// Оригинал - Строка - Путь к оригинальному файлу или папке - from
// Путь - Строка - Путь назначение для перемещения - to
// Перезаписывать - Булево - Перезаписывать если файл с таким именем уже существует - rewrite
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПереместитьОбъект(Знач Токен, Знач Оригинал, Знач Путь, Знач Перезаписывать = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Оригинал);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьБулево(Перезаписывать);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://cloud-api.yandex.net/v1/disk/resources/move";
Href = "href";
Параметры = Новый Структура;
Параметры.Вставить("from" , Оригинал);
Параметры.Вставить("path" , Путь);
Параметры.Вставить("overwrite" , Перезаписывать);
Параметры = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL + Параметры, , Заголовки, Ложь);
URLОтвета = Ответ[Href];
Если Не ЗначениеЗаполнено(URLОтвета) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URLОтвета, , Заголовки);
Возврат Ответ;
КонецФункции
// Загрузить файл
// Загружает файл на диск по заданному пути
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь для сохранение файла на Диске - path
// Файл - Строка,ДвоичныеДанные - Файл для загрузки - file
// Перезаписывать - Булево - Перезаписывать, если файл с таким именем уже существует - rewrite
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ЗагрузитьФайл(Знач Токен, Знач Путь, Знач Файл, Знач Перезаписывать = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьБулево(Перезаписывать);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Href = "href";
Файл = Новый Структура("file", Файл);
Параметры = Новый Структура;
Параметры.Вставить("path" , Путь);
Параметры.Вставить("overwrite" , Перезаписывать);
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/resources/upload", Параметры, Заголовки);
URL = Ответ[Href];
Если Не ЗначениеЗаполнено(URL) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.PutMultipart(URL, Новый Структура(), Файл, "multipart", Заголовки);
Возврат Ответ;
КонецФункции
// Загрузить файл по URL
// Загружает файл на диск, забирая его по заданному URL
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь помещения загруженного файла - path
// Адрес - Строка - URL файла - url
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ЗагрузитьФайлПоURL(Знач Токен, Знач Путь, Знач Адрес) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Адрес);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://cloud-api.yandex.net/v1/disk/resources/upload";
Параметры = Новый Структура;
Параметры.Вставить("url" , КодироватьСтроку(Адрес, СпособКодированияСтроки.КодировкаURL));
Параметры.Вставить("path", Путь);
Параметры = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL + Параметры, , Заголовки, Ложь);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область УправлениеПубличнымДоступом
// Опубликовать объект
// Публикует объект диска в публичный доступ
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к публикуемому объекту - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ОпубликоватьОбъект(Знач Токен, Знач Путь) Экспорт
Возврат ПереключениеОбщегоДоступа(Токен, Путь, Истина);
КонецФункции
// Отменить публикацию объекта
// Отменяет публикацию ранее опубликованного объекта
//
// Параметры:
// Токен - Строка - Токен - token
// Путь - Строка - Путь к опубликованному ранее объекту - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ОтменитьПубликациюОбъекта(Знач Токен, Знач Путь) Экспорт
Возврат ПереключениеОбщегоДоступа(Токен, Путь, Ложь);
КонецФункции
// Получить список опубликованных объектов.
// Получает список опубликованных объектов
//
// Параметры:
// Токен - Строка - Токен - token
// Количество - Число - Количество возвращаемых объектов - amount
// СмещениеОтНачала - Число - Смещение для получение объектов не из начала списка - offset
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСписокОпубликованныхОбъектов(Знач Токен, Знач Количество = 0, Знач СмещениеОтНачала = 0) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Количество);
OPI_ПреобразованиеТипов.ПолучитьСтроку(СмещениеОтНачала);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Количество) Тогда
Параметры.Вставить("limit", Количество);
КонецЕсли;
Если ЗначениеЗаполнено(СмещениеОтНачала) Тогда
Параметры.Вставить("offset", СмещениеОтНачала);
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/resources/public", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить публичный объект
// Получает информацию об опубликованном объекте по его URL
//
// Параметры:
// Токен - Строка - Токен - token
// URL - Строка - Адрес объекта - url
// Количество - Число - Количество возвращаемых вложенных объектов (для каталога) - amount
// СмещениеОтНачала - Число - Смещение для получение вложенных объектов не из начала списка - offset
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьПубличныйОбъект(Знач Токен, Знач URL, Знач Количество = 0, Знач СмещениеОтНачала = 0) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Количество);
OPI_ПреобразованиеТипов.ПолучитьСтроку(СмещениеОтНачала);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Количество) Тогда
Параметры.Вставить("limit", OPI_Инструменты.ЧислоВСтроку(Количество));
КонецЕсли;
Если ЗначениеЗаполнено(СмещениеОтНачала) Тогда
Параметры.Вставить("offset", OPI_Инструменты.ЧислоВСтроку(СмещениеОтНачала));
КонецЕсли;
Параметры.Вставить("public_key", URL);
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/public/resources", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить ссылку скачивания публичного объекта
// Получает прямую ссылку для скачивания публичного объекта
//
// Параметры:
// Токен - Строка - Токен - token
// URL - Строка - Адрес объекта - url
// Путь - Строка - Путь внутри объекта - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСсылкуСкачиванияПубличногоОбъекта(Знач Токен, Знач URL, Знач Путь = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Параметры = Новый Структура;
Если ЗначениеЗаполнено(Путь) Тогда
Параметры.Вставить("path", Путь);
КонецЕсли;
Параметры.Вставить("public_key", URL);
Ответ = OPI_ЗапросыHTTP.Get("https://cloud-api.yandex.net/v1/disk/public/resources/download", Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Сохранить публичный объект на диск
// Сохраняет публичный объект на ваш диск
//
// Параметры:
// Токен - Строка - Токен - token
// URL - Строка - Адрес объекта - url
// Откуда - Строка - Путь внутри публичного каталога (только для папок) - from
// Куда - Строка - Путь сохранения файла - to
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция СохранитьПубличныйОбъектНаДиск(Знач Токен, Знач URL, Откуда = "", Куда = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(URL);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Откуда);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Куда);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Адрес = "https://cloud-api.yandex.net/v1/disk/public/resources/save-to-disk";
Href = "href";
Параметры = Новый Структура;
Параметры.Вставить("public_key", КодироватьСтроку(URL, СпособКодированияСтроки.КодировкаURL));
Если ЗначениеЗаполнено(Откуда) Тогда
Параметры.Вставить("path", Откуда);
КонецЕсли;
Если ЗначениеЗаполнено(Куда) Тогда
Параметры.Вставить("save_path", Куда);
КонецЕсли;
Параметры = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(Адрес + Параметры, , Заголовки, Ложь);
URLОтвета = Ответ[Href];
Если Не ЗначениеЗаполнено(URLОтвета) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URLОтвета, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ПереключениеОбщегоДоступа(Знач Токен, Знач Путь, Знач ОбщийДоступ)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьБулево(ОбщийДоступ);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
Назначение = ?(ОбщийДоступ, "publish", "unpublish");
Href = "href";
URL = "https://cloud-api.yandex.net/v1/disk/resources/" + Назначение;
Параметры = Новый Структура;
Параметры.Вставить("path", Путь);
Параметры = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры);
Ответ = OPI_ЗапросыHTTP.PutСТелом(URL + Параметры, , Заголовки, Ложь);
URLОтвета = Ответ[Href];
Если Не ЗначениеЗаполнено(URLОтвета) Тогда
Возврат Ответ;
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URLОтвета, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="32379ca2-0f58-4143-9b34-cb552c54b962">
<Properties>
<Name>OPI_YandexID</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>YandexID (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с YandexID из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,130 @@
// OneScript: ./OInt/core/Modules/OPI_YandexID.os
// Lib: Yandex ID
// CLI: yandex
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область ПрограммныйИнтерфейс
// Получить код подтверждения
// Получает код подтверждения и адрес страницы, на которой его необходимо ввести
//
// Параметры:
// ClientId - Строка - Client id - id
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьКодПодтверждения(Знач ClientId) Экспорт // Service
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientId);
Параметры = Новый Структура("client_id", ClientId);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://oauth.yandex.ru/device/code", Параметры, , Ложь);
Возврат Ответ;
КонецФункции
// Преобразовать код в токен
// Преобразовывает код в токен после ввода кода при выполнении ПолучитьКодПодтверждения
//
// Параметры:
// ClientId - Строка - Client id - id
// ClientSecret - Строка - Client secret - secret
// КодУстройства - Строка - device_code из ПолучитьКодПодтверждения() - device
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПреобразоватьКодВТокен(Знач ClientId, Знач ClientSecret, Знач КодУстройства) Экспорт // Service
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientId);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientSecret);
OPI_ПреобразованиеТипов.ПолучитьСтроку(КодУстройства);
Параметры = Новый Структура;
Параметры.Вставить("grant_type" , "device_code");
Параметры.Вставить("code" , КодУстройства);
Параметры.Вставить("client_id" , ClientId);
Параметры.Вставить("client_secret" , ClientSecret);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://oauth.yandex.ru/token", Параметры, , Ложь);
Возврат Ответ;
КонецФункции
// Обновить токен
// Обновляет токен по Refresh token
//
// Параметры:
// ClientId - Строка - Client id - id
// ClientSecret - Строка - Client secret - secret
// RefreshToken - Строка - Refresh token - refresh
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ОбновитьТокен(Знач ClientId, Знач ClientSecret, Знач RefreshToken) Экспорт // Service
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientId);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ClientSecret);
OPI_ПреобразованиеТипов.ПолучитьСтроку(RefreshToken);
Параметры = Новый Структура;
Параметры.Вставить("grant_type" , "refresh_token");
Параметры.Вставить("refresh_token" , RefreshToken);
Параметры.Вставить("client_id" , ClientId);
Параметры.Вставить("client_secret" , ClientSecret);
Ответ = OPI_ЗапросыHTTP.PostСТелом("https://oauth.yandex.ru/token", Параметры, , Ложь);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьЗаголовокАвторизации(Знач Токен) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "OAuth " + Токен);
Возврат Заголовки;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="7c183b97-38f5-4fe6-a19f-c5af2ab85875">
<Properties>
<Name>OPI_YandexMarket</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Yandex Market (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Yandex Market из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,428 @@
// OneScript: ./OInt/core/Modules/OPI_YandexMarket.os
// Lib: Yandex Market
// CLI: yamarket
// Depends: OPI_YandexID
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область КабинетыИМагазины
// Получить список магазинов
// Получает список магазинов в кабинете по токену
//
// Примечание:
// Метод в документации API: [Список магазинов пользователя](@yandex.ru/dev/market/partner-api/doc/ru/reference/campaigns/getCampaigns)
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// Страница - Число - Номер страницы выдачи списка - page
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ПолучитьСписокМагазинов(Знач Токен, Знач Страница = 1) Экспорт
URL = "https://api.partner.market.yandex.ru/campaigns";
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
РазмерСтраницы = 100;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("page" , Страница , "Число", Параметры);
OPI_Инструменты.ДобавитьПоле("pageSize", РазмерСтраницы, "Число", Параметры);
Ответ = OPI_ЗапросыHTTP.Get(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить магазин
// Получает информацию о магазине (кампании) по ID
//
// Примечание:
// Метод в документации API: [Информация о магазине](@yandex.ru/dev/market/partner-api/doc/ru/reference/campaigns/getCampaign)
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// IDМагазина - Строка, Число - ID магазина (кампании) - campaign
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ПолучитьМагазин(Знач Токен, Знач IDМагазина) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDМагазина);
URL = "https://api.partner.market.yandex.ru/campaigns/" + IDМагазина;
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить настройки кабинета
// Получает значения настроек кабинета по ID
//
// Примечание:
// Метод в документации API: [Настройки кабинета](@yandex.ru/dev/market/partner-api/doc/ru/reference/businesses/getBusinessSettings)
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// IDКабинета - Строка, Число - ID кабинета - business
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ПолучитьНастройкиКабинета(Знач Токен, Знач IDКабинета) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDКабинета);
URL = "https://api.partner.market.yandex.ru/businesses/%1/settings";
URL = СтрШаблон(URL, IDКабинета);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить настройки магазина
// Получает настройки магазина по ID
//
// Примечание:
// Метод в документации API: [Настройки магазина](@yandex.ru/dev/market/partner-api/doc/ru/reference/campaigns/getCampaignSettings)
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// IDМагазина - Строка, Число - ID магазина (кампании) - campaign
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ПолучитьНастройкиМагазина(Знач Токен, Знач IDМагазина) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDМагазина);
URL = "https://api.partner.market.yandex.ru/campaigns/%1/settings";
URL = СтрШаблон(URL, IDМагазина);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область РаботаСТоварами
// Добавить обновить товары
// Добавляет или обновляет информацию о товарах в каталоге
//
// Примечание:
// Метод в документации API: [Добавление товаров в каталог и изменение информации о них](@yandex.ru/dev/market/partner-api/doc/ru/reference/business-assortment/updateOfferMappings)
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// IDКабинета - Строка, Число - ID кабинета - business
// МассивТоваров - Структура, Массив Из Структура - Массив описаний товаров - offers
// СвоиИзображения - Булево - Признак использования только своих изображений товаров - pmedia
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ДобавитьОбновитьТовары(Знач Токен, Знач IDКабинета, Знач МассивТоваров, Знач СвоиИзображения = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDКабинета);
URL = "https://api.partner.market.yandex.ru/businesses/%1/offer-mappings/update";
URL = СтрШаблон(URL, IDКабинета);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("offerMappings" , МассивТоваров , "Массив", Параметры);
OPI_Инструменты.ДобавитьПоле("onlyPartnerMediaContent", СвоиИзображения, "Булево", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить товары магазина
// Получает список товаров выбранного магазина
//
// Примечание:
// Метод в документации API: [Информация о товарах, которые размещены в заданном магазине](@https://yandex.ru/dev/market/partner-api/doc/ru/reference/assortment/getCampaignOffers)
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// IDМагазина - Строка, Число - ID магазина - business
// Фильтры - Структура Из КлючИЗначение - Фильтры для отбора товаров - filters
// ТокенСтраницы - Строка - Токен следующей страницы при большой выборке - page
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ПолучитьТоварыМагазина(Знач Токен, Знач IDМагазина, Знач Фильтры = "", Знач ТокенСтраницы = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDМагазина);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТокенСтраницы);
URL = "https://api.partner.market.yandex.ru/campaigns/%1/offers";
URL = СтрШаблон(URL, IDМагазина);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Если ЗначениеЗаполнено(ТокенСтраницы) Тогда
URL = URL + "?page_token=" + ТокенСтраницы;
КонецЕсли;
Если ЗначениеЗаполнено(Фильтры) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Фильтры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Фильтры, Заголовки);
Иначе
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, , Заголовки);
КонецЕсли;
Возврат Ответ;
КонецФункции
// Получить товары кабинета
// Получает список товаров выбранного кабинета
//
// Параметры:
// Токен - Строка - Токен авторизации (Api-Key) - token
// IDКабинета - Строка, Число - ID кабинета - business
// Фильтры - Структура Из КлючИЗначение - Фильтры для отбора товаров - filters
// ТокенСтраницы - Строка - Токен следующей страницы при большой выборке - page
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex Market
Функция ПолучитьТоварыКабинета(Знач Токен, Знач IDКабинета, Знач Фильтры = "", Знач ТокенСтраницы = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDКабинета);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТокенСтраницы);
URL = "https://api.partner.market.yandex.ru/businesses/%1/offer-mappings";
URL = СтрШаблон(URL, IDКабинета);
Заголовки = СоздатьЗаголовкиЗапроса(Токен);
Если ЗначениеЗаполнено(ТокенСтраницы) Тогда
URL = URL + "?page_token=" + ТокенСтраницы;
КонецЕсли;
Если ЗначениеЗаполнено(Фильтры) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Фильтры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Фильтры, Заголовки);
Иначе
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, , Заголовки);
КонецЕсли;
Возврат Ответ;
КонецФункции
// Получить структуру товара
// Получает структуру стандартных полей товара
//
// Примечание:
// Описание в документации API: [UpdateOfferDTO](@https://yandex.ru/dev/market/partner-api/doc/ru/reference/business-assortment/updateOfferMappings#updateofferdto)
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей товара
Функция ПолучитьСтруктуруТовара(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
// BSLLS:DuplicateStringLiteral-off
СтруктураТовара = Новый Структура;
СтруктураТовара.Вставить("offerId", "<идентификатор товара в вашей системе>");
СтруктураРасходов = Новый Структура;
СтруктураРасходов.Вставить("currencyId" , "<код валюты>");
СтруктураРасходов.Вставить("value" , "<доп. расходы>");
СтруктураТовара.Вставить("additionalExpenses", СтруктураРасходов);
СтруктураТовара.Вставить("adult" , "<параметр включает для товара пометку 18+>");
СтруктураВозраста = Новый Структура;
СтруктураВозраста.Вставить("ageUnit", "<единица измерения: YEAR, MONTH>");
СтруктураВозраста.Вставить("value" , "<возрастное ограничение>");
СтруктураТовара.Вставить("age", СтруктураВозраста);
МассивШтрихкодов = Новый Массив;
МассивШтрихкодов.Добавить("<штрихкод>");
СтруктураТовара.Вставить("barcodes", МассивШтрихкодов);
СтруктураБазовойЦены = Новый Структура;
СтруктураБазовойЦены.Вставить("currencyId" , "<код валюты>");
СтруктураБазовойЦены.Вставить("value" , "<цена>");
СтруктураБазовойЦены.Вставить("discountBase", "<цена до скидки>");
СтруктураТовара.Вставить("basicPrice", СтруктураБазовойЦены);
СтруктураТовара.Вставить("boxCount" , "<количество грузовых мест>");
СтруктураТовара.Вставить("category" , "<категория товара в вашем магазине>");
МассивСертификатов = Новый Массив;
МассивСертификатов.Добавить("<номер документа на товар>");
СтруктураТовара.Вставить("certificates", МассивСертификатов);
СтруктураЦеныДляСкидок = Новый Структура;
СтруктураЦеныДляСкидок.Вставить("currencyId" , "<код валюты>");
СтруктураЦеныДляСкидок.Вставить("value" , "<цена>");
СтруктураТовара.Вставить("cofinancePrice", СтруктураЦеныДляСкидок);
СтруктураСостояния = Новый Структура;
СтруктураСостояния.Вставить("quality", "<внешний вид товара>");
СтруктураСостояния.Вставить("reason" , "<описание дефектов>");
СтруктураСостояния.Вставить("type" , "<тип уценки>");
СтруктураТовара.Вставить("condition", СтруктураСостояния);
СтруктураТовара.Вставить("customsCommodityCode", "<код товара ТН ВЭД>");
СтруктураТовара.Вставить("description" , "<подробное описание товара>");
СтруктураТовара.Вставить("downloadable" , "<признак цифрового товара>");
СтруктураПериода = Новый Структура;
СтруктураПериода.Вставить("timePeriod", "<значение продолжительности>");
СтруктураПериода.Вставить("timeUnit" , "<единица измерения>");
СтруктураПериода.Вставить("comment" , "<комментарий>");
СтруктураТовара.Вставить("guaranteePeriod", СтруктураПериода);
СтруктураТовара.Вставить("lifeTime" , СтруктураПериода);
МассивРуководств = Новый Массив;
СтруктураРуководства = Новый Структура;
СтруктураРуководства.Вставить("url" , "<сслыка на руководство>");
СтруктураРуководства.Вставить("title", "<заголовок руководства>");
МассивРуководств.Добавить(СтруктураРуководства);
СтруктураТовара.Вставить("manuals", МассивРуководств);
МассивСтран = Новый Массив;
МассивСтран.Добавить("<страна производства>");
СтруктураТовара.Вставить("manufacturerCountries", МассивСтран);
СтруктураТовара.Вставить("marketCategoryId" , "<идентификатор категории на Маркете>");
СтруктураТовара.Вставить("name" , "<имя товара>");
МассивХарактеристик = Новый Массив;
СтруктураХарактеристики = Новый Структура;
СтруктураХарактеристики.Вставить("parameterId", "<идентификатор характеристики>");
СтруктураХарактеристики.Вставить("unitId" , "<идентификатор единицы измерения>");
СтруктураХарактеристики.Вставить("value" , "<значение>");
СтруктураХарактеристики.Вставить("valueId" , "<идентификатор значения для перечислений>");
МассивХарактеристик.Добавить(СтруктураХарактеристики);
СтруктураТовара.Вставить("parameterValues", МассивХарактеристик);
МассивКартинок = Новый Массив;
МассивКартинок.Добавить("<ссылка на картинку товара>");
СтруктураТовара.Вставить("pictures" , МассивКартинок);
СтруктураЦеныЗакупки = Новый Структура;
СтруктураЦеныЗакупки.Вставить("currencyId" , "<код валюты>");
СтруктураЦеныЗакупки.Вставить("value" , "<цена>");
СтруктураТовара.Вставить("purchasePrice", СтруктураЦеныЗакупки);
СтруктураТовара.Вставить("shelfLife" , СтруктураПериода);
МассивТэгов = Новый Массив;
МассивТэгов.Добавить("<метка>");
СтруктураТовара.Вставить("tags" , МассивТэгов);
СтруктураТовара.Вставить("type" , "<особый тип товара>");
СтруктураТовара.Вставить("vendor" , "<название бренда или производителя>");
СтруктураТовара.Вставить("vendorCode", "<артикул товара от производителя>");
МассивВидео = Новый Массив;
МассивВидео.Добавить("<ссылка на видео>");
СтруктураТовара.Вставить("videos" , МассивВидео);
СтруктураРазмеров = Новый Структура;
СтруктураРазмеров.Вставить("height", "<высота в см.>");
СтруктураРазмеров.Вставить("length", "<длина в см.>");
СтруктураРазмеров.Вставить("weight", "<вес в кг. (брутто)>");
СтруктураРазмеров.Вставить("width" , "<ширина в см.>");
СтруктураТовара.Вставить("weightDimensions", "<габариты и вес товара>");
// BSLLS:DuplicateStringLiteral-on
Если Пустая Тогда
СтруктураТовара = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураТовара);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураТовара;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция СоздатьЗаголовкиЗапроса(Знач Токен)
OPI_ПреобразованиеТипов.ПолучитьСтроку(Токен);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Api-Key", Токен);
Возврат Заголовки;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="6a6134d2-7e5b-4fae-9656-7e67388bf27a">
<Properties>
<Name>OPI_YandexMetrika</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Yandex Metrika (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль для работы с Yandex Metrika из набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,588 @@
// OneScript: ./OInt/core/Modules/OPI_YandexMetrika.os
// Lib: Yandex Metrika
// CLI: metrika
// Depends: OPI_YandexID
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область УправлениеМетками
// Создать метку
// Создает метку с указанным именем
//
// Примечание:
// Метод в документации API: [Создание метки](@yandex.ru/dev/metrika/ru/management/openapi/label/createLabel)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// Наименование - Строка - Наименование метки - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция СоздатьМетку(Знач Токен, Знач Наименование) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/labels";
Метка = Новый Структура;
OPI_Инструменты.ДобавитьПоле("name", Наименование, "Строка", Метка);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Новый Структура("label", Метка), Заголовки);
Возврат Ответ;
КонецФункции
// Изменить метку
// Изменяет имя метки по ID
//
// Примечание:
// Метод в документации API: [Изменение метки](@yandex.ru/dev/metrika/ru/management/openapi/label/updateLabel)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDМетки - Строка - ID метки для изменения - label
// Наименование - Строка - Новое наименование - title
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ИзменитьМетку(Знач Токен, Знач IDМетки, Знач Наименование) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDМетки);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/label/" + IDМетки;
Метка = Новый Структура;
OPI_Инструменты.ДобавитьПоле("name", Наименование, "Строка", Метка);
Ответ = OPI_ЗапросыHTTP.PutСТелом(URL, Новый Структура("label", Метка), Заголовки);
Возврат Ответ;
КонецФункции
// Получить метку
// Получает метку по ID
//
// Примечание:
// Метод в документации API: [Информация о метке](@yandex.ru/dev/metrika/ru/management/openapi/label/getLabel)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDМетки - Строка - ID метки - label
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьМетку(Знач Токен, Знач IDМетки) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDМетки);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/label/" + IDМетки;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Удалить метку
// Удаляет метку по ID
//
// Примечание:
// Метод в документации API: [Удаление метки](@yandex.ru/dev/metrika/ru/management/openapi/label/deleteLabel)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDМетки - Строка - ID метки для удаления - label
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция УдалитьМетку(Знач Токен, Знач IDМетки) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDМетки);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/label/" + IDМетки;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить список меток
// Получает список меток пользователя
//
// Примечание:
// Метод в документации API: [Список меток пользователя](@yandex.ru/dev/metrika/ru/management/openapi/label/getLabels)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСписокМеток(Знач Токен) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/labels";
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#Область УправлениеСчетчиками
// Создать счетчик
// Создает счетчик по описанию полей
//
// Примечание:
// Метод в документации API: [Создание счетчика](@yandex.ru/dev/metrika/ru/management/openapi/counter/addCounter)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// СтруктураСчетчика - Структура Из КлючИЗначение - Структура счетчика. См. ПолучитьСтруктуруСчетчика - fields
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция СоздатьСчетчик(Знач Токен, Знач СтруктураСчетчика) Экспорт
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counters";
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("counter", СтруктураСчетчика, "Коллекция", Параметры);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Изменить счетчик
// Изменяет значения полей счетчика по ID
//
// Примечание:
// Метод в документации API: [Изменение счетчика](@yandex.ru/dev/metrika/ru/management/openapi/counter/editCounter)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDСчетчика - Строка, Число - ID счетчика для изменения - counter
// СтруктураСчетчика - Структура Из КлючИЗначение - Структура изменяемых полей. См. ПолучитьСтруктуруСчетчика - fields
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ИзменитьСчетчик(Знач Токен, Знач IDСчетчика, Знач СтруктураСчетчика) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDСчетчика);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counter/" + IDСчетчика;
Параметры = Новый Структура;
OPI_Инструменты.ДобавитьПоле("counter", СтруктураСчетчика, "Коллекция", Параметры);
Ответ = OPI_ЗапросыHTTP.PutСТелом(URL, Параметры, Заголовки);
Возврат Ответ;
КонецФункции
// Получить счетчик
// Получает информацию о счетчике по ID
//
// Примечание:
// Метод в документации API: [Информация о счетчике](@yandex.ru/dev/metrika/ru/management/openapi/counter/counter)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDСчетчика - Строка, Число - ID счетчика - counter
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСчетчик(Знач Токен, Знач IDСчетчика) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDСчетчика);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counter/" + IDСчетчика;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Удалить счетчик
// Удаляет счетчик по ID
//
// Примечание:
// Метод в документации API: [Удаление счетчика](@yandex.ru/dev/metrika/ru/management/openapi/counter/deleteCounter)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDСчетчика - Число, Строка - ID счетчика для удаления - counter
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция УдалитьСчетчик(Знач Токен, Знач IDСчетчика) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDСчетчика);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counter/" + IDСчетчика;
Ответ = OPI_ЗапросыHTTP.Delete(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Восстановить счетчик
// Восстанавливает ранее удаленный счетчик по ID
//
// Примечание:
// Метод в документации API: [Восстановление счетчика](@yandex.ru/dev/metrika/ru/management/openapi/counter/undeleteCounter)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDСчетчика - Строка, Число - ID счетчика для восстановления - counter
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ВосстановитьСчетчик(Знач Токен, Знач IDСчетчика) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDСчетчика);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counter/%1/undelete";
URL = СтрШаблон(URL, IDСчетчика);
Ответ = OPI_ЗапросыHTTP.PostСТелом(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить список счетчиков
// Получает список доступных счетчиков с фильтром или без
//
// Примечание:
// Метод в документации API: [Список доступных счетчиков](@yandex.ru/dev/metrika/ru/management/openapi/counter/counters)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// Фильтр - Структура Из КлючИЗначение - Фильтр списка. См. ПолучитьСтруктуруФильтраСчетчиков - filter
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСписокСчетчиков(Знач Токен, Знач Фильтр = Неопределено) Экспорт
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Фильтр);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counters";
Если ТипЗнч(Фильтр) <> Тип("Массив") И ЗначениеЗаполнено(Фильтр) Тогда
URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Фильтр, Истина);
КонецЕсли;
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
// Получить структуру счетчика
// Получает структуру стандартных полей для создания счетчика
//
// Примечание:
// Описание в документации API: [Создание счетчика](@yandex.ru/dev/metrika/ru/management/openapi/counter/addCounter)
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей счетчика
Функция ПолучитьСтруктуруСчетчика(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
// BSLLS:DuplicateStringLiteral-off
СтруктураСчетчика = Новый Структура;
СтруктураСчетчика.Вставить("autogoals_enabled", "<включение автоматических целей>");
СтруктураНастроекКода = Новый Структура;
СтруктураНастроекКода.Вставить("async" , "<асинхронный код счетчика>");
СтруктураНастроекКода.Вставить("clickmap" , "<сбор статистики для работы Карты кликов>");
СтруктураНастроекКода.Вставить("ecommerce" , "<сбор данных по электронной коммерции>");
СтруктураНастроекКода.Вставить("in_one_line" , "<выводить код счетчика в одну строку>");
СтруктураНастроекКода.Вставить("track_hash" , "<отслеживание хеша в адресной строке браузера>");
СтруктураНастроекКода.Вставить("visor" , "<запись и анализ поведения посетителей сайта>");
СтруктураНастроекКода.Вставить("xml_site" , "<для XML-сайтов>");
СтруктураНастроекКода.Вставить("ytm" , "<использование системы управления тегами>");
СтруктураНастроекКода.Вставить("alternative_cdn"
, "<учитывать посещения из регионов без доступ к ресурсам Яндекса>");
СтруктураИнформера = Новый Структура;
СтруктураИнформера.Вставить("color_arrow", "<цвет стрелки на информере>");
СтруктураИнформера.Вставить("color_end" , "<конечный (нижний) цвет информера в формате RRGGBBAA>");
СтруктураИнформера.Вставить("color_start", "<начальный (верхний) цвет информера в формате RRGGBBAA>");
СтруктураИнформера.Вставить("color_text" , "<цвет текста на информере>");
СтруктураИнформера.Вставить("enabled" , "<разрешение отображения информера>");
СтруктураИнформера.Вставить("indicator" , "<показатель информера>");
СтруктураИнформера.Вставить("size" , "<размер информера>");
СтруктураИнформера.Вставить("type" , "<тип информера>");
СтруктураНастроекКода.Вставить("informer", СтруктураИнформера);
СтруктураСчетчика.Вставить("code_options", СтруктураНастроекКода);
СтруктураФлагов = Новый Структура;
СтруктураФлагов.Вставить("collect_first_party_data" , "<использовать доп. настройки отслеживания>");
СтруктураФлагов.Вставить("measurement_enabled" , "<включить опцию Measurement Protocol>");
СтруктураФлагов.Вставить("use_in_benchmarks" , "<получать доступ к отчетам по рынку>");
СтруктураФлагов.Вставить("direct_allow_use_goals_without_access"
, "<разрешить в рекламных кампаниях оптимизацию по целям без доступа к счетчику>");
СтруктураСчетчика.Вставить("counter_flags", СтруктураФлагов);
СтруктураСчетчика.Вставить("favorite" , "<избранное>");
СтруктураСчетчика.Вставить("filter_robots", "<фильтрация роботов>");
МассивФильтров = Новый Массив;
СтруктураФильтра = Новый Структура;
СтруктураФильтра.Вставить("action" , "<тип фильтра>");
СтруктураФильтра.Вставить("attr" , "<тип данных, к которым применяется фильтр>");
СтруктураФильтра.Вставить("status" , "<статус фильтра>");
СтруктураФильтра.Вставить("type" , "<отношение или действие для фильтра>");
СтруктураФильтра.Вставить("end_ip" , "<последний IP-адрес диапазона>");
СтруктураФильтра.Вставить("id" , "<идентификатор фильтра для изменения>");
СтруктураФильтра.Вставить("start_ip" , "<первый IP-адрес диапазона>");
СтруктураФильтра.Вставить("value" , "<значение>");
СтруктураФильтра.Вставить("with_subdomains", "<фильтровать по поддоменам>");
МассивФильтров.Добавить(СтруктураФильтра);
СтруктураСчетчика.Вставить("filters" , МассивФильтров);
СтруктураСчетчика.Вставить("gdpr_agreement_accepted", "<согласие с Договором об обработке данных>");
МассивЦелей = Новый Массив;
СтруктураЦели = Новый Структура;
СтруктураЦели.Вставить("name" , "<наименование цели>");
СтруктураЦели.Вставить("type" , "<тип цели>");
СтруктураЦели.Вставить("default_price", "<цена цели по умолчанию>");
СтруктураЦели.Вставить("id" , "<id цели для изменения>");
СтруктураЦели.Вставить("is_favorite" , "<избранное>");
МассивЦелей.Добавить(СтруктураЦели);
СтруктураСчетчика.Вставить("goals", МассивЦелей);
МассивПрав = Новый Массив;
СтруктураПрав = Новый Структура;
СтруктураПрав.Вставить("perm" , "<уровень доступа>");
СтруктураПрав.Вставить("comment" , "<произвольный комментарий>");
СтруктураПрав.Вставить("partner_data_access", "<доступ к группе отчетов Монетизация>");
СтруктураПрав.Вставить("user_login" , "<логин пользователя, которому выдано разрешение>");
СтруктураПрав.Вставить("user_uid" , "<uid пользователя, которому выдано разрешение>");
МассивПрав.Добавить(СтруктураПрав);
СтруктураСчетчика.Вставить("grants", МассивПрав);
МассивЯрлыков = Новый Массив;
СтруктураЯрлыка = Новый Структура;
СтруктураЯрлыка.Вставить("name", "<имя метки>");
МассивЯрлыков.Добавить(СтруктураЯрлыка);
СтруктураСчетчика.Вставить("labels" , МассивЯрлыков);
СтруктураСчетчика.Вставить("measurement_tokens", "<список активных токенов>");
МассивЗеркал = Новый Массив;
СтруктураЗеркала = Новый Структура;
СтруктураЗеркала.Вставить("site", "<полный домен сайта>");
МассивЗеркал.Добавить(СтруктураЗеркала);
СтруктураСчетчика.Вставить("mirrors2", МассивЗеркал);
СтруктураСчетчика.Вставить("name" , "<наименование счетчика>");
СтруктураОффлайнОпций = Новый Структура;
СтруктураОффлайнОпций.Вставить("offline_calls_extended_threshold" , "<расширенный период учета звонков>");
СтруктураОффлайнОпций.Вставить("offline_conversion_extended_threshold"
, "<расширенный период учета офлайн-конверсий>");
СтруктураОффлайнОпций.Вставить("offline_visits_extended_threshold"
, "<расширенный период учета оффлайн-заходов>");
СтруктураСчетчика.Вставить("offline_options", СтруктураОффлайнОпций);
МассивОпераций = Новый Массив;
СтруктураОперации = Новый Структура;
СтруктураОперации.Вставить("action", "<тип операции>");
СтруктураОперации.Вставить("attr" , "<поле фильтрации>");
СтруктураОперации.Вставить("status", "<статус операции>");
СтруктураОперации.Вставить("id" , "<операции для изменения>");
СтруктураОперации.Вставить("value" , "<значение для замены>");
МассивОпераций.Добавить(СтруктураОперации);
СтруктураСчетчика.Вставить("operations" , МассивОпераций);
СтруктураСчетчика.Вставить("owner_login", "<логин владельца>");
СтруктураСчетчика.Вставить("permission" , "<уровень доступа к счетчику>");
СтруктураАналитики = Новый Структура;
СтруктураАналитики.Вставить("enabled" , "<сбор данных контентной аналитики>");
СтруктураАналитики.Вставить("schema" , "<используемый на сайте тип разметки>");
СтруктураАналитики.Вставить("schema_options", "<доступные варианты разметки сайта>");
СтруктураСчетчика.Вставить("publisher_options", СтруктураАналитики);
СтруктураСчетчика.Вставить("site2" , МассивЗеркал);
СтруктураСчетчика.Вставить("source" , "<тип счетчика>");
СтруктураСчетчика.Вставить("time_zone_name" , "<часовой пояс>");
СтруктураСчетчика.Вставить("visit_threshold" , "<таймаут визита в секундах>");
СтруктураВебвизора = Новый Структура;
СтруктураВебвизора.Вставить("arch_enabled" , "<сохранение страниц сайта>");
СтруктураВебвизора.Вставить("arch_type" , "<запись содержимого страниц>");
СтруктураВебвизора.Вставить("load_player_type", "<загрузка страниц в плеер>");
СтруктураВебвизора.Вставить("urls" , "<список страниц для сохранения>");
СтруктураВебвизора.Вставить("wv_forms" , "<запись содержимого полей и форм>");
СтруктураВебвизора.Вставить("wv_version" , "<версия вебвизора>");
СтруктураСчетчика.Вставить("webvisor", СтруктураВебвизора);
// BSLLS:DuplicateStringLiteral-on
Если Пустая Тогда
СтруктураСчетчика = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураСчетчика);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураСчетчика;
КонецФункции
// Получить структуру фильтра счетчиков
// Получает структуру полей фильтра для получения списка счетчиков
//
// Примечание:
// Описание в документации API: [Список доступных счетчиков](@yandex.ru/dev/metrika/ru/management/openapi/counter/counters)
//
// Параметры:
// Пустая - Булево - Истина > структура с пустыми значениями, Ложь > в значениях будут описания полей - empty
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура полей счетчика
Функция ПолучитьСтруктуруФильтраСчетчиков(Знач Пустая = Ложь) Экспорт
OPI_ПреобразованиеТипов.ПолучитьБулево(Пустая);
СтруктураФильтра = Новый Структура;
МассивID = Новый Массив;
МассивID.Добавить("<id счетчика для отбора>");
СтруктураФильтра.Вставить("counter_ids" , МассивID);
СтруктураФильтра.Вставить("label_id" , "<фмльтр по метке>");
СтруктураФильтра.Вставить("offset" , "<порядковый номер первого счетчика в списке>");
СтруктураФильтра.Вставить("per_page" , "<максимальное количество счетчиков в выдаче>");
СтруктураФильтра.Вставить("permission" , "<фильтр по уровню доступа>");
СтруктураФильтра.Вставить("search_string", "<фильтр по содержанию подстроки в полях>");
СтруктураФильтра.Вставить("status" , "<фильтр по статусу>");
СтруктураФильтра.Вставить("type" , "<фильтр по типу>");
СтруктураФильтра.Вставить("sort" , "<сортировка>");
Если Пустая Тогда
СтруктураФильтра = OPI_Инструменты.ОчиститьКоллекциюРекурсивно(СтруктураФильтра);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураФильтра;
КонецФункции
#КонецОбласти
#Область УправлениеОперациями
// Получить список операций
// Получает список операций выбранного счетчика
//
// Примечание:
// Метод в документации API: [Список операций](@yandex.ru/dev/metrika/ru/management/openapi/operation/operations)
//
// Параметры:
// Токен - Строка - Токен авторизации - token
// IDСчетчика - Строка, Число - ID счетчика - counter
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - сериализованный JSON ответа от Yandex
Функция ПолучитьСписокОпераций(Знач Токен, Знач IDСчетчика) Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDСчетчика);
Заголовки = OPI_YandexID.ПолучитьЗаголовокАвторизации(Токен);
URL = "https://api-metrika.yandex.net/management/v1/counter/%1/operations";
URL = СтрШаблон(URL, IDСчетчика);
Ответ = OPI_ЗапросыHTTP.Get(URL, , Заголовки);
Возврат Ответ;
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="6a9469ae-ee9b-4a26-a61b-715c5cb13e17">
<Properties>
<Name>OPI_ЗапросыHTTP</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>HTTP (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Служебный модуль работы с HTTP набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,351 @@
// OneScript: ./OInt/tools/Modules/OPI_ЗапросыHTTP.os
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UnusedLocalVariable-off
// BSLLS:UsingServiceTag-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-unused-local-variable
//@skip-check method-too-many-params
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check use-non-recommended-method
// Раскомментировать, если выполняется OneScript
// #Использовать "./internal"
#Область ПрограммныйИнтерфейс
// Новый запрос
// Создает новый объект для работы с HTTP
//
// Возвращаемое значение:
// ОбработкаОбъект.OPI_HTTPКлиент - Объект обработки
Функция НовыйЗапрос() Экспорт
Если OPI_Инструменты.ЭтоOneScript() Тогда
//@skip-check property-not-writable
//@skip-check bsl-legacy-check-static-feature-access
Обработки = Неопределено;
ИмяТипа = "OPI_HTTPКлиент";
HTTPКлиент = Новый(ИмяТипа);
Иначе
HTTPКлиент = Обработки.OPI_HTTPКлиент.Создать();
КонецЕсли;
Возврат HTTPКлиент;
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
#Область ЗапросыБезТела
Функция Get(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено
, Знач ПолныйОтвет = Ложь) Экспорт
Возврат ВыполнитьЗапросБезТела(URL, "GET", Параметры, ДопЗаголовки, ФайлОтвета, ПолныйОтвет);
КонецФункции
Функция Head(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено
, Знач ПолныйОтвет = Ложь) Экспорт
Возврат ВыполнитьЗапросБезТела(URL, "HEAD", Параметры, ДопЗаголовки, ФайлОтвета, ПолныйОтвет);
КонецФункции
Функция Delete(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено
, Знач ПолныйОтвет = Ложь) Экспорт
Возврат ВыполнитьЗапросБезТела(URL, "DELETE", Параметры, ДопЗаголовки, ФайлОтвета, ПолныйОтвет);
КонецФункции
#КонецОбласти
#Область ЗапросыСТелом
Функция PostСТелом(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач JSON = Истина
, Знач ПолныйОтвет = Ложь
, Знач ФайлОтвета = Неопределено) Экспорт
Возврат ВыполнитьЗапросСТелом(URL, "POST", Параметры, ДопЗаголовки, JSON, ПолныйОтвет, ФайлОтвета);
КонецФункции
Функция PatchСТелом(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач JSON = Истина
, Знач ПолныйОтвет = Ложь
, Знач ФайлОтвета = Неопределено) Экспорт
Возврат ВыполнитьЗапросСТелом(URL, "PATCH", Параметры, ДопЗаголовки, JSON, ПолныйОтвет, ФайлОтвета);
КонецФункции
Функция PutСТелом(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач JSON = Истина
, Знач ПолныйОтвет = Ложь
, Знач ФайлОтвета = Неопределено) Экспорт
Возврат ВыполнитьЗапросСТелом(URL, "PUT", Параметры, ДопЗаголовки, JSON, ПолныйОтвет, ФайлОтвета);
КонецФункции
Функция DeleteСТелом(Знач URL
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач JSON = Истина
, Знач ПолныйОтвет = Ложь
, Знач ФайлОтвета = Неопределено) Экспорт
Возврат ВыполнитьЗапросСТелом(URL, "DELETE", Параметры, ДопЗаголовки, JSON, ПолныйОтвет, ФайлОтвета);
КонецФункции
#КонецОбласти
#Область ЗапросыMultipart
Функция PostMultipart(Знач URL
, Знач Параметры = ""
, Знач Файлы = ""
, Знач ТипКонтента = "image/jpeg"
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено) Экспорт
HttpКлиент = НовыйЗапрос()
.Инициализировать(URL)
.УстановитьЗаголовки(ДопЗаголовки)
.УстановитьФайлОтвета(ФайлОтвета)
.НачатьЗаписьТелаMultipart();
Если ЗначениеЗаполнено(Файлы) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Файлы);
//@skip-check bsl-legacy-check-for-each-statetement-collection
Для Каждого Файл Из Файлы Цикл
СтруктураИнформации = РазобратьКлючФайла(Файл.Ключ, ТипКонтента);
ИмяПоля = СтруктураИнформации["ИмяПоля"];
ИмяФайла = СтруктураИнформации["ИмяФайла"];
HttpКлиент.ДобавитьФайлMultipartFormData(ИмяПоля, ИмяФайла, Файл.Значение, ТипКонтента);
КонецЦикла;
КонецЕсли;
Если ЗначениеЗаполнено(Параметры) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Параметры);
//@skip-check bsl-legacy-check-for-each-statetement-collection
Для Каждого Параметр Из Параметры Цикл
HttpКлиент.ДобавитьПолеMultipartFormData(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
КонецЕсли;
HttpКлиент.ОбработатьЗапрос("POST");
Результат = HttpКлиент.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Если HttpКлиент.Ошибка Тогда
ВызватьИсключение HttpКлиент.ПолучитьЛог(Истина);
Иначе
Возврат Результат;
КонецЕсли;
КонецФункции
Функция PutMultipart(Знач URL
, Знач Параметры = ""
, Знач Файлы = ""
, Знач ТипКонтента = "image/jpeg"
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено) Экспорт
Возврат ВыполнитьЗапросМультипарт(URL, "PUT", Параметры, Файлы, ТипКонтента, ДопЗаголовки, ФайлОтвета);
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ВыполнитьЗапросСТелом(Знач URL
, Знач Вид
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач JSON = Истина
, Знач ПолныйОтвет = Ложь
, Знач ФайлОтвета = Неопределено)
HttpКлиент = НовыйЗапрос()
.Инициализировать(URL)
.УстановитьЗаголовки(ДопЗаголовки)
.УстановитьФайлОтвета(ФайлОтвета);
Если JSON Тогда
HttpКлиент.УстановитьJsonТело(Параметры);
Иначе
HttpКлиент.УстановитьFormТело(Параметры);
КонецЕсли;
HttpКлиент.ОбработатьЗапрос(Вид);
Если ПолныйОтвет Тогда
Результат = HttpКлиент.ВернутьОтвет(Ложь, Истина);
Иначе
Результат = HttpКлиент.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ВыполнитьЗапросБезТела(Знач URL
, Знач Вид
, Знач Параметры = ""
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено
, Знач ПолныйОтвет = Ложь)
HttpКлиент = НовыйЗапрос()
.Инициализировать(URL)
.УстановитьПараметрыURL(Параметры)
.УстановитьЗаголовки(ДопЗаголовки)
.УстановитьФайлОтвета(ФайлОтвета)
.ОбработатьЗапрос(Вид);
Если ПолныйОтвет Тогда
Результат = HttpКлиент.ВернутьОтвет(Ложь, Истина);
Иначе
Результат = HttpКлиент.ВернутьОтветКакJSONКоллекцию(Истина, Истина);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ВыполнитьЗапросМультипарт(Знач URL
, Знач Вид
, Знач Параметры = ""
, Знач Файлы = ""
, Знач ТипКонтента = "image/jpeg"
, Знач ДопЗаголовки = ""
, Знач ФайлОтвета = Неопределено)
HttpКлиент = НовыйЗапрос()
.Инициализировать(URL)
.УстановитьЗаголовки(ДопЗаголовки)
.УстановитьФайлОтвета(ФайлОтвета)
.НачатьЗаписьТелаMultipart();
//@skip-check bsl-legacy-check-for-each-statetement-collection
Для Каждого Файл Из Файлы Цикл
СтруктураИнформации = РазобратьКлючФайла(Файл.Ключ, ТипКонтента);
ИмяПоля = СтруктураИнформации["ИмяПоля"];
ИмяФайла = СтруктураИнформации["ИмяФайла"];
HttpКлиент.ДобавитьФайлMultipartFormData(ИмяПоля, ИмяФайла, Файл.Значение, ТипКонтента);
КонецЦикла;
//@skip-check bsl-legacy-check-for-each-statetement-collection
Для Каждого Параметр Из Параметры Цикл
HttpКлиент.ДобавитьПолеMultipartFormData(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
Результат = HttpКлиент.ОбработатьЗапрос("POST").ВернутьОтветКакJSONКоллекцию(Истина, Истина);
Возврат Результат;
КонецФункции
Функция РазобратьКлючФайла(Знач ДанныеФайла, Знач ТипКонтента)
ЗаменаТочки = "___";
ИмяФайла = СтрЗаменить(ДанныеФайла, ЗаменаТочки, ".");
МассивИмени = СтрРазделить(ИмяФайла, "|", Ложь);
ЧастейИмени = 2;
Если МассивИмени.Количество() = ЧастейИмени Тогда
ИмяПоля = МассивИмени[0];
ИмяФайла = МассивИмени[1];
Иначе
Если ТипКонтента = "image/jpeg" Тогда
ИмяПоля = "photo";
Иначе
ИмяПоля = Лев(ИмяФайла, СтрНайти(ИмяФайла, ".") - 1);
ИмяПоля = ?(ЗначениеЗаполнено(ИмяПоля), ИмяПоля, СтрЗаменить(ДанныеФайла, ЗаменаТочки, "."));
КонецЕсли;
КонецЕсли;
СтруктураВозврата = Новый Структура("ИмяПоля,ИмяФайла", ИмяПоля, ИмяФайла);
Возврат СтруктураВозврата;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="715648f2-d9af-4b70-bbba-21d3173cec43">
<Properties>
<Name>OPI_ЗапросыSQL</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SQL (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Общий модуль инструментов работы с SQL набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="b59f0d9d-94ec-4c4b-80a2-c75fa4e29094">
<Properties>
<Name>OPI_ЗапросыSSH</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>SSH (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Общий модуль инструментов работы с SSH набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,321 @@
// OneScript: ./OInt/tools/Modules/OPI_ЗапросыSSH.os
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:QueryParseError-off
// BSLLS:AssignAliasFieldsInQuery-off
// BSLLS:NumberOfParams-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
// Раскомментировать, если выполняется OneScript
// #Использовать "./internal"
#Область СлужебныйПрограммныйИнтерфейс
Функция ОткрытьСоединение(Знач НастройкиSSH, Знач Прокси = "") Экспорт
Result_ = "result";
Если ЭтоКоннектор(НастройкиSSH) Тогда
Возврат НастройкиSSH;
КонецЕсли;
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("SSH");
УстановкаКонфигурации = УстановитьНастройки(Коннектор, НастройкиSSH);
Если Не OPI_Инструменты.ПолучитьИли(УстановкаКонфигурации, Result_, Ложь) Тогда
Возврат УстановкаКонфигурации;
КонецЕсли;
УстановкаПрокси = УстановитьПрокси(Коннектор, Прокси);
Если Не OPI_Инструменты.ПолучитьИли(УстановкаПрокси, Result_, Ложь) Тогда
Возврат УстановкаПрокси;
КонецЕсли;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Возврат ?(Результат[Result_], Коннектор, Результат);
КонецФункции
Функция ПолучитьКонфигурациюСоединения(Знач НастройкиSSH, Знач Прокси = Неопределено) Экспорт
СтруктураКонфигурации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("set" , НастройкиSSH, "Коллекция", СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("proxy", Прокси , "Коллекция", СтруктураКонфигурации);
Возврат СтруктураКонфигурации;
КонецФункции
Функция ВыполнитьКоманду(Знач Соединение, Знач Команда) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Команда);
Результат = Соединение.Execute(Команда);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Вывод = Результат["stdout"];
Если Вывод <> Неопределено Тогда
Если СтрЗаканчиваетсяНа(Вывод, Символы.ПС) Тогда
Результат["stdout"] = Лев(Вывод, СтрДлина(Вывод) - 1);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
КонецЕсли;
Результат = Соединение.Disconnect();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
//@skip-check constructor-function-return-section
Возврат Результат;
КонецФункции
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_SSH.Main";
КонецФункции
Функция ПолучитьНастройкиЛогинПароль(Знач Хост, Знач Порт, Знач Логин, Знач Пароль = "") Экспорт
Строка_ = "Строка";
СтруктураКонфигурации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("auth_type", "password", Строка_ , СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("host" , Хост , Строка_ , СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("port" , Порт , "Число" , СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("username" , Логин , Строка_ , СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("password" , Пароль , Строка_ , СтруктураКонфигурации);
Возврат СтруктураКонфигурации;
КонецФункции
Функция ПолучитьНастройкиПриватныйКлюч(Знач Хост
, Знач Порт
, Знач Логин
, Знач Приватный
, Знач Публичный = ""
, Знач Пароль = "") Экспорт
Строка_ = "Строка";
OPI_ПреобразованиеТипов.ПолучитьФайлНаДиске(Приватный);
Приватный_ = Приватный.Путь;
Если ЗначениеЗаполнено(Публичный) Тогда
OPI_ПреобразованиеТипов.ПолучитьФайлНаДиске(Публичный);
Публичный_ = Публичный.Путь;
Иначе
Публичный_ = Неопределено;
КонецЕсли;
СтруктураКонфигурации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("auth_type" , "private_key" , Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("host" , Хост , Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("port" , Порт , "Число", СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("username" , Логин , Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("key_path" , Приватный_ , Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("pub_path" , Публичный_ , Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("passphrase", Пароль , Строка_, СтруктураКонфигурации);
Возврат СтруктураКонфигурации;
КонецФункции
Функция ПолучитьНастройкиЧерезАгента(Знач Хост, Знач Порт, Знач Логин) Экспорт
Строка_ = "Строка";
СтруктураКонфигурации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("auth_type" , "agent", Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("host" , Хост , Строка_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("port" , Порт , "Число", СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("username" , Логин , Строка_, СтруктураКонфигурации);
Возврат СтруктураКонфигурации;
КонецФункции
Функция ПолучитьНастройкиПрокси(Знач Адрес
, Знач Порт
, Знач Вид = "socks5"
, Знач Логин = Неопределено
, Знач Пароль = Неопределено) Экспорт
//@skip-check constructor-function-return-section
Возврат OPI_Компоненты.ПолучитьНастройкиПрокси(Адрес, Порт, Вид, Логин, Пароль);
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ПроверитьСоздатьСоединение(Соединение)
Если Не ЭтоКоннектор(Соединение) Тогда
ЗакрыватьСоединение = Истина;
Соединение = ОткрытьСоединениеПоКонфигурации(Соединение);
Иначе
ЗакрыватьСоединение = Ложь;
КонецЕсли;
Возврат ЗакрыватьСоединение;
КонецФункции
Функция ОткрытьСоединениеПоКонфигурации(Знач СтруктураКонфигурации)
Если ЭтоКоннектор(СтруктураКонфигурации) Тогда
Возврат СтруктураКонфигурации;
КонецЕсли;
ШаблонОшибки = "Передана некорректная конфигурация соединения: %1";
Попытка
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураКонфигурации);
Исключение
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, ОписаниеОшибки()));
Возврат Результат;
КонецПопытки;
Если Не OPI_Инструменты.ПолеКоллекцииСуществует(СтруктураКонфигурации, "set") Тогда
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, "отсутствуют основные параметры соединения"));
Возврат Результат;
КонецЕсли;
НастройкиSSH = СтруктураКонфигурации["set"];
Прокси = OPI_Инструменты.ПолучитьИли(СтруктураКонфигурации, "proxy", Неопределено);
Возврат ОткрытьСоединение(НастройкиSSH, Прокси);
КонецФункции
Функция УстановитьНастройки(Знач Коннектор, Знач НастройкиSSH)
ШаблонОшибки = "Передана некорректная конфигурация соединения: %1";
Попытка
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(НастройкиSSH);
Исключение
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, ОписаниеОшибки()));
Возврат Результат;
КонецПопытки;
СтрокаНастроек = OPI_Инструменты.JSONСтрокой(НастройкиSSH);
Результат = Коннектор.SetSettings(СтрокаНастроек);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Возврат Результат;
КонецФункции
Функция УстановитьПрокси(Знач Коннектор, Знач Прокси)
Если Не ЗначениеЗаполнено(Прокси) Тогда
Возврат Новый Структура("result", Истина);
КонецЕсли;
ШаблонОшибки = "Передана некорректная конфигурация прокси: %1";
Попытка
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Прокси);
Исключение
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, ОписаниеОшибки()));
Возврат Результат;
КонецПопытки;
СтрокаПрокси = OPI_Инструменты.JSONСтрокой(Прокси);
Результат = Коннектор.SetProxy(СтрокаПрокси);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Возврат Результат;
КонецФункции
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="e810f1d2-6714-4c85-94b1-c3ce20788e78">
<Properties>
<Name>OPI_Инструменты</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Инструменты (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Основной модуль инструментов набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="77a83b22-9e8c-4b2b-8b81-781d39673746">
<Properties>
<Name>OPI_Компоненты</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Компоненты (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль работы с внешними компонентами набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,291 @@
// OneScript: ./OInt/tools/Modules/OPI_Компоненты.os
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UsingHardcodePath-off
// BSLLS:Typo-off
// BSLLS:DeprecatedMessage-off
// BSLLS:UsingServiceTag-off
// BSLLS:ExecuteExternalCodeInCommonModule-off
// BSLLS:DuplicateStringLiteral-off
// BSLLS:MagicNumber-off
// BSLLS:UsingHardcodeNetworkAddress-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check use-non-recommended-method
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check undefined-function-or-procedure
//@skip-check wrong-string-literal-content
// Раскомментировать, если выполняется OneScript
// #Использовать "./internal"
#Область СлужебныйПрограммныйИнтерфейс
Функция ПолучитьКомпоненту(Знач ИмяКомпоненты, Знач Класс = "Main") Экспорт
Компонента = Неопределено;
Ошибка = "";
ИмяКомпоненты = "OPI_" + ИмяКомпоненты;
Если Не ИнициализироватьВнешнююКомпоненту(ИмяКомпоненты, Класс, Компонента) Тогда
Ошибка = Неопределено;
Компонента = ПодключитьКомпонентуНаСервере(ИмяКомпоненты, Класс, Ошибка);
Если ЗначениеЗаполнено(Ошибка) Тогда
СформироватьИсключениеКомпоненты(Ошибка);
КонецЕсли;
КонецЕсли;
Возврат Компонента;
КонецФункции
Функция ЭтоКомпонента(Знач Значение) Экспорт
ТипЗначения = Строка(ТипЗнч(Значение));
Возврат СтрНачинаетсяС(ТипЗначения, "AddIn.");
КонецФункции
Функция УстановитьTls(Знач Компонета, Знач Tls) Экспорт
Результат = Новый Структура("result", Истина);
Если ЗначениеЗаполнено(Tls) Тогда
СообщениеОшибки = "Переданы некорректные настройки Tls!";
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Tls, СообщениеОшибки);
ИспользоватьTls = OPI_Инструменты.ПолучитьИли(Tls, "use_tls" , Ложь);
ОтключитьВалидацию = OPI_Инструменты.ПолучитьИли(Tls, "accept_invalid_certs", Ложь);
ПутьКСертификату = OPI_Инструменты.ПолучитьИли(Tls, "ca_cert_path" , "");
OPI_ПреобразованиеТипов.ПолучитьБулево(ИспользоватьTls);
OPI_ПреобразованиеТипов.ПолучитьБулево(ОтключитьВалидацию);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ПутьКСертификату);
Результат = Компонета.SetTLS(ИспользоватьTls, ОтключитьВалидацию, ПутьКСертификату);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
СтруктураСертификата = Новый Структура;
OPI_Инструменты.ДобавитьПоле("use_tls" , Истина , "Булево", СтруктураСертификата);
OPI_Инструменты.ДобавитьПоле("accept_invalid_certs", ОтключитьПроверкуСертификатов, "Булево", СтруктураСертификата);
OPI_Инструменты.ДобавитьПоле("ca_cert_path" , ПутьКСертификату , "Строка", СтруктураСертификата);
Возврат СтруктураСертификата;
КонецФункции
Функция ПолучитьНастройкиПрокси(Знач Адрес
, Знач Порт
, Знач Вид = "socks5"
, Знач Логин = Неопределено
, Знач Пароль = Неопределено) Экспорт
СтруктураНастроек = Новый Структура;
OPI_Инструменты.ДобавитьПоле("server" , Адрес, "Строка", СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("port" , Порт , "Число" , СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("proxy_type", Вид , "Строка", СтруктураНастроек);
Если Не Логин = Неопределено Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
СтруктураНастроек.Вставить("login", Логин);
КонецЕсли;
Если Не Пароль = Неопределено Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
СтруктураНастроек.Вставить("password", Пароль);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураНастроек;
КонецФункции
Функция ТребуетсяПередачаЧерезФайл() Экспорт
// BSLLS:CommentedCode-off
// Компоненты в 1С на Linux не могут стабильно отдавать и принимать данные свыше 30 КБ
// https://github.com/Bayselonarrend/OpenIntegrations/issues/72
// UPD: В неизолированном режиме не падает
// Возврат Не OPI_Инструменты.ЭтоWindows() И Не OPI_Инструменты.ЭтоOneScript();
// BSLLS:CommentedCode-on
Возврат Ложь;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ИнициализироватьВнешнююКомпоненту(Знач ИмяКомпоненты, Знач Класс, Компонента)
Попытка
Компонента = Новый("AddIn." + ИмяКомпоненты + "." + Класс);
Возврат Истина;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Функция ПодключитьКомпонентуНаСервере(Знач ИмяКомпоненты, Знач Класс, Ошибка)
Если OPI_Инструменты.ЭтоOneScript() Тогда
ИмяМакета = КаталогКомпонентOS() + ИмяКомпоненты + ".zip";
Иначе
ИмяМакета = "ОбщийМакет." + ИмяКомпоненты;
КонецЕсли;
Попытка
ПодключитьКомпонентуНеИзолированно(ИмяМакета, ИмяКомпоненты);
Компонента = Новый("AddIn." + ИмяКомпоненты + "." + Класс);
Ошибка = Неопределено;
Возврат Компонента;
Исключение
Ошибка = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
Возврат Неопределено;
КонецПопытки;
КонецФункции
Функция ПодключитьКомпонентуНеИзолированно(ИмяМакета, ИмяКомпоненты)
ЭтоOneScript = OPI_Инструменты.ЭтоOneScript();
НеобходимТипПоСистеме = Не ЭтоOneScript И Не OPI_Инструменты.ЭтоWindows();
Если ЭтоOneScript Тогда
НеобходимТипПоВерсии = Ложь;
Иначе
СистемнаяИнформация = Новый СистемнаяИнформация();
Версия1С = СистемнаяИнформация.ВерсияПриложения;
Версия1С = СтрРазделить(Версия1С, ".");
Часть1 = Число(Версия1С[0]);
Часть2 = Число(Версия1С[1]);
Часть3 = Число(Версия1С[2]);
НеобходимТипПоВерсии = Часть1 > 8 Или Часть2 > 3 Или Часть3 > 20;
КонецЕсли;
НеобходимТип = НеобходимТипПоВерсии И НеобходимТипПоСистеме;
Если Не НеобходимТип Тогда
Если Не НеобходимТипПоВерсии Тогда
ТипПодключенияВнешнейКомпоненты = Неопределено;
КонецЕсли;
Результат = ПодключитьВнешнююКомпоненту(ИмяМакета, ИмяКомпоненты, ТипВнешнейКомпоненты.Native);
Иначе
// BSLLS:UnusedLocalVariable-off
//@skip-check module-unused-local-variable
ТипПодключения = ТипПодключенияВнешнейКомпоненты.НеИзолированно;
//@skip-check server-execution-safe-mode
// BSLLS:UnusedLocalVariable-on
Результат = Вычислить("ПодключитьВнешнююКомпоненту(ИмяМакета, ИмяКомпоненты, ТипВнешнейКомпоненты.Native, ТипПодключения)");
КонецЕсли;
Возврат Результат;
КонецФункции
Функция КаталогКомпонентOS() Экспорт
КаталогПрограммы = СтрЗаменить(КаталогПрограммы(), "\", "/");
ЭлементыПути = СтрРазделить(КаталогПрограммы, "/");
ЭлементыПути.Удалить(ЭлементыПути.ВГраница());
// BSLLS:UsingHardcodePath-off
КаталогКомпонент = СтрСоединить(ЭлементыПути, "/") + "/lib/oint/addins/";
// BSLLS:UsingHardcodePath-on
Возврат КаталогКомпонент;
КонецФункции
Процедура СформироватьИсключениеКомпоненты(Знач Ошибка)
Текст = "Не удалось инициализировать внешнюю компоненту. Возможно, она несовместима с вашей операционной системой.";
Если Не OPI_Инструменты.ЭтоWindows() Тогда
Текст = Текст
+ Символы.ПС
+ Символы.ПС
+ "Важно: Для работы компоненты требуется GLIBC >=2.18"
+ " и OpenSSL версии 3.x"
+ Символы.ПС
+ "Проверьте, что данные зависимости удоволетворены в вашей системе!";
КонецЕсли;
Текст = Текст
+ Символы.ПС
+ Символы.ПС
+ "Подробнее: https://openintegrations.dev/docs/Start/Component-requirements"
+ Символы.ПС
+ Символы.ПС
+ "Системная информация:"
+ Ошибка;
ВызватьИсключение Текст;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="55bb3987-d7ac-4ed7-a6fd-aa4cfeb61c27">
<Properties>
<Name>OPI_Криптография</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Криптография (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль работы с криптографией набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,244 @@
// OneScript: ./OInt/tools/Modules/internal/Modules/OPI_Криптография.os
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UnusedLocalVariable-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
#Область СлужебныйПрограммныйИнтерфейс
Функция СоздатьПодпись(Знач КлючПодписи, Знач ДанныеПодписи, Знач Алгоритм, Знач ФункцияХеша) Экспорт
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(КлючПодписи);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(ДанныеПодписи);
OPI_ПреобразованиеТипов.ПолучитьСтроку(Алгоритм);
Алгоритм = вРег(Алгоритм);
ФункцияХеша = вРег(ФункцияХеша);
Если Алгоритм = "HMAC" Тогда
Результат = HMAC(КлючПодписи, ДанныеПодписи, ФункцияХеша);
ИначеЕсли Алгоритм = "RSA" Тогда
Результат = RSA(КлючПодписи, ДанныеПодписи, ФункцияХеша);
Иначе
ВызватьИсключение "Ошибка работы с криптографией: неподдерживаемый метод";
КонецЕсли;
Возврат Результат;
КонецФункции
Функция RSA(Знач Ключ, Знач Данные, Знач ФункцияХеша) Экспорт
Компонента = OPI_Компоненты.ПолучитьКомпоненту("Cryptography");
Если ФункцияХеша = "SHA256" Тогда
Результат = Компонента.RsaSha256(Ключ, Данные);
ИначеЕсли ФункцияХеша = "SHA1" Тогда
Результат = Компонента.RsaSha1(Ключ, Данные);
Иначе
Результат = "неподдерживаемый метод хеширования";
КонецЕсли;
Если ТипЗнч(Результат) = Тип("Строка") Тогда
ВызватьИсключение СтрШаблон("Ошибка работы с криптографией: %1", Результат);
Иначе
Возврат Результат;
КонецЕсли;
КонецФункции
Функция JWT(Знач Payload, Знач КлючПодписи, Знач Метод, Знач ДопЗаголовки = "") Экспорт
OPI_ПреобразованиеТипов.ПолучитьСтроку(Метод);
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Payload);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(КлючПодписи, Истина, Ложь);
Метод = вРег(Метод);
Если Метод = "HS256" Тогда
Алгоритм = "HMAC";
ФункцияХеша = "SHA256";
ИначеЕсли Метод = "RS256" Тогда
Алгоритм = "RSA";
ФункцияХеша = "SHA256";
Иначе
ВызватьИсключение "JWT: Неподдерживаемый метод";
КонецЕсли;
Заголовки = Новый Структура("alg,typ", Метод, "JWT");
Если ЗначениеЗаполнено(ДопЗаголовки) Тогда
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ДопЗаголовки);
//@skip-check bsl-legacy-check-for-each-statetement-collection
Для Каждого КлючЗначение Из ДопЗаголовки Цикл
Заголовки.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение);
КонецЦикла;
КонецЕсли;
PayloadСтрокой = OPI_Инструменты.JSONСтрокой(Payload, , Ложь);
ЗаголовкиСтрокой = OPI_Инструменты.JSONСтрокой(Заголовки, , Ложь);
PayloadДвоичные = ПолучитьДвоичныеДанныеИзСтроки(PayloadСтрокой);
ЗаголовкиДвоичные = ПолучитьДвоичныеДанныеИзСтроки(ЗаголовкиСтрокой);
PayloadBase64 = Base64UrlEncode(PayloadДвоичные);
ЗаголовкиBase64 = Base64UrlEncode(ЗаголовкиДвоичные);
Токен = СтрШаблон("%1.%2", ЗаголовкиBase64, PayloadBase64);
ТокенДвоичные = ПолучитьДвоичныеДанныеИзСтроки(Токен);
Подпись = СоздатьПодпись(КлючПодписи, ТокенДвоичные, Алгоритм, ФункцияХеша);
ПодписьBase64 = Base64UrlEncode(Подпись);
Токен = СтрШаблон("%1.%2", Токен, ПодписьBase64);
Возврат Токен;
КонецФункции
#Область Заимстованные
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
Функция HMAC(Знач Ключ, Знач Данные, Знач ФункцияХеша) Экспорт
Дважды = 2;
РазмерБлока = 64;
ТипХеша = ХешФункция[ФункцияХеша];
Если Ключ.Размер() > РазмерБлока Тогда
Ключ = Хеш(Ключ, ТипХеша);
КонецЕсли;
Если Ключ.Размер() <= РазмерБлока Тогда
Ключ = ПолучитьHexСтрокуИзДвоичныхДанных(Ключ);
Ключ = Лев(Ключ + ПовторитьСтроку("00", РазмерБлока), РазмерБлока * Дважды);
КонецЕсли;
Ключ = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ПолучитьДвоичныеДанныеИзHexСтроки(Ключ));
Ipad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьСтроку("36", РазмерБлока));
Opad = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ПовторитьСтроку("5c", РазмерБлока));
Ipad.ЗаписатьПобитовоеИсключительноеИли(0, Ключ);
Ikeypad = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ipad);
Opad.ЗаписатьПобитовоеИсключительноеИли(0, Ключ);
Okeypad = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(opad);
Возврат Хеш(СклеитьДвоичныеДанные(okeypad, Хеш(СклеитьДвоичныеДанные(ikeypad, Данные), ТипХеша)), ТипХеша);
КонецФункции
Функция Хеш(ДвоичныеДанные, Тип) Экспорт
Хеширование = Новый ХешированиеДанных(Тип);
Хеширование.Добавить(ДвоичныеДанные);
Возврат Хеширование.ХешСумма;
КонецФункции
Функция СклеитьДвоичныеДанные(ДвоичныеДанные1, ДвоичныеДанные2) Экспорт
МассивДвоичныхДанных = Новый Массив;
МассивДвоичныхДанных.Добавить(ДвоичныеДанные1);
МассивДвоичныхДанных.Добавить(ДвоичныеДанные2);
Возврат СоединитьДвоичныеДанные(МассивДвоичныхДанных);
КонецФункции
Функция ПовторитьСтроку(Строка, Количество) Экспорт
Части = Новый Массив(Количество);
Для К = 1 По Количество Цикл
Части.Добавить(Строка);
КонецЦикла;
Возврат СтрСоединить(Части, "");
КонецФункции
// The MIT License (MIT)
//
// Copyright (c) 2017 Vasily Pintov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/pintov/1c-jwt
Функция Base64UrlEncode(Знач Значение) Экспорт
Вывод = Base64Строка(Значение);
Вывод = СтрРазделить(Вывод, "=")[0];
Вывод = СтрЗаменить(Вывод, Символы.ВК + Символы.ПС, "");
Вывод = СтрЗаменить(Вывод, "+" , "-");
Вывод = СтрЗаменить(Вывод, "/" , "_");
Возврат Вывод;
КонецФункции
#КонецОбласти
#КонецОбласти

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="546edcad-c9a0-4823-a44c-fefd7200de6c">
<Properties>
<Name>OPI_ПолучениеДанныхТестов</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI получение данных тестов</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Получение данных тестов (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Набор получения данных и нстроек для выполнения тестов набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="e15aee63-1565-4f37-ba54-4d4e79723fc5">
<Properties>
<Name>OPI_ПреобразованиеТипов</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Преобразование типов (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль приведения типов набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

View File

@@ -0,0 +1,437 @@
// OneScript: ./OInt/tools/Modules/OPI_ПреобразованиеТипов.os
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:UnusedLocalVariable-off
// BSLLS:UsingServiceTag-off
// BSLLS:UsingSynchronousCalls-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check undefined-function-or-procedure
//@skip-check wrong-string-literal-content
// #Использовать "./internal"
#Область СлужебныйПрограммныйИнтерфейс
Процедура ПолучитьДвоичныеДанные(Значение, Знач Безусловно = Ложь, Знач ПопыткаB64 = Истина) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Попытка
Если ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда
Возврат;
ИначеЕсли ЭтоКоллекция(Значение) Тогда
Значение = OPI_Инструменты.JSONСтрокой(Значение);
Значение = ПолучитьДвоичныеДанныеИзСтроки(Значение);
Иначе
ПолучитьСтроку(Значение);
ПреобразоватьИсточникВЗначение(Значение, ПопыткаB64);
КонецЕсли;
Исключение
Если Безусловно Тогда
ПолучитьСтроку(Значение);
Значение = ПолучитьДвоичныеДанныеИзСтроки(Значение);
Иначе
ВызватьИсключение "Ошибка получения двоичных данных из параметра: " + ОписаниеОшибки();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Процедура ПолучитьДвоичныеИлиПоток(Значение) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Если ТипЗнч(Значение) <> Тип("Строка") Тогда
ПолучитьДвоичныеДанные(Значение);
Возврат;
КонецЕсли;
ЗначениеУП = Значение;
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ЗначениеУП);
Файл = Новый Файл(ЗначениеУП);
Если Файл.Существует() Тогда
Значение = Новый ФайловыйПоток(ЗначениеУП, РежимОткрытияФайла.Открыть);
Иначе
ПолучитьДвоичныеДанные(Значение);
КонецЕсли;
КонецПроцедуры
Процедура ПолучитьКоллекцию(Значение, ПоСети = Истина) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Попытка
// BSLLS:ExternalAppStarting-off
ИсходноеЗначение = Значение;
Если ЭтоКоллекция(Значение) Тогда
Возврат;
Иначе
Если ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда
Значение = ПолучитьСтрокуИзДвоичныхДанных(Значение);
Иначе
Значение = OPI_Инструменты.ЧислоВСтроку(Значение);
КонецЕсли;
ЗначениеУП = Значение;
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ЗначениеУП);
Файл = Новый Файл(ЗначениеУП);
ЧтениеJSON = Новый ЧтениеJSON;
Если Файл.Существует() Тогда
ЧтениеJSON.ОткрытьФайл(ЗначениеУП);
Значение = ПрочитатьJSON(ЧтениеJSON, Истина, Неопределено, ФорматДатыJSON.ISO);
ЧтениеJSON.Закрыть();
ИначеЕсли ПоСети И (СтрНачинаетсяС(СокрЛ(ЗначениеУП), "http://")
Или СтрНачинаетсяС(СокрЛ(ЗначениеУП), "https://")) Тогда
Значение = OPI_ЗапросыHTTP.Get(ЗначениеУП);
Иначе
ЧтениеJSON.УстановитьСтроку(СокрЛП(Значение));
Значение = ПрочитатьJSON(ЧтениеJSON, Истина, Неопределено, ФорматДатыJSON.ISO);
ЧтениеJSON.Закрыть();
КонецЕсли;
Если (Не ЭтоКоллекция(Значение)) Или Не ЗначениеЗаполнено(Значение) Тогда
Значение = ИсходноеЗначение;
OPI_Инструменты.ЗначениеВМассив(Значение);
КонецЕсли;
КонецЕсли;
// BSLLS:ExternalAppStarting-on
Исключение
Значение = ИсходноеЗначение;
OPI_Инструменты.ЗначениеВМассив(Значение);
КонецПопытки;
КонецПроцедуры
Процедура ПолучитьКоллекциюКлючИЗначение(Значение
, Знач СообщениеОшибки = "Указанное значение не является подходящей коллекцией!") Экспорт
ПолучитьКоллекцию(Значение);
Если ТипЗнч(Значение) = Тип("Массив") Тогда
ВызватьИсключение СообщениеОшибки;
КонецЕсли;
КонецПроцедуры
Процедура ПолучитьМассив(Значение) Экспорт
Если ТипЗнч(Значение) = Тип("Массив") Тогда
Возврат;
КонецЕсли;
ПолучитьКоллекцию(Значение);
Если Не ТипЗнч(Значение) = Тип("Массив") Тогда
OPI_Инструменты.ЗначениеВМассив(Значение);
КонецЕсли;
КонецПроцедуры
Процедура ПолучитьБулево(Значение) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Попытка
Если ТипЗнч(Значение) = Тип("Булево") Тогда
Возврат;
Иначе
Значение = Булево(Значение);
КонецЕсли;
Исключение
ВызватьИсключение "Ошибка получения данных булево из параметра";
КонецПопытки;
КонецПроцедуры
Процедура ПолучитьСтроку(Значение, Знач ИзИсточника = Ложь) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Попытка
Если ЭтоСимвольное(Значение) Тогда
Значение = OPI_Инструменты.ЧислоВСтроку(Значение);
Если Не ИзИсточника Тогда
Возврат;
КонецЕсли;
ЗначениеУП = Значение;
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ЗначениеУП);
Файл = Новый Файл(ЗначениеУП);
Если Файл.Существует() Тогда
ЧтениеТекста = Новый ЧтениеТекста(ЗначениеУП);
Значение = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
ИначеЕсли СтрНачинаетсяС(СокрЛ(ЗначениеУП), "http://")
Или СтрНачинаетсяС(СокрЛ(ЗначениеУП), "https://") Тогда
Значение = OPI_ЗапросыHTTP.Get(ЗначениеУП);
ПолучитьСтроку(Значение);
Иначе
Значение = OPI_Инструменты.ЧислоВСтроку(Значение);
КонецЕсли;
ИначеЕсли ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда
Значение = ПолучитьСтрокуИзДвоичныхДанных(Значение);
ИначеЕсли ЭтоКоллекция(Значение) Тогда
Значение = OPI_Инструменты.JSONСтрокой(Значение);
ИначеЕсли ТипЗнч(Значение) = Тип("ЗаписьXML") Тогда
Значение = Значение.Закрыть();
Иначе
Возврат;
КонецЕсли;
Исключение
Значение = Строка(Значение);
Возврат;
КонецПопытки;
КонецПроцедуры
Процедура ПолучитьДату(Значение) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Дата = "Дата";
Попытка
Если ТипЗнч(Значение) = Тип(Дата) Тогда
Возврат;
Иначе
Значение = XMLЗначение(Тип(Дата), Значение);
КонецЕсли;
Исключение
ООД = Новый ОписаниеТипов(Дата);
Значение = ООД.ПривестиЗначение(Значение);
КонецПопытки;
КонецПроцедуры
Процедура ПолучитьЧисло(Значение) Экспорт
Если ТипЗнч(Значение) = Тип("Число") Тогда
Возврат;
ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
Значение = ?(Значение, 1, 0);
Иначе
ОписаниеТипа = Новый ОписаниеТипов("Число");
Значение_ = ОписаниеТипа.ПривестиЗначение(Значение);
Если Значение_ = 0 Тогда
Попытка
Значение_ = Строка(Значение);
Значение_ = СтрЗаменить(Значение, Символы.НПП, "");
Значение_ = СтрЗаменить(Значение, " " , "");
Значение_ = СтрЗаменить(Значение, "," , ".");
Если СтрЧислоВхождений(Значение_, ".") > 1 Тогда
МассивЧастей = СтрРазделить(Значение_, ".");
ПоследняяЧасть = МассивЧастей.ВГраница();
ДробнаяЧасть = МассивЧастей[ПоследняяЧасть];
МассивЧастей.Удалить(ПоследняяЧасть);
Значение_ = СтрШаблон("%1.%2", СтрСоединить(МассивЧастей), ДробнаяЧасть);
КонецЕсли;
// BSLLS:TryNumber-off
Значение = Число(Значение_);
// BSLLS:TryNumber-on
Исключение
Возврат;
КонецПопытки;
Иначе
Значение = Значение_;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ПолучитьФайлНаДиске(Значение, Знач Расширение = "tmp") Экспорт
СтруктураВозврата = Новый Структура("Путь,Временный", "", Ложь);
ЗначениеСтрокой = OPI_Инструменты.ЧислоВСтроку(Значение);
ЗначениеФайл = Новый Файл(ЗначениеСтрокой);
Если ЗначениеФайл.Существует() Тогда
СтруктураВозврата.Вставить("Путь", ЗначениеФайл.ПолноеИмя);
Иначе
ПолучитьДвоичныеДанные(Значение, Истина);
// BSLLS:MissingTemporaryFileDeletion-off
//@skip-check missing-temporary-file-deletion
Путь = ПолучитьИмяВременногоФайла(Расширение);
// BSLLS:MissingTemporaryFileDeletion-on
Значение.Записать(Путь);
СтруктураВозврата.Вставить("Путь" , Путь);
СтруктураВозврата.Вставить("Временный", Истина);
КонецЕсли;
Значение = СтруктураВозврата;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ЭтоКоллекция(Знач Значение)
Возврат ТипЗнч(Значение) = Тип("Массив")
Или ТипЗнч(Значение) = Тип("Структура")
Или ТипЗнч(Значение) = Тип("Соответствие");
КонецФункции
Функция ЭтоСимвольное(Знач Значение)
Возврат ТипЗнч(Значение) = Тип("Строка")
Или ТипЗнч(Значение) = Тип("Число")
Или ТипЗнч(Значение) = Тип("Дата");
КонецФункции
Процедура ПреобразоватьИсточникВЗначение(Значение, ПопыткаB64)
ЗначениеУП = Значение;
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ЗначениеУП);
Файл = Новый Файл(ЗначениеУП);
Если Файл.Существует() Тогда
Значение = Новый ДвоичныеДанные(ЗначениеУП);
ИначеЕсли СтрНачинаетсяС(СокрЛ(ЗначениеУП), "http://")
Или СтрНачинаетсяС(СокрЛ(ЗначениеУП), "https://") Тогда
Значение = OPI_ЗапросыHTTP.Get(ЗначениеУП);
Иначе
Если ПопыткаB64 Тогда
Значение = Base64Значение(Значение);
Иначе
ВызватьИсключение "значение не является путем к файлу или Base64 строкой";
КонецЕсли;
КонецЕсли;
КонецПроцедуры
#КонецОбласти

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="ca6868b2-8987-4ae3-9d97-50a8becc72df">
<Properties>
<Name>OPI_Тесты</Name>
<Synonym>
<v8:item>
<v8:lang/>
<v8:content>OPI тесты</v8:content>
</v8:item>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Тесты для YaxUnit/1testrunner (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Основной модуль тестов набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonModule uuid="c8f0d0dd-27b1-4c84-9874-a0adeb256793">
<Properties>
<Name>OPI_ТестыCLI</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Тесты CLI-приложения (служебный, ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment>Модуль тестов консольного приложения (CLI) набора ОПИ</Comment>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>true</ExternalConnection>
<ClientOrdinaryApplication>true</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonTemplate uuid="2fbb1523-522e-42e1-8167-986b0706ee39">
<Properties>
<Name>OPI_Cryptography</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Компонента криптографии (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment/>
<TemplateType>AddIn</TemplateType>
</Properties>
</CommonTemplate>
</MetaDataObject>

Binary file not shown.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonTemplate uuid="4d395e12-f3b7-4903-9db6-289028ccf30e">
<Properties>
<Name>OPI_FTP</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Компонента FTP (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment/>
<TemplateType>AddIn</TemplateType>
</Properties>
</CommonTemplate>
</MetaDataObject>

Binary file not shown.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.9">
<CommonTemplate uuid="d9661565-cc17-4009-8df2-27ce855a8128">
<Properties>
<Name>OPI_MSSQL</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Компонента MS SQL (ОПИ)</v8:content>
</v8:item>
</Synonym>
<Comment/>
<TemplateType>AddIn</TemplateType>
</Properties>
</CommonTemplate>
</MetaDataObject>

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More