You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.5 KiB
JavaScript

'use strict';
const util = require('util');
const db = require('../database');
const plugins = require('../plugins');
const rewards = module.exports;
rewards.checkConditionAndRewardUser = async function (params) {
const { uid, condition, method } = params;
const isActive = await isConditionActive(condition);
if (!isActive) {
return;
}
const ids = await getIDsByCondition(condition);
let rewardData = await getRewardDataByIDs(ids);
rewardData = await filterCompletedRewards(uid, rewardData);
rewardData = rewardData.filter(Boolean);
if (!rewardData || !rewardData.length) {
return;
}
const eligible = await Promise.all(rewardData.map(reward => checkCondition(reward, method)));
const eligibleRewards = rewardData.filter((reward, index) => eligible[index]);
await giveRewards(uid, eligibleRewards);
};
async function isConditionActive(condition) {
return await db.isSetMember('conditions:active', condition);
}
async function getIDsByCondition(condition) {
return await db.getSetMembers(`condition:${condition}:rewards`);
}
async function filterCompletedRewards(uid, rewards) {
const data = await db.getSortedSetRangeByScoreWithScores(`uid:${uid}:rewards`, 0, -1, 1, '+inf');
const userRewards = {};
data.forEach((obj) => {
userRewards[obj.value] = parseInt(obj.score, 10);
});
return rewards.filter((reward) => {
if (!reward) {
return false;
}
const claimable = parseInt(reward.claimable, 10);
return claimable === 0 || (!userRewards[reward.id] || userRewards[reward.id] < reward.claimable);
});
}
async function getRewardDataByIDs(ids) {
return await db.getObjects(ids.map(id => `rewards:id:${id}`));
}
async function getRewardsByRewardData(rewards) {
return await db.getObjects(rewards.map(reward => `rewards:id:${reward.id}:rewards`));
}
async function checkCondition(reward, method) {
if (method.constructor && method.constructor.name !== 'AsyncFunction') {
method = util.promisify(method);
}
const value = await method();
const bool = await plugins.hooks.fire(`filter:rewards.checkConditional:${reward.conditional}`, { left: value, right: reward.value });
return bool;
}
async function giveRewards(uid, rewards) {
const rewardData = await getRewardsByRewardData(rewards);
for (let i = 0; i < rewards.length; i++) {
/* eslint-disable no-await-in-loop */
await plugins.hooks.fire(`action:rewards.award:${rewards[i].rid}`, { uid: uid, reward: rewardData[i] });
await db.sortedSetIncrBy(`uid:${uid}:rewards`, 1, rewards[i].id);
}
}
require('../promisify')(rewards);