'use strict'; var async = require('async'); var _ = require('underscore'); var validator = require('validator'); var db = require('../database'); var posts = require('../posts'); var topics = require('../topics'); module.exports = function (User) { User.getLatestBanInfo = function (uid, callback) { // Simply retrieves the last record of the user's ban, even if they've been unbanned since then. var timestamp, expiry, reason; async.waterfall([ async.apply(db.getSortedSetRevRangeWithScores, 'uid:' + uid + ':bans', 0, 0), function (record, next) { timestamp = record[0].score; expiry = record[0].value; db.getSortedSetRangeByScore('banned:' + uid + ':reasons', 0, -1, timestamp, timestamp, next); }, function (_reason, next) { reason = _reason && _reason.length ? _reason[0] : ''; next(); } ], function (err) { if (err) { return callback(err); } callback(null, { uid: uid, timestamp: timestamp, expiry: parseInt(expiry, 10), expiry_readable: new Date(parseInt(expiry, 10)).toString().replace(/:/g, '%3A'), reason: validator.escape(String(reason)) }); }) }; User.getModerationHistory = function (uid, callback) { async.waterfall([ function (next) { async.parallel({ flags: async.apply(db.getSortedSetRevRangeWithScores, 'uid:' + uid + ':flag:pids', 0, 19), bans: async.apply(db.getSortedSetRevRangeWithScores, 'uid:' + uid + ':bans', 0, 19), reasons: async.apply(db.getSortedSetRevRangeWithScores, 'banned:' + uid + ':reasons', 0, 19) }, next); }, function (data, next) { getFlagMetadata(data, next); } ], function (err, data) { if (err) { return callback(err); } formatBanData(data); callback(null, data); }); }; User.getHistory = function (set, callback) { db.getSortedSetRevRangeWithScores(set, 0, -1, function (err, data) { if (err) { return callback(err); } callback(null, data.map(function (set) { set.timestamp = set.score; set.timestampISO = new Date(set.score).toISOString(); set.value = validator.escape(String(set.value.split(':')[0])); delete set.score; return set; })); }); }; function getFlagMetadata(data, callback) { var pids = data.flags.map(function (flagObj) { return parseInt(flagObj.value, 10); }); posts.getPostsFields(pids, ['tid'], function (err, postData) { if (err) { return callback(err); } var tids = postData.map(function (post) { return post.tid; }); topics.getTopicsFields(tids, ['title'], function (err, topicData) { if (err) { return callback(err); } data.flags = data.flags.map(function (flagObj, idx) { flagObj.pid = flagObj.value; flagObj.timestamp = flagObj.score; flagObj.timestampISO = new Date(flagObj.score).toISOString(); flagObj.timestampReadable = new Date(flagObj.score).toString(); delete flagObj.value; delete flagObj.score; return _.extend(flagObj, topicData[idx]); }); callback(null, data); }); }); } function formatBanData(data) { var reasons = data.reasons.reduce(function (memo, cur) { memo[cur.score] = cur.value; return memo; }, {}); data.bans = data.bans.map(function (banObj) { banObj.until = parseInt(banObj.value, 10); banObj.untilReadable = new Date(banObj.until).toString(); banObj.timestamp = parseInt(banObj.score, 10); banObj.timestampReadable = new Date(banObj.score).toString(); banObj.timestampISO = new Date(banObj.score).toISOString(); banObj.reason = validator.escape(String(reasons[banObj.score])) || '[[user:info.banned-no-reason]]'; delete banObj.value; delete banObj.score; delete data.reasons; return banObj; }); } };