fore.st/src/channel/voteskip.js
2018-11-11 16:08:00 -08:00

139 lines
3.6 KiB
JavaScript

var ChannelModule = require("./module");
var Flags = require("../flags");
var Poll = require("../poll").Poll;
function VoteskipModule(_channel) {
ChannelModule.apply(this, arguments);
this.poll = false;
}
VoteskipModule.prototype = Object.create(ChannelModule.prototype);
VoteskipModule.prototype.onUserPostJoin = function (user) {
user.socket.on("voteskip", this.handleVoteskip.bind(this, user));
};
VoteskipModule.prototype.onUserPart = function(user) {
if (!this.poll) {
return;
}
this.unvote(user.realip);
this.update();
};
VoteskipModule.prototype.handleVoteskip = function (user) {
if (!this.channel.modules.options.get("allow_voteskip")) {
return;
}
if (!this.channel.modules.playlist) {
return;
}
if (!this.channel.modules.permissions.canVoteskip(user)) {
return;
}
if (!this.poll) {
this.poll = new Poll("[server]", "voteskip", ["skip"], false);
}
if (!this.poll.vote(user.realip, 0)) {
// Vote was already recorded for this IP, no update needed
return;
}
var title = "";
if (this.channel.modules.playlist.current) {
title = " " + this.channel.modules.playlist.current.media.title;
}
var name = user.getName() || "(anonymous)";
this.channel.logger.log("[playlist] " + name + " voteskipped " + title);
user.setAFK(false);
this.update();
};
VoteskipModule.prototype.unvote = function(ip) {
if (!this.poll) {
return;
}
this.poll.unvote(ip);
};
VoteskipModule.prototype.update = function () {
if (!this.channel.modules.options.get("allow_voteskip")) {
return;
}
if (!this.poll) {
return;
}
if (this.channel.modules.playlist.meta.count === 0) {
return;
}
const { total, eligible, noPermission, afk } = this.calcUsercounts();
const need = Math.ceil(eligible * this.channel.modules.options.get("voteskip_ratio"));
if (this.poll.counts[0] >= need) {
const info = `${this.poll.counts[0]}/${eligible} skipped; ` +
`eligible voters: ${eligible} = total (${total}) - AFK (${afk}) ` +
`- no permission (${noPermission}); ` +
`ratio = ${this.channel.modules.options.get("voteskip_ratio")}`;
this.channel.logger.log(`[playlist] Voteskip passed: ${info}`);
this.reset();
this.channel.modules.playlist._playNext();
} else {
this.sendVoteskipData(this.channel.users);
}
};
VoteskipModule.prototype.sendVoteskipData = function (users) {
const { eligible } = this.calcUsercounts();
var data = {
count: this.poll ? this.poll.counts[0] : 0,
need: this.poll ? Math.ceil(eligible * this.channel.modules.options.get("voteskip_ratio"))
: 0
};
var perms = this.channel.modules.permissions;
users.forEach(function (u) {
if (perms.canSeeVoteskipResults(u)) {
u.socket.emit("voteskip", data);
}
});
};
VoteskipModule.prototype.calcUsercounts = function () {
const perms = this.channel.modules.permissions;
const counts = { total: 0, noPermission: 0, afk: 0 };
this.channel.users.forEach(u => {
counts.total++;
if (!perms.canVoteskip(u)) counts.noPermission++;
else if (u.is(Flags.U_AFK)) counts.afk++;
});
counts.eligible = counts.total - (counts.noPermission + counts.afk);
return counts;
};
VoteskipModule.prototype.reset = function reset() {
this.poll = false;
this.sendVoteskipData(this.channel.users);
};
VoteskipModule.prototype.onMediaChange = function (_data) {
this.reset();
};
module.exports = VoteskipModule;