From 3c0223cf5685cca97647291463a0c9322ea0caef Mon Sep 17 00:00:00 2001 From: Anton Date: Fri, 26 Jan 2024 16:31:33 +0300 Subject: [PATCH] =?UTF-8?q?Notion=20API:=20=D0=91=D0=BB=D0=BE=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OPI/src/CommonModules/OPI_Notion/Module.bsl | 181 +++++++++++++++-- .../CommonModules/OPI_Инструменты/Module.bsl | 183 +++++++++--------- 2 files changed, 262 insertions(+), 102 deletions(-) diff --git a/OPI/src/CommonModules/OPI_Notion/Module.bsl b/OPI/src/CommonModules/OPI_Notion/Module.bsl index 4200998e5..41e8b8707 100644 --- a/OPI/src/CommonModules/OPI_Notion/Module.bsl +++ b/OPI/src/CommonModules/OPI_Notion/Module.bsl @@ -254,7 +254,7 @@ ДобавитьСвойстваБазы(Свойства, Параметры); КонецЕсли; - Ответ = OPI_Инструменты.Patch("https://api.notion.com/v1/databases"+ База, Параметры, Заголовки); + Ответ = OPI_Инструменты.Patch("https://api.notion.com/v1/databases/"+ База, Параметры, Заголовки); Возврат Ответ; @@ -262,6 +262,144 @@ #КонецОбласти +#Область РаботаСБлоками + +// Создать блок. +// +// Параметры: +// Токен - Строка - Токен +// Родитель - Строка - ID родительского блока или страницы +// ИДБлока - Строка - ID блока, копию которого необходимо добавить +// ВставитьПосле - Строка - ID блока, после которого необходимо встаивть новый, если родитель уже имеет дочерние блоки +// +// Возвращаемое значение: +// Строка, Произвольный, Неопределено, ДвоичныеДанные, HTTPОтвет - Ответ сервера Notion +Функция СоздатьБлок(Знач Токен, Знач Родитель, Знач ИДБлока, Знач ВставитьПосле = "") Экспорт + + ПреобразоватьИД(Родитель); + ПреобразоватьИД(ИДБлока); + + Заголовки = СоздатьЗаголовкиЗапроса(Токен); + Блок = ВернутьБлок(Токен, ИДБлока); + УдалитьЛишниеПоляБлока(Блок); + + МассивБлоков = Новый Массив; + МассивБлоков.Добавить(Блок); + + Параметры = Новый Соответствие; + Параметры.Вставить("children", МассивБлоков); + + Если ЗначениеЗаполнено(ВставитьПосле) Тогда + Параметры.Вставить("after", ВставитьПосле); + КонецЕсли; + + Ответ = OPI_Инструменты.Patch("https://api.notion.com/v1/blocks/" + Родитель + "/children" + , Параметры + , Заголовки); + + Возврат Ответ; + +КонецФункции + +// Вернуть блок. +// +// Параметры: +// Токен - Строка - Токен +// ИДБлока - Строка - ID блока +// +// Возвращаемое значение: +// Неопределено, ДвоичныеДанные, Строка, Произвольный - Ответ сервера Notion +Функция ВернутьБлок(Знач Токен, Знач ИДБлока) Экспорт + + ПреобразоватьИД(ИДБлока); + + Заголовки = СоздатьЗаголовкиЗапроса(Токен); + Ответ = OPI_Инструменты.Get("https://api.notion.com/v1/blocks/" + ИДБлока, , Заголовки); + + Возврат Ответ; + +КонецФункции + +// Вернуть дочерние блоки. +// +// Параметры: +// Токен - Строка - Токен +// ИДБлока - Строка - ID блока-родителя +// +// Возвращаемое значение: +// Неопределено, ДвоичныеДанные, Строка, Произвольный - Ответ сервера Notion +Функция ВернутьДочерниеБлоки(Знач Токен, Знач ИДБлока) Экспорт + + ПреобразоватьИД(ИДБлока); + + Заголовки = СоздатьЗаголовкиЗапроса(Токен); + Ответ = OPI_Инструменты.Get("https://api.notion.com/v1/blocks/" + ИДБлока + "/children", , Заголовки); + + Возврат Ответ; + +КонецФункции + +// Удалить блок. +// +// Параметры: +// Токен - Строка - Токен +// ИДБлока - Строка - ID блока +// +// Возвращаемое значение: +// Неопределено, ДвоичныеДанные, Строка, Произвольный - Ответ сервера Notion +Функция УдалитьБлок(Знач Токен, Знач ИДБлока) Экспорт + + ПреобразоватьИД(ИДБлока); + + Заголовки = СоздатьЗаголовкиЗапроса(Токен); + Ответ = OPI_Инструменты.Delete("https://api.notion.com/v1/blocks/" + ИДБлока, , Заголовки); + + Возврат Ответ; + +КонецФункции + + +#КонецОбласти + +#Область Пользователи + +// Список пользователей. +// +// Параметры: +// Токен - Строка - Токен +// +// Возвращаемое значение: +// Неопределено, ДвоичныеДанные, Строка, Произвольный - Ответ сервера Notion +Функция СписокПользователей(Знач Токен) Экспорт + + Заголовки = СоздатьЗаголовкиЗапроса(Токен); + Ответ = OPI_Инструменты.Get("https://api.notion.com/v1/users", , Заголовки); + + Возврат Ответ; + +КонецФункции + +// Получить данные пользователя. +// +// Параметры: +// Токен - Строка - Токен +// ИДПользователя - Строка - ID целевого пользователя +// +// Возвращаемое значение: +// Неопределено, ДвоичныеДанные, Строка, Произвольный - Получить данные пользователя +Функция ПолучитьДанныеПользователя(Знач Токен, Знач ИДПользователя) Экспорт + + ПреобразоватьИД(ИДПользователя); + + Заголовки = СоздатьЗаголовкиЗапроса(Токен); + Ответ = OPI_Инструменты.Get("https://api.notion.com/v1/users/" + ИДПользователя, , Заголовки); + + Возврат Ответ; + +КонецФункции + +#КонецОбласти + #КонецОбласти #Область СлужебныеПроцедурыИФункции @@ -277,19 +415,8 @@ КонецФункции Процедура ПреобразоватьИД(Идентификатор) - - Если СтрНайти(Идентификатор, "-" = 0) Тогда - - МассивЧастей = Новый Массив; - МассивЧастей.Добавить(Лев(Идентификатор , 8)); - МассивЧастей.Добавить(Сред(Идентификатор , 9 , 4)); - МассивЧастей.Добавить(Сред(Идентификатор , 12, 4)); - МассивЧастей.Добавить(Сред(Идентификатор , 15, 4)); - МассивЧастей.Добавить(Прав(Идентификатор , 12)); - - Идентификатор = СтрСоединить(МассивЧастей, "-"); - - КонецЕсли + + Идентификатор = СтрЗаменить(Идентификатор, "-", ""); КонецПроцедуры @@ -374,6 +501,10 @@ ВыборЗначения = СформироватьЗначенияВыбора(Свойство.Значение); СоответствиеПараметров.Вставить(Свойство.Ключ, Новый Структура("select", ВыборЗначения)) + + Иначе + + СоответствиеПараметров.Вставить(Свойство.Ключ, Свойство.Значение); КонецЕсли; @@ -441,6 +572,28 @@ КонецФункции +Процедура УдалитьЛишниеПоляБлока(Знач Блок) + + МассивЛишних = Новый Массив; + МассивЛишних.Добавить("request_id"); + МассивЛишних.Добавить("archived"); + МассивЛишних.Добавить("created_by"); + МассивЛишних.Добавить("last_edited_time"); + МассивЛишних.Добавить("created_time"); + МассивЛишних.Добавить("has_children"); + МассивЛишних.Добавить("parrent"); + МассивЛишних.Добавить("last_edited_by"); + МассивЛишних.Добавить("id"); + + Для Каждого Поле Из МассивЛишних Цикл + + Если Не Блок.Получить(Поле) = Неопределено Тогда + Блок.Удалить(Поле); + КонецЕсли; + КонецЦикла + +КонецПроцедуры + #Область ПреобразованиеТипов Функция ПреобразоватьЗначениеПоТипу(Знач Тип, Знач Значение) diff --git a/OPI/src/CommonModules/OPI_Инструменты/Module.bsl b/OPI/src/CommonModules/OPI_Инструменты/Module.bsl index 430b78ae3..e0efcd314 100644 --- a/OPI/src/CommonModules/OPI_Инструменты/Module.bsl +++ b/OPI/src/CommonModules/OPI_Инструменты/Module.bsl @@ -26,34 +26,11 @@ #Область HTTPМетоды Функция Get(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "") Экспорт + Возврат ВыполнитьЗапросБезТела(URL, "GET", Параметры, ДопЗаголовки); +КонецФункции - Если Не ЗначениеЗаполнено(Параметры) Тогда - Параметры = Новый Структура; - КонецЕсли; - - Заголовки = Новый Соответствие; - - Если ТипЗнч(ДопЗаголовки) = Тип("Соответствие") Тогда - - Для Каждого Заголовок Из ДопЗаголовки Цикл - Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение); - КонецЦикла; - - КонецЕсли; - - СтруктураURL = РазбитьURL(URL); - Соединение = Новый HTTPСоединение(СтруктураURL["Сервер"], 443, , , , 300, Новый ЗащищенноеСоединениеOpenSSL); - Запрос = Новый HTTPЗапрос(СтруктураURL["Адрес"] + ПараметрыЗапросаВСтроку(Параметры), Заголовки); - Ответ = Соединение.Получить(Запрос); - - Попытка - ТелоОтвета = JsonВСтруктуру(Ответ.ПолучитьТелоКакДвоичныеДанные()); - Исключение - ТелоОтвета = Ответ.ПолучитьТелоКакДвоичныеДанные(); - КонецПопытки; - - Возврат ТелоОтвета; - +Функция Delete(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "") Экспорт + Возврат ВыполнитьЗапросБезТела(URL, "DELETE", Параметры, ДопЗаголовки); КонецФункции // BSLLS:CognitiveComplexity-off @@ -215,67 +192,6 @@ #Область Служебные -Функция ВыполнитьЗапросСТелом(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина) - - Если Не ЗначениеЗаполнено(Параметры) Тогда - Параметры = Новый Структура; - КонецЕсли; - - GZip = "gzip"; - ТипДанных = ?(JSON, "application/json", "application/x-www-form-urlencoded"); - СтруктураURL = РазбитьURL(URL); - - Заголовки = Новый Соответствие; - Заголовки.Вставить("Content-Type", ТипДанных); - Заголовки.Вставить("Accept-Encoding", GZip); - Заголовки.Вставить("Accept", "*/*"); - Заголовки.Вставить("Connection", "keep-alive"); - - Если ТипЗнч(ДопЗаголовки) = Тип("Соответствие") Тогда - - Для Каждого Заголовок Из ДопЗаголовки Цикл - Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение); - КонецЦикла; - - КонецЕсли; - - Соединение = Новый HTTPСоединение(СтруктураURL["Сервер"], 443, , , , 300, Новый ЗащищенноеСоединениеOpenSSL); - НовыйЗапрос = Новый HTTPЗапрос(СтруктураURL["Адрес"], Заголовки); - - Если JSON Тогда - Данные = JSONСтрокой(Параметры); - Иначе - СтрокаПараметров = ПараметрыЗапросаВСтроку(Параметры); - Данные = Прав(СтрокаПараметров, СтрДлина(СтрокаПараметров) - 1); - КонецЕсли; - - НовыйЗапрос.УстановитьТелоИзСтроки(Данные); - - Ответ = Соединение.ВызватьHTTPМетод(Вид, НовыйЗапрос); - - НужнаРаспаковка = Ответ.Заголовки.Получить("Content-Encoding") = GZip Или Ответ.Заголовки.Получить( - "content-encoding") = GZip; - - Если НужнаРаспаковка Тогда - Ответ = РаспаковатьОтвет(Ответ); - КонецЕсли; - - Ответ = ?(ТипЗнч(Ответ) = Тип("HTTPОтвет"), Ответ.ПолучитьТелоКакДвоичныеДанные(), Ответ); - - Если ТипЗнч(Ответ) = Тип("ДвоичныеДанные") Тогда - - Попытка - Ответ = JsonВСтруктуру(Ответ); - Исключение - Ответ = ПолучитьСтрокуИзДвоичныхДанных(Ответ); - КонецПопытки; - - КонецЕсли; - - Возврат Ответ; - -КонецФункции - Функция ПараметрыЗапросаВСтроку(Знач Параметры) Экспорт Если Параметры.Количество() = 0 Тогда @@ -365,6 +281,97 @@ #Область СлужебныеПроцедурыИФункции +Функция ВыполнитьЗапросСТелом(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина) + + Если Не ЗначениеЗаполнено(Параметры) Тогда + Параметры = Новый Структура; + КонецЕсли; + + GZip = "gzip"; + ТипДанных = ?(JSON, "application/json", "application/x-www-form-urlencoded"); + СтруктураURL = РазбитьURL(URL); + + Заголовки = Новый Соответствие; + Заголовки.Вставить("Content-Type", ТипДанных); + Заголовки.Вставить("Accept-Encoding", GZip); + Заголовки.Вставить("Accept", "*/*"); + Заголовки.Вставить("Connection", "keep-alive"); + + Если ТипЗнч(ДопЗаголовки) = Тип("Соответствие") Тогда + + Для Каждого Заголовок Из ДопЗаголовки Цикл + Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение); + КонецЦикла; + + КонецЕсли; + + Соединение = Новый HTTPСоединение(СтруктураURL["Сервер"], 443, , , , 300, Новый ЗащищенноеСоединениеOpenSSL); + НовыйЗапрос = Новый HTTPЗапрос(СтруктураURL["Адрес"], Заголовки); + + Если JSON Тогда + Данные = JSONСтрокой(Параметры); + Иначе + СтрокаПараметров = ПараметрыЗапросаВСтроку(Параметры); + Данные = Прав(СтрокаПараметров, СтрДлина(СтрокаПараметров) - 1); + КонецЕсли; + + НовыйЗапрос.УстановитьТелоИзСтроки(Данные); + + Ответ = Соединение.ВызватьHTTPМетод(Вид, НовыйЗапрос); + + НужнаРаспаковка = Ответ.Заголовки.Получить("Content-Encoding") = GZip Или Ответ.Заголовки.Получить( + "content-encoding") = GZip; + + Если НужнаРаспаковка Тогда + Ответ = РаспаковатьОтвет(Ответ); + КонецЕсли; + + Ответ = ?(ТипЗнч(Ответ) = Тип("HTTPОтвет"), Ответ.ПолучитьТелоКакДвоичныеДанные(), Ответ); + + Если ТипЗнч(Ответ) = Тип("ДвоичныеДанные") Тогда + + Попытка + Ответ = JsonВСтруктуру(Ответ); + Исключение + Ответ = ПолучитьСтрокуИзДвоичныхДанных(Ответ); + КонецПопытки; + + КонецЕсли; + + Возврат Ответ; + +КонецФункции + +Функция ВыполнитьЗапросБезТела(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "") + + Если Не ЗначениеЗаполнено(Параметры) Тогда + Параметры = Новый Структура; + КонецЕсли; + + Заголовки = Новый Соответствие; + + Если ТипЗнч(ДопЗаголовки) = Тип("Соответствие") Тогда + + Для Каждого Заголовок Из ДопЗаголовки Цикл + Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение); + КонецЦикла; + + КонецЕсли; + + СтруктураURL = РазбитьURL(URL); + Соединение = Новый HTTPСоединение(СтруктураURL["Сервер"], 443, , , , 300, Новый ЗащищенноеСоединениеOpenSSL); + Запрос = Новый HTTPЗапрос(СтруктураURL["Адрес"] + ПараметрыЗапросаВСтроку(Параметры), Заголовки); + Ответ = Соединение.ВызватьHTTPМетод(Вид, Запрос); + + Попытка + ТелоОтвета = JsonВСтруктуру(Ответ.ПолучитьТелоКакДвоичныеДанные()); + Исключение + ТелоОтвета = Ответ.ПолучитьТелоКакДвоичныеДанные(); + КонецПопытки; + + Возврат ТелоОтвета; + +КонецФункции #Область GZip // Описание структур см. здесь https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT