Инструкция по миграции🔗
Данный документ содержит инструкцию по обновлению MRGS SDK, в случае, когда в код или настройки проекта нужно внести какие-либо изменения.
4.x.x → 6.0.0🔗
MRGSAuthentication🔗
- Класс
MRGSAuthenticationVKontakteперемещен в свой собственный модуль MRGSAuthenticationVK. -
Класс
MRGSAuthenticationGoogleGamesпереименован вMRGSAuthenticationGoogleSignInи перемещен в свой собственный модуль MRGSAuthenticationGoogleSignIn -
Enum
MRGSAuthenticationNetworkудален. - Enum
MRGSAuthenticationNetwork#Unknownудален. - Enum
MRGSAuthenticationNetwork#Amazonудален. ИспользуйтеMRGSAuthenticationAmazon#SocialID. - Enum
MRGSAuthenticationNetwork#AppleGameCenterудален. ИспользуйтеMRGSAuthenticationAppleGameCenter#SocialID. - Enum
MRGSAuthenticationNetwork#Facebookудален. ИспользуйтеMRGSAuthenticationFacebook#SocialID. - Enum
MRGSAuthenticationNetwork#GoogleGamesудален. ИспользуйтеMRGSAuthenticationGoogleSignIn#SocialID. - Enum
MRGSAuthenticationNetwork#MyGamesудален. ИспользуйтеMRGSAuthenticationMyGames#SocialID. - Enum
MRGSAuthenticationNetwork#Plariumудален. ИспользуйтеMRGSAuthenticationPlarium#SocialID. - Enum
MRGSAuthenticationNetwork#SignInWithAppleудален. ИспользуйтеMRGSAuthenticationSignInWithApple#SocialID. - Enum
MRGSAuthenticationNetwork#VKontakteудален. ИспользуйтеMRGSAuthenticationVKontakte#SocialID. -
Enum
MRGSAuthenticationNetwork#VKIdудален. ИспользуйтеMRGSAuthenticationVKId#SocialID. -
Enum
MRGSAuthenticationScopeудален. - Enum
MRGSAuthenticationScope#AmazonPostalCodeудален. ИспользуйтеMRGSAuthenticationAmazon.Scopes#PostalCode. -
Enum
MRGSAuthenticationScope#AmazonProfileудален. ИспользуйтеMRGSAuthenticationAmazon.Scopes#Profile. -
Enum
MRGSAuthenticationScope#FacebookBirthdayудален. ИспользуйтеMRGSAuthenticationFacebook.Scopes#UserBirthday. - Enum
MRGSAuthenticationScope#FacebookEmailудален. ИспользуйтеMRGSAuthenticationFacebook.Scopes#Email. - Enum
MRGSAuthenticationScope#FacebookFriendsудален. ИспользуйтеMRGSAuthenticationFacebook.Scopes#UserFriends. - Enum
MRGSAuthenticationScope#FacebookGenderудален. ИспользуйтеMRGSAuthenticationFacebook.Scopes#UserGender. - Enum
MRGSAuthenticationScope#FacebookHometownудален. ИспользуйтеMRGSAuthenticationFacebook.Scopes#UserHometown. -
Enum
MRGSAuthenticationScope#FacebookLocationудален. ИспользуйтеMRGSAuthenticationFacebook.Scopes#UserLocation. -
Enum
MRGSAuthenticationScope#SignInWithAppleEmailудален. ИспользуйтеMRGSAuthenticationSignInWithApple.Scopes#Email. -
Enum
MRGSAuthenticationScope#SignInWithAppleFullNameудален. ИспользуйтеMRGSAuthenticationSignInWithApple.Scopes#FullName. -
Enum
MRGSAuthenticationScope#VKontakteEmailудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Email. - Enum
MRGSAuthenticationScope#VKontakteFriendsудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Friends. - Enum
MRGSAuthenticationScope#VKontakteGroupsудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Groups. - Enum
MRGSAuthenticationScope#VKontakteMessagesудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Messages. - Enum
MRGSAuthenticationScope#VKontakteNotificationsудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Notifications. - Enum
MRGSAuthenticationScope#VKontaktePhotosудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Photos. - Enum
MRGSAuthenticationScope#VKontakteStatusудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Status. -
Enum
MRGSAuthenticationScope#VKontakteWallудален. ИспользуйтеMRGSAuthenticationVKontakte.Scopes#Wall. -
Свойство
MRGSAuthenticationAchievement#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. - Свойство
MRGSAuthenticationLeaderboard#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. - Свойство
MRGSAuthenticationLeaderboardScore#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. - Свойство
MRGSAuthenticationInvite#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. -
Свойство
MRGSAuthenticationPost#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. -
Свойство
MRGSAuthenticationAccessToken#AuthorizedScopesтеперь возвращаетList<string>вместоList<MRGSAuthenticationScope>. -
Свойство
MRGSAuthenticationAccessToken#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. -
Свойство
MRGSAuthenticationCredential#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. -
Свойство
MRGSAuthenticationUser#SocialIdтеперь возвращаетstringвместоMRGSAuthenticationNetwork. -
Метод
MRGSAuthenticationPost#HasPermissionsтеперь принимаетList<string>вместоList<MRGSAuthenticationScope>. - Метод
MRGSAuthentication#Login(List<MRGSAuthenticationScope>, Action<MRGSAuthenticationCredential, MRGSError>)заменен наMRGSAuthentication#Login(List<string>, Action<MRGSAuthenticationCredential, MRGSError>). - Метод
MRGSAuthentication#SocialId()теперь возвращаетstringвместоMRGSAuthenticationNetwork.
MRGService🔗
-
MRGSMyTracker был перемещен в свой собственный модуль MRGSMyTracker и больше не поставляется с MRGService модулем.
-
Класс
MRGSMyTrackerParamsперемещен в модуль MRGSMyTracker. - Класс
MRGSVKontakteParamsперемещен в модуль MRGSAuthenticationVK. -
Класс
MRGSVKIdParamsперемещен в модуль MRGSAuthenticationVKId. -
Enum
BankSubstitutionудален. ИспользуйтеMRGSMyGamesBank#UseAsMainBank()иMRGSVKPay#UseAsMainBank(). -
Свойство
MRGSMyGamesParams#VKPlayModeудалено. ИспользуйтеMRGSMyGamesParams#CustomHost. -
Добавлен новый метод для инициализации
MRGService#Initialize(MRGServiceParams, IEnumerable<MRGSExternalSDKSettings>, IMRGSServerDataDelegate).var serviceParams = new MRGServiceParams("xxxxxx", "xxxxxx"); var trackerParams = new MRGSMyTrackerParams("xxxxxx") { Debug = true, ForwardMetrics = true, TrackingLocationEnabled = true }; var vkParams = new MRGSVKontakteParams("xxxxxxx"); var vkIdParams = new MRGSVKIdParams("xxxxx", "xxxxxxxxxxx") { Debug = true }; MRGSExternalSDKSettings[] additionalParams = { trackerParams, vkParams, vkIdParams }; MRGService.Instance.Initialize(serviceParams, sdkParams, additionalParams, this);
MRGSSupport🔗
- Enum
MRGSMyGamesSupportCredential.SocialNetwork#Vkontakteудален.
3.x.x → 4.0.0🔗
MRGSAdvertising🔗
-
Изменен делегат
MRGSAdvertising.MRGSAdvertisingLoadDelegate: -
Изменен делегат
MRGSAdvertising.MRGSAdvertisingShowDelegate: -
Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
MRGSAnalytics🔗
-
Изменен делегат
MRGSAppsFlyerDelegate: -
Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов, реализация вынесена во внутреннюю часть
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGSAuthentication🔗
-
Все классы работы с соцсетями переделаны на интерфейсы, метод
.Instance(getInstance()) теперь возвращает интерфейс:MRGSAuthenticationAmazon.Instance теперь возвращает IMRGSAuthenticationAmazon MRGSAuthenticationAppleGameCenter.Instance теперь возвращает IMRGSAuthenticationAppleGameCenter MRGSAuthenticationFacebook.Instance теперь возвращает IMRGSAuthenticationFacebook MRGSAuthenticationGoogleGames.Instance теперь возвращает IMRGSAuthenticationGoogleGames MRGSAuthenticationMyGames.Instance теперь возвращает IMRGSAuthenticationMyGames MRGSAuthenticationPlarium.Instance теперь возвращает IMRGSAuthenticationPlarium MRGSAuthenticationSignInWithApple.Instance теперь возвращает IMRGSAuthenticationSignInWithApple MRGSAuthenticationVKontakte.Instance теперь возвращает IMRGSAuthenticationVKontakte -
Изменены значения в
MRGSAuthenticationScope: -
Изменен enum
MRGSAuthenticationAchievementState->MRGSAuthenticationAchievement.State - Изменен делегат
IMRGSAuthenticationDelegate:onAuthenticationProviderDidLogoutUser->OnAuthenticationProviderDidLogoutUser - Добавлены коды и домены ошибок:
MRGSAuthenticationErrorCodeиMRGSAuthenticationErrorDomain - Удалены
Obsoleteметоды - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов, исправлены уровни доступа к полям классов, реализация вынесена во внутреннюю часть
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:MRGSAuthenticationAmazon.getInstance().method() -> MRGSAuthenticationAmazon.Instance.Method() MRGSAuthenticationAppleGameCenter.getInstance().method() -> MRGSAuthenticationAppleGameCenter.Instance.Method() MRGSAuthenticationFacebook.getInstance().method() -> MRGSAuthenticationFacebook.Instance.Method() MRGSAuthenticationGoogleGames.getInstance().method() -> MRGSAuthenticationGoogleGames.Instance.Method() MRGSAuthenticationMyGames.getInstance().method() -> MRGSAuthenticationMyGames.Instance.Method() MRGSAuthenticationPlarium.getInstance().method() -> MRGSAuthenticationPlarium.Instance.Method() MRGSAuthenticationSignInWithApple.getInstance().method() -> MRGSAuthenticationSignInWithApple.Instance.Method() MRGSAuthenticationVKontakte.getInstance().method() -> MRGSAuthenticationVKontakte.Instance.Method()
MRGSBank🔗
- Переименован класс
MRGSBankProductsResponce -> MRGSBankProductsResponse -
Делегат
MRGSBankDelegateExи полеMRGSBank.getInstance.DelegateExtendedотмечены какObsolete, используйте аналогIMRGSBankDelegateи полеMRGSBank.Instance.Delegate:MRGSBankDelegateEx -> IMRGSBankDelegate MRGSBank.getInstance.DelegateExtended -> MRGSBank.Instance.Delegate onReceiveProductsResponce -> OnReceiveProductsResponse onReceiveProductsError -> OnReceiveProductsError onReceiveSucessfullPurchase -> OnReceiveSuccessfulPurchase onReceiveFailedPurchase -> OnReceiveFailedPurchase onReceivePendingPurchase -> OnReceivePendingPurchase onReceiveCancelledPurchase -> OnReceiveCancelledPurchase onTransactionsRestoreCompleted -> OnTransactionsRestoreCompleted -
Изменен enum
MRGSSubscriptionPeriod.MRGSSubscriptionPeriodUnit->MRGSSubscriptionPeriod.PeriodUnit: -
Изменен enum
MRGSBankProductDiscount.MRGSDiscountPaymentMode->MRGSBankProductDiscount.DiscountPaymentMode: -
Изменен enum
MRGSBankProductDiscount.MRGSDiscountType->MRGSBankProductDiscount.DiscountType: -
Удалены
Obsoleteметоды - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов, исправлены уровни доступа к полям классов
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGService🔗
- Класс
MRGSFlurryParamsудален. - Класс
MRGSChartboostParamsудален. - Класс
MRGSGoogleConversionTrackingParamsудален. - Интерфейс
MRGSServerDataDelegateпереименован вIMRGSServerDataDelegate - Свойство
MRGSExtraOptionsiOS#MRGSNotificationCenterSupportedудалено - Свойство
MRGSExternalSDKParams#FlurryParamsудалено - Свойство
MRGSExternalSDKParams#ChartboostParamsудалено - Свойство
MRGSExternalSDKParams#GoogleConversionTrackingParamsудалено - Метод
MRGSLog#addPaymentLog(string)удален. - Проверка интеграции теперь возвращает объект нового класса
MRGSIntegrationCheckResult -
Добавлена поддержка async/await для методов в классе
MRGSDevice: -
Для async/await методов MRGS добавлено расширение
.Throwable(): -
Удалены
Obsoleteметоды - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:MRGService.getInstance().method() -> MRGService.Instance.Method() MRGSDevice.getInstance().method() -> MRGSDevice.Instance.Method() MRGSLog.getInstance().method() -> MRGSLog.Instance.Method() MRGSMetrics.getInstance().method() -> MRGSMetrics.Instance.Method() MRGSMyTracker.getInstance().method() -> MRGSMyTracker.Instance.Method() MRGSUsers.getInstance().method() -> MRGSUsers.Instance.Method() -
Теперь для новой инициализации MRGService под Android требуется указывать MRGSPlatform аналогично платформе из MRGS админки вашего проекта.
MRGSFirebase🔗
- Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGSGameCenter🔗
- Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
- Интерфейс
MRGSGameCenterClientDelegateудален. ИспользуйтеIMRGSGameCenterClientDelegate -
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGSGDPR🔗
- Интерфейс
MRGSCOPPA.IMRGSCOPPADelegateпереименован вMRGSCOPPA.IShowDelegate - Интерфейс
MRGSCOPPA.IMRGSGDPRDelegateпереименован вMRGSCOPPA.IShowDelegate - Удалены
Obsoleteметоды - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
- Enum
MRGSCCPAUserPreference.MRGSCCPAUserPreferenceShareпереименован вMRGSCCPAUserPreference.Share - Enum
MRGSCCPAUserPreference.MRGSCCPAUserPreferenceNotSharingпереименован вMRGSCCPAUserPreference.NotSharing -
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGSNotifications🔗
- В
MRGServiceParamsубран флагMRGSNotificationCenterSupported - В
MRGServiceParamsпереименован флагDefferedMRGSNotificationCenterStart -> DeferredMRGSNotificationCenterStart -
Изменен enum
LockScreenVisibility: -
Изменен enum
MRGSNotificationTriggerType->MRGSNotificationTrigger.Type: -
Удалены
Obsoleteметоды и классы - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGSRecommendations🔗
- Удалены
Obsoleteметоды - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
MRGSShowcase🔗
- Метод интерфейса
IMRGSShowcaseDelegate#didReceiveNewShowcaseContent(int)переименован вIMRGSShowcaseDelegate#OnReceiveNewShowcaseContent(int) - Все методы, начинающиеся со строчной буквы и не соответствующие "naming conventions" помечены как
Obsoleteи были добавлены аналогичные с заглавной буквы, соответствующие конвенциям. - Скрыта private часть, изменена структура файлов
-
Изменен доступ к singleton - метод
getInstanceперенесен в полеInstance:
2.x.x - 3.0.0🔗
Мигрировать на новую версию просто - сначала переместите файл Assets/Plugins/MRGS/iOS/MRGService.plist на новое место Assets/Plugins/iOS/MRGService.plist (если вы используете инициализацию из файлов, в противном случае можно пропустить данный шаг), далее достаточно удалить папки Assets/Plugins/Editor/MRGS и Assets/Plugins/MRGS, а затем добавить наш репозиторий в раздел scopedRegistries (подробнее смотрите на странице интеграции SDK). Либо можно импортировать unitypackage файлы из архива, скачанного с сайта MRGS.
Но проще всего будет использовать специальный MigrationScript, доступный по ссылке, либо в скачанном архиве. Достаточно добавить его в проект, в верхнем меню выбрать раздел MRGS, и выбрать опцию миграции на UPM (MRGS сам удалит старые файлы, определит используемые модули, и добавит раздел scopedRegistries и используемые модули), либо удаления старого проекта MRGS.
Также, мы сделали сборку Legacy формата, она так же лежит в архиве.
2.0.x - 2.1.0🔗
Основное изменение - MRGService Android теперь зависит от библиотек серии androidx, вместо support-library.
MRGSUnityLegacy🔗
Если вы используете Legacy версию плагина, отредактируйте mainTemplate.gradle файл
Удалите старые зависимости, такие как:
'com.my.tracker:mytracker-sdk:1.5.8'
'com.google.android.gms:play-services-ads-identifier:16.0.0'
'com.android.support:support-v4:28.0.0'
'com.android.support:recyclerview-v7:28.0.0'
'com.android.support:appcompat-v7:28.0.0'
'com.android.support:support-vector-drawable:28.0.0'
'com.android.support:multidex:1.0.3'
'com.google.firebase:firebase-core:16.0.9'
'com.google.firebase:firebase-messaging:18.0.0'
Добавьте новые:
'com.my.tracker:mytracker-sdk:1.5.12'
'androidx.appcompat:appcompat:1.1.0'
'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
'androidx.recyclerview:recyclerview:1.0.0'
'androidx.vectordrawable:vectordrawable:1.1.0'
'androidx.multidex:multidex:2.0.0'
'com.google.firebase:firebase-analytics:17.2.1'
'com.google.firebase:firebase-messaging:20.0.0'
Так же вам необходимо заменить в mainTemplate.gradle classpath 'com.android.tools.build:gradle:3.2.0' на classpath 'com.android.tools.build:gradle:3.4.0'
MRGSUnity и MRGSBaseUnity🔗
Если вы используете MRGService Unity с поддержкой Google Play Services Resolver, то зависимости будут обновлены автоматически. Для надежности можете удалить все aar и jar файлы из директории Assets/Plugins/Android и вызвать в Assets -> Play Services Resolver -> Android -> Force Resolve
1.0.49 - 2.0.0🔗
В версии 2.0.0 плагин MRGS был разбит на модули (отдельные unitypackage), отвечающие за отдельные компоненты MRGS. Во избежании проблем, при обновлении с версии 1.0.х на версию 2.0.0 мы рекомендуем вам загружать версию вез модулей (архив под названием MRGServiceUnityLegacy.zip)
Если вы все же решили перейти на версию с модулями, вы можете импортировать все .unitypacakge файлы из архива MRGServiceUnity.zip Данная сборка включает в себя Google Play Services Resolver. Вам необходимо либо отключить его, либо удалить старые зависимости. Для этого отредактируйте файл mainTemplate.gradle и удалите из секции dependencies вот эти зависимости
compile 'com.my.tracker:mytracker-sdk:1.5.8'
compile 'com.google.android.gms:play-services-ads-identifier:16.0.0'
compile 'com.android.billingclient:billing:2.0.3'
compile 'com.android.support:support-v4:28.0.0'
compile 'com.android.support:recyclerview-v7:28.0.0'
compile 'com.android.support:appcompat-v7:28.0.0'
compile 'com.android.support:support-vector-drawable:28.0.0'
compile 'com.google.firebase:firebase-core:16.0.9'
compile 'com.google.firebase:firebase-messaging:18.0.0'
Если внутри директории Assets/Plugins/MRGS/iOS/Frameworks/ у вас есть файл MRGServiceResources.bundle, его необходимо удалить
1.0.48 - 1.0.49🔗
В версии 1.0.49 произошло большое изменение библиотеки MRGS для Android. Она обновилась до версии 4.0 и теперь представляет из себя набор из 9 aar файлов
MRGSAdvertising.aar
MRGSAnalytics.aar
MRGSBilling.aar
MRGSGDPR.aar
MRGSGameCenter.aar
MRGSNotifications.aar
MRGSSupport.aar
MRGService.aar
- Перед импортом новой версии MRGSUnity.unitypackage удалите старые aar файлы в директории Assets/Plugins/MRGS/Android
-
После импорта всех файлов, обратите внимание на шаблон mainTemplate.gradle
-
Удалены зависимости
'com.google.android.gms:play-services-analytics:16.0.3'
'com.google.android.gms:play-services-gcm:15.0.1'
- Обновлены зависимости
'com.android.support:multidex:1.0.1' -> 'com.android.support:multidex:1.0.3'
'com.android.support:support-v4:27.1.1' -> 'com.android.support:support-v4:28.0.0'
'com.android.support:appcompat-v7:27.1.1' -> 'com.android.support:appcompat-v7:28.0.0'
'com.android.support:recyclerview-v7:27.1.1' -> 'com.android.support:recyclerview-v7:28.0.0'
'com.google.firebase:firebase-core:16.0.3' -> 'com.google.firebase:firebase-core:16.0.9'
'com.google.firebase:firebase-messaging:17.3.0' -> 'com.google.firebase:firebase-messaging:18.0.0'
- Добавлены зависимости
'com.google.android.gms:play-services-ads-identifier:16.0.0'
'com.android.support:support-vector-drawable:28.0.0'
-
Если вы использовали Billing Samsung
-
Необходимо в секции
<SamsungBilling>указать тип сборки (mode) "test" или "production"
- В архиве с библиотекой MRGS, в директории Extra необходимо взять библиотеку IAP5Helper.aar и добавить ее в свой проект.
Дата создания: 2020-01-16