'use strict'; var async = require('async'); var db = require('../../database'); var user = require('../../user'); var posts = require('../../posts'); var favourites = require('../../favourites'); var plugins = require('../../plugins'); var websockets = require('../index'); var privileges = require('../../privileges'); module.exports = function(SocketPosts) { SocketPosts.getVoters = function(socket, data, callback) { if (!data || !data.pid || !data.cid) { return callback(new Error('[[error:invalid-data]]')); } async.waterfall([ function (next) { privileges.categories.isAdminOrMod(data.cid, socket.uid, next); }, function (isAdminOrMod, next) { if (!isAdminOrMod) { return next(new Error('[[error:no-privileges]]')); } async.parallel({ upvoteUids: function(next) { db.getSetMembers('pid:' + data.pid + ':upvote', next); }, downvoteUids: function(next) { db.getSetMembers('pid:' + data.pid + ':downvote', next); } }, next); }, function (results, next) { async.parallel({ upvoters: function(next) { user.getMultipleUserFields(results.upvoteUids, ['username', 'userslug', 'picture'], next); }, upvoteCount: function(next) { next(null, results.upvoteUids.length); }, downvoters: function(next) { user.getMultipleUserFields(results.downvoteUids, ['username', 'userslug', 'picture'], next); }, downvoteCount: function(next) { next(null, results.downvoteUids.length); } }, next); } ], callback); }; SocketPosts.getUpvoters = function(socket, pids, callback) { if (!Array.isArray(pids)) { return callback(new Error('[[error:invalid-data]]')); } favourites.getUpvotedUidsByPids(pids, function(err, data) { if (err || !Array.isArray(data) || !data.length) { return callback(err, []); } async.map(data, function(uids, next) { var otherCount = 0; if (uids.length > 6) { otherCount = uids.length - 5; uids = uids.slice(0, 5); } user.getUsernamesByUids(uids, function(err, usernames) { next(err, { otherCount: otherCount, usernames: usernames }); }); }, callback); }); }; SocketPosts.upvote = function(socket, data, callback) { favouriteCommand(socket, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data, callback); }; SocketPosts.downvote = function(socket, data, callback) { favouriteCommand(socket, 'downvote', 'voted', '', data, callback); }; SocketPosts.unvote = function(socket, data, callback) { favouriteCommand(socket, 'unvote', 'voted', '', data, callback); }; SocketPosts.favourite = function(socket, data, callback) { favouriteCommand(socket, 'favourite', 'favourited', 'notifications:favourited_your_post_in', data, callback); }; SocketPosts.unfavourite = function(socket, data, callback) { favouriteCommand(socket, 'unfavourite', 'favourited', '', data, callback); }; function favouriteCommand(socket, command, eventName, notification, data, callback) { if(!data || !data.pid || !data.room_id) { return callback(new Error('[[error:invalid-data]]')); } async.parallel({ exists: function(next) { posts.exists(data.pid, next); }, deleted: function(next) { posts.getPostField(data.pid, 'deleted', next); } }, function(err, results) { if (err || !results.exists) { return callback(err || new Error('[[error:invalid-pid]]')); } if (parseInt(results.deleted, 10) === 1) { return callback(new Error('[[error:post-deleted]]')); } /* hooks: filter.post.upvote filter.post.downvote filter.post.unvote filter.post.favourite filter.post.unfavourite */ plugins.fireHook('filter:post.' + command, {data: data, uid: socket.uid}, function(err, filteredData) { if (err) { return callback(err); } executeFavouriteCommand(socket, command, eventName, notification, filteredData.data, callback); }); }); } function executeFavouriteCommand(socket, command, eventName, notification, data, callback) { favourites[command](data.pid, socket.uid, function(err, result) { if (err) { return callback(err); } if (result && eventName) { socket.emit('posts.' + command, result); websockets.in(data.room_id).emit('event:' + eventName, result); } if (result && notification) { SocketPosts.sendNotificationToPostOwner(data.pid, socket.uid, notification); } callback(); }); } };