mirror of
https://hk.gh-proxy.com/https://github.com/NodeBB/nodebb-plugin-poll.git
synced 2025-10-03 04:31:04 +08:00
298 lines
7.7 KiB
JavaScript
Executable file
298 lines
7.7 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
const async = require('async');
|
|
|
|
const NodeBB = require('./nodebb');
|
|
|
|
const Vote = require('./vote');
|
|
const Scheduler = require('./scheduler');
|
|
|
|
(function (Poll) {
|
|
const POLL_DATA_VERSION = 2;
|
|
|
|
Poll.add = function (pollData, postData, callback) {
|
|
NodeBB.db.incrObjectField('global', 'nextPollId', (err, pollId) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
const poll = {
|
|
pollId: pollId,
|
|
uid: postData.editor || postData.uid,
|
|
tid: postData.tid,
|
|
pid: postData.pid,
|
|
deleted: 0,
|
|
ended: 0,
|
|
timestamp: postData.edited || postData.timestamp,
|
|
version: POLL_DATA_VERSION,
|
|
};
|
|
|
|
pollData.options = pollData.options.map((val, i) => ({
|
|
id: i,
|
|
title: val,
|
|
}));
|
|
|
|
// async this bitch up
|
|
async.parallel([
|
|
async.apply(async.each, pollData.options, (option, next) => {
|
|
async.series([
|
|
async.apply(NodeBB.db.setObject, `poll:${pollId}:options:${option.id}`, option),
|
|
async.apply(NodeBB.db.setAdd, `poll:${pollId}:options`, option.id),
|
|
], next);
|
|
}),
|
|
async.apply(NodeBB.db.setObject, `poll:${pollId}`, poll),
|
|
async.apply(NodeBB.db.setObject, `poll:${pollId}:settings`, pollData.settings),
|
|
async.apply(NodeBB.db.listAppend, 'polls', pollId),
|
|
async.apply(NodeBB.db.setObjectField, `topic:${poll.tid}`, 'pollId', pollId),
|
|
], (err) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
// Check if this poll is scheduled to end
|
|
if (parseInt(pollData.settings.end, 10) > 0) {
|
|
Poll.schedule(pollId);
|
|
}
|
|
|
|
return callback(null, pollId);
|
|
});
|
|
});
|
|
};
|
|
|
|
Poll.get = function (pollId, uid, withVotes, callback) {
|
|
async.parallel({
|
|
info: function (next) {
|
|
Poll.getInfo(pollId, next);
|
|
},
|
|
options: function (next) {
|
|
Poll.getOptions(pollId, withVotes, next);
|
|
},
|
|
settings: function (next) {
|
|
Poll.getSettings(pollId, next);
|
|
},
|
|
hasVoted: function (next) {
|
|
if (uid) {
|
|
Vote.hasUidVoted(uid, pollId, next);
|
|
} else {
|
|
next(null, false);
|
|
}
|
|
},
|
|
vote: function (next) {
|
|
if (uid) {
|
|
Vote.getUidVote(uid, pollId, next);
|
|
} else {
|
|
next(null, null);
|
|
}
|
|
},
|
|
}, (err, pollData) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
pollData.options.forEach((option) => {
|
|
const percentage = ((option.voteCount / pollData.info.voteCount) * 100).toFixed(0);
|
|
option.percentage = isNaN(percentage) ? 0 : percentage;
|
|
});
|
|
pollData.settings.disallowVoteUpdate = parseInt(pollData.settings.disallowVoteUpdate, 10);
|
|
callback(null, pollData);
|
|
});
|
|
};
|
|
|
|
Poll.getPollIdByTid = function (tid, callback) {
|
|
NodeBB.db.getObjectField(`topic:${tid}`, 'pollId', callback);
|
|
};
|
|
|
|
Poll.getPollIdByPid = function (pid, callback) {
|
|
NodeBB.db.getObjectField(`post:${pid}`, 'pollId', callback);
|
|
};
|
|
|
|
Poll.getInfo = function (pollId, callback) {
|
|
async.parallel({
|
|
poll: function (next) {
|
|
NodeBB.db.getObject(`poll:${pollId}`, next);
|
|
},
|
|
voteCount: function (next) {
|
|
Poll.getVoteCount(pollId, next);
|
|
},
|
|
}, (err, results) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
results.poll.voteCount = parseInt(results.voteCount, 10) || 0;
|
|
callback(null, results.poll);
|
|
});
|
|
};
|
|
|
|
Poll.getOptions = function (pollId, withVotes, callback) {
|
|
if (typeof withVotes === 'function') {
|
|
callback = withVotes;
|
|
withVotes = false;
|
|
}
|
|
|
|
NodeBB.db.getSetMembers(`poll:${pollId}:options`, (err, options) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
async.map(options, (option, next) => {
|
|
Poll.getOption(pollId, option, withVotes, next);
|
|
}, callback);
|
|
});
|
|
};
|
|
|
|
Poll.getOption = function (pollId, option, withVotes, callback) {
|
|
async.parallel({
|
|
option: function (next) {
|
|
NodeBB.db.getObject(`poll:${pollId}:options:${option}`, next);
|
|
},
|
|
votes: function (next) {
|
|
if (withVotes) {
|
|
NodeBB.db.getSortedSetRange(`poll:${pollId}:options:${option}:votes`, 0, -1, next);
|
|
} else {
|
|
next();
|
|
}
|
|
},
|
|
voteCount: function (next) {
|
|
Poll.getOptionVoteCount(pollId, option, next);
|
|
},
|
|
}, (err, results) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
if (results.votes) {
|
|
results.option.votes = results.votes;
|
|
}
|
|
results.option.voteCount = parseInt(results.voteCount, 10) || 0;
|
|
|
|
callback(null, results.option);
|
|
});
|
|
};
|
|
|
|
Poll.getVotersCount = function (pollId, callback) {
|
|
NodeBB.db.sortedSetCard(`poll:${pollId}:voters`, callback);
|
|
};
|
|
|
|
Poll.getVoteCount = function (pollId, callback) {
|
|
NodeBB.db.getSetMembers(`poll:${pollId}:options`, (err, options) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
async.map(options, (option, next) => {
|
|
Poll.getOptionVoteCount(pollId, option, next);
|
|
}, (err, results) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
callback(null, results.reduce((a, b) => a + b, 0));
|
|
});
|
|
});
|
|
};
|
|
|
|
Poll.getOptionVoteCount = function (pollId, option, callback) {
|
|
NodeBB.db.sortedSetCard(`poll:${pollId}:options:${option}:votes`, callback);
|
|
};
|
|
|
|
Poll.hasOption = function (pollId, option, callback) {
|
|
NodeBB.db.isSetMember(`poll:${pollId}:options`, option, callback);
|
|
};
|
|
|
|
Poll.hasOptions = function (pollId, options, callback) {
|
|
NodeBB.db.isSetMembers(`poll:${pollId}:options`, options, callback);
|
|
};
|
|
|
|
Poll.getSettings = function (pollId, callback) {
|
|
NodeBB.db.getObject(`poll:${pollId}:settings`, callback);
|
|
};
|
|
|
|
Poll.isDeleted = function (pollId, callback) {
|
|
Poll.getField(pollId, 'deleted', (err, result) => {
|
|
callback(err, parseInt(result, 10) === 1);
|
|
});
|
|
};
|
|
|
|
Poll.delete = function (pollId) {
|
|
Poll.setField(pollId, 'deleted', 1);
|
|
};
|
|
|
|
Poll.restore = function (pollId) {
|
|
Poll.setField(pollId, 'edited', 0);
|
|
Poll.setField(pollId, 'deleted', 0);
|
|
};
|
|
|
|
Poll.schedule = function (pollId) {
|
|
NodeBB.db.setAdd('polls:scheduled', pollId);
|
|
Scheduler.add(pollId);
|
|
};
|
|
|
|
Poll.getScheduled = function (callback) {
|
|
NodeBB.db.getSetMembers('polls:scheduled', callback);
|
|
};
|
|
|
|
Poll.hasEnded = function (pollId, callback) {
|
|
Poll.getField(pollId, 'ended', (err, result) => {
|
|
callback(err, parseInt(result, 10) === 1);
|
|
});
|
|
};
|
|
|
|
Poll.doesDisallowVoteUpdate = function (pollId, callback) {
|
|
Poll.getSettingsField(pollId, 'disallowVoteUpdate', (err, result) => {
|
|
callback(err, parseInt(result, 10) === 1);
|
|
});
|
|
};
|
|
|
|
Poll.doesAllowVoteUpdate = function (pollId, callback) {
|
|
Poll.getSettingsField(pollId, 'disallowVoteUpdate', (err, result) => {
|
|
callback(err, parseInt(result, 10) !== 1);
|
|
});
|
|
};
|
|
|
|
Poll.end = function (pollId) {
|
|
NodeBB.db.setRemove('polls:scheduled', pollId);
|
|
Poll.setField(pollId, 'ended', 1);
|
|
};
|
|
|
|
Poll.changePid = function (pollId, pid, callback) {
|
|
async.parallel([
|
|
function (next) {
|
|
Poll.setField(pollId, 'pid', pid, next);
|
|
},
|
|
function (next) {
|
|
NodeBB.db.setObjectField(`post:${pid}`, 'pollId', pollId, next);
|
|
},
|
|
], callback);
|
|
};
|
|
|
|
Poll.changeTid = function (pollId, tid, callback) {
|
|
async.parallel([
|
|
function (next) {
|
|
Poll.setField(pollId, 'tid', tid, next);
|
|
},
|
|
function (next) {
|
|
NodeBB.db.setObjectField(`topic:${tid}`, 'pollId', pollId, next);
|
|
},
|
|
], callback);
|
|
};
|
|
|
|
Poll.setField = function (pollId, field, value, callback) {
|
|
NodeBB.db.setObjectField(`poll:${pollId}`, field, value, callback);
|
|
};
|
|
|
|
Poll.setFields = function (pollId, fields, values, callback) {
|
|
NodeBB.db.setObjectFields(`poll:${pollId}`, fields, values, callback);
|
|
};
|
|
|
|
Poll.getField = function (pollId, field, callback) {
|
|
NodeBB.db.getObjectField(`poll:${pollId}`, field, callback);
|
|
};
|
|
|
|
Poll.getFields = function (pollId, fields, callback) {
|
|
NodeBB.db.getObjectFields(`poll:${pollId}`, fields, callback);
|
|
};
|
|
|
|
Poll.getSettingsField = function (pollId, field, callback) {
|
|
NodeBB.db.getObjectField(`poll:${pollId}:settings`, field, callback);
|
|
};
|
|
|
|
Poll.setSettingsField = function (pollId, field, value, callback) {
|
|
NodeBB.db.setObjectField(`poll:${pollId}:settings`, field, callback);
|
|
};
|
|
}(exports));
|