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(function (obj) {
userRewards[obj.value] = parseInt(obj.score, 10);
});
return rewards.filter(function (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);