新增活动发放道具券处理
This commit is contained in:
parent
71b40bbb50
commit
b1b04030af
@ -16,6 +16,11 @@ public enum PropsActivityRewardEnum {
|
||||
*/
|
||||
PROPS,
|
||||
|
||||
/**
|
||||
* 道具券
|
||||
*/
|
||||
PROP_COUPON,
|
||||
|
||||
/**
|
||||
* 金币
|
||||
*/
|
||||
|
||||
@ -14,10 +14,13 @@ import com.red.circle.other.app.dto.clientobject.activity.ActivityResourceCO;
|
||||
import com.red.circle.other.app.dto.clientobject.gift.GiftConfigCO;
|
||||
import com.red.circle.other.domain.gateway.props.ActivitySourceGroupGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.ranking.RankingActivityType;
|
||||
import com.red.circle.other.domain.ranking.RankingCycleType;
|
||||
import com.red.circle.other.infra.common.activity.PropsActivitySendCommon;
|
||||
import com.red.circle.other.infra.common.activity.send.SendRewardGroup;
|
||||
import com.red.circle.other.infra.database.cache.service.user.CacheEnumConfigManagerService;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.AgentActivityCount;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.RankingActivityRecord;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.WeekStarGiftCount;
|
||||
import com.red.circle.other.infra.database.mongo.entity.user.count.WeekCpValueCount;
|
||||
import com.red.circle.other.infra.database.mongo.entity.user.count.WeekFriendshipCardCount;
|
||||
@ -37,6 +40,7 @@ import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRul
|
||||
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.WeekStarGiftService;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.WeekStarGroupService;
|
||||
import com.red.circle.other.infra.gateway.RankingActivityGateway;
|
||||
import com.red.circle.other.infra.utils.DateFormatEnum;
|
||||
import com.red.circle.other.infra.utils.ZonedDateTimeUtils;
|
||||
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
|
||||
@ -60,6 +64,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.ImmutableTriple;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -97,6 +102,7 @@ public class WeeklyRewardsSentManager {
|
||||
private final SysActivityConfigClient sysActivityConfigClient;
|
||||
private final WeekKingQueenClient weekKingQueenClient;
|
||||
private final PropsActivityClient propsActivityClient;
|
||||
private final RankingActivityGateway rankingActivityGateway;
|
||||
|
||||
/**
|
||||
* 每周一发送奖励业务.
|
||||
@ -185,13 +191,111 @@ public class WeeklyRewardsSentManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sendLastRankingActivity(Long templateId) {
|
||||
try {
|
||||
// 1. 获取活动配置信息
|
||||
ActivityConfigDTO activityConfigDTO = getActivityConfig(templateId);
|
||||
// 国王皇后活动单独发放。
|
||||
long kingQueenTemplateId = getKingQueenTemplateId();
|
||||
if (activityConfigDTO == null || activityConfigDTO.getTemplateId() == kingQueenTemplateId) {
|
||||
log.warn("未找到有效的活动配置");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 检查奖励是否已发放
|
||||
if (Boolean.TRUE.equals(activityConfigDTO.getAwardStatus())) {
|
||||
log.info("奖励已发放,跳过处理");
|
||||
return;
|
||||
}
|
||||
|
||||
Long activityId = activityConfigDTO.getId();
|
||||
String lastWeekDate = getLastWeekDate();
|
||||
|
||||
String sysOrigin = SysOriginPlatformEnum.LIKEI.name();
|
||||
// 获取枚举
|
||||
RankingActivityType activityType = RankingActivityType.HEROES_DAY;
|
||||
RankingCycleType cycleType = RankingCycleType.WEEKLY;
|
||||
// 4. 获取奖励配置并更新
|
||||
List<ActivityConfigRewardsDTO> kingRewardList = activityConfigDTO.getButOneRewards();
|
||||
List<RankingActivityRecord> records = rankingActivityGateway.getRankingList(
|
||||
sysOrigin,
|
||||
activityType,
|
||||
cycleType,
|
||||
lastWeekDate,
|
||||
null,
|
||||
3
|
||||
);
|
||||
|
||||
// 发放活动奖励
|
||||
sendRankingActivityRewards(SysOriginPlatformEnum.LIKEI, activityId, records, kingRewardList);
|
||||
|
||||
|
||||
log.info("上周{}活动奖励发放完成, 活动ID: {}", activityConfigDTO.getRemark(), activityId);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("发送活动奖励异常, 错误信息: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发放活动奖励
|
||||
*/
|
||||
private void sendRankingActivityRewards(SysOriginPlatformEnum sysOriginPlatformEnum, Long activityId,
|
||||
List<RankingActivityRecord> topUsers,
|
||||
List<ActivityConfigRewardsDTO> rewardsDTOList) {
|
||||
if (CollectionUtils.isEmpty(topUsers) || CollectionUtils.isEmpty(rewardsDTOList)) {
|
||||
log.warn("活动奖励为空, 跳过国王奖励发放");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Math.min(topUsers.size(), rewardsDTOList.size()); i++) {
|
||||
try {
|
||||
RankingActivityRecord user = topUsers.get(i);
|
||||
|
||||
// 判断金额是否达到100K,如果没有则跳过不发奖励
|
||||
if (user.getQuantity() == null || user.getQuantity() < 100000) {
|
||||
log.warn("活动奖励 - 排名: {}, 用户ID: {}, 金额: {} 未达到100K要求,跳过发奖励",
|
||||
i + 1, user.getUserId(), user.getQuantity());
|
||||
continue;
|
||||
}
|
||||
|
||||
ActivityConfigRewardsDTO reward = rewardsDTOList.get(i);
|
||||
|
||||
// 发送奖励
|
||||
sendRewardToUser(sysOriginPlatformEnum, activityId, user.getUserId(), reward.getResourceGroupId());
|
||||
|
||||
log.info("活动奖励发放成功 - 排名: {}, 用户ID: {}, 奖励组ID: {}",
|
||||
i + 1, user.getUserId(), reward.getResourceGroupId());
|
||||
} catch (Exception e) {
|
||||
log.error("活动奖励发放失败 - 排名: {}, 错误信息: {}", i + 1, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活动配置信息
|
||||
*/
|
||||
private ActivityConfigDTO getActivityConfig(Long templateId) {
|
||||
try {
|
||||
ActivityConfigBackQryCmd query = new ActivityConfigBackQryCmd();
|
||||
query.setSysOrigin(SysOriginPlatformEnum.LIKEI.name());
|
||||
query.setTemplateId(templateId);
|
||||
return ResponseAssert.requiredSuccess(sysActivityConfigClient.effectiveActivityConf(query));
|
||||
} catch (Exception e) {
|
||||
log.error("[KingQueen] 获取活动配置失败, 错误信息: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取国王皇后活动配置信息
|
||||
*/
|
||||
private ActivityConfigDTO getActivityConfig(String sysOrigin) {
|
||||
try {
|
||||
ActivityConfigBackQryCmd query = new ActivityConfigBackQryCmd();
|
||||
query.setSysOrigin(sysOrigin);
|
||||
query.setTemplateId(getKingQueenTemplateId());
|
||||
return ResponseAssert.requiredSuccess(sysActivityConfigClient.effectiveActivityConf(query));
|
||||
} catch (Exception e) {
|
||||
log.error("[KingQueen] 获取活动配置失败, 系统平台: {}, 错误信息: {}", sysOrigin, e.getMessage(), e);
|
||||
@ -199,6 +303,10 @@ public class WeeklyRewardsSentManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static long getKingQueenTemplateId() {
|
||||
return 1966020557831610370L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排行榜数据
|
||||
*/
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
package com.red.circle.other.app.scheduler;
|
||||
|
||||
|
||||
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
||||
import com.red.circle.other.app.manager.activity.award.WeeklyRewardsSentManager;
|
||||
import com.red.circle.other.infra.database.mongo.entity.sys.ActivityConfig;
|
||||
import com.red.circle.other.infra.database.mongo.service.sys.ActivityConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* rankingActivity 活动奖励发放
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RankingActivityRewardTask {
|
||||
|
||||
private final WeeklyRewardsSentManager weeklyRewardsSentManager;
|
||||
private final ActivityConfigService activityConfigService;
|
||||
|
||||
/**
|
||||
* 每周一 0点0分执行.
|
||||
*/
|
||||
// @Scheduled(cron = "0 0 0 ? * MON", zone = "Asia/Riyadh")
|
||||
@TaskCacheLock(key = "RANKING_ACTIVITY_REWARD_TASK", expireSecond = 86400)
|
||||
public void sendRankingActivityReward() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.warn("========== rankingActivity 活动奖励发放定时任务开始 ==========");
|
||||
|
||||
try {
|
||||
|
||||
// 查询上周结束的活动
|
||||
List<ActivityConfig> lastWeekActivities =
|
||||
activityConfigService.listRecentlyEndedActivities("LIKEI", 10);
|
||||
lastWeekActivities.forEach(activityConfig -> {
|
||||
weeklyRewardsSentManager.sendLastRankingActivity(activityConfig.getTemplateId());
|
||||
});
|
||||
|
||||
log.warn("========== rankingActivity 活动奖励发放定时任务完成,耗时:{} ms ==========",
|
||||
System.currentTimeMillis() - startTime);
|
||||
} catch (Exception e) {
|
||||
log.error("========== rankingActivity 活动奖励发放定时任务异常 ==========", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,12 +11,17 @@ import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExt
|
||||
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||
import com.red.circle.other.domain.gateway.PropCouponGateway;
|
||||
import com.red.circle.other.domain.gateway.props.PropsNobleVipGateway;
|
||||
import com.red.circle.other.domain.gateway.props.PropsStoreGateway;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.domain.model.user.ability.RegionConfig;
|
||||
import com.red.circle.other.domain.propcoupon.PropCoupon;
|
||||
import com.red.circle.other.domain.propcoupon.PropCouponSource;
|
||||
import com.red.circle.other.domain.propcoupon.PropCouponStatus;
|
||||
import com.red.circle.other.domain.propcoupon.PropCouponType;
|
||||
import com.red.circle.other.infra.convertor.material.PropsMaterialInfraConvertor;
|
||||
import com.red.circle.other.infra.database.cache.service.other.EmojiCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomSetting;
|
||||
@ -34,13 +39,17 @@ import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordSe
|
||||
import com.red.circle.other.infra.database.rds.service.props.PropsVipActualEquityService;
|
||||
import com.red.circle.other.infra.database.rds.service.user.user.ConsumptionLevelService;
|
||||
import com.red.circle.other.infra.utils.I18nUtils;
|
||||
import com.red.circle.other.inner.asserts.OtherErrorCode;
|
||||
import com.red.circle.other.inner.enums.material.NobleVipEnum;
|
||||
import com.red.circle.other.inner.enums.material.PropsCommodityType;
|
||||
import com.red.circle.other.inner.model.cmd.material.PrizeDescribe;
|
||||
import com.red.circle.other.inner.model.cmd.material.PrizeDescribeRewardCmd;
|
||||
import com.red.circle.other.inner.model.cmd.material.PropCouponGrantCmd;
|
||||
import com.red.circle.other.inner.model.dto.material.PropsResourcesDTO;
|
||||
import com.red.circle.other.inner.model.dto.material.props.NobleVipAbility;
|
||||
import com.red.circle.other.inner.model.dto.material.props.ProductProps;
|
||||
import com.red.circle.other.inner.model.dto.material.props.PropsResources;
|
||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.num.NumConstant;
|
||||
@ -54,10 +63,8 @@ import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
|
||||
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -88,7 +95,7 @@ public class PropsSendCommon {
|
||||
private final PropsMaterialInfraConvertor propsMaterialInfraConvertor;
|
||||
private final PropsVipActualEquityService propsVipActualEquityService;
|
||||
private final ConsumptionLevelService consumptionLevelService;
|
||||
private final UserRegionGateway userRegionGateway;
|
||||
private final PropCouponGateway propCouponGateway;
|
||||
private final OfficialNoticeClient officialNoticeClient;
|
||||
|
||||
/**
|
||||
@ -152,6 +159,10 @@ public class PropsSendCommon {
|
||||
List<PrizeDescribe> exps = filterPrize(cmd, PropsActivityRewardEnum.CUSTOMIZE);
|
||||
sendUserExp(cmd.getAcceptUserId(), exps);
|
||||
|
||||
// 发放道具券
|
||||
List<PrizeDescribe> coupons = filterPrize(cmd, PropsActivityRewardEnum.PROP_COUPON);
|
||||
sendPropCoupon(cmd.getAcceptUserId(), coupons);
|
||||
|
||||
saveSendLog(cmd);
|
||||
}
|
||||
|
||||
@ -165,6 +176,37 @@ public class PropsSendCommon {
|
||||
});
|
||||
}
|
||||
|
||||
private void sendPropCoupon(Long acceptUserId, List<PrizeDescribe> coupons) {
|
||||
coupons.forEach(prizeDescribe -> {
|
||||
String content = prizeDescribe.getContent();
|
||||
|
||||
PropsSourceRecord propsSourceRecord = propsSourceRecordService.getById(Long.parseLong(content));
|
||||
if (propsSourceRecord != null) {
|
||||
PropCouponType couponType = PropCouponType.getByName(propsSourceRecord.getType());
|
||||
if (Objects.nonNull(couponType)) {
|
||||
PropCouponGrantCmd grantCmd = new PropCouponGrantCmd();
|
||||
grantCmd.setPropId(propsSourceRecord.getId().toString());
|
||||
grantCmd.setPropIcon(propsSourceRecord.getCover());
|
||||
grantCmd.setPropName(propsSourceRecord.getName());
|
||||
grantCmd.setCouponType(couponType.getCode());
|
||||
grantCmd.setValidDays(prizeDescribe.getQuantity());
|
||||
|
||||
List<PropCoupon> propCoupons = generateCoupons(grantCmd, couponType, Collections.singleton(acceptUserId));
|
||||
// 5. 批量插入券记录
|
||||
propCouponGateway.batchSave(propCoupons);
|
||||
|
||||
officialNoticeClient.send(
|
||||
NoticeExtTemplateCustomizeCmd.builder()
|
||||
.toAccount(acceptUserId)
|
||||
.noticeType(OfficialNoticeTypeEnum.RECEIVE_PROP_COUPON)
|
||||
.content("You have received a Coupon. Please check it.")
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<PrizeDescribe> filterPrize(PrizeDescribeRewardCmd cmd, PropsActivityRewardEnum type) {
|
||||
return cmd.getPrizes().stream()
|
||||
.filter(prizeDescribe -> type.eq(prizeDescribe.getType()))
|
||||
@ -429,5 +471,76 @@ public class PropsSendCommon {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成券
|
||||
*/
|
||||
private List<PropCoupon> generateCoupons(PropCouponGrantCmd cmd, PropCouponType couponType, Set<Long> userIds) {
|
||||
List<PropCoupon> propCoupons = new ArrayList<>();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime expireTime = now.plusDays(cmd.getValidDays());
|
||||
|
||||
// 转换贵族等级名称为VIP等级
|
||||
String displayPropName = convertNobleNameToVipLevel(cmd.getPropName());
|
||||
for (Long userId : userIds) {
|
||||
PropCoupon propCoupon = new PropCoupon();
|
||||
propCoupon.setCouponNo(generateCouponNo());
|
||||
propCoupon.setUserId(userId);
|
||||
propCoupon.setCouponType(couponType);
|
||||
propCoupon.setPropId(Long.parseLong(cmd.getPropId()));
|
||||
propCoupon.setPropIcon(cmd.getPropIcon());
|
||||
propCoupon.setPropName(displayPropName);
|
||||
propCoupon.setValidDays(cmd.getValidDays());
|
||||
propCoupon.setStatus(PropCouponStatus.UNUSED);
|
||||
propCoupon.setSource(PropCouponSource.ADMIN_GRANT);
|
||||
propCoupon.setExpireTime(expireTime);
|
||||
propCoupon.setCreateTime(now);
|
||||
propCoupon.setUpdateTime(now);
|
||||
|
||||
propCoupons.add(propCoupon);
|
||||
}
|
||||
|
||||
return propCoupons;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换贵族等级名称为VIP等级
|
||||
*
|
||||
* @param propName 道具名称
|
||||
* @return VIP等级名称
|
||||
*/
|
||||
private String convertNobleNameToVipLevel(String propName) {
|
||||
if (propName == null) {
|
||||
return propName;
|
||||
}
|
||||
|
||||
// 贵族等级映射
|
||||
switch (propName.toUpperCase()) {
|
||||
case "VISCOUNT":
|
||||
return "VIP 1";
|
||||
case "EARL":
|
||||
return "VIP 2";
|
||||
case "MARQUIS":
|
||||
return "VIP 3";
|
||||
case "DUKE":
|
||||
return "VIP 4";
|
||||
case "KING":
|
||||
return "VIP 5";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成券编号(唯一)
|
||||
*/
|
||||
private String generateCouponNo() {
|
||||
// 使用雪花算法生成唯一ID
|
||||
long id = IdWorkerUtils.getId();
|
||||
// 格式: COUPON + 时间戳 + ID
|
||||
return String.format("COUPON%d", id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -68,4 +68,6 @@ public interface ActivityConfigService {
|
||||
* 查询有效i的活动配置
|
||||
*/
|
||||
ActivityConfig getEffectiveActivityConf(ActivityConfigBackQryCmd query);
|
||||
|
||||
List<ActivityConfig> listRecentlyEndedActivities(String sysOrigin, Integer limit);
|
||||
}
|
||||
|
||||
@ -9,10 +9,12 @@ import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
@ -237,4 +239,20 @@ public class ActivityConfigServiceImpl implements ActivityConfigService {
|
||||
, ActivityConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActivityConfig> listRecentlyEndedActivities(String sysOrigin, Integer limit) {
|
||||
Date now = TimestampUtils.now();
|
||||
|
||||
Criteria criteria = Criteria.where("sysOrigin").is(sysOrigin)
|
||||
.and("showcase").is(true)
|
||||
.and("startTime").lte(now);
|
||||
|
||||
return mongoTemplate.find(
|
||||
Query.query(criteria)
|
||||
.with(Sort.by(Sort.Order.desc("id")))
|
||||
.limit(limit != null ? limit : 100),
|
||||
ActivityConfig.class
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import com.red.circle.OtherServiceApplication;
|
||||
import com.red.circle.other.app.scheduler.DailyTask;
|
||||
import com.red.circle.other.app.scheduler.RankingActivityRewardTask;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -12,10 +13,17 @@ public class DailTaskTest {
|
||||
|
||||
@Autowired
|
||||
private DailyTask dailyTask;
|
||||
@Autowired
|
||||
private RankingActivityRewardTask rankingActivityRewardTask;
|
||||
|
||||
@Test
|
||||
public void DailTaskTest() {
|
||||
dailyTask. nobleDailyGoldRewardTask();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void DailTaskTest2() {
|
||||
rankingActivityRewardTask.sendRankingActivityReward();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user