refactor: async/await rewards
parent
8b7f6566cc
commit
b110aec6ed
@ -1,143 +1,80 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
const plugins = require('../plugins');
|
||||||
var plugins = require('../plugins');
|
const db = require('../database');
|
||||||
var db = require('../database');
|
const utils = require('../utils');
|
||||||
|
|
||||||
var rewards = module.exports;
|
const rewards = module.exports;
|
||||||
|
|
||||||
rewards.save = function (data, callback) {
|
rewards.save = async function (data) {
|
||||||
async.each(data, function save(data, next) {
|
async function save(data) {
|
||||||
if (!Object.keys(data.rewards).length) {
|
if (!Object.keys(data.rewards).length) {
|
||||||
return next();
|
return;
|
||||||
}
|
}
|
||||||
|
const rewardsData = data.rewards;
|
||||||
var rewardsData = data.rewards;
|
|
||||||
delete data.rewards;
|
delete data.rewards;
|
||||||
|
if (!parseInt(data.id, 10)) {
|
||||||
async.waterfall([
|
data.id = await db.incrObjectField('global', 'rewards:id');
|
||||||
function (next) {
|
|
||||||
if (!parseInt(data.id, 10)) {
|
|
||||||
db.incrObjectField('global', 'rewards:id', next);
|
|
||||||
} else {
|
|
||||||
next(null, data.id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function (rid, next) {
|
|
||||||
data.id = rid;
|
|
||||||
|
|
||||||
async.series([
|
|
||||||
function (next) {
|
|
||||||
rewards.delete(data, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.setAdd('rewards:list', data.id, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.setObject('rewards:id:' + data.id, data, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.setObject('rewards:id:' + data.id + ':rewards', rewardsData, next);
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
}, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
}
|
||||||
|
await rewards.delete(data);
|
||||||
|
await db.setAdd('rewards:list', data.id);
|
||||||
|
await db.setObject('rewards:id:' + data.id, data);
|
||||||
|
await db.setObject('rewards:id:' + data.id + ':rewards', rewardsData);
|
||||||
|
}
|
||||||
|
|
||||||
saveConditions(data, callback);
|
await Promise.all(data.map(data => save(data)));
|
||||||
});
|
await saveConditions(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
rewards.delete = function (data, callback) {
|
rewards.delete = async function (data) {
|
||||||
async.parallel([
|
await Promise.all([
|
||||||
function (next) {
|
db.setRemove('rewards:list', data.id),
|
||||||
db.setRemove('rewards:list', data.id, next);
|
db.delete('rewards:id:' + data.id),
|
||||||
},
|
db.delete('rewards:id:' + data.id + ':rewards'),
|
||||||
function (next) {
|
]);
|
||||||
db.delete('rewards:id:' + data.id, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.delete('rewards:id:' + data.id + ':rewards', next);
|
|
||||||
},
|
|
||||||
], callback);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rewards.get = function (callback) {
|
rewards.get = async function () {
|
||||||
async.parallel({
|
return await utils.promiseParallel({
|
||||||
active: getActiveRewards,
|
active: getActiveRewards,
|
||||||
conditions: function (next) {
|
conditions: plugins.fireHook('filter:rewards.conditions', []),
|
||||||
plugins.fireHook('filter:rewards.conditions', [], next);
|
conditionals: plugins.fireHook('filter:rewards.conditionals', []),
|
||||||
},
|
rewards: plugins.fireHook('filter:rewards.rewards', []),
|
||||||
conditionals: function (next) {
|
});
|
||||||
plugins.fireHook('filter:rewards.conditionals', [], next);
|
|
||||||
},
|
|
||||||
rewards: function (next) {
|
|
||||||
plugins.fireHook('filter:rewards.rewards', [], next);
|
|
||||||
},
|
|
||||||
}, callback);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function saveConditions(data, callback) {
|
async function saveConditions(data) {
|
||||||
var rewardsPerCondition = {};
|
const rewardsPerCondition = {};
|
||||||
async.waterfall([
|
await db.delete('conditions:active');
|
||||||
function (next) {
|
const conditions = [];
|
||||||
db.delete('conditions:active', next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
var conditions = [];
|
|
||||||
|
|
||||||
data.forEach(function (reward) {
|
|
||||||
conditions.push(reward.condition);
|
|
||||||
rewardsPerCondition[reward.condition] = rewardsPerCondition[reward.condition] || [];
|
|
||||||
rewardsPerCondition[reward.condition].push(reward.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
db.setAdd('conditions:active', conditions, next);
|
data.forEach(function (reward) {
|
||||||
},
|
conditions.push(reward.condition);
|
||||||
function (next) {
|
rewardsPerCondition[reward.condition] = rewardsPerCondition[reward.condition] || [];
|
||||||
async.each(Object.keys(rewardsPerCondition), function (condition, next) {
|
rewardsPerCondition[reward.condition].push(reward.id);
|
||||||
db.setAdd('condition:' + condition + ':rewards', rewardsPerCondition[condition], next);
|
|
||||||
}, next);
|
|
||||||
},
|
|
||||||
], function (err) {
|
|
||||||
callback(err);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
function getActiveRewards(callback) {
|
|
||||||
var activeRewards = [];
|
|
||||||
|
|
||||||
function load(id, next) {
|
await db.setAdd('conditions:active', conditions);
|
||||||
async.parallel({
|
|
||||||
main: function (next) {
|
|
||||||
db.getObject('rewards:id:' + id, next);
|
|
||||||
},
|
|
||||||
rewards: function (next) {
|
|
||||||
db.getObject('rewards:id:' + id + ':rewards', next);
|
|
||||||
},
|
|
||||||
}, function (err, data) {
|
|
||||||
if (data.main) {
|
|
||||||
data.main.disabled = data.main.disabled === 'true';
|
|
||||||
data.main.rewards = data.rewards;
|
|
||||||
activeRewards.push(data.main);
|
|
||||||
}
|
|
||||||
|
|
||||||
next(err);
|
await Promise.all(Object.keys(rewardsPerCondition).map(c => db.setAdd('condition:' + c + ':rewards', rewardsPerCondition[c])));
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
db.getSetMembers('rewards:list', function (err, rewards) {
|
async function getActiveRewards() {
|
||||||
if (err) {
|
async function load(id) {
|
||||||
return callback(err);
|
const [main, rewards] = await Promise.all([
|
||||||
|
db.getObject('rewards:id:' + id),
|
||||||
|
db.getObject('rewards:id:' + id + ':rewards'),
|
||||||
|
]);
|
||||||
|
if (main) {
|
||||||
|
main.disabled = main.disabled === 'true';
|
||||||
|
main.rewards = rewards;
|
||||||
}
|
}
|
||||||
|
return main;
|
||||||
|
}
|
||||||
|
|
||||||
async.eachSeries(rewards, load, function (err) {
|
const rewardsList = await db.getSetMembers('rewards:list');
|
||||||
callback(err, activeRewards);
|
const rewardData = await Promise.all(rewardsList.map(id => load(id)));
|
||||||
});
|
return rewardData.filter(Boolean);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require('../promisify')(rewards);
|
require('../promisify')(rewards);
|
||||||
|
@ -1,123 +1,78 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const util = require('util');
|
||||||
var async = require('async');
|
|
||||||
var db = require('../database');
|
const db = require('../database');
|
||||||
var plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
|
|
||||||
var rewards = module.exports;
|
const rewards = module.exports;
|
||||||
|
|
||||||
rewards.checkConditionAndRewardUser = function (uid, condition, method, callback) {
|
rewards.checkConditionAndRewardUser = async function (uid, condition, method) {
|
||||||
callback = callback || function () {};
|
const isActive = await isConditionActive(condition);
|
||||||
|
if (!isActive) {
|
||||||
async.waterfall([
|
return;
|
||||||
function (next) {
|
}
|
||||||
isConditionActive(condition, next);
|
const ids = await getIDsByCondition(condition);
|
||||||
},
|
let rewardData = await getRewardDataByIDs(ids);
|
||||||
function (isActive, next) {
|
rewardData = await filterCompletedRewards(uid, rewardData);
|
||||||
if (!isActive) {
|
rewardData = rewardData.filter(Boolean);
|
||||||
return callback();
|
if (!rewardData || !rewardData.length) {
|
||||||
}
|
return;
|
||||||
getIDsByCondition(condition, next);
|
}
|
||||||
},
|
const eligible = await Promise.all(rewardData.map(reward => checkCondition(reward, method)));
|
||||||
function (ids, next) {
|
const eligibleRewards = rewardData.filter((reward, index) => eligible[index]);
|
||||||
getRewardDataByIDs(ids, next);
|
await giveRewards(uid, eligibleRewards);
|
||||||
},
|
|
||||||
function (rewards, next) {
|
|
||||||
filterCompletedRewards(uid, rewards, next);
|
|
||||||
},
|
|
||||||
function (rewards, next) {
|
|
||||||
if (!rewards || !rewards.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
async.filter(rewards, function (reward, next) {
|
|
||||||
if (!reward) {
|
|
||||||
return next(null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkCondition(reward, method, next);
|
|
||||||
}, function (err, eligible) {
|
|
||||||
if (err || !eligible) {
|
|
||||||
return next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
giveRewards(uid, eligible, next);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
], callback);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function isConditionActive(condition, callback) {
|
async function isConditionActive(condition) {
|
||||||
db.isSetMember('conditions:active', condition, callback);
|
return await db.isSetMember('conditions:active', condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIDsByCondition(condition, callback) {
|
async function getIDsByCondition(condition) {
|
||||||
db.getSetMembers('condition:' + condition + ':rewards', callback);
|
return await db.getSetMembers('condition:' + condition + ':rewards');
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterCompletedRewards(uid, rewards, callback) {
|
async function filterCompletedRewards(uid, rewards) {
|
||||||
async.waterfall([
|
const data = await db.getSortedSetRangeByScoreWithScores('uid:' + uid + ':rewards', 0, -1, 1, '+inf');
|
||||||
function (next) {
|
const userRewards = {};
|
||||||
db.getSortedSetRangeByScoreWithScores('uid:' + uid + ':rewards', 0, -1, 1, '+inf', next);
|
|
||||||
},
|
|
||||||
function (data, next) {
|
|
||||||
var userRewards = {};
|
|
||||||
|
|
||||||
data.forEach(function (obj) {
|
data.forEach(function (obj) {
|
||||||
userRewards[obj.value] = parseInt(obj.score, 10);
|
userRewards[obj.value] = parseInt(obj.score, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
rewards = rewards.filter(function (reward) {
|
return rewards.filter(function (reward) {
|
||||||
if (!reward) {
|
if (!reward) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var claimable = parseInt(reward.claimable, 10);
|
const claimable = parseInt(reward.claimable, 10);
|
||||||
return claimable === 0 || (!userRewards[reward.id] || userRewards[reward.id] < reward.claimable);
|
return claimable === 0 || (!userRewards[reward.id] || userRewards[reward.id] < reward.claimable);
|
||||||
});
|
});
|
||||||
|
|
||||||
next(null, rewards);
|
|
||||||
},
|
|
||||||
], callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRewardDataByIDs(ids, callback) {
|
async function getRewardDataByIDs(ids) {
|
||||||
db.getObjects(ids.map(function (id) {
|
return await db.getObjects(ids.map(id => 'rewards:id:' + id));
|
||||||
return 'rewards:id:' + id;
|
|
||||||
}), callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRewardsByRewardData(rewards, callback) {
|
async function getRewardsByRewardData(rewards) {
|
||||||
db.getObjects(rewards.map(function (reward) {
|
return await db.getObjects(rewards.map(reward => 'rewards:id:' + reward.id + ':rewards'));
|
||||||
return 'rewards:id:' + reward.id + ':rewards';
|
|
||||||
}), callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkCondition(reward, method, callback) {
|
async function checkCondition(reward, method) {
|
||||||
async.waterfall([
|
if (method.constructor && method.constructor.name !== 'AsyncFunction') {
|
||||||
function (next) {
|
method = util.promisify(method);
|
||||||
method(next);
|
}
|
||||||
},
|
const value = await method();
|
||||||
function (value, next) {
|
const bool = await plugins.fireHook('filter:rewards.checkConditional:' + reward.conditional, { left: value, right: reward.value });
|
||||||
plugins.fireHook('filter:rewards.checkConditional:' + reward.conditional, { left: value, right: reward.value }, next);
|
return bool;
|
||||||
},
|
|
||||||
function (bool, next) {
|
|
||||||
next(null, bool);
|
|
||||||
},
|
|
||||||
], callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function giveRewards(uid, rewards, callback) {
|
async function giveRewards(uid, rewards) {
|
||||||
async.waterfall([
|
const rewardData = await getRewardsByRewardData(rewards);
|
||||||
function (next) {
|
await Promise.all(rewards.map(async function (reward) {
|
||||||
getRewardsByRewardData(rewards, next);
|
plugins.fireHook('action:rewards.award:' + reward.rid, { uid: uid, reward: rewardData[rewards.indexOf(reward)] });
|
||||||
},
|
await db.sortedSetIncrBy('uid:' + uid + ':rewards', 1, reward.id);
|
||||||
function (rewardData, next) {
|
}));
|
||||||
async.each(rewards, function (reward, next) {
|
|
||||||
plugins.fireHook('action:rewards.award:' + reward.rid, { uid: uid, reward: rewardData[rewards.indexOf(reward)] });
|
|
||||||
db.sortedSetIncrBy('uid:' + uid + ':rewards', 1, reward.id, next);
|
|
||||||
}, next);
|
|
||||||
},
|
|
||||||
], callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require('../promisify')(rewards);
|
||||||
|
Loading…
Reference in New Issue