commit
141516bf36
28
index.js
Normal file
28
index.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Calvin Montgomery
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Server = require("./lib/server");
|
||||||
|
var Config = require("./lib/config");
|
||||||
|
var Logger = require("./lib/logger");
|
||||||
|
|
||||||
|
Config.load("cfg.json", function (cfg) {
|
||||||
|
var sv = Server.init(cfg);
|
||||||
|
if(!cfg["debug"]) {
|
||||||
|
process.on("uncaughtException", function (err) {
|
||||||
|
Logger.errlog.log("[SEVERE] Uncaught Exception: " + err);
|
||||||
|
Logger.errlog.log(err.stack);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on("SIGINT", function () {
|
||||||
|
sv.shutdown();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
30
lib/acp.js
30
lib/acp.js
|
@ -10,24 +10,25 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Logger = require("./logger");
|
var Logger = require("./logger");
|
||||||
|
var Server = require("./server");
|
||||||
|
var ActionLog = require("./actionlog");
|
||||||
|
|
||||||
module.exports = function (Server) {
|
module.exports = {
|
||||||
var db = Server.db;
|
|
||||||
var ActionLog = Server.actionlog;
|
|
||||||
return {
|
|
||||||
init: function (user) {
|
init: function (user) {
|
||||||
|
var sv = Server.getServer();
|
||||||
|
var db = sv.db;
|
||||||
ActionLog.record(user.ip, user.name, "acp-init");
|
ActionLog.record(user.ip, user.name, "acp-init");
|
||||||
user.socket.on("acp-announce", function(data) {
|
user.socket.on("acp-announce", function(data) {
|
||||||
ActionLog.record(user.ip, user.name, "acp-announce", data);
|
ActionLog.record(user.ip, user.name, "acp-announce", data);
|
||||||
Server.announcement = data;
|
sv.announcement = data;
|
||||||
Server.io.sockets.emit("announcement", data);
|
sv.io.sockets.emit("announcement", data);
|
||||||
if (Server.cfg["enable-ssl"])
|
if (sv.cfg["enable-ssl"])
|
||||||
Server.sslio.sockets.emit("announcement", data);
|
sv.ioSecure.sockets.emit("announcement", data);
|
||||||
});
|
});
|
||||||
|
|
||||||
user.socket.on("acp-announce-clear", function() {
|
user.socket.on("acp-announce-clear", function() {
|
||||||
ActionLog.record(user.ip, user.name, "acp-announce-clear");
|
ActionLog.record(user.ip, user.name, "acp-announce-clear");
|
||||||
Server.announcement = null;
|
sv.announcement = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
user.socket.on("acp-global-ban", function(data) {
|
user.socket.on("acp-global-ban", function(data) {
|
||||||
|
@ -113,7 +114,7 @@ module.exports = function (Server) {
|
||||||
|
|
||||||
user.socket.on("acp-list-loaded", function() {
|
user.socket.on("acp-list-loaded", function() {
|
||||||
var chans = [];
|
var chans = [];
|
||||||
var all = Server.channels;
|
var all = sv.channels;
|
||||||
for(var c in all) {
|
for(var c in all) {
|
||||||
var chan = all[c];
|
var chan = all[c];
|
||||||
|
|
||||||
|
@ -131,8 +132,8 @@ module.exports = function (Server) {
|
||||||
});
|
});
|
||||||
|
|
||||||
user.socket.on("acp-channel-unload", function(data) {
|
user.socket.on("acp-channel-unload", function(data) {
|
||||||
if(Server.channelLoaded(data.name)) {
|
if(sv.isChannelLoaded(data.name)) {
|
||||||
var c = Server.getChannel(data.name);
|
var c = sv.getChannel(data.name);
|
||||||
if(!c)
|
if(!c)
|
||||||
return;
|
return;
|
||||||
ActionLog.record(user.ip, user.name, "acp-channel-unload");
|
ActionLog.record(user.ip, user.name, "acp-channel-unload");
|
||||||
|
@ -146,8 +147,8 @@ module.exports = function (Server) {
|
||||||
|
|
||||||
// At this point c should be unloaded
|
// At this point c should be unloaded
|
||||||
// if it's still loaded, kill it
|
// if it's still loaded, kill it
|
||||||
if(Server.channelLoaded(data.name))
|
if(sv.isChannelLoaded(data.name))
|
||||||
Server.unloadChannel(Server.getChannel(data.name));
|
sv.unloadChannel(sv.getChannel(data.name));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -176,4 +177,3 @@ module.exports = function (Server) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -10,11 +10,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Logger = require("./logger");
|
var Logger = require("./logger");
|
||||||
|
var Server = require("./server");
|
||||||
|
|
||||||
module.exports = function (Server) {
|
module.exports = {
|
||||||
var db = Server.db;
|
|
||||||
return {
|
|
||||||
record: function (ip, name, action, args) {
|
record: function (ip, name, action, args) {
|
||||||
|
var db = Server.getServer().db;
|
||||||
if(!args)
|
if(!args)
|
||||||
args = "";
|
args = "";
|
||||||
else {
|
else {
|
||||||
|
@ -29,14 +29,17 @@ module.exports = function (Server) {
|
||||||
},
|
},
|
||||||
|
|
||||||
clear: function (actions) {
|
clear: function (actions) {
|
||||||
|
var db = Server.getServer().db;
|
||||||
db.clearActions(actions);
|
db.clearActions(actions);
|
||||||
},
|
},
|
||||||
|
|
||||||
clearOne: function (item) {
|
clearOne: function (item) {
|
||||||
|
var db = Server.getServer().db;
|
||||||
db.clearSingleAction(item);
|
db.clearSingleAction(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
throttleRegistrations: function (ip, callback) {
|
throttleRegistrations: function (ip, callback) {
|
||||||
|
var db = Server.getServer().db;
|
||||||
db.recentRegistrationCount(ip, function (err, count) {
|
db.recentRegistrationCount(ip, function (err, count) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback(err, null);
|
callback(err, null);
|
||||||
|
@ -48,11 +51,12 @@ module.exports = function (Server) {
|
||||||
},
|
},
|
||||||
|
|
||||||
listActionTypes: function (callback) {
|
listActionTypes: function (callback) {
|
||||||
|
var db = Server.getServer().db;
|
||||||
db.listActionTypes(callback);
|
db.listActionTypes(callback);
|
||||||
},
|
},
|
||||||
|
|
||||||
listActions: function (types, callback) {
|
listActions: function (types, callback) {
|
||||||
|
var db = Server.getServer().db;
|
||||||
db.listActions(types, callback);
|
db.listActions(types, callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ var Logger = require("./logger");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var $util = require("./utilities");
|
var $util = require("./utilities");
|
||||||
|
var ActionLog = require("./actionlog");
|
||||||
|
|
||||||
module.exports = function (Server) {
|
module.exports = function (Server) {
|
||||||
var ActionLog = Server.actionlog;
|
|
||||||
function getIP(req) {
|
function getIP(req) {
|
||||||
var raw = req.connection.remoteAddress;
|
var raw = req.connection.remoteAddress;
|
||||||
var forward = req.header("x-forwarded-for");
|
var forward = req.header("x-forwarded-for");
|
||||||
|
@ -51,7 +51,7 @@ module.exports = function (Server) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
var app = Server.app;
|
var app = Server.express;
|
||||||
var db = Server.db;
|
var db = Server.db;
|
||||||
|
|
||||||
/* <https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol> */
|
/* <https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol> */
|
||||||
|
|
|
@ -12,24 +12,26 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
var url = require("url");
|
||||||
|
var Server = require("./server");
|
||||||
var Poll = require("./poll.js").Poll;
|
var Poll = require("./poll.js").Poll;
|
||||||
var Media = require("./media.js").Media;
|
var Media = require("./media.js").Media;
|
||||||
var Logger = require("./logger.js");
|
var Logger = require("./logger.js");
|
||||||
var Rank = require("./rank.js");
|
|
||||||
var ChatCommand = require("./chatcommand.js");
|
var ChatCommand = require("./chatcommand.js");
|
||||||
var Filter = require("./filter.js").Filter;
|
var Filter = require("./filter.js").Filter;
|
||||||
var Playlist = require("./playlist");
|
var Playlist = require("./playlist");
|
||||||
var sanitize = require("validator").sanitize;
|
var sanitize = require("validator").sanitize;
|
||||||
var $util = require("./utilities");
|
var $util = require("./utilities");
|
||||||
var url = require("url");
|
|
||||||
var AsyncQueue = require("./asyncqueue");
|
var AsyncQueue = require("./asyncqueue");
|
||||||
|
var ActionLog = require("./actionlog");
|
||||||
|
var InfoGetter = require("./get-info");
|
||||||
|
|
||||||
var Channel = function(name, Server) {
|
var Channel = function(name) {
|
||||||
var self = this;
|
var self = this;
|
||||||
Logger.syslog.log("Opening channel " + name);
|
Logger.syslog.log("Opening channel " + name);
|
||||||
self.initialized = false;
|
self.initialized = false;
|
||||||
self.dbloaded = false;
|
self.dbloaded = false;
|
||||||
self.server = Server;
|
self.server = Server.getServer();
|
||||||
|
|
||||||
self.name = name;
|
self.name = name;
|
||||||
self.canonical_name = name.toLowerCase();
|
self.canonical_name = name.toLowerCase();
|
||||||
|
@ -123,7 +125,7 @@ var Channel = function(name, Server) {
|
||||||
self.ipkey += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[parseInt(Math.random() * 65)]
|
self.ipkey += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[parseInt(Math.random() * 65)]
|
||||||
}
|
}
|
||||||
|
|
||||||
Server.db.loadChannelData(self, function (err) {
|
Server.getServer().db.loadChannelData(self, function (err) {
|
||||||
if (err && err === "channel_dead")
|
if (err && err === "channel_dead")
|
||||||
return;
|
return;
|
||||||
else if (!err || err === "channel_unregistered")
|
else if (!err || err === "channel_unregistered")
|
||||||
|
@ -384,7 +386,7 @@ Channel.prototype.tryReadLog = function (user) {
|
||||||
Channel.prototype.tryRegister = function (user) {
|
Channel.prototype.tryRegister = function (user) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if(self.registered) {
|
if(self.registered) {
|
||||||
self.server.actionlog.record(user.ip, user.name, "channel-register-failure",
|
ActionLog.record(user.ip, user.name, "channel-register-failure",
|
||||||
[self.name, "Channel already registered"]);
|
[self.name, "Channel already registered"]);
|
||||||
user.socket.emit("registerChannel", {
|
user.socket.emit("registerChannel", {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -392,7 +394,7 @@ Channel.prototype.tryRegister = function (user) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if(!user.loggedIn) {
|
else if(!user.loggedIn) {
|
||||||
self.server.actionlog.record(user.ip, user.name, "channel-register-failure",
|
ActionLog.record(user.ip, user.name, "channel-register-failure",
|
||||||
[self.name, "Not logged in"]);
|
[self.name, "Not logged in"]);
|
||||||
user.socket.emit("registerChannel", {
|
user.socket.emit("registerChannel", {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -400,8 +402,8 @@ Channel.prototype.tryRegister = function (user) {
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(!Rank.hasPermission(user, "registerChannel")) {
|
else if(user.rank < 10) {
|
||||||
self.server.actionlog.record(user.ip, user.name, "channel-register-failure",
|
ActionLog.record(user.ip, user.name, "channel-register-failure",
|
||||||
[self.name, "Insufficient permissions"]);
|
[self.name, "Insufficient permissions"]);
|
||||||
user.socket.emit("registerChannel", {
|
user.socket.emit("registerChannel", {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -419,7 +421,7 @@ Channel.prototype.tryRegister = function (user) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.server.actionlog.record(user.ip, user.name,
|
ActionLog.record(user.ip, user.name,
|
||||||
"channel-register-success", self.name);
|
"channel-register-success", self.name);
|
||||||
if (self.dead)
|
if (self.dead)
|
||||||
return;
|
return;
|
||||||
|
@ -927,7 +929,7 @@ Channel.prototype.sendBanlist = function(user) {
|
||||||
var name = this.ipbans[ip][0];
|
var name = this.ipbans[ip][0];
|
||||||
var ip_hidden = this.hideIP(ip);
|
var ip_hidden = this.hideIP(ip);
|
||||||
var disp = ip;
|
var disp = ip;
|
||||||
if(user.rank < Rank.Siteadmin) {
|
if(user.rank < 255) {
|
||||||
disp = $util.maskIP(ip);
|
disp = $util.maskIP(ip);
|
||||||
}
|
}
|
||||||
ents.push({
|
ents.push({
|
||||||
|
@ -971,7 +973,7 @@ Channel.prototype.sendRankStuff = function(user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.sendChannelRanks = function(user) {
|
Channel.prototype.sendChannelRanks = function(user) {
|
||||||
if(Rank.hasPermission(user, "acl") && this.registered) {
|
if(user.rank >= 3 && this.registered) {
|
||||||
this.server.db.listChannelRanks(this.name, function (err, res) {
|
this.server.db.listChannelRanks(this.name, function (err, res) {
|
||||||
if(err) {
|
if(err) {
|
||||||
user.socket.emit("errorMsg", {
|
user.socket.emit("errorMsg", {
|
||||||
|
@ -1028,12 +1030,12 @@ Channel.prototype.sendAll = function(message, data) {
|
||||||
return;
|
return;
|
||||||
this.server.io.sockets.in(this.name).emit(message, data);
|
this.server.io.sockets.in(this.name).emit(message, data);
|
||||||
if (this.server.cfg["enable-ssl"])
|
if (this.server.cfg["enable-ssl"])
|
||||||
this.server.sslio.sockets.in(this.name).emit(message, data);
|
this.server.ioSecure.sockets.in(this.name).emit(message, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.sendAllWithPermission = function(perm, msg, data) {
|
Channel.prototype.sendAllWithRank = function(rank, msg, data) {
|
||||||
for(var i = 0; i < this.users.length; i++) {
|
for(var i = 0; i < this.users.length; i++) {
|
||||||
if(Rank.hasPermission(this.users[i], perm)) {
|
if(this.users[i].rank >= rank) {
|
||||||
this.users[i].socket.emit(msg, data);
|
this.users[i].socket.emit(msg, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1101,7 +1103,7 @@ Channel.prototype.broadcastNewUser = function(user) {
|
||||||
profile: user.profile
|
profile: user.profile
|
||||||
});
|
});
|
||||||
|
|
||||||
if(user.rank > Rank.Guest) {
|
if(user.rank > 0) {
|
||||||
self.saveRank(user);
|
self.saveRank(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1209,7 +1211,7 @@ Channel.prototype.broadcastBanlist = function() {
|
||||||
}
|
}
|
||||||
for(var i = 0; i < this.users.length; i++) {
|
for(var i = 0; i < this.users.length; i++) {
|
||||||
if(this.hasPermission(this.users[i], "ban")) {
|
if(this.hasPermission(this.users[i], "ban")) {
|
||||||
if(this.users[i].rank >= Rank.Siteadmin) {
|
if(this.users[i].rank >= 255) {
|
||||||
this.users[i].socket.emit("banlist", adminents);
|
this.users[i].socket.emit("banlist", adminents);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1248,8 +1250,7 @@ Channel.prototype.broadcastVoteskipUpdate = function() {
|
||||||
var count = this.calcVoteskipMax();
|
var count = this.calcVoteskipMax();
|
||||||
var need = this.voteskip ? Math.ceil(count * this.opts.voteskip_ratio) : 0;
|
var need = this.voteskip ? Math.ceil(count * this.opts.voteskip_ratio) : 0;
|
||||||
for(var i = 0; i < this.users.length; i++) {
|
for(var i = 0; i < this.users.length; i++) {
|
||||||
if(Rank.hasPermission(this.users[i], "seeVoteskip") ||
|
if(this.users[i].rank >= 1.5) {
|
||||||
this.leader == this.users[i]) {
|
|
||||||
this.users[i].socket.emit("voteskip", {
|
this.users[i].socket.emit("voteskip", {
|
||||||
count: amt,
|
count: amt,
|
||||||
need: need
|
need: need
|
||||||
|
@ -1332,7 +1333,7 @@ Channel.prototype.tryQueue = function(user, data) {
|
||||||
sustained: 1
|
sustained: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (user.rank >= Rank.Moderator || this.leader == user) {
|
if (user.rank >= 2 || this.leader == user) {
|
||||||
limit = {
|
limit = {
|
||||||
burst: 10,
|
burst: 10,
|
||||||
sustained: 2
|
sustained: 2
|
||||||
|
@ -1471,7 +1472,7 @@ Channel.prototype.addMedia = function(data, user) {
|
||||||
self.plqueue.queue(function (q) {
|
self.plqueue.queue(function (q) {
|
||||||
if (self.dead)
|
if (self.dead)
|
||||||
return;
|
return;
|
||||||
self.server.infogetter.getMedia(data.id, data.type,
|
InfoGetter.getMedia(data.id, data.type,
|
||||||
function (e, vids) {
|
function (e, vids) {
|
||||||
if (e) {
|
if (e) {
|
||||||
user.socket.emit("queueFail", {
|
user.socket.emit("queueFail", {
|
||||||
|
@ -1506,7 +1507,7 @@ Channel.prototype.addMedia = function(data, user) {
|
||||||
if (self.dead)
|
if (self.dead)
|
||||||
return;
|
return;
|
||||||
var cb = afterData.bind(self, q, false);
|
var cb = afterData.bind(self, q, false);
|
||||||
self.server.infogetter.getMedia(data.id, data.type,
|
InfoGetter.getMedia(data.id, data.type,
|
||||||
function (e, m) {
|
function (e, m) {
|
||||||
if (self.dead)
|
if (self.dead)
|
||||||
return;
|
return;
|
||||||
|
@ -1550,7 +1551,7 @@ Channel.prototype.addMedia = function(data, user) {
|
||||||
|
|
||||||
afterData.bind(self, q, true)(item);
|
afterData.bind(self, q, true)(item);
|
||||||
} else {
|
} else {
|
||||||
self.server.infogetter.getMedia(data.id, data.type,
|
InfoGetter.getMedia(data.id, data.type,
|
||||||
function (e, m) {
|
function (e, m) {
|
||||||
if (self.dead)
|
if (self.dead)
|
||||||
return;
|
return;
|
||||||
|
@ -1671,7 +1672,7 @@ Channel.prototype.tryDequeue = function(user, data) {
|
||||||
|
|
||||||
Channel.prototype.tryUncache = function(user, data) {
|
Channel.prototype.tryUncache = function(user, data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if(!Rank.hasPermission(user, "uncache")) {
|
if(user.rank < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(typeof data.id != "string") {
|
if(typeof data.id != "string") {
|
||||||
|
@ -1923,7 +1924,7 @@ Channel.prototype.setLock = function(locked) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.trySetLock = function(user, data) {
|
Channel.prototype.trySetLock = function(user, data) {
|
||||||
if(!Rank.hasPermission(user, "qlock")) {
|
if(user.rank < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1936,7 +1937,7 @@ Channel.prototype.trySetLock = function(user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.tryToggleLock = function(user) {
|
Channel.prototype.tryToggleLock = function(user) {
|
||||||
if(!Rank.hasPermission(user, "qlock")) {
|
if(user.rank < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2028,7 +2029,7 @@ Channel.prototype.tryMoveFilter = function(user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.tryUpdatePermissions = function(user, perms) {
|
Channel.prototype.tryUpdatePermissions = function(user, perms) {
|
||||||
if(!Rank.hasPermission(user, "channelperms")) {
|
if(user.rank < 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(var key in perms) {
|
for(var key in perms) {
|
||||||
|
@ -2039,7 +2040,7 @@ Channel.prototype.tryUpdatePermissions = function(user, perms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.tryUpdateOptions = function(user, data) {
|
Channel.prototype.tryUpdateOptions = function(user, data) {
|
||||||
if(!Rank.hasPermission(user, "channelOpts")) {
|
if(user.rank < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2058,7 +2059,7 @@ Channel.prototype.tryUpdateOptions = function(user, data) {
|
||||||
|
|
||||||
for(var key in this.opts) {
|
for(var key in this.opts) {
|
||||||
if(key in data) {
|
if(key in data) {
|
||||||
if(key in adminonly && user.rank < Rank.Owner) {
|
if(key in adminonly && user.rank < 3) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(key === "afk_timeout" && this.opts[key] != data[key]) {
|
if(key === "afk_timeout" && this.opts[key] != data[key]) {
|
||||||
|
@ -2075,7 +2076,7 @@ Channel.prototype.tryUpdateOptions = function(user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.trySetCSS = function(user, data) {
|
Channel.prototype.trySetCSS = function(user, data) {
|
||||||
if(!Rank.hasPermission(user, "setcss")) {
|
if(user.rank < 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2092,7 +2093,7 @@ Channel.prototype.trySetCSS = function(user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.trySetJS = function(user, data) {
|
Channel.prototype.trySetJS = function(user, data) {
|
||||||
if(!Rank.hasPermission(user, "setjs")) {
|
if(user.rank < 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2234,7 +2235,7 @@ Channel.prototype.sendMessage = function(username, msg, msgclass, data) {
|
||||||
|
|
||||||
Channel.prototype.trySetRank = function(user, data) {
|
Channel.prototype.trySetRank = function(user, data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if(!Rank.hasPermission(user, "promote"))
|
if(user.rank < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(typeof data.user !== "string" || typeof data.rank !== "number")
|
if(typeof data.user !== "string" || typeof data.rank !== "number")
|
||||||
|
@ -2265,7 +2266,7 @@ Channel.prototype.trySetRank = function(user, data) {
|
||||||
|
|
||||||
self.logger.log("*** " + user.name + " set " +
|
self.logger.log("*** " + user.name + " set " +
|
||||||
data.user + "'s rank to " + data.rank);
|
data.user + "'s rank to " + data.rank);
|
||||||
self.sendAllWithPermission("acl", "setChannelRank", data);
|
self.sendAllWithRank(3, "setChannelRank", data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.broadcastUserUpdate(receiver);
|
self.broadcastUserUpdate(receiver);
|
||||||
|
@ -2286,7 +2287,7 @@ Channel.prototype.trySetRank = function(user, data) {
|
||||||
|
|
||||||
self.logger.log("*** " + user.name + " set " +
|
self.logger.log("*** " + user.name + " set " +
|
||||||
data.user + "'s rank to " + data.rank);
|
data.user + "'s rank to " + data.rank);
|
||||||
self.sendAllWithPermission("acl", "setChannelRank", data);
|
self.sendAllWithRank(3, "setChannelRank", data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2329,7 +2330,7 @@ Channel.prototype.changeLeader = function(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel.prototype.tryChangeLeader = function(user, data) {
|
Channel.prototype.tryChangeLeader = function(user, data) {
|
||||||
if(!Rank.hasPermission(user, "assignLeader")) {
|
if(user.rank < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ The above copyright notice and this permission notice shall be included in all c
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Rank = require("./rank.js");
|
|
||||||
var Poll = require("./poll.js").Poll;
|
|
||||||
var Logger = require("./logger.js");
|
var Logger = require("./logger.js");
|
||||||
|
|
||||||
function handle(chan, user, msg, data) {
|
function handle(chan, user, msg, data) {
|
||||||
|
@ -19,7 +17,7 @@ function handle(chan, user, msg, data) {
|
||||||
else if(msg.indexOf("/sp ") == 0)
|
else if(msg.indexOf("/sp ") == 0)
|
||||||
chan.sendMessage(user.name, msg.substring(4), "spoiler", data);
|
chan.sendMessage(user.name, msg.substring(4), "spoiler", data);
|
||||||
else if(msg.indexOf("/say ") == 0) {
|
else if(msg.indexOf("/say ") == 0) {
|
||||||
if(Rank.hasPermission(user, "shout") || chan.leader == user) {
|
if(user.rank >= 1.5) {
|
||||||
chan.sendMessage(user.name, msg.substring(5), "shout", data);
|
chan.sendMessage(user.name, msg.substring(5), "shout", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,12 +25,12 @@ function handle(chan, user, msg, data) {
|
||||||
user.setAFK(!user.meta.afk);
|
user.setAFK(!user.meta.afk);
|
||||||
}
|
}
|
||||||
else if(msg.indexOf("/m ") == 0) {
|
else if(msg.indexOf("/m ") == 0) {
|
||||||
if(user.rank >= Rank.Moderator) {
|
if(user.rank >= 2) {
|
||||||
chan.chainMessage(user, msg.substring(3), {modflair: user.rank})
|
chan.chainMessage(user, msg.substring(3), {modflair: user.rank})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(msg.indexOf("/a ") == 0) {
|
else if(msg.indexOf("/a ") == 0) {
|
||||||
if(user.rank >= Rank.Siteadmin) {
|
if(user.rank >= 255) {
|
||||||
var flair = {
|
var flair = {
|
||||||
superadminflair: {
|
superadminflair: {
|
||||||
labelclass: "label-important",
|
labelclass: "label-important",
|
||||||
|
@ -241,7 +239,7 @@ function handleDrink(chan, user, msg, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClear(chan, user) {
|
function handleClear(chan, user) {
|
||||||
if(user.rank < Rank.Moderator) {
|
if(user.rank < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ function save(cfg, file) {
|
||||||
fs.writeFileSync(file, JSON.stringify(x, null, 4));
|
fs.writeFileSync(file, JSON.stringify(x, null, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.load = function (Server, file, callback) {
|
exports.load = function (file, callback) {
|
||||||
var cfg = {};
|
var cfg = {};
|
||||||
for(var k in defaults)
|
for(var k in defaults)
|
||||||
cfg[k] = defaults[k];
|
cfg[k] = defaults[k];
|
||||||
|
@ -102,7 +102,6 @@ exports.load = function (Server, file, callback) {
|
||||||
cfg["loaded"] = true;
|
cfg["loaded"] = true;
|
||||||
|
|
||||||
save(cfg, file);
|
save(cfg, file);
|
||||||
Server.cfg = cfg;
|
callback(cfg);
|
||||||
callback();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,9 @@ var $util = require("./utilities");
|
||||||
var Logger = require("./logger");
|
var Logger = require("./logger");
|
||||||
|
|
||||||
var Database = function (cfg) {
|
var Database = function (cfg) {
|
||||||
this.cfg = cfg;
|
var self = this;
|
||||||
this.pool = mysql.createPool({
|
self.cfg = cfg;
|
||||||
|
self.pool = mysql.createPool({
|
||||||
host: cfg["mysql-server"],
|
host: cfg["mysql-server"],
|
||||||
user: cfg["mysql-user"],
|
user: cfg["mysql-user"],
|
||||||
password: cfg["mysql-pw"],
|
password: cfg["mysql-pw"],
|
||||||
|
@ -15,16 +16,16 @@ var Database = function (cfg) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test the connection
|
// Test the connection
|
||||||
this.pool.getConnection(function (err, conn) {
|
self.pool.getConnection(function (err, conn) {
|
||||||
if(err) {
|
if(err) {
|
||||||
Logger.errlog.log("! DB connection failed");
|
Logger.errlog.log("! DB connection failed");
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
self.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.global_ipbans = {};
|
self.global_ipbans = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Database.prototype.query = function (query, sub, callback) {
|
Database.prototype.query = function (query, sub, callback) {
|
||||||
|
|
|
@ -15,8 +15,8 @@ var domain = require("domain");
|
||||||
var Logger = require("./logger.js");
|
var Logger = require("./logger.js");
|
||||||
var Media = require("./media.js").Media;
|
var Media = require("./media.js").Media;
|
||||||
var CustomEmbedFilter = require("./customembed").filter;
|
var CustomEmbedFilter = require("./customembed").filter;
|
||||||
|
var Server = require("./server");
|
||||||
|
|
||||||
module.exports = function (Server) {
|
|
||||||
var urlRetrieve = function (transport, options, callback) {
|
var urlRetrieve = function (transport, options, callback) {
|
||||||
// Catch any errors that crop up along the way of the request
|
// Catch any errors that crop up along the way of the request
|
||||||
// in order to prevent them from reaching the global handler.
|
// in order to prevent them from reaching the global handler.
|
||||||
|
@ -47,7 +47,8 @@ module.exports = function (Server) {
|
||||||
var Getters = {
|
var Getters = {
|
||||||
/* youtube.com */
|
/* youtube.com */
|
||||||
yt: function (id, callback) {
|
yt: function (id, callback) {
|
||||||
if(Server.cfg["enable-ytv3"] && Server.cfg["ytv3apikey"]) {
|
var sv = Server.getServer();
|
||||||
|
if (sv.cfg["enable-ytv3"] && sv.cfg["ytv3apikey"]) {
|
||||||
Getters["ytv3"](id, callback);
|
Getters["ytv3"](id, callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -69,9 +70,9 @@ module.exports = function (Server) {
|
||||||
timeout: 1000
|
timeout: 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
if(Server.cfg["ytv2devkey"]) {
|
if(sv.cfg["ytv2devkey"]) {
|
||||||
options.headers = {
|
options.headers = {
|
||||||
"X-Gdata-Key": "key=" + Server.cfg["ytv2devkey"]
|
"X-Gdata-Key": "key=" + sv.cfg["ytv2devkey"]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +139,7 @@ module.exports = function (Server) {
|
||||||
|
|
||||||
/* youtube.com API v3 (requires API key) */
|
/* youtube.com API v3 (requires API key) */
|
||||||
ytv3: function (id, callback) {
|
ytv3: function (id, callback) {
|
||||||
|
var sv = Server.getServer();
|
||||||
var m = id.match(/([\w-]+)/);
|
var m = id.match(/([\w-]+)/);
|
||||||
if (m) {
|
if (m) {
|
||||||
id = m[1];
|
id = m[1];
|
||||||
|
@ -148,7 +150,7 @@ module.exports = function (Server) {
|
||||||
var params = [
|
var params = [
|
||||||
"part=" + encodeURIComponent("id,snippet,contentDetails"),
|
"part=" + encodeURIComponent("id,snippet,contentDetails"),
|
||||||
"id=" + id,
|
"id=" + id,
|
||||||
"key=" + Server.cfg["ytapikey"]
|
"key=" + sv.cfg["ytapikey"]
|
||||||
].join("&");
|
].join("&");
|
||||||
var options = {
|
var options = {
|
||||||
host: "www.googleapis.com",
|
host: "www.googleapis.com",
|
||||||
|
@ -192,6 +194,7 @@ module.exports = function (Server) {
|
||||||
|
|
||||||
/* youtube.com playlists */
|
/* youtube.com playlists */
|
||||||
yp: function (id, callback, url) {
|
yp: function (id, callback, url) {
|
||||||
|
var sv = Server.getServer();
|
||||||
var m = id.match(/([\w-]+)/);
|
var m = id.match(/([\w-]+)/);
|
||||||
if (m) {
|
if (m) {
|
||||||
id = m[1];
|
id = m[1];
|
||||||
|
@ -214,9 +217,9 @@ module.exports = function (Server) {
|
||||||
timeout: 1000
|
timeout: 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
if(Server.cfg["ytv2devkey"]) {
|
if(sv.cfg["ytv2devkey"]) {
|
||||||
options.headers = {
|
options.headers = {
|
||||||
"X-Gdata-Key": "key=" + Server.cfg["ytv2devkey"]
|
"X-Gdata-Key": "key=" + sv.cfg["ytv2devkey"]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,6 +268,7 @@ module.exports = function (Server) {
|
||||||
|
|
||||||
/* youtube.com search */
|
/* youtube.com search */
|
||||||
ytSearch: function (terms, callback) {
|
ytSearch: function (terms, callback) {
|
||||||
|
var sv = Server.getServer();
|
||||||
for(var i in terms)
|
for(var i in terms)
|
||||||
terms[i] = encodeURIComponent(terms[i]);
|
terms[i] = encodeURIComponent(terms[i]);
|
||||||
var query = terms.join("+");
|
var query = terms.join("+");
|
||||||
|
@ -278,9 +282,9 @@ module.exports = function (Server) {
|
||||||
timeout: 1000
|
timeout: 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
if(Server.cfg["ytv2devkey"]) {
|
if(sv.cfg["ytv2devkey"]) {
|
||||||
options.headers = {
|
options.headers = {
|
||||||
"X-Gdata-Key": "key=" + Server.cfg["ytv2devkey"]
|
"X-Gdata-Key": "key=" + sv.cfg["ytv2devkey"]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +618,7 @@ module.exports = function (Server) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
module.exports = {
|
||||||
Getters: Getters,
|
Getters: Getters,
|
||||||
getMedia: function (id, type, callback) {
|
getMedia: function (id, type, callback) {
|
||||||
if(type in this.Getters) {
|
if(type in this.Getters) {
|
||||||
|
@ -624,4 +628,3 @@ module.exports = function (Server) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
55
lib/rank.js
55
lib/rank.js
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
The MIT License (MIT)
|
|
||||||
Copyright (c) 2013 Calvin Montgomery
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.Anonymous = -1;
|
|
||||||
exports.Guest = 0;
|
|
||||||
exports.Member = 1;
|
|
||||||
exports.Moderator = 2;
|
|
||||||
exports.Owner = 3;
|
|
||||||
exports.Siteadmin = 255;
|
|
||||||
|
|
||||||
var permissions = {
|
|
||||||
acp : exports.Siteadmin,
|
|
||||||
announce : exports.Siteadmin,
|
|
||||||
registerChannel : exports.Owner,
|
|
||||||
acl : exports.Owner,
|
|
||||||
chatFilter : exports.Owner,
|
|
||||||
setcss : exports.Owner,
|
|
||||||
setjs : exports.Owner,
|
|
||||||
channelperms : exports.Owner,
|
|
||||||
queue : exports.Moderator,
|
|
||||||
assignLeader : exports.Moderator,
|
|
||||||
kick : exports.Moderator,
|
|
||||||
ipban : exports.Moderator,
|
|
||||||
ban : exports.Moderator,
|
|
||||||
promote : exports.Moderator,
|
|
||||||
qlock : exports.Moderator,
|
|
||||||
poll : exports.Moderator,
|
|
||||||
shout : exports.Moderator,
|
|
||||||
channelOpts : exports.Moderator,
|
|
||||||
jump : exports.Moderator,
|
|
||||||
updateMotd : exports.Moderator,
|
|
||||||
drink : exports.Moderator,
|
|
||||||
seeVoteskip : exports.Moderator,
|
|
||||||
uncache : exports.Moderator,
|
|
||||||
seenlogins : exports.Moderator,
|
|
||||||
settemp : exports.Moderator,
|
|
||||||
search : exports.Guest,
|
|
||||||
chat : exports.Guest,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if someone has permission to do shit
|
|
||||||
exports.hasPermission = function(user, what) {
|
|
||||||
if(what in permissions) {
|
|
||||||
return user.rank >= permissions[what];
|
|
||||||
}
|
|
||||||
else return false;
|
|
||||||
}
|
|
555
lib/server.js
555
lib/server.js
|
@ -1,268 +1,20 @@
|
||||||
var path = require("path");
|
/*
|
||||||
var fs = require("fs");
|
The MIT License (MIT)
|
||||||
var http = require("http");
|
Copyright (c) 2013 Calvin Montgomery
|
||||||
var https = require("https");
|
|
||||||
var express = require("express");
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
var Config = require("./config");
|
|
||||||
var Logger = require("./logger");
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
var Channel = require("./channel");
|
|
||||||
var User = require("./user");
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
const VERSION = "2.4.3";
|
const VERSION = "2.4.3";
|
||||||
|
var singleton = null;
|
||||||
|
|
||||||
function getIP(req) {
|
module.exports = {
|
||||||
var raw = req.connection.remoteAddress;
|
init: function (cfg) {
|
||||||
var forward = req.header("x-forwarded-for");
|
|
||||||
if((Server.cfg["trust-x-forward"] || raw === "127.0.0.1") && forward) {
|
|
||||||
var ip = forward.split(",")[0];
|
|
||||||
Logger.syslog.log("REVPROXY " + raw + " => " + ip);
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSocketIP(socket) {
|
|
||||||
var raw = socket.handshake.address.address;
|
|
||||||
if(Server.cfg["trust-x-forward"] || raw === "127.0.0.1") {
|
|
||||||
if(typeof socket.handshake.headers["x-forwarded-for"] == "string") {
|
|
||||||
var ip = socket.handshake.headers["x-forwarded-for"]
|
|
||||||
.split(",")[0];
|
|
||||||
Logger.syslog.log("REVPROXY " + raw + " => " + ip);
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
var Server = {
|
|
||||||
channels: [],
|
|
||||||
channelLoaded: function (name) {
|
|
||||||
for(var i in this.channels) {
|
|
||||||
if(this.channels[i].canonical_name == name.toLowerCase())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
getChannel: function (name) {
|
|
||||||
for(var i in this.channels) {
|
|
||||||
if(this.channels[i].canonical_name == name.toLowerCase())
|
|
||||||
return this.channels[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
var c = new Channel(name, this);
|
|
||||||
this.channels.push(c);
|
|
||||||
return c;
|
|
||||||
},
|
|
||||||
unloadChannel: function(chan) {
|
|
||||||
if(chan.registered)
|
|
||||||
chan.saveDump();
|
|
||||||
chan.playlist.die();
|
|
||||||
chan.logger.close();
|
|
||||||
for(var i in this.channels) {
|
|
||||||
if(this.channels[i].canonical_name == chan.canonical_name) {
|
|
||||||
this.channels.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var keys = Object.keys(chan);
|
|
||||||
for (var i in keys) {
|
|
||||||
delete chan[keys[i]];
|
|
||||||
}
|
|
||||||
chan.dead = true;
|
|
||||||
},
|
|
||||||
app: null,
|
|
||||||
io: null,
|
|
||||||
httpserv: null,
|
|
||||||
sslserv: null,
|
|
||||||
sslio: null,
|
|
||||||
ioserv: null,
|
|
||||||
db: null,
|
|
||||||
ips: {},
|
|
||||||
acp: null,
|
|
||||||
announcement: null,
|
|
||||||
httpaccess: null,
|
|
||||||
actionlog: null,
|
|
||||||
logHTTP: function (req, status) {
|
|
||||||
if(status === undefined)
|
|
||||||
status = 200;
|
|
||||||
var ip = req.connection.remoteAddress;
|
|
||||||
var ip2 = false;
|
|
||||||
if(this.cfg["trust-x-forward"])
|
|
||||||
ip2 = req.header("x-forwarded-for") || req.header("cf-connecting-ip");
|
|
||||||
var ipstr = !ip2 ? ip : ip + " (X-Forwarded-For " + ip2 + ")";
|
|
||||||
var url = req.url;
|
|
||||||
// Remove query
|
|
||||||
if(url.indexOf("?") != -1)
|
|
||||||
url = url.substring(0, url.lastIndexOf("?"));
|
|
||||||
this.httpaccess.log([ipstr, req.method, url, status, req.headers["user-agent"]].join(" "));
|
|
||||||
},
|
|
||||||
handleIOConnection: function (socket) {
|
|
||||||
var self = this;
|
|
||||||
var ip = getSocketIP(socket);
|
|
||||||
socket._ip = ip;
|
|
||||||
self.db.isGlobalIPBanned(ip, function (err, bant) {
|
|
||||||
if(bant) {
|
|
||||||
Logger.syslog.log("Disconnecting " + ip + " - gbanned");
|
|
||||||
socket.emit("kick", {
|
|
||||||
reason: "You're globally banned."
|
|
||||||
});
|
|
||||||
socket.disconnect(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("disconnect", function () {
|
|
||||||
self.ips[ip]--;
|
|
||||||
}.bind(self));
|
|
||||||
|
|
||||||
if(!(ip in self.ips))
|
|
||||||
self.ips[ip] = 0;
|
|
||||||
self.ips[ip]++;
|
|
||||||
|
|
||||||
if(self.ips[ip] > Server.cfg["ip-connection-limit"]) {
|
|
||||||
socket.emit("kick", {
|
|
||||||
reason: "Too many connections from your IP address"
|
|
||||||
});
|
|
||||||
socket.disconnect(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally a valid user
|
|
||||||
Logger.syslog.log("Accepted socket from /" + socket._ip);
|
|
||||||
new User(socket, self);
|
|
||||||
},
|
|
||||||
init: function () {
|
|
||||||
var self = this;
|
|
||||||
// init database
|
|
||||||
var Database = require("./database");
|
|
||||||
this.db = new Database(self.cfg);
|
|
||||||
this.db.init();
|
|
||||||
this.actionlog = require("./actionlog")(self);
|
|
||||||
this.httpaccess = new Logger.Logger(path.join(__dirname,
|
|
||||||
"../httpaccess.log"));
|
|
||||||
this.app = express();
|
|
||||||
this.app.use(express.bodyParser());
|
|
||||||
// channel path
|
|
||||||
self.app.get("/r/:channel(*)", function (req, res, next) {
|
|
||||||
var c = req.params.channel;
|
|
||||||
if(!c.match(/^[\w-_]+$/)) {
|
|
||||||
res.redirect("/" + c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.logHTTP(req);
|
|
||||||
res.sendfile("channel.html", {
|
|
||||||
root: path.join(__dirname, "../www")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// api path
|
|
||||||
self.api = require("./api")(self);
|
|
||||||
|
|
||||||
self.app.get("/", function (req, res, next) {
|
|
||||||
self.logHTTP(req);
|
|
||||||
res.sendfile("index.html", {
|
|
||||||
root: path.join(__dirname, "../www")
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// default path
|
|
||||||
self.app.get("/:thing(*)", function (req, res, next) {
|
|
||||||
var opts = {
|
|
||||||
root: path.join(__dirname, "../www"),
|
|
||||||
maxAge: self.cfg["asset-cache-ttl"]
|
|
||||||
}
|
|
||||||
res.sendfile(req.params.thing, opts, function (err) {
|
|
||||||
if(err) {
|
|
||||||
self.logHTTP(req, err.status);
|
|
||||||
// Damn path traversal attacks
|
|
||||||
if(req.params.thing.indexOf("%2e") != -1) {
|
|
||||||
res.send("Don't try that again, I'll ban you");
|
|
||||||
Logger.syslog.log("WARNING: Attempted path "+
|
|
||||||
"traversal from /" + getIP(req));
|
|
||||||
Logger.syslog.log("URL: " + req.url);
|
|
||||||
}
|
|
||||||
// Something actually went wrong
|
|
||||||
else {
|
|
||||||
// Status codes over 500 are server errors
|
|
||||||
if(err.status >= 500)
|
|
||||||
Logger.errlog.log(err);
|
|
||||||
res.send(err.status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.logHTTP(req);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// fallback
|
|
||||||
self.app.use(function (err, req, res, next) {
|
|
||||||
self.logHTTP(req, err.status);
|
|
||||||
if(err.status == 404) {
|
|
||||||
res.send(404);
|
|
||||||
} else {
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// bind servers
|
|
||||||
if (self.cfg["enable-ssl"]) {
|
|
||||||
var key = fs.readFileSync(path.resolve(__dirname, "..",
|
|
||||||
self.cfg["ssl-keyfile"]));
|
|
||||||
var cert = fs.readFileSync(path.resolve(__dirname, "..",
|
|
||||||
self.cfg["ssl-certfile"]));
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
key: key,
|
|
||||||
passphrase: self.cfg["ssl-passphrase"],
|
|
||||||
cert: cert
|
|
||||||
};
|
|
||||||
|
|
||||||
self.sslserv = https.createServer(options, self.app)
|
|
||||||
.listen(self.cfg["ssl-port"]);
|
|
||||||
self.sslio = require("socket.io").listen(self.sslserv);
|
|
||||||
self.sslio.set("log level", 1);
|
|
||||||
self.sslio.sockets.on("connection", function (socket) {
|
|
||||||
self.handleIOConnection(socket);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
self.httpserv = self.app.listen(Server.cfg["web-port"],
|
|
||||||
Server.cfg["express-host"]);
|
|
||||||
self.ioserv = express().listen(Server.cfg["io-port"],
|
|
||||||
Server.cfg["io-host"]);
|
|
||||||
|
|
||||||
// init socket.io
|
|
||||||
self.io = require("socket.io").listen(self.ioserv);
|
|
||||||
self.io.set("log level", 1);
|
|
||||||
self.io.sockets.on("connection", function (socket) {
|
|
||||||
self.handleIOConnection(socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// init ACP
|
|
||||||
self.acp = require("./acp")(self);
|
|
||||||
|
|
||||||
// init background tasks
|
|
||||||
require("./bgtask")(self);
|
|
||||||
|
|
||||||
// init media retriever
|
|
||||||
self.infogetter = require("./get-info")(self);
|
|
||||||
},
|
|
||||||
shutdown: function () {
|
|
||||||
Logger.syslog.log("Unloading channels");
|
|
||||||
for(var i in this.channels) {
|
|
||||||
if(this.channels[i].registered) {
|
|
||||||
Logger.syslog.log("Saving /r/" + this.channels[i].name);
|
|
||||||
this.channels[i].saveDump();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.syslog.log("Goodbye");
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Logger.syslog.log("Starting CyTube v" + VERSION);
|
Logger.syslog.log("Starting CyTube v" + VERSION);
|
||||||
|
|
||||||
var chanlogpath = path.join(__dirname, "../chanlogs");
|
var chanlogpath = path.join(__dirname, "../chanlogs");
|
||||||
fs.exists(chanlogpath, function (exists) {
|
fs.exists(chanlogpath, function (exists) {
|
||||||
exists || fs.mkdir(chanlogpath);
|
exists || fs.mkdir(chanlogpath);
|
||||||
|
@ -272,17 +24,282 @@ var chandumppath = path.join(__dirname, "../chandump");
|
||||||
fs.exists(chandumppath, function (exists) {
|
fs.exists(chandumppath, function (exists) {
|
||||||
exists || fs.mkdir(chandumppath);
|
exists || fs.mkdir(chandumppath);
|
||||||
});
|
});
|
||||||
|
singleton = new Server(cfg);
|
||||||
|
return singleton;
|
||||||
|
},
|
||||||
|
|
||||||
Config.load(Server, path.join(__dirname, "../cfg.json"), function () {
|
getServer: function () {
|
||||||
Server.init();
|
return singleton;
|
||||||
if(!Server.cfg["debug"]) {
|
}
|
||||||
process.on("uncaughtException", function (err) {
|
};
|
||||||
Logger.errlog.log("[SEVERE] Uncaught Exception: " + err);
|
|
||||||
Logger.errlog.log(err.stack);
|
var path = require("path");
|
||||||
|
var fs = require("fs");
|
||||||
|
var http = require("http");
|
||||||
|
var https = require("https");
|
||||||
|
var express = require("express");
|
||||||
|
var Config = require("./config");
|
||||||
|
var Logger = require("./logger");
|
||||||
|
var Channel = require("./channel");
|
||||||
|
var User = require("./user");
|
||||||
|
var $util = require("./utilities");
|
||||||
|
|
||||||
|
var Server = function (cfg) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.cfg = cfg;
|
||||||
|
self.channels = [],
|
||||||
|
self.express = null;
|
||||||
|
self.http = null;
|
||||||
|
self.https = null;
|
||||||
|
self.io = null;
|
||||||
|
self.ioWeb = null;
|
||||||
|
self.ioSecure = null;
|
||||||
|
self.ipCount = {};
|
||||||
|
self.db = null;
|
||||||
|
self.api = null;
|
||||||
|
self.announcement = null;
|
||||||
|
self.httplog = null;
|
||||||
|
self.actionlog = null;
|
||||||
|
self.infogetter = null;
|
||||||
|
|
||||||
|
// database init ------------------------------------------------------
|
||||||
|
var Database = require("./database");
|
||||||
|
self.db = new Database(self.cfg);
|
||||||
|
|
||||||
|
// webserver init -----------------------------------------------------
|
||||||
|
self.httplog = new Logger.Logger(path.join(__dirname,
|
||||||
|
"../httpaccess.log"));
|
||||||
|
self.express = express();
|
||||||
|
self.express.use(express.bodyParser());
|
||||||
|
|
||||||
|
// channel route
|
||||||
|
self.express.get("/r/:channel(*)", function (req, res, next) {
|
||||||
|
var c = req.params.channel;
|
||||||
|
if (!$util.isValidChannelName(c)) {
|
||||||
|
res.redirect("/" + c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.logHTTP(req);
|
||||||
|
res.sendfile("channel.html", {
|
||||||
|
root: path.join(__dirname, "../www")
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("SIGINT", function () {
|
// api route
|
||||||
Server.shutdown();
|
self.api = require("./api")(self);
|
||||||
|
|
||||||
|
// index
|
||||||
|
self.express.get("/", function (req, res, next) {
|
||||||
|
self.logHTTP(req);
|
||||||
|
res.sendfile("index.html", {
|
||||||
|
root: path.join(__dirname, "../www")
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// default route
|
||||||
|
self.express.get("/:thing(*)", function (req, res, next) {
|
||||||
|
var opts = {
|
||||||
|
root: path.join(__dirname, "../www"),
|
||||||
|
maxAge: self.cfg["asset-cache-ttl"]
|
||||||
|
};
|
||||||
|
|
||||||
|
res.sendfile(req.params.thing, opts, function (e) {
|
||||||
|
if (e) {
|
||||||
|
self.logHTTP(req, e.status);
|
||||||
|
if (req.params.thing.match(/\.\.|(%25)?%2e(%25)?%2e/)) {
|
||||||
|
res.send("Don't try that again.");
|
||||||
|
Logger.syslog.log("WARNING: Attempted path traversal "+
|
||||||
|
"from IP " + self.getHTTPIP(req));
|
||||||
|
Logger.syslog.log("Path was: " + req.url);
|
||||||
|
self.actionlog.record(self.getHTTPIP(req), "",
|
||||||
|
"path-traversal",
|
||||||
|
req.url);
|
||||||
|
} else if (e.status >= 500) {
|
||||||
|
Logger.errlog.log(err);
|
||||||
|
}
|
||||||
|
res.send(e.status);
|
||||||
|
} else {
|
||||||
|
self.logHTTP(req);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// fallback route
|
||||||
|
self.express.use(function (err, req, res, next) {
|
||||||
|
self.logHTTP(req, err.status);
|
||||||
|
if (err.status === 404) {
|
||||||
|
res.send(404);
|
||||||
|
} else {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// http/https/sio server init -----------------------------------------
|
||||||
|
if (self.cfg["enable-ssl"]) {
|
||||||
|
var key = fs.readFileSync(path.resolve(__dirname, "..",
|
||||||
|
self.cfg["ssl-keyfile"]));
|
||||||
|
var cert = fs.readFileSync(path.resolve(__dirname, "..",
|
||||||
|
self.cfg["ssl-certfile"]));
|
||||||
|
var opts = {
|
||||||
|
key: key,
|
||||||
|
cert: cert,
|
||||||
|
passphrase: self.cfg["ssl-passphrase"]
|
||||||
|
};
|
||||||
|
|
||||||
|
self.https = https.createServer(opts, self.express)
|
||||||
|
.listen(self.cfg["ssl-port"]);
|
||||||
|
self.ioSecure = require("socket.io").listen(self.https);
|
||||||
|
self.ioSecure.set("log level", 1);
|
||||||
|
self.ioSecure.on("connection", function (sock) {
|
||||||
|
self.handleSocketConnection(sock);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.http = self.express.listen(self.cfg["web-port"],
|
||||||
|
self.cfg["express-host"]);
|
||||||
|
self.ioWeb = express().listen(self.cfg["io-port"], self.cfg["io-host"]);
|
||||||
|
self.io = require("socket.io").listen(self.ioWeb);
|
||||||
|
self.io.set("log level", 1);
|
||||||
|
self.io.sockets.on("connection", function (sock) {
|
||||||
|
self.handleSocketConnection(sock);
|
||||||
|
});
|
||||||
|
|
||||||
|
// background tasks init ----------------------------------------------
|
||||||
|
require("./bgtask")(self);
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.getHTTPIP = function (req) {
|
||||||
|
var raw = req.connection.remoteAddress;
|
||||||
|
var forward = req.header("x-forwarded-for");
|
||||||
|
if((this.cfg["trust-x-forward"] || raw === "127.0.0.1") && forward) {
|
||||||
|
var ip = forward.split(",")[0];
|
||||||
|
Logger.syslog.log("REVPROXY " + raw + " => " + ip);
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.getSocketIP = function (socket) {
|
||||||
|
var raw = socket.handshake.address.address;
|
||||||
|
if(this.cfg["trust-x-forward"] || raw === "127.0.0.1") {
|
||||||
|
if(typeof socket.handshake.headers["x-forwarded-for"] == "string") {
|
||||||
|
var ip = socket.handshake.headers["x-forwarded-for"]
|
||||||
|
.split(",")[0];
|
||||||
|
Logger.syslog.log("REVPROXY " + raw + " => " + ip);
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.isChannelLoaded = function (name) {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
for (var i = 0; i < this.channels.length; i++) {
|
||||||
|
if (this.channels[i].canonical_name == name)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.getChannel = function (name) {
|
||||||
|
var cname = name.toLowerCase();
|
||||||
|
for (var i = 0; i < this.channels.length; i++) {
|
||||||
|
if (this.channels[i].canonical_name == name)
|
||||||
|
return this.channels[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = new Channel(name);
|
||||||
|
this.channels.push(c);
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.unloadChannel = function (chan) {
|
||||||
|
if (chan.registered)
|
||||||
|
chan.saveDump();
|
||||||
|
|
||||||
|
chan.playlist.die();
|
||||||
|
chan.logger.close();
|
||||||
|
for (var i = 0; i < this.channels.length; i++) {
|
||||||
|
if (this.channels[i].canonical_name === chan.canonical_name) {
|
||||||
|
this.channels.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty all outward references from the channel
|
||||||
|
var keys = Object.keys(chan);
|
||||||
|
for (var i in keys) {
|
||||||
|
delete chan[keys[i]];
|
||||||
|
}
|
||||||
|
chan.dead = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.logHTTP = function (req, status) {
|
||||||
|
if (status === undefined)
|
||||||
|
status = 200;
|
||||||
|
|
||||||
|
var ip = req.connection.remoteAddress;
|
||||||
|
var ip2 = req.header("x-forwarded-for") ||
|
||||||
|
req.header("cf-connecting-ip");
|
||||||
|
var ipstr = !ip2 ? ip : ip + " (X-Forwarded-For " + ip2 + ")";
|
||||||
|
var url = req.url;
|
||||||
|
// Remove query
|
||||||
|
if(url.indexOf("?") != -1)
|
||||||
|
url = url.substring(0, url.lastIndexOf("?"));
|
||||||
|
this.httplog.log([
|
||||||
|
ipstr,
|
||||||
|
req.method,
|
||||||
|
url,
|
||||||
|
status,
|
||||||
|
req.header("user-agent")
|
||||||
|
].join(" "));
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.handleSocketConnection = function (socket) {
|
||||||
|
var self = this;
|
||||||
|
var ip = self.getSocketIP(socket);
|
||||||
|
socket._ip = ip;
|
||||||
|
|
||||||
|
// Check for global ban on the IP
|
||||||
|
self.db.isGlobalIPBanned(ip, function (err, banned) {
|
||||||
|
if (banned) {
|
||||||
|
Logger.syslog.log("Disconnecting " + ip + " - global banned");
|
||||||
|
socket.emit("kick", { reason: "Your IP is globally banned." });
|
||||||
|
socket.disconnect(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("disconnect", function () {
|
||||||
|
self.ipCount[ip]--;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!(ip in self.ipCount))
|
||||||
|
self.ipCount[ip] = 0;
|
||||||
|
|
||||||
|
self.ipCount[ip]++;
|
||||||
|
if (self.ipCount[ip] > self.cfg["ip-connection-limit"]) {
|
||||||
|
socket.emit("kick", {
|
||||||
|
reason: "Too many connections from your IP address"
|
||||||
|
});
|
||||||
|
socket.disconnect(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.syslog.log("Accepted socket from " + ip);
|
||||||
|
new User(socket);
|
||||||
|
};
|
||||||
|
|
||||||
|
Server.prototype.shutdown = function () {
|
||||||
|
Logger.syslog.log("Unloading channels");
|
||||||
|
for (var i = 0; i < this.channels.length; i++) {
|
||||||
|
if (this.channels[i].registered) {
|
||||||
|
Logger.syslog.log("Saving /r/" + this.channels[i].name);
|
||||||
|
this.channels[i].saveDump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logger.syslog.log("Goodbye");
|
||||||
|
process.exit(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
27
lib/user.js
27
lib/user.js
|
@ -9,21 +9,24 @@ The above copyright notice and this permission notice shall be included in all c
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Rank = require("./rank.js");
|
|
||||||
var Channel = require("./channel.js").Channel;
|
var Channel = require("./channel.js").Channel;
|
||||||
var Logger = require("./logger.js");
|
var Logger = require("./logger.js");
|
||||||
var $util = require("./utilities");
|
var $util = require("./utilities");
|
||||||
|
var ActionLog = require("./actionlog");
|
||||||
|
var Server = require("./server");
|
||||||
|
var ACP = require("./acp");
|
||||||
|
var InfoGetter = require("./get-info");
|
||||||
|
|
||||||
// Represents a client connected via socket.io
|
// Represents a client connected via socket.io
|
||||||
var User = function (socket, Server) {
|
var User = function (socket) {
|
||||||
this.ip = socket._ip;
|
this.ip = socket._ip;
|
||||||
this.server = Server;
|
this.server = Server.getServer();
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.loggedIn = false;
|
this.loggedIn = false;
|
||||||
this.loggingIn = false;
|
this.loggingIn = false;
|
||||||
this.saverank = false;
|
this.saverank = false;
|
||||||
this.rank = Rank.Anonymous;
|
this.rank = -1
|
||||||
this.global_rank = Rank.Anonymous;
|
this.global_rank = -1;
|
||||||
this.channel = null;
|
this.channel = null;
|
||||||
this.name = "";
|
this.name = "";
|
||||||
this.meta = {
|
this.meta = {
|
||||||
|
@ -42,8 +45,8 @@ var User = function (socket, Server) {
|
||||||
this.autoAFK();
|
this.autoAFK();
|
||||||
|
|
||||||
this.initCallbacks();
|
this.initCallbacks();
|
||||||
if (Server.announcement !== null) {
|
if (this.server.announcement !== null) {
|
||||||
this.socket.emit("announcement", Server.announcement);
|
this.socket.emit("announcement", this.server.announcement);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -321,7 +324,7 @@ User.prototype.initCallbacks = function () {
|
||||||
self.socket.on("searchMedia", function (data) {
|
self.socket.on("searchMedia", function (data) {
|
||||||
if (self.inChannel()) {
|
if (self.inChannel()) {
|
||||||
if (data.source == "yt") {
|
if (data.source == "yt") {
|
||||||
var searchfn = self.server.infogetter.Getters.ytSearch;
|
var searchfn = InfoGetter.Getters.ytSearch;
|
||||||
searchfn(data.query.split(" "), function (e, vids) {
|
searchfn(data.query.split(" "), function (e, vids) {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
self.socket.emit("searchResults", {
|
self.socket.emit("searchResults", {
|
||||||
|
@ -556,8 +559,8 @@ User.prototype.initCallbacks = function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
self.socket.on("acp-init", function () {
|
self.socket.on("acp-init", function () {
|
||||||
if (self.global_rank >= Rank.Siteadmin)
|
if (self.global_rank >= 255)
|
||||||
self.server.acp.init(self);
|
ACP.init(self);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.socket.on("borrow-rank", function (rank) {
|
self.socket.on("borrow-rank", function (rank) {
|
||||||
|
@ -662,7 +665,7 @@ User.prototype.login = function (name, pw, session) {
|
||||||
self.server.db.userLogin(name, pw, session, function (err, row) {
|
self.server.db.userLogin(name, pw, session, function (err, row) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.loggingIn = false;
|
self.loggingIn = false;
|
||||||
self.server.actionlog.record(self.ip, name, "login-failure",
|
ActionLog.record(self.ip, name, "login-failure",
|
||||||
err);
|
err);
|
||||||
self.socket.emit("login", {
|
self.socket.emit("login", {
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -686,7 +689,7 @@ User.prototype.login = function (name, pw, session) {
|
||||||
}
|
}
|
||||||
// Record logins for administrator accounts
|
// Record logins for administrator accounts
|
||||||
if (self.global_rank >= 255)
|
if (self.global_rank >= 255)
|
||||||
self.server.actionlog.record(self.ip, name, "login-success");
|
ActionLog.record(self.ip, name, "login-success");
|
||||||
self.loggedIn = true;
|
self.loggedIn = true;
|
||||||
self.loggingIn = false;
|
self.loggingIn = false;
|
||||||
self.socket.emit("login", {
|
self.socket.emit("login", {
|
||||||
|
|
Loading…
Reference in a new issue