添加GuruSDKService实现GuruSDK接口
commit
db6324507d
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f647ee76aa4564f8897ce89748ce73b5
|
||||||
|
timeCreated: 1702610996
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "GuruSDKService.Editor",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d6c9b9a5879c04077be02fc6801ad1c7
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a5e437dfefb504adc8311fcd64360dac
|
||||||
|
timeCreated: 1702610991
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
using System;
|
||||||
|
using Guru;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace GuruSDKService
|
||||||
|
{
|
||||||
|
public partial class GuruSDKService
|
||||||
|
{
|
||||||
|
private void AddCallbackListener()
|
||||||
|
{
|
||||||
|
GuruSDK.Callbacks.App.OnAppPaused += OnAppPaused;
|
||||||
|
GuruSDK.Callbacks.App.OnAppQuit += OnAppQuit;
|
||||||
|
|
||||||
|
GuruSDK.Callbacks.ConsentFlow.OnConsentResult += OnConsentResult;
|
||||||
|
GuruSDK.Callbacks.ConsentFlow.OnAttResult += OnAttResult;
|
||||||
|
|
||||||
|
GuruSDK.Callbacks.SDK.OnFirebaseReady += OnFirebaseReady;
|
||||||
|
GuruSDK.Callbacks.SDK.OnGuruServiceReady += OnGuruServiceReady;
|
||||||
|
GuruSDK.Callbacks.SDK.OnUserAuthResult += OnUserAuthResult;
|
||||||
|
GuruSDK.Callbacks.SDK.OnFirebaseAuthResult += OnFirebaseAuthResult;
|
||||||
|
|
||||||
|
GuruSDK.Callbacks.Ads.OnAdsInitComplete += OnAdsInitComplete;
|
||||||
|
GuruSDK.Callbacks.Ads.OnBannerADLoaded += OnBannerADLoaded;
|
||||||
|
GuruSDK.Callbacks.Ads.OnInterstitialADLoaded += OnInterstitialADLoaded;
|
||||||
|
GuruSDK.Callbacks.Ads.OnInterstitialADFailed += OnInterstitialADFailed;
|
||||||
|
GuruSDK.Callbacks.Ads.OnRewardedADLoaded += OnRewardedADLoaded;
|
||||||
|
GuruSDK.Callbacks.Ads.OnRewardADFailed += OnRewardADFailed;
|
||||||
|
|
||||||
|
GuruSDK.Callbacks.Remote.OnRemoteFetchComplete += OnRemoteFetchComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region App Callbacks
|
||||||
|
|
||||||
|
private void OnAppPaused(bool paused)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnAppPaused] paused:{paused}");
|
||||||
|
_serviceImp?.OnAppPaused(paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAppQuit()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnAppQuit]");
|
||||||
|
_serviceImp?.OnAppQuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region SDK Callbacks
|
||||||
|
|
||||||
|
private Action _onFirebaseReady;
|
||||||
|
|
||||||
|
private void OnFirebaseReady(bool success)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnFirebaseReady] success:{success}");
|
||||||
|
if (success) _onFirebaseReady?.Invoke();
|
||||||
|
_serviceImp?.OnFirebaseReady(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGuruServiceReady()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnGuruServiceReady]");
|
||||||
|
_serviceImp?.OnGuruServiceReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUserAuthResult(bool success)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnUserAuthResult] success:{success}");
|
||||||
|
_serviceImp?.OnUserAuthResult(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFirebaseAuthResult(bool success)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnFirebaseAuthResult] success:{success}");
|
||||||
|
_serviceImp?.OnFirebaseAuthResult(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConsentFlow Callbacks
|
||||||
|
|
||||||
|
private void OnAttResult(int authorizationTrackingStatus)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnAttResult] authorizationTrackingStatus:{authorizationTrackingStatus}");
|
||||||
|
_serviceImp?.OnAttResult(authorizationTrackingStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnConsentResult(int statusCode)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnConsentResult] statusCode:{statusCode}");
|
||||||
|
_serviceImp?.OnConsentResult(statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region AD Callbacks
|
||||||
|
|
||||||
|
private void OnAdsInitComplete()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnAdsInitComplete]");
|
||||||
|
_serviceImp?.OnAdsInitComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasBannerADLoaded;
|
||||||
|
|
||||||
|
private void OnBannerADLoaded()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnBannerADLoaded]");
|
||||||
|
GuruSDK.Callbacks.Ads.OnBannerADLoaded -= OnBannerADLoaded; //只监听第一次banner加载成功,处理banner显示逻辑
|
||||||
|
HasBannerADLoaded = true;
|
||||||
|
_serviceImp?.OnBannerADLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInterstitialADLoaded()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnInterstitialADLoaded]");
|
||||||
|
_serviceImp?.OnInterstitialADLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInterstitialADFailed()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnInterstitialADFailed]");
|
||||||
|
_serviceImp?.OnInterstitialADFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRewardedADLoaded()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnRewardedADLoaded]");
|
||||||
|
_serviceImp?.OnRewardedADLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRewardADFailed()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnRewardADFailed]");
|
||||||
|
_serviceImp?.OnRewardADFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Firebase Component Callbacks
|
||||||
|
|
||||||
|
public bool IsRemoteConfigFetchSuccess = false;
|
||||||
|
|
||||||
|
private void OnRemoteFetchComplete(bool success)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnRemoteFetchComplete] success:{success}");
|
||||||
|
IsRemoteConfigFetchSuccess = success;
|
||||||
|
_serviceImp?.OnRemoteFetchComplete(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 80bb2eef12fb4131b6add5667fabfe80
|
||||||
|
timeCreated: 1711961092
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
using Guru;
|
||||||
|
using UnityEngine.Purchasing;
|
||||||
|
|
||||||
|
namespace GuruSDKService
|
||||||
|
{
|
||||||
|
public partial class GuruSDKService
|
||||||
|
{
|
||||||
|
private void AddIAPCallbackListener()
|
||||||
|
{
|
||||||
|
GuruSDK.Callbacks.IAP.OnIAPInitStart += OnIAPInitStart;
|
||||||
|
GuruSDK.Callbacks.IAP.OnIAPInitComplete += OnIAPInitComplete;
|
||||||
|
GuruSDK.Callbacks.IAP.OnPurchaseStart += OnPurchaseStart;
|
||||||
|
GuruSDK.Callbacks.IAP.OnPurchaseEnd += OnPurchaseEnd;
|
||||||
|
GuruSDK.Callbacks.IAP.OnPurchaseFailed += OnPurchaseFailed;
|
||||||
|
GuruSDK.Callbacks.IAP.OnIAPRestored += OnIAPRestored;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region callbacks
|
||||||
|
|
||||||
|
private void OnIAPInitStart()
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnIAPInitStart]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnIAPInitComplete(bool success)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnIAPInitComplete] success:{success}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPurchaseStart(string productName)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnPurchaseStart] productName:{productName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPurchaseEnd(string productName, bool success)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnPurchaseEnd] productName:{productName}, success:{success}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPurchaseFailed(string productName, string reason)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnPurchaseFailed] productName:{productName}, reason:{reason}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnIAPRestored(bool success, string msg)
|
||||||
|
{
|
||||||
|
Log.I($"[GuruCallback][OnIAPRestored] success:{success}, msg:{msg}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 查询接口
|
||||||
|
|
||||||
|
public string GetProductCurrencyCode(string productName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(productName))
|
||||||
|
return Fallback();
|
||||||
|
|
||||||
|
var productInfo = GuruSDK.GetProductInfo(productName);
|
||||||
|
if (productInfo == null)
|
||||||
|
return Fallback();
|
||||||
|
|
||||||
|
return productInfo.CurrencyCode;
|
||||||
|
|
||||||
|
string Fallback()
|
||||||
|
{
|
||||||
|
return "USD";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetProductPriceString(string productName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(productName))
|
||||||
|
return Fallback();
|
||||||
|
|
||||||
|
var productInfo = GuruSDK.GetProductInfo(productName);
|
||||||
|
if (productInfo == null)
|
||||||
|
return Fallback();
|
||||||
|
|
||||||
|
return productInfo.LocalizedPriceString;
|
||||||
|
|
||||||
|
string Fallback()
|
||||||
|
{
|
||||||
|
return "$0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetProductPrice(string productName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(productName))
|
||||||
|
return Fallback();
|
||||||
|
|
||||||
|
var productInfo = GuruSDK.GetProductInfo(productName);
|
||||||
|
if (productInfo == null)
|
||||||
|
return Fallback();
|
||||||
|
|
||||||
|
return productInfo.Price;
|
||||||
|
|
||||||
|
double Fallback()
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void ShowIAPLoadingView() => _serviceImp.ShowIAPBuyLoadingView();
|
||||||
|
public void CloseIAPLoadingView() => _serviceImp.CloseIAPLoadingView();
|
||||||
|
public void IAPBuySuccessTip() => _serviceImp.IAPBuySuccessTip();
|
||||||
|
public void IAPBuyFailTip() => _serviceImp.IAPBuyFailTip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ad27e726ba8d45d2a9a2d363dda6105d
|
||||||
|
timeCreated: 1711961364
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
using Guru;
|
||||||
|
|
||||||
|
namespace GuruSDKService
|
||||||
|
{
|
||||||
|
public partial class GuruSDKService
|
||||||
|
{
|
||||||
|
private void InitSDKModel()
|
||||||
|
{
|
||||||
|
if (_serviceImp != null)
|
||||||
|
{
|
||||||
|
SetGuruSDK_BLevel(_serviceImp.b_level);
|
||||||
|
SetGuruSDK_BPlay(_serviceImp.b_play);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetGuruSDK_BLevel(int level)
|
||||||
|
{
|
||||||
|
GuruSDK.SuccessLevelCount = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetGuruSDK_BPlay(int play)
|
||||||
|
{
|
||||||
|
GuruSDK.TotalPlayedCount = play;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ed356411d778456f92641f70d047df48
|
||||||
|
timeCreated: 1711961510
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "GuruSDKService",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:e241d247f550f427da05939864204192",
|
||||||
|
"GUID:85fac0454e8c64a0da25f1f632acaa75",
|
||||||
|
"GUID:94e1de2458b07d0bf1e9f13e6ae06443",
|
||||||
|
"GUID:e63a64384cc3ef04cac761c1ce76e9c2",
|
||||||
|
"GUID:d0bf1e9f644394e1de13e6ae02458b07"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 32693d56dfa3a46a3a0c9f54101785f1
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Guru;
|
||||||
|
|
||||||
|
namespace GuruSDKService
|
||||||
|
{
|
||||||
|
public partial class GuruSDKService : Singleton<GuruSDKService>
|
||||||
|
{
|
||||||
|
private bool _initService;
|
||||||
|
private IGuruSDKServiceImp _serviceImp;
|
||||||
|
|
||||||
|
public void InitService(IGuruSDKServiceImp serviceImp, Action onFirebaseReady)
|
||||||
|
{
|
||||||
|
if(_initService) return;
|
||||||
|
_initService = true;
|
||||||
|
_serviceImp = serviceImp;
|
||||||
|
_onFirebaseReady = onFirebaseReady;
|
||||||
|
InitSDKModel();
|
||||||
|
AddCallbackListener();
|
||||||
|
AddIAPCallbackListener();
|
||||||
|
|
||||||
|
Guru.Analytics.EnableTch02Event = true;
|
||||||
|
GuruSDKInitConfig config = new GuruSDKInitConfig
|
||||||
|
{
|
||||||
|
UseCustomConsent = false,
|
||||||
|
AutoLoadWhenAdsReady = true,
|
||||||
|
AutoRecordFinishedLevels = true,
|
||||||
|
IsBuyNoAds = _serviceImp.IsNoAD,
|
||||||
|
CustomServiceKey = _serviceImp.CustomServiceKey,
|
||||||
|
BannerBackgroundColor = _serviceImp.BannerBackgroundColor,
|
||||||
|
IAPEnabled = _serviceImp.IsIAPEnabled,
|
||||||
|
DebugMode = _serviceImp.IsDebugMode,
|
||||||
|
DefaultRemoteData = _serviceImp.GetDefaultRemoteData(),
|
||||||
|
GoogleKeys = _serviceImp.GetGooglePlayTangleData(),
|
||||||
|
AppleRootCerts = _serviceImp.GetAppleTangleData()
|
||||||
|
};
|
||||||
|
GuruSDK.Init(config, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 66b76eee6ce0469087e581f05beb810f
|
||||||
|
timeCreated: 1711960633
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace GuruSDKService
|
||||||
|
{
|
||||||
|
public interface IGuruSDKServiceImp
|
||||||
|
{
|
||||||
|
#region GuruSDKInitConfig初始化参数
|
||||||
|
|
||||||
|
string CustomServiceKey { get; }
|
||||||
|
string BannerBackgroundColor { get; }
|
||||||
|
bool IsNoAD { get; }
|
||||||
|
bool IsIAPEnabled { get; }
|
||||||
|
bool IsDebugMode { get; }
|
||||||
|
Dictionary<string, object> GetDefaultRemoteData();
|
||||||
|
byte[] GetGooglePlayTangleData();
|
||||||
|
byte[] GetAppleTangleData();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Model映射
|
||||||
|
|
||||||
|
int b_level { get; set; }
|
||||||
|
int b_play { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Callbacks回调
|
||||||
|
|
||||||
|
void OnAppPaused(bool paused);
|
||||||
|
void OnAppQuit();
|
||||||
|
|
||||||
|
void OnFirebaseReady(bool success);
|
||||||
|
void OnGuruServiceReady();
|
||||||
|
void OnUserAuthResult(bool success);
|
||||||
|
void OnFirebaseAuthResult(bool success);
|
||||||
|
|
||||||
|
void OnAttResult(int authorizationTrackingStatus);
|
||||||
|
void OnConsentResult(int statusCode);
|
||||||
|
|
||||||
|
void OnAdsInitComplete();
|
||||||
|
void OnBannerADLoaded();
|
||||||
|
void OnInterstitialADLoaded();
|
||||||
|
void OnInterstitialADFailed();
|
||||||
|
void OnRewardedADLoaded();
|
||||||
|
void OnRewardADFailed();
|
||||||
|
|
||||||
|
void OnRemoteFetchComplete(bool success);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IAP回调
|
||||||
|
|
||||||
|
void OnIAPInitStart();
|
||||||
|
void OnIAPInitComplete(bool success);
|
||||||
|
void OnPurchaseStart(string productName);
|
||||||
|
void OnPurchaseEnd(string productName, bool success);
|
||||||
|
void OnPurchaseFailed(string productName, string reason);
|
||||||
|
void OnIAPRestored(bool success, string msg);
|
||||||
|
|
||||||
|
void ShowIAPBuyLoadingView();
|
||||||
|
void CloseIAPLoadingView();
|
||||||
|
void IAPBuySuccessTip();
|
||||||
|
void IAPBuyFailTip();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7ceb27a94150440981555f022a7a628b
|
||||||
|
timeCreated: 1711961309
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<linker>
|
||||||
|
<assembly fullname="GuruSDKService">
|
||||||
|
<namespace fullname="GuruSDKService" preserve="all"/>
|
||||||
|
</assembly>
|
||||||
|
</linker>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2f1de04af38814476b397f7803cfe3a4
|
||||||
|
timeCreated: 1703388178
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "com.guru.sdk.service",
|
||||||
|
"displayName": "Guru SDK Service",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Guru SDK Service for unity project",
|
||||||
|
"unity": "2020.3",
|
||||||
|
"author":{
|
||||||
|
"name": "Guru Games"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"category": "Game,Tool,Development",
|
||||||
|
"dependencies": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 76154b361987a46ea8809e66e06f7a38
|
||||||
|
timeCreated: 1702610734
|
||||||
Loading…
Reference in New Issue