mirror of
https://github.com/Bayselonarrend/OpenIntegrations.git
synced 2024-12-25 02:42:28 +02:00
Google: авторизация, первые методы календаря
This commit is contained in:
parent
16cefb34b5
commit
7bc606f19d
202
OPI/src/CommonModules/OPI_GoogleCalendar/Module.bsl
Normal file
202
OPI/src/CommonModules/OPI_GoogleCalendar/Module.bsl
Normal file
@ -0,0 +1,202 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2023 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
|
||||
|
||||
#Область ПрограммныйИнтерфейс
|
||||
|
||||
#Область РаботаСоСпискомКалендарей
|
||||
|
||||
// Получить список календарей.
|
||||
//
|
||||
// Параметры:
|
||||
// Токен - Строка - Токен
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Соответствие Из КлючИЗначение - Массив соответствий данных календарей
|
||||
Функция ПолучитьСписокКалендарей(Знач Токен) Экспорт
|
||||
|
||||
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
|
||||
МассивКалендарей = Новый Массив;
|
||||
|
||||
ПолучитьСписокКалендарейРекурсивно(Заголовки, МассивКалендарей);
|
||||
|
||||
Возврат МассивКалендарей;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Добавить календарь в список.
|
||||
//
|
||||
// Параметры:
|
||||
// Токен - Строка - Токен
|
||||
// Календарь - Строка - ID календаря
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - ответ сервера Google
|
||||
Функция ДобавитьКалендарьВСписок(Знач Токен, Знач Календарь) Экспорт
|
||||
|
||||
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
|
||||
URL = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
|
||||
|
||||
Параметры = Новый Структура;
|
||||
Параметры.Вставить("id", Календарь);
|
||||
|
||||
Ответ = OPI_Инструменты.Post(URL, Параметры, Заголовки);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область РаботаСКалендарями
|
||||
|
||||
// Создать календарь.
|
||||
//
|
||||
// Параметры:
|
||||
// Токен - Строка - Токен
|
||||
// Наименование - Строка - Наименование создаваемого календаря
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - ответ сервера Google
|
||||
Функция СоздатьКалендарь(Знач Токен, Знач Наименование) Экспорт
|
||||
|
||||
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
|
||||
URL = "https://www.googleapis.com/calendar/v3/calendars";
|
||||
|
||||
Параметры = Новый Структура;
|
||||
Параметры.Вставить("summary", Наименование);
|
||||
|
||||
Ответ = OPI_Инструменты.Post(URL, Параметры, Заголовки);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Получить календарь.
|
||||
//
|
||||
// Параметры:
|
||||
// Токен - Строка - Токен
|
||||
// Календарь - Строка - ID календаря
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - ответ сервера Google
|
||||
Функция ПолучитьКалендарь(Знач Токен, Знач Календарь) Экспорт
|
||||
|
||||
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
|
||||
URL = "https://www.googleapis.com/calendar/v3/calendars/" + Календарь;
|
||||
Ответ = OPI_Инструменты.Get(URL, , Заголовки);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Изменить календарь.
|
||||
//
|
||||
// Параметры:
|
||||
// Токен - Строка - Токен
|
||||
// Календарь - Строка - ID календаря
|
||||
// Наименование - Строка - Новое наименование
|
||||
// Описание - Строка - Новое описание календаря
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - ответ сервера Google
|
||||
Функция ИзменитьКалендарь(Знач Токен, Знач Календарь, Знач Наименование = "", Знач Описание = "") Экспорт
|
||||
|
||||
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
|
||||
URL = "https://www.googleapis.com/calendar/v3/calendars/" + Календарь;
|
||||
|
||||
Параметры = Новый Структура;
|
||||
|
||||
Если ЗначениеЗаполнено(Наименование) Тогда
|
||||
Параметры.Вставить("summary", Наименование);
|
||||
КонецЕсли;
|
||||
|
||||
Если ЗначениеЗаполнено(Описание) Тогда
|
||||
Параметры.Вставить("description", Описание);
|
||||
КонецЕсли;
|
||||
|
||||
Ответ = OPI_Инструменты.Put(URL, Параметры, Заголовки);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Удалить календарь.
|
||||
//
|
||||
// Параметры:
|
||||
// Токен - Строка - Токен
|
||||
// Календарь - Строка - ID календаря
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - ответ сервера Google
|
||||
Функция УдалитьКалендарь(Знач Токен, Знач Календарь) Экспорт
|
||||
|
||||
Заголовки = ПолучитьЗаголовокАвторизации(Токен);
|
||||
URL = "https://www.googleapis.com/calendar/v3/calendars/" + Календарь;
|
||||
Ответ = OPI_Инструменты.Delete(URL, , Заголовки);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область СлужебныеПроцедурыИФункции
|
||||
|
||||
Функция ПолучитьЗаголовокАвторизации(Знач Токен)
|
||||
|
||||
Заголовки = Новый Соответствие;
|
||||
Заголовки.Вставить("Authorization", "Bearer " + Токен);
|
||||
|
||||
Возврат Заголовки;
|
||||
|
||||
КонецФункции
|
||||
|
||||
Процедура ПолучитьСписокКалендарейРекурсивно(Знач Заголовки, МассивКалендарей, Страница = "")
|
||||
|
||||
Параметры = Новый Структура;
|
||||
|
||||
Если ЗначениеЗаполнено(Страница) Тогда
|
||||
Параметры.Вставить("pageToken", Страница);
|
||||
КонецЕсли;
|
||||
|
||||
Результат = OPI_Инструменты.Get("https://www.googleapis.com/calendar/v3/users/me/calendarList"
|
||||
,
|
||||
, Заголовки);
|
||||
|
||||
Календари = Результат["items"];
|
||||
Страница = Результат["nextPageToken"];
|
||||
|
||||
Для Каждого Календарь Из Календари Цикл
|
||||
МассивКалендарей.Добавить(Календарь);
|
||||
КонецЦикла;
|
||||
|
||||
Если Календари.Количество() > 0 И ЗначениеЗаполнено(Страница) Тогда
|
||||
ПолучитьСписокКалендарейРекурсивно(Заголовки, МассивКалендарей, Страница);
|
||||
КонецЕсли;
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
#КонецОбласти
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="d27d4ffb-31c2-4362-bd6d-d785ce171b49">
|
||||
<name>OPI_GoogleCalendar</name>
|
||||
<synonym>
|
||||
<key></key>
|
||||
<value>OPI google calendar</value>
|
||||
</synonym>
|
||||
<server>true</server>
|
||||
<externalConnection>true</externalConnection>
|
||||
<clientOrdinaryApplication>true</clientOrdinaryApplication>
|
||||
</mdclass:CommonModule>
|
114
OPI/src/CommonModules/OPI_GoogleWorkspace/Module.bsl
Normal file
114
OPI/src/CommonModules/OPI_GoogleWorkspace/Module.bsl
Normal file
@ -0,0 +1,114 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2023 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
|
||||
|
||||
#Область ПрограммныйИнтерфейс
|
||||
|
||||
// Сформировать ссылку получения кода.
|
||||
//
|
||||
// Параметры:
|
||||
// ClientID - Строка - Client ID
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка - Сформировать ссылку получения кода
|
||||
Функция СформироватьСсылкуПолученияКода(Знач ClientID) Экспорт
|
||||
|
||||
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" , ПолучитьСписокРазрешений());
|
||||
|
||||
URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL);
|
||||
|
||||
Возврат URL;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Получить токен по коду.
|
||||
//
|
||||
// Параметры:
|
||||
// ClientID - Строка - Client ID
|
||||
// ClientSecret - Строка - Client secret
|
||||
// Code - Строка - Code из браузера
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - Получить токен по коду
|
||||
Функция ПолучитьТокенПоКоду(Знач ClientID, Знач ClientSecret, Знач 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_Инструменты.Post(URL, ПараметрыURL, , Ложь);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
// Обновить токен.
|
||||
//
|
||||
// Параметры:
|
||||
// ClientID - Строка - Client ID
|
||||
// ClientSecret - Строка - Client secret
|
||||
// RefreshToken - Строка - Refresh token
|
||||
//
|
||||
// Возвращаемое значение:
|
||||
// Строка, Произвольный, ДвоичныеДанные, Неопределено, HTTPОтвет - Обновить токен
|
||||
Функция ОбновитьТокен(Знач ClientID, Знач ClientSecret, Знач 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_Инструменты.Post(URL, ПараметрыURL, , Ложь);
|
||||
|
||||
Возврат Ответ;
|
||||
|
||||
КонецФункции
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область СлужебныеПроцедурыИфункции
|
||||
|
||||
Функция ПолучитьСписокРазрешений()
|
||||
|
||||
МассивРазрешений = Новый Массив;
|
||||
МассивРазрешений.Добавить("https://www.googleapis.com/auth/calendar");
|
||||
|
||||
Возврат СтрСоединить(МассивРазрешений, " ");
|
||||
|
||||
КонецФункции
|
||||
#КонецОбласти
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="e5bf1867-4c83-4724-91f2-931150325ea0">
|
||||
<name>OPI_GoogleWorkspace</name>
|
||||
<synonym>
|
||||
<key></key>
|
||||
<value>OPI google workspace</value>
|
||||
</synonym>
|
||||
<server>true</server>
|
||||
<externalConnection>true</externalConnection>
|
||||
<clientOrdinaryApplication>true</clientOrdinaryApplication>
|
||||
</mdclass:CommonModule>
|
@ -137,7 +137,7 @@
|
||||
|
||||
URL = СтрЗаменить(URL, "https://", "");
|
||||
URL = СтрЗаменить(URL, "http://", "");
|
||||
URL = СтрЗаменить(URL, "www.", "");
|
||||
//URL = СтрЗаменить(URL, "www.", "");
|
||||
URL = СтрЗаменить(URL, ":443", "");
|
||||
|
||||
СтруктураВозврата = Новый Структура;
|
||||
|
@ -58,7 +58,14 @@
|
||||
.ДобавитьСерверныйТест("ЯДиск_ПолучитьСписокФайлов" , "Получить список файлов")
|
||||
.ДобавитьСерверныйТест("ЯДиск_ПереместитьОбъект" , "Переместить объект")
|
||||
.ДобавитьСерверныйТест("ЯДиск_ДействияПубличныхОбъектов" , "Действия с публичными объектами")
|
||||
.ДобавитьСерверныйТест("ЯДиск_ПолучитьСписокОпубликованных" , "Получить список опубликованных");
|
||||
.ДобавитьСерверныйТест("ЯДиск_ПолучитьСписокОпубликованных" , "Получить список опубликованных")
|
||||
|
||||
.ДобавитьТестовыйНабор("Google Calendar")
|
||||
.ДобавитьСерверныйТест("ГК_ПолучитьСсылкуАвторизации" , "Получить ссылку авторизации")
|
||||
.ДобавитьСерверныйТест("ГК_ПолучитьТокен" , "Получить токен")
|
||||
.ДобавитьСерверныйТест("ГК_ОбновитьТокен" , "Обновить токен")
|
||||
.ДобавитьСерверныйТест("ГК_ПолучитьСписокКалендарей" , "Получить список календарей")
|
||||
.ДобавитьСерверныйТест("ГК_СоздатьУдалитьКалендарь" , "Создать/удалить календарь");
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
@ -1484,6 +1491,108 @@
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#Область GoogleCalendar
|
||||
|
||||
Процедура ГК_ПолучитьСсылкуАвторизации() Экспорт
|
||||
|
||||
ClientID = ПолучитьПараметр("Google_ClientID");
|
||||
Результат = OPI_GoogleWorkspace.СформироватьСсылкуПолученияКода(ClientID);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат)
|
||||
.ИмеетТип("Строка")
|
||||
.Заполнено();
|
||||
|
||||
ЗаписатьПараметр("Google_Link", Результат);
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура ГК_ПолучитьТокен() Экспорт
|
||||
|
||||
ClientID = ПолучитьПараметр("Google_ClientID");
|
||||
ClientSecret = ПолучитьПараметр("Google_ClientSecret");
|
||||
Code = ПолучитьПараметр("Google_Code");
|
||||
|
||||
Результат = OPI_GoogleWorkspace.ПолучитьТокенПоКоду(ClientID, ClientSecret, Code);
|
||||
|
||||
Если ЗначениеЗаполнено(Результат["access_token"])
|
||||
И ЗначениеЗаполнено(Результат["refresh_token"]) Тогда
|
||||
|
||||
ЗаписатьПараметр("Google_Token" , Результат["access_token"]);
|
||||
ЗаписатьПараметр("Google_Refresh", Результат["refresh_token"]);
|
||||
|
||||
КонецЕсли;
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура ГК_ОбновитьТокен() Экспорт
|
||||
|
||||
ClientID = ПолучитьПараметр("Google_ClientID");
|
||||
ClientSecret = ПолучитьПараметр("Google_ClientSecret");
|
||||
RefreshToken = ПолучитьПараметр("Google_Refresh");
|
||||
|
||||
Результат = OPI_GoogleWorkspace.ОбновитьТокен(ClientID, ClientSecret, RefreshToken);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат)
|
||||
.ИмеетТип("Соответствие")
|
||||
.Свойство("access_token").Заполнено();
|
||||
|
||||
ЗаписатьПараметр("Google_Token" , Результат["access_token"]);
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура ГК_ПолучитьСписокКалендарей() Экспорт
|
||||
|
||||
Токен = ПолучитьПараметр("Google_Token");
|
||||
Результат = OPI_GoogleCalendar.ПолучитьСписокКалендарей(Токен);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат)
|
||||
.ИмеетТип("Массив");
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура ГК_СоздатьУдалитьКалендарь() Экспорт
|
||||
|
||||
Токен = ПолучитьПараметр("Google_Token");
|
||||
Наименование = "Тестовый календарь";
|
||||
Описание = "Тестовое описание";
|
||||
НаименованиеИзмененное = Наименование + " (изм.)";
|
||||
|
||||
Результат = OPI_GoogleCalendar.СоздатьКалендарь(Токен, Наименование);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат)
|
||||
.ИмеетТип("Соответствие")
|
||||
.Свойство("summary").Равно(Наименование)
|
||||
.Свойство("id").ИмеетТип("Строка").Заполнено();
|
||||
|
||||
Календарь = Результат["id"];
|
||||
|
||||
Результат = OPI_GoogleCalendar.ИзменитьКалендарь(Токен
|
||||
, Календарь
|
||||
, НаименованиеИзмененное
|
||||
, Описание);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат)
|
||||
.ИмеетТип("Соответствие")
|
||||
.Свойство("summary").Равно(НаименованиеИзмененное)
|
||||
.Свойство("description").Равно(Описание)
|
||||
.Свойство("id").ИмеетТип("Строка").Заполнено();
|
||||
|
||||
Результат = OPI_GoogleCalendar.ПолучитьКалендарь(Токен, Календарь);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат)
|
||||
.ИмеетТип("Соответствие")
|
||||
.Свойство("summary").Равно(НаименованиеИзмененное)
|
||||
.Свойство("description").Равно(Описание)
|
||||
.Свойство("id").ИмеетТип("Строка").Заполнено();
|
||||
|
||||
Результат = OPI_GoogleCalendar.УдалитьКалендарь(Токен, Календарь);
|
||||
|
||||
ЮТест.ОжидаетЧто(Результат).НеЗаполнено();
|
||||
|
||||
КонецПроцедуры
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#КонецОбласти
|
||||
|
||||
#КонецОбласти
|
||||
|
@ -48,13 +48,15 @@
|
||||
<languageCode>ru</languageCode>
|
||||
</languages>
|
||||
<commonModules>CommonModule.OPI_Инструменты</commonModules>
|
||||
<commonModules>CommonModule.OPI_Криптография</commonModules>
|
||||
<commonModules>CommonModule.OPI_Telegram</commonModules>
|
||||
<commonModules>CommonModule.OPI_VK</commonModules>
|
||||
<commonModules>CommonModule.OPI_Viber</commonModules>
|
||||
<commonModules>CommonModule.OPI_Twitter</commonModules>
|
||||
<commonModules>CommonModule.OPI_Notion</commonModules>
|
||||
<commonModules>CommonModule.OPI_Криптография</commonModules>
|
||||
<commonModules>CommonModule.OPI_YandexID</commonModules>
|
||||
<commonModules>CommonModule.OPI_YandexDisk</commonModules>
|
||||
<commonModules>CommonModule.OPI_GoogleWorkspace</commonModules>
|
||||
<commonModules>CommonModule.OPI_GoogleCalendar</commonModules>
|
||||
<commonModules>CommonModule.YAX_Тесты</commonModules>
|
||||
</mdclass:Configuration>
|
||||
|
Loading…
Reference in New Issue
Block a user