mirror of https://github.com/calzoneman/sync.git
Start rewriting channel.js
This commit is contained in:
parent
e27667b6d2
commit
ba0664641e
|
@ -0,0 +1,210 @@
|
|||
var DEFAULT_FILTERS = [
|
||||
new Filter("monospace", "`(.+?)`", "g", "<code>$1</code>"),
|
||||
new Filter("bold", "\\*(.+?)\\*", "g", "<strong>$1</strong>"),
|
||||
new Filter("italic", "_(.+?)_", "g", "<em>$1</em>"),
|
||||
new Filter("strike", "~~(.+?)~~", "g", "<s>$1</s>"),
|
||||
new Filter("inline spoiler", "\\[sp\\](.*?)\\[\\/sp\\]", "ig", "<span class=\"spoiler\">$1</span>")
|
||||
];
|
||||
|
||||
function Channel(name) {
|
||||
var self = this; // Alias `this` to prevent scoping issues
|
||||
Logger.syslog.log("Loading channel " + name);
|
||||
|
||||
// Defaults
|
||||
self.ready = false;
|
||||
self.name = name;
|
||||
self.uniqueName = name.toLowerCase(); // To prevent casing issues
|
||||
self.registered = false; // set to true if the channel exists in the database
|
||||
self.users = [];
|
||||
self.mutedUsers = new $util.Set();
|
||||
self.playlist = new Playlist(self);
|
||||
self.plqueue = new AsyncQueue(); // For synchronizing playlist actions
|
||||
self.drinks = 0;
|
||||
self.leader = null;
|
||||
self.chatbuffer = [];
|
||||
self.playlistLock = true;
|
||||
self.poll = null;
|
||||
self.voteskip = null;
|
||||
self.permissions = {
|
||||
playlistadd: 1.5, // Add video to the playlist
|
||||
playlistnext: 1.5, // TODO I don't think this is used
|
||||
playlistmove: 1.5, // Move a video on the playlist
|
||||
playlistdelete: 2, // Delete a video from the playlist
|
||||
playlistjump: 1.5, // Start a different video on the playlist
|
||||
playlistaddlist: 1.5, // Add a list of videos to the playlist
|
||||
oplaylistadd: -1, // Same as above, but for open (unlocked) playlist
|
||||
oplaylistnext: 1.5,
|
||||
oplaylistmove: 1.5,
|
||||
oplaylistdelete: 2,
|
||||
oplaylistjump: 1.5,
|
||||
oplaylistaddlist: 1.5,
|
||||
playlistaddcustom: 3, // Add custom embed to the playlist
|
||||
playlistaddlive: 1.5, // Add a livestream to the playlist
|
||||
exceedmaxlength: 2, // Add a video longer than the maximum length set
|
||||
addnontemp: 2, // Add a permanent video to the playlist
|
||||
settemp: 2, // Toggle temporary status of a playlist item
|
||||
playlistgeturl: 1.5, // TODO is this even used?
|
||||
playlistshuffle: 2, // Shuffle the playlist
|
||||
playlistclear: 2, // Clear the playlist
|
||||
pollctl: 1.5, // Open/close polls
|
||||
pollvote: -1, // Vote in polls
|
||||
viewhiddenpoll: 1.5, // View results of hidden polls
|
||||
voteskip: -1, // Vote to skip the current video
|
||||
mute: 1.5, // Mute other users
|
||||
kick: 1.5, // Kick other users
|
||||
ban: 2, // Ban other users
|
||||
motdedit: 3, // Edit the MOTD
|
||||
filteredit: 3, // Control chat filters
|
||||
drink: 1.5, // Use the /d command
|
||||
chat: 0 // Send chat messages
|
||||
};
|
||||
self.opts = {
|
||||
allow_voteskip: true, // Allow users to voteskip
|
||||
voteskip_ratio: 0.5, // Ratio of skip votes:non-afk users needed to skip the video
|
||||
afk_timeout: 600, // Number of seconds before a user is automatically marked afk
|
||||
pagetitle: self.name, // Title of the browser tab
|
||||
maxlength: 0, // Maximum length (in seconds) of a video queued
|
||||
externalcss: "", // Link to external stylesheet
|
||||
externaljs: "", // Link to external script
|
||||
chat_antiflood: false, // Throttle chat messages
|
||||
chat_antiflood_params: {
|
||||
burst: 4, // Number of messages to allow with no throttling
|
||||
sustained: 1, // Throttle rate (messages/second)
|
||||
cooldown: 4 // Number of seconds with no messages before burst is reset
|
||||
},
|
||||
show_public: false, // List the channel on the index page
|
||||
enable_link_regex: true, // Use the built-in link filter
|
||||
password: false // Channel password (false -> no password required for entry)
|
||||
};
|
||||
self.motd = {
|
||||
motd: "", // Raw MOTD text
|
||||
html: "" // Filtered MOTD text (XSS removed; \n replaced by <br>)
|
||||
};
|
||||
self.filters = DEFAULT_FILTERS;
|
||||
self.banlist = new Banlist();
|
||||
self.logger = new Logger.Logger(path.join(__dirname, "../chanlogs",
|
||||
self.uniqueName + ".log"));
|
||||
self.css = ""; // Up to 20KB of inline CSS
|
||||
self.js = ""; // Up to 20KB of inline Javascript
|
||||
|
||||
self.error = false; // Set to true if something bad happens => don't save state
|
||||
|
||||
self.on("ready", function () {
|
||||
self.ready = true;
|
||||
});
|
||||
|
||||
// Load from database
|
||||
db.channels.load(self, function (err) {
|
||||
if (err && err !== "Channel is not registered") {
|
||||
return;
|
||||
} else {
|
||||
// Load state from JSON blob
|
||||
self.tryLoadState();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Channel.prototype = EventEmitter;
|
||||
|
||||
Channel.prototype.tryLoadState = function () {
|
||||
var self = this;
|
||||
if (self.name === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't load state if the channel isn't registered
|
||||
if (!self.registered) {
|
||||
self.emit("ready");
|
||||
return;
|
||||
}
|
||||
|
||||
var file = path.join(__dirname, "../chandump", self.uniqueName);
|
||||
fs.stat(file, function (err, stats) {
|
||||
if (!err) {
|
||||
var mb = stats.size / 1048576;
|
||||
mb = Math.floor(mb * 100) / 100;
|
||||
if (mb > 1) {
|
||||
Logger.errlog.log("Large chandump detected: " + self.uniqueName +
|
||||
" (" + mb + " MiB)");
|
||||
self.setMOTD("Your channel file has exceeded the maximum size of 1MB " +
|
||||
"and cannot be loaded. Please ask an administrator for " +
|
||||
"assistance in restoring it.");
|
||||
self.error = true;
|
||||
self.emit("ready");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.loadState();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the channel state from disk.
|
||||
*
|
||||
* SHOULD ONLY BE CALLED FROM tryLoadState
|
||||
*/
|
||||
Channel.prototype.loadState = function () {
|
||||
var self = this;
|
||||
if (self.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.readFile(path.join(__dirname, "../chandump", self.name),
|
||||
function (err, data) {
|
||||
if (err) {
|
||||
// File didn't exist => start fresh
|
||||
if (err.code === "ENOENT") {
|
||||
self.emit("ready");
|
||||
self.saveState();
|
||||
} else {
|
||||
Logger.errlog.log("Failed to open channel dump " + self.uniqueName);
|
||||
Logger.errlog.log(err);
|
||||
self.setMOTD("Internal error when loading channel");
|
||||
self.error = true;
|
||||
self.emit("ready");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.logger.log("*** Loading channel state");
|
||||
data = JSON.parse(data);
|
||||
|
||||
// Load the playlist
|
||||
if ("playlist" in data) {
|
||||
}
|
||||
|
||||
// Playlist lock
|
||||
self.setLock(data.playlistLock || false);
|
||||
|
||||
// Configurables
|
||||
if ("opts" in data) {
|
||||
for (var key in data.opts) {
|
||||
self.opts[key] = data.opts;
|
||||
}
|
||||
}
|
||||
|
||||
// Permissions
|
||||
if ("permissions" in data) {
|
||||
for (var key in data.permissions) {
|
||||
self.permissions[key] = data.permissions[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Chat filters
|
||||
if ("filters" in data) {
|
||||
for (var i = 0; i < data.filters.length; i++) {
|
||||
var f = data.filters[i];
|
||||
var filt = new Filter(f.name, f.source, f.flags, f.replace);
|
||||
filt.active = f.active;
|
||||
filt.filterlinks = f.filterlinks;
|
||||
self.updateFilter(filt, false);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
});
|
||||
};
|
|
@ -1315,20 +1315,25 @@ Channel.prototype.calcVoteskipMax = function () {
|
|||
}, 0);
|
||||
};
|
||||
|
||||
Channel.prototype.broadcastVoteskipUpdate = function() {
|
||||
Channel.prototype.getVoteskipPacket = function() {
|
||||
var amt = this.voteskip ? this.voteskip.counts[0] : 0;
|
||||
var count = this.calcVoteskipMax();
|
||||
var need = this.voteskip ? Math.ceil(count * this.opts.voteskip_ratio) : 0;
|
||||
for(var i = 0; i < this.users.length; i++) {
|
||||
if(this.users[i].rank >= 1.5) {
|
||||
this.users[i].socket.emit("voteskip", {
|
||||
count: amt,
|
||||
need: need
|
||||
});
|
||||
}
|
||||
}
|
||||
return {
|
||||
count: amt,
|
||||
need: need
|
||||
};
|
||||
}
|
||||
|
||||
Channel.prototype.broadcastVoteskipUpdate = function () {
|
||||
var pkt = this.getVoteskipPacket();
|
||||
this.users.forEach(function (u) {
|
||||
if (u.rank >= 1.5) {
|
||||
u.socket.emit("voteskip", pkt);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Channel.prototype.broadcastMotd = function() {
|
||||
this.sendAll("setMotd", this.motd);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ var User = function (socket) {
|
|||
this.name = "";
|
||||
this.meta = {
|
||||
afk: false,
|
||||
icon: false
|
||||
icon: false,
|
||||
aliases: []
|
||||
};
|
||||
this.queueLimiter = $util.newRateLimiter();
|
||||
this.chatLimiter = $util.newRateLimiter();
|
||||
|
|
|
@ -67,7 +67,8 @@ function handleLoginPage(req, res) {
|
|||
}
|
||||
}
|
||||
sendJade(res, 'login', {
|
||||
loggedIn: false
|
||||
loggedIn: false,
|
||||
redirect: req.header('Referrer')
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,15 @@ html(lang="en")
|
|||
ul.nav.navbar-nav
|
||||
mixin navdefaultlinks("/login")
|
||||
if loggedIn
|
||||
mixin navlogoutform("/login")
|
||||
if redirect
|
||||
mixin navlogoutform(redirect)
|
||||
else
|
||||
mixin navlogoutform("/login")
|
||||
section#mainpage.container
|
||||
if wasAlreadyLoggedIn
|
||||
.col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
|
||||
.alert.alert-info.messagebox.center
|
||||
h3(style="margin: 5px auto") Logged in as #{loginName}
|
||||
// TODO Link to My Account page
|
||||
else if !loggedIn
|
||||
.col-lg-6.col-lg-offset-3.col-md-6.col-md-offset-3
|
||||
if loginError
|
||||
|
@ -27,6 +29,8 @@ html(lang="en")
|
|||
p= loginError
|
||||
h2 Login
|
||||
form(role="form", action="/login", method="post")
|
||||
if redirect
|
||||
input(type="hidden", name="redirect", value=redirect)
|
||||
.form-group
|
||||
label(for="username") Username
|
||||
input#username.form-control(type="text", name="name")
|
||||
|
|
|
@ -55,7 +55,7 @@ mixin navloginform(redirect)
|
|||
|
||||
mixin navlogoutform(redirect)
|
||||
if redirect
|
||||
- url = "/logout?redirect=#{redirect}"
|
||||
- url = "/logout?redirect=" + redirect
|
||||
else
|
||||
- url = "/logout"
|
||||
p#logoutform.navbar-text.pull-right
|
||||
|
|
Loading…
Reference in New Issue