fix:1、更换项目,使用winter来创建
This commit is contained in:
@@ -1,46 +1,42 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using AppsFlyerSDK;
|
||||
using DG.Tweening;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using SGModule.NetKit;
|
||||
|
||||
// using AppsFlyerSDK;
|
||||
|
||||
// using AppsFlyerSDK;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
|
||||
namespace FlowerPower
|
||||
namespace LoveLegend
|
||||
{
|
||||
public class MaxADKit
|
||||
{
|
||||
public static string SDKKey =
|
||||
"oXM0CzVDi7P1HstOpKvFMInPMOzpQ9uA6t3x75q5f5wQvsEy9vuiiiM94ZJCJSV7PcZGroSSInQCTGsu04QEiE";
|
||||
|
||||
public static string interstitialADUnitID = "12480e9974faffec";
|
||||
public static string interstitialADUnitID = "e3b89b902a31fb28";
|
||||
|
||||
|
||||
public static string rewardedADUnitID = "487d531ebc72302d";
|
||||
public static string AppOpenAdUnitId = "df561dae26462676";
|
||||
public static string rewardedADUnitID = "a19836405c24924d";
|
||||
|
||||
|
||||
private const float RevenueThreshold = 0.1f;
|
||||
private const float RevenueThreshold = 0;
|
||||
|
||||
|
||||
public static Dictionary<string, string> adCallbackInfo;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
MaxSdkCallbacks.OnSdkInitializedEvent += sdkConfiguration =>
|
||||
{
|
||||
if (PlayerPrefs.GetInt("OpenAD", 1) == 1) InitOpenAds();
|
||||
else GameDispatcher.Instance.Dispatch(GameMsg.CloseMask);
|
||||
|
||||
DOVirtual.DelayedCall(7, () =>
|
||||
{
|
||||
InitializeRewardedAds();
|
||||
InitializeInterstitialAds();
|
||||
});
|
||||
InitializeRewardedAds();
|
||||
InitializeInterstitialAds();
|
||||
};
|
||||
|
||||
|
||||
@@ -56,8 +52,15 @@ namespace FlowerPower
|
||||
MaxSdk.InitializeSdk();
|
||||
|
||||
// MaxSdk.ShowMediationDebugger();
|
||||
// #if !UNITY_EDITOR
|
||||
// MBridgeSDKManager.initialize("368295", "fc0155e8f6e8bda23b06d22414379609");
|
||||
// #endif
|
||||
}
|
||||
|
||||
adCallbackInfo = new Dictionary<string, string>();
|
||||
public static void SetUserID(string userID)
|
||||
{
|
||||
user_id = userID;
|
||||
MaxSdk.SetUserId(user_id);
|
||||
}
|
||||
|
||||
#region 插屏广告相关
|
||||
@@ -100,12 +103,15 @@ namespace FlowerPower
|
||||
private static void LoadInterstitial()
|
||||
{
|
||||
MaxSdk.LoadInterstitial(interstitialADUnitID);
|
||||
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_REQUEST, "Interstitial");
|
||||
}
|
||||
|
||||
private static void OnInterstitialLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
retryAttemptInterstitial = 0;
|
||||
NetworkKit.BuriedPoint(BuriedPointEvent.video_type, BuriedPointEvent.Interstitial_videos_fill_number, 1);
|
||||
// NetworkKit.BuriedPoint(BuriedPointEvent.video_type, BuriedPointEvent.Interstitial_videos_fill_number, 1);
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_INVENTORY, "Interstitial", adInfo.Placement, adInfo.NetworkName);
|
||||
}
|
||||
|
||||
private static void OnInterstitialLoadFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo)
|
||||
@@ -118,6 +124,9 @@ namespace FlowerPower
|
||||
|
||||
private static void OnInterstitialDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_IMP, "Interstitial", adInfo.Placement, adInfo.NetworkName,
|
||||
adInfo.Revenue, _placement);
|
||||
}
|
||||
|
||||
private static void OnInterstitialAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo,
|
||||
@@ -128,6 +137,7 @@ namespace FlowerPower
|
||||
|
||||
private static void OnInterstitialClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_CLICK, "Interstitial", adInfo.Placement, adInfo.NetworkName);
|
||||
}
|
||||
|
||||
private static void OnInterstitialHiddenEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
@@ -135,112 +145,71 @@ namespace FlowerPower
|
||||
LoadInterstitial();
|
||||
onInterstitialAdCompleted?.Invoke(true);
|
||||
onInterstitialAdCompleted = null;
|
||||
#if !GAME_RELEASE
|
||||
GameHelper.AdOverRevenueEvent(2, 0.1f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 开屏相关
|
||||
public static UnityAction<bool> onAppOpenAdCompleted;
|
||||
private static void LoadAppOpenAd()
|
||||
{
|
||||
Debug.Log("LOAD APP. AD");
|
||||
MaxSdk.LoadAppOpenAd(AppOpenAdUnitId);
|
||||
}
|
||||
|
||||
|
||||
public static void ShowOpenAdIfReady(UnityAction<bool> onCompleted = null)
|
||||
{
|
||||
// #if UNITY_EDITOR
|
||||
// onCompleted?.Invoke(true);
|
||||
// #else
|
||||
onAppOpenAdCompleted = onCompleted;
|
||||
if (!IsLoaded)
|
||||
{
|
||||
MaxSdkCallbacks.AppOpen.OnAdLoadedEvent += ShowOpenAd;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// bool isFinished = NetworkManager.isWatchedAD;
|
||||
// onCompleted?.Invoke(isFinished);
|
||||
ShowOpenAd(null, null);
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
public static void ShowOpenAd(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
MaxSdk.ShowAppOpenAd(AppOpenAdUnitId);
|
||||
}
|
||||
|
||||
|
||||
public static void InitOpenAds()
|
||||
{
|
||||
|
||||
MaxSdkCallbacks.AppOpen.OnAdLoadedEvent += OnAppOpenLoadedEvent;
|
||||
MaxSdkCallbacks.AppOpen.OnAdLoadFailedEvent += OnOpendAdLoadFailedEvent;
|
||||
// MaxSdkCallbacks.AppOpen.OnAdDisplayedEvent += OnInterstitialDisplayedEvent;
|
||||
MaxSdkCallbacks.AppOpen.OnAdClickedEvent += OnOpenClickedEvent;
|
||||
MaxSdkCallbacks.AppOpen.OnAdHiddenEvent += OnOpenAdHiddenEvent;
|
||||
// MaxSdkCallbacks.AppOpen.OnAdDisplayFailedEvent += OnInterstitialAdFailedToDisplayEvent;
|
||||
MaxSdkCallbacks.AppOpen.OnAdRevenuePaidEvent += OnOpenAdRevenueEvent;
|
||||
LoadAppOpenAd();
|
||||
}
|
||||
private static void OnOpenClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
NetworkKit.BuriedPoint(BuriedPointEvent.open_ad, BuriedPointEvent.open_show, 1);
|
||||
NetworkKit.BuriedPoint(BuriedPointEvent.open_ad, BuriedPointEvent.open_show_people, 1);
|
||||
}
|
||||
private static bool IsLoaded = false;
|
||||
private static void OnAppOpenLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
IsLoaded = true;
|
||||
}
|
||||
private static void OnOpendAdLoadFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo)
|
||||
{
|
||||
// retryAttempt++;
|
||||
// double retryDelay = Math.Pow(2, Math.Min(6, retryAttempt));
|
||||
|
||||
// CrazyAsyKit.StartAction("LoadRewardedAd", LoadRewardedAd, (float)retryDelay);
|
||||
GameDispatcher.Instance.Dispatch(GameMsg.CloseMask);
|
||||
InitializeRewardedAds();
|
||||
InitializeInterstitialAds();
|
||||
}
|
||||
private static void OnOpenAdHiddenEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
// LoadAppOpenAd();
|
||||
onAppOpenAdCompleted?.Invoke(true);
|
||||
onAppOpenAdCompleted = null;
|
||||
// if (GameHelper.IsGiftSwitch() && !SaveData.GetSaveObject().is_get_removead && (Random.Range(0, 100) < GameHelper.GetCommonModel().rewardinsertion))
|
||||
// {
|
||||
// TrackManager.GetInstance.SendTrackEvent(TrackKeys.AfterRewardAdShow);
|
||||
|
||||
// GameHelper.ShowInterstitial("AfterReward");
|
||||
// }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 激励视频广告相关
|
||||
|
||||
|
||||
public static UnityAction<bool> onVideoAdCompleted = null;
|
||||
private static string _placement = "";
|
||||
private static Coroutine _waitForVideoAd = null;
|
||||
public static void ShowVideo(string placement = "DefaultVideo", UnityAction<bool> onCompleted = null)
|
||||
{
|
||||
onVideoAdCompleted = onCompleted;
|
||||
_placement = placement;
|
||||
#if UNITY_EDITOR
|
||||
onCompleted?.Invoke(true);
|
||||
onVideoAdCompleted?.Invoke(true);
|
||||
#else
|
||||
NetworkKit.BuriedPoint(BuriedPointEvent.video_behavior,BuriedPointEvent.watch_ad_people,1);
|
||||
NetworkKit.BuriedPoint(BuriedPointEvent.video_type,BuriedPointEvent.Rewarded_videos_trigger_number,1);
|
||||
TrackKit.SendEvent(VideoBehaviorTrack.Event, VideoBehaviorTrack.Property.watch_ad_people);
|
||||
TrackKit.SendEvent(VideoBehaviorTrack.Event, VideoBehaviorTrack.Property.Rewarded_videos_trigger_number);
|
||||
|
||||
if (MaxSdk.IsRewardedAdReady(rewardedADUnitID))
|
||||
{
|
||||
MaxSdk.ShowRewardedAd(rewardedADUnitID, placement);
|
||||
onVideoAdCompleted=onCompleted;
|
||||
MaxSdk.ShowRewardedAd(rewardedADUnitID, _placement);
|
||||
}
|
||||
else
|
||||
{
|
||||
onCompleted?.Invoke(false);
|
||||
if (_waitForVideoAd != null)
|
||||
{
|
||||
CrazyAsyKit.StopCoroutine(_waitForVideoAd);
|
||||
}
|
||||
_waitForVideoAd = CrazyAsyKit.StartCoroutine(WaitForVideoAd());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
private static IEnumerator WaitForVideoAd()
|
||||
{
|
||||
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PayloadingUI_Open);
|
||||
var count = 0;
|
||||
var result = false;
|
||||
while (count < 6)
|
||||
{
|
||||
if (MaxSdk.IsRewardedAdReady(rewardedADUnitID))
|
||||
{
|
||||
result = true;
|
||||
MaxSdk.ShowRewardedAd(rewardedADUnitID, _placement);
|
||||
break;
|
||||
}
|
||||
|
||||
count++;
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
onVideoAdCompleted?.Invoke(result);
|
||||
}
|
||||
|
||||
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.PayloadingUI_Close);
|
||||
_waitForVideoAd = null;
|
||||
}
|
||||
|
||||
static int retryAttempt;
|
||||
@@ -264,32 +233,24 @@ namespace FlowerPower
|
||||
private static void LoadRewardedAd()
|
||||
{
|
||||
MaxSdk.LoadRewardedAd(rewardedADUnitID);
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_REQUEST, "RewardedVideo");
|
||||
}
|
||||
|
||||
private static void OnInterstitialAdRevenueEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
OnAdRevenuePaidEvent(adUnitId, adInfo, 2);
|
||||
#if !FlowerPowerRelease
|
||||
GameHelper.AdOverRevenueEvent(2, 0.1f);
|
||||
#endif
|
||||
DOVirtual.DelayedCall(0.1f, () =>
|
||||
{
|
||||
OnAdRevenuePaidEvent(adUnitId, adInfo, 2);
|
||||
});
|
||||
}
|
||||
|
||||
private static void OnRewardedAdRevenueEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
OnAdRevenuePaidEvent(adUnitId, adInfo, 1);
|
||||
#if !FlowerPowerRelease
|
||||
GameHelper.AdOverRevenueEvent(1, 0.1f);
|
||||
#endif
|
||||
DOVirtual.DelayedCall(0.1f, () =>
|
||||
{
|
||||
OnAdRevenuePaidEvent(adUnitId, adInfo, 1);
|
||||
});
|
||||
}
|
||||
|
||||
private static void OnOpenAdRevenueEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
OnAdRevenuePaidEvent(adUnitId, adInfo, 3);
|
||||
#if !FlowerPowerRelease
|
||||
GameHelper.AdOverRevenueEvent(3, 0.1f);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string user_id = "";
|
||||
private static void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo, int adType)
|
||||
{
|
||||
@@ -297,40 +258,27 @@ namespace FlowerPower
|
||||
// //string networkName = adInfo.NetworkName; // Display name of the network that showed the ad
|
||||
// // string adUnitIdentifier = adInfo.AdUnitIdentifier; // The MAX Ad Unit ID
|
||||
// //string placement = adInfo.Placement; // The placement this ad's postbacks are tied to
|
||||
// // string networkPlacement = adInfo.NetworkPlacement; // The placement ID from the network that showed the ad
|
||||
string countryCode = "USD";
|
||||
|
||||
adCallbackInfo.Clear();
|
||||
adCallbackInfo.Add("appsflyer_id", AppsFlyer.getAppsFlyerId());
|
||||
adCallbackInfo.Add("customer_user_id", user_id);
|
||||
adCallbackInfo.Add("af_currency", countryCode);
|
||||
|
||||
//广告收益上传(扣量)((用户累计收益大于0.1上报50%,50%可配置))
|
||||
double revenue = Convert.ToDouble(PlayerPrefs.GetString($"adInfoRevenue_{user_id}", "0"));
|
||||
revenue += adInfo.Revenue;
|
||||
|
||||
if (adInfo.Revenue > 0)
|
||||
|
||||
//广告收益上传(用户收益,每次上传)
|
||||
double revenue = adInfo.Revenue;
|
||||
|
||||
if (revenue > 0)
|
||||
{
|
||||
GameHelper.AdOverRevenueEvent(adType, (float)adInfo.Revenue);
|
||||
GameHelper.AdOverRevenueEvent(adType, (float)revenue);
|
||||
}
|
||||
|
||||
// Debug.Log($"revenue: {revenue} \n adInfo.Revenue: {adInfo.Revenue}");
|
||||
Debug.Log($"[OnAdRevenuePaidEvent] revenue: {revenue} \n adInfo.Revenue: {JsonConvert.SerializeObject(adInfo)}");
|
||||
|
||||
// if (revenue >= RevenueThreshold)
|
||||
// {
|
||||
Dictionary<string, string> adCallbackInfo = new Dictionary<string, string>();
|
||||
if (revenue > RevenueThreshold)
|
||||
{
|
||||
adCallbackInfo.Add("af_revenue", revenue.ToString(CultureInfo.InvariantCulture));
|
||||
AppsFlyer.sendEvent("af_ad_revenue", adCallbackInfo);
|
||||
PlayerPrefs.SetString($"adInfoRevenue_{user_id}", "0");
|
||||
|
||||
int adrate = ConfigSystem.GetConfig<CommonModel>().adrate / 100;
|
||||
double revenueAdrate = revenue * adrate;
|
||||
adCallbackInfo["af_revenue"] = revenueAdrate.ToString(CultureInfo.InvariantCulture);
|
||||
AppsFlyer.sendEvent("Af_new_ad_revenue", adCallbackInfo);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// PlayerPrefs.SetString($"adInfoRevenue_{user_id}", revenue.ToString());
|
||||
// }
|
||||
}
|
||||
|
||||
int highSend;
|
||||
if (!PlayerPrefs.HasKey($"sendHighRevenue_{user_id}"))
|
||||
@@ -359,58 +307,91 @@ namespace FlowerPower
|
||||
PlayerPrefs.SetString($"adRevenueTotal_{user_id}", totalNum.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ATTRIBUTION_PLATFORM_APPSFLYER = "AppsFlyer";
|
||||
ATTRIBUTION_PLATFORM_ADJUST = "Adjust";
|
||||
ATTRIBUTION_PLATFORM_TENJIN = "Tenjin";
|
||||
ATTRIBUTION_PLATFORM_SINGULAR = "Singular";
|
||||
ATTRIBUTION_PLATFORM_KOCHAVA = "Kochava";
|
||||
ATTRIBUTION_PLATFORM_BRANCH = "Branch";
|
||||
ATTRIBUTION_PLATFORM_REYUN = "Reyun";
|
||||
ATTRIBUTION_PLATFORM_SOLAR_ENGINE = "SolarEngine";
|
||||
...
|
||||
...
|
||||
*/
|
||||
|
||||
//这里需要改成自己的归因平台名称,这里以Adjust为例,"userid"替换为归因平台UID
|
||||
// MBridgeRevenueParamsEntity mBridgeRevenueParamsEntity = new MBridgeRevenueParamsEntity(MBridgeRevenueParamsEntity.ATTRIBUTION_PLATFORM_ADJUST, PlayerPrefs.GetString("adjust_adid", "default"));
|
||||
|
||||
///MaxSdkBase.AdInfo类型的adInfo
|
||||
// mBridgeRevenueParamsEntity.SetMaxAdInfo(adInfo);
|
||||
// MBridgeRevenueManager.Track(mBridgeRevenueParamsEntity);
|
||||
|
||||
}
|
||||
private static void OnRewardedAdLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
retryAttempt = 0;
|
||||
TrackKit.SendEvent(ADEventTrack.Event, $"{ADEventTrack.Property.ad_load_code}Succeed");
|
||||
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_INVENTORY, "RewardedVideo", adInfo.Placement, adInfo.NetworkName);
|
||||
}
|
||||
|
||||
private static void OnRewardedAdLoadFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo)
|
||||
{
|
||||
retryAttempt++;
|
||||
double retryDelay = Math.Pow(2, Math.Min(6, retryAttempt));
|
||||
double retryDelay = Math.Pow(2, Math.Min(3, retryAttempt));
|
||||
|
||||
TrackKit.SendEvent(ADEventTrack.Event, $"{ADEventTrack.Property.ad_load_code}{errorInfo.Code}");
|
||||
CrazyAsyKit.StartAction("LoadRewardedAd", LoadRewardedAd, (float)retryDelay);
|
||||
}
|
||||
|
||||
private static void OnRewardedAdDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
TrackKit.SendEvent(ADEventTrack.Event, $"{ADEventTrack.Property.ad_show_code}Succeed");
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_IMP, "RewardedVideo", adInfo.Placement, adInfo.NetworkName, adInfo.Revenue, _placement);
|
||||
}
|
||||
|
||||
private static void OnRewardedAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo,
|
||||
MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
TrackKit.SendEvent(ADEventTrack.Event, $"{ADEventTrack.Property.ad_show_code}{errorInfo.Code}");
|
||||
|
||||
LoadRewardedAd();
|
||||
}
|
||||
|
||||
private static void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
BIManager.Instance.TrackAdEvent(BIEvent.AD_CLICK, "RewardedVideo", adInfo.Placement, adInfo.NetworkName);
|
||||
}
|
||||
|
||||
private static bool hasReceivedReward = false;
|
||||
private static void OnRewardedAdHiddenEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
LoadRewardedAd();
|
||||
if (hasReceivedReward && onVideoAdCompleted != null)
|
||||
|
||||
if (_hasReceivedReward && onVideoAdCompleted != null)
|
||||
{
|
||||
onVideoAdCompleted(true);
|
||||
}
|
||||
// 重置标志
|
||||
hasReceivedReward = false;
|
||||
onVideoAdCompleted = null;
|
||||
_hasReceivedReward = false;
|
||||
|
||||
if (GameHelper.IsGiftSwitch() && !SaveData.GetSaveobject().is_get_removead && (UnityEngine.Random.Range(0, 100) < GameHelper.GetCommonModel().rewardinsertion))
|
||||
if (GameHelper.IsGiftSwitch() && !SaveData.GetSaveObject().is_get_removead && (UnityEngine.Random.Range(0, 100) < GameHelper.GetCommonModel().rewardinsertion))
|
||||
{
|
||||
NetworkKit.BuriedPoint(BuriedPointEvent.Apple_pay_event, BuriedPointEvent.afterRewardAdShow, 1);
|
||||
TrackKit.SendEvent(ADEventTrack.Event, ADEventTrack.Property.afterRewardAdShow);
|
||||
|
||||
GameHelper.ShowInterstitial("AfterReward");
|
||||
}
|
||||
#if !GAME_RELEASE
|
||||
GameHelper.AdOverRevenueEvent(1, 0.1f);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static bool _hasReceivedReward = false;
|
||||
private static void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward,
|
||||
MaxSdkBase.AdInfo adInfo)
|
||||
{
|
||||
hasReceivedReward = true;
|
||||
_hasReceivedReward = true;
|
||||
}
|
||||
|
||||
private static void OnRewardedAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||
|
||||
Reference in New Issue
Block a user