sync/src/poll.js

104 lines
3.1 KiB
JavaScript
Raw Normal View History

2018-04-07 15:30:30 -07:00
const link = /(\w+:\/\/(?:[^:/[\]\s]+|\[[0-9a-f:]+\])(?::\d+)?(?:\/[^/\s]*)*)/ig;
2021-07-22 22:34:16 -07:00
const XSS = require('./xss');
2013-03-16 16:49:58 -05:00
2021-07-22 22:34:16 -07:00
function sanitizedWithLinksReplaced(text) {
return XSS.sanitizeText(text)
.replace(link, '<a href="$1" target="_blank" rel="noopener noreferer">$1</a>');
}
2013-12-01 17:20:42 -06:00
2021-07-22 22:34:16 -07:00
class Poll {
2021-08-11 21:13:59 -07:00
static create(createdBy, title, choices, options = { hideVotes: false, retainVotes: false }) {
2021-07-22 22:34:16 -07:00
let poll = new Poll();
poll.createdAt = new Date();
poll.createdBy = createdBy;
poll.title = sanitizedWithLinksReplaced(title);
poll.choices = choices.map(choice => sanitizedWithLinksReplaced(choice));
poll.hideVotes = options.hideVotes;
2021-08-11 21:13:59 -07:00
poll.retainVotes = options.retainVotes;
2021-07-22 22:34:16 -07:00
poll.votes = new Map();
return poll;
2013-12-01 17:20:42 -06:00
}
2021-07-22 22:34:16 -07:00
2021-08-11 21:13:59 -07:00
static fromChannelData({ initiator, title, options, _counts, votes, timestamp, obscured, retainVotes }) {
2021-07-22 22:34:16 -07:00
let poll = new Poll();
if (timestamp === undefined) // Very old polls still in the database lack timestamps
timestamp = Date.now();
poll.createdAt = new Date(timestamp);
poll.createdBy = initiator;
poll.title = title;
poll.choices = options;
poll.votes = new Map();
Object.keys(votes).forEach(key => {
if (votes[key] !== null)
poll.votes.set(key, votes[key]);
});
poll.hideVotes = obscured;
2021-08-11 21:13:59 -07:00
poll.retainVotes = retainVotes || false;
2021-07-22 22:34:16 -07:00
return poll;
}
toChannelData() {
let counts = new Array(this.choices.length);
counts.fill(0);
// TODO: it would be desirable one day to move away from using an Object here.
// This is just for backwards-compatibility with the existing format.
let votes = {};
this.votes.forEach((index, key) => {
votes[key] = index;
counts[index]++;
});
return {
title: this.title,
initiator: this.createdBy,
options: this.choices,
counts,
votes,
obscured: this.hideVotes,
2021-08-11 21:13:59 -07:00
retainVotes: this.retainVotes,
2021-07-22 22:34:16 -07:00
timestamp: this.createdAt.getTime()
};
2013-03-16 16:49:58 -05:00
}
2021-07-22 22:34:16 -07:00
countVote(key, choiceId) {
if (choiceId < 0 || choiceId >= this.choices.length)
return false;
let changed = !this.votes.has(key) || this.votes.get(key) !== choiceId;
this.votes.set(key, choiceId);
return changed;
2013-03-16 16:49:58 -05:00
}
2021-07-22 22:34:16 -07:00
uncountVote(key) {
let changed = this.votes.has(key);
this.votes.delete(key);
return changed;
2013-03-16 16:49:58 -05:00
}
2021-07-22 22:34:16 -07:00
toUpdateFrame(showHiddenVotes) {
let counts = new Array(this.choices.length);
counts.fill(0);
this.votes.forEach(index => counts[index]++);
if (this.hideVotes) {
counts = counts.map(c => {
if (showHiddenVotes) return `${c}?`;
else return '?';
});
2013-09-11 20:22:00 -05:00
}
2021-07-22 22:34:16 -07:00
return {
title: this.title,
options: this.choices,
counts: counts,
initiator: this.createdBy,
timestamp: this.createdAt.getTime()
};
2013-09-11 20:22:00 -05:00
}
2021-07-22 22:34:16 -07:00
}
2013-03-16 16:49:58 -05:00
exports.Poll = Poll;