mirror of https://github.com/calzoneman/sync.git
Continue work on channel.js
This commit is contained in:
parent
9611f86d55
commit
01aab965ad
|
@ -341,6 +341,56 @@ Channel.prototype.getRank = function (name, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up the highest rank of any alias of an IP address
|
||||||
|
*/
|
||||||
|
Channel.prototype.getIPRank = function (ip, callback) {
|
||||||
|
var self = this;
|
||||||
|
db.getAliases(ip, function (err, names) {
|
||||||
|
if (self.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.users.getGlobalRanks(names, function (err, res) {
|
||||||
|
if (self.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
callback(err, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rank = res.reduce(function (a, b) {
|
||||||
|
return Math.max(a, b);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
if (!self.registered) {
|
||||||
|
callback(null, rank);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.channels.getRanks(self.name, names,
|
||||||
|
function (err, res) {
|
||||||
|
if (self.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
callback(err, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rank = res.reduce(function (a, b) {
|
||||||
|
return Math.max(a, b);
|
||||||
|
}, rank);
|
||||||
|
|
||||||
|
callback(null, rank);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a user joins a channel
|
* Called when a user joins a channel
|
||||||
*/
|
*/
|
||||||
|
@ -479,12 +529,383 @@ Channel.prototype.sendMOTD = function (users) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to channel moderators
|
||||||
|
*/
|
||||||
|
Channel.prototype.sendModMessage = function (msg, minrank) {
|
||||||
|
if (isNaN(minrank)) {
|
||||||
|
minrank = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
var notice = {
|
||||||
|
username: "[server]",
|
||||||
|
msg: msg
|
||||||
|
meta: {
|
||||||
|
addClass: "server-whisper" ,
|
||||||
|
addClassToNameAndTimestamp: true
|
||||||
|
},
|
||||||
|
time: Date.now()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.users.forEach(function(u) {
|
||||||
|
if (u.rank > minrank) {
|
||||||
|
u.socket.emit("chatMsg", notice);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a video in the channel's library
|
||||||
|
*/
|
||||||
|
Channel.prototype.cacheMedia = function (media) {
|
||||||
|
// Don't cache Google Drive videos because of their time limit
|
||||||
|
if (media.type === "gd") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.registered) {
|
||||||
|
db.channels.addToLibrary(self.name, media);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to ban a user by name
|
||||||
|
*/
|
||||||
|
Channel.prototype.tryNameBan = function (actor, name, reason) {
|
||||||
|
var self = this;
|
||||||
|
if (!self.hasPermission(actor, "ban")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = name.toLowerCase();
|
||||||
|
if (name == actor.name.toLowerCase()) {
|
||||||
|
actor.socket.emit("costanza", {
|
||||||
|
msg: "Trying to ban yourself?"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up the name's rank so people can't ban others with higher rank than themselves
|
||||||
|
self.getRank(name, function (err, rank) {
|
||||||
|
if (self.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
actor.socket.emit("errorMsg", {
|
||||||
|
msg: "Internal error " + err
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rank >= actor.rank) {
|
||||||
|
actor.socket.emit("errorMsg", {
|
||||||
|
msg: "You don't have permission to ban " + name
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof reason !== "string") {
|
||||||
|
reason = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
reason = reason.substring(0, 255);
|
||||||
|
self.namebans[name] = {
|
||||||
|
ip: "*",
|
||||||
|
name: name,
|
||||||
|
bannedby: actor.name,
|
||||||
|
reason: reason
|
||||||
|
};
|
||||||
|
|
||||||
|
// If in the channel already, kick the banned user
|
||||||
|
for (var i = 0; i < self.users.length; i++) {
|
||||||
|
if (self.users[i].name.toLowerCase() == name) {
|
||||||
|
self.kick(self.users[i], "You're banned!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.logger.log("*** " + actor.name + " namebanned " + name);
|
||||||
|
self.sendModMessage(actor.name + " banned " + name, self.permissions.ban);
|
||||||
|
|
||||||
|
if (!self.registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel, ip, name, reason, actor
|
||||||
|
db.channels.ban(self.name, "*", name, reason, actor.name);
|
||||||
|
// TODO send banlist?
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a name ban
|
||||||
|
*/
|
||||||
|
Channel.prototype.tryUnbanName = function (actor, name) {
|
||||||
|
var self = this;
|
||||||
|
if (!self.hasPermission(actor, "ban")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete self.namebans[name];
|
||||||
|
self.logger.log("*** " + actor.name + " un-namebanned " + name);
|
||||||
|
self.sendModMessage(actor.name + " unbanned " + name, self.permissions.ban);
|
||||||
|
|
||||||
|
if (!self.registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.channels.unbanName(self.name, name);
|
||||||
|
// TODO send banlist?
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bans all IP addresses associated with a username
|
||||||
|
*/
|
||||||
|
Channel.prototype.tryBanAllIP = function (actor, name, reason, range) {
|
||||||
|
var self = this;
|
||||||
|
if (!self.hasPermission(actor, "ban")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof name !== "string") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = name.toLowerCase();
|
||||||
|
if (name === actor.name.toLowerCase()) {
|
||||||
|
actor.socket.emit("costanza", {
|
||||||
|
msg: "Trying to ban yourself?"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.getIPs(name, function (err, ips) {
|
||||||
|
if (self.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
actor.socket.emit("errorMsg", {
|
||||||
|
msg: "Internal error: " + err
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ips.forEach(function (ip) {
|
||||||
|
self.tryBanIP(actor, ip, name, range);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bans an individual IP
|
||||||
|
*/
|
||||||
|
Channel.prototype.tryBanIP = function (actor, ip, name, reason, range) {
|
||||||
|
if (range) {
|
||||||
|
ip = ip.replace(/(\d+)\.(\d+)\.(\d+)\.(\d+)/, "$1.$2.$3");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof reason !== "string") {
|
||||||
|
reason = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
reason = reason.substring(0, 255);
|
||||||
|
|
||||||
|
self.getIPRank(ip, function (err, rank) {
|
||||||
|
if (self.dead) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
actor.socket.emit("errorMsg", {
|
||||||
|
msg: "Internal error: " + err
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rank >= actor.rank) {
|
||||||
|
actor.socket.emit("errorMsg", {
|
||||||
|
msg: "You don't have permission to ban IP: " + util.maskIP(ip)
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ipbans[ip] = {
|
||||||
|
ip: ip,
|
||||||
|
name: name,
|
||||||
|
bannedby: actor.name,
|
||||||
|
reason: reason
|
||||||
|
};
|
||||||
|
|
||||||
|
self.logger.log("*** " + actor.name + " banned " + ip + " (" + name + ")");
|
||||||
|
self.sendModMessage(actor.name + " banned " + ip + " (" + name + ")", self.permissions.ban);
|
||||||
|
// If in the channel already, kick the banned user
|
||||||
|
for (var i = 0; i < self.users.length; i++) {
|
||||||
|
if (self.users[i].ip === ip) {
|
||||||
|
self.kick(self.users[i], "You're banned!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// channel, ip, name, reason, ban actor
|
||||||
|
db.channels.ban(self.name, ip, name, reason, actor.name);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an IP ban
|
||||||
|
*/
|
||||||
|
Channel.prototype.unbanIP = function (actor, ip) {
|
||||||
|
var self = this;
|
||||||
|
if (!self.hasPermission(actor, "ban")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var record = self.ipbans[ip];
|
||||||
|
delete self.ipbans[ip];
|
||||||
|
self.logger.log("*** " + actor.name + " unbanned " + ip + " (" + record.name + ")");
|
||||||
|
self.sendModMessage(actor.name + " unbanned " + util.maskIP(ip) + " (" + record.name + ")", self.permissions.ban);
|
||||||
|
|
||||||
|
if (!self.registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.channels.unbanIP(self.name, ip);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the banlist
|
||||||
|
*/
|
||||||
|
Channel.prototype.sendBanlist = function (users) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var bans = [];
|
||||||
|
var unmaskedbans = [];
|
||||||
|
for (var ip in self.ipbans) {
|
||||||
|
bans.push({
|
||||||
|
ip: util.maskIP(ip),
|
||||||
|
name: self.ipbans[ip].name,
|
||||||
|
reason: self.ipbans[ip].reason,
|
||||||
|
bannedby: self.ipbans[ip].bannedby
|
||||||
|
});
|
||||||
|
unmaskedbans.push({
|
||||||
|
ip: ip,
|
||||||
|
name: self.ipbans[ip].name,
|
||||||
|
reason: self.ipbans[ip].reason,
|
||||||
|
bannedby: self.ipbans[ip].bannedby
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
users.forEach(function (u) {
|
||||||
|
if (!self.hasPermission(u, "ban")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.rank >= 255) {
|
||||||
|
u.socket.emit("banlist", unmaskedbans);
|
||||||
|
} else {
|
||||||
|
u.socket.emit("banlist", bans);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the chat filter list
|
||||||
|
*/
|
||||||
|
Channel.prototype.sendChatFilters = function (users) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var pkt = self.filters.map(function (f) {
|
||||||
|
return f.pack();
|
||||||
|
});
|
||||||
|
|
||||||
|
users.forEach(function (u) {
|
||||||
|
if (!self.hasPermission(u, "filteredit")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u.socket.emit("chatFilters", f);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the playlist
|
||||||
|
*/
|
||||||
|
Channel.prototype.sendPlaylist = function (users) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var pl = self.playlist.items.toArray();
|
||||||
|
var current = null;
|
||||||
|
if (self.playlist.current) {
|
||||||
|
current = self.playlist.current.uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
users.forEach(function (u) {
|
||||||
|
u.socket.emit("playlist", pl);
|
||||||
|
u.socket.emit("setPlaylistMeta", self.plmeta);
|
||||||
|
if (current !== null) {
|
||||||
|
u.socket.emit("setCurrent", current);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches channel library
|
||||||
|
*/
|
||||||
|
Channel.prototype.search = function (query, callback) {
|
||||||
|
var self = this;
|
||||||
|
if (!self.registered) {
|
||||||
|
callback([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof query !== "string") {
|
||||||
|
query = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.substring(0, 100);
|
||||||
|
|
||||||
|
db.channels.searchLibrary(self.name, query, function (err, res) {
|
||||||
|
if (err) {
|
||||||
|
res = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
res.sort(function(a, b) {
|
||||||
|
var x = a.title.toLowerCase();
|
||||||
|
var y = b.title.toLowerCase();
|
||||||
|
|
||||||
|
return (x == y) ? 0 : (x < y ? -1 : 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
res.forEach(function (r) {
|
||||||
|
r.duration = util.formatTime(r.seconds);
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(res);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the result of readLog() to a user if the user has sufficient permission
|
||||||
|
*/
|
||||||
Channel.prototype.tryReadLog = function (user) {
|
Channel.prototype.tryReadLog = function (user) {
|
||||||
if (user.rank < 3) {
|
if (user.rank < 3) {
|
||||||
user.kick("Attempted readChanLog with insufficient permission");
|
user.kick("Attempted readChanLog with insufficient permission");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!self.registered) {
|
||||||
|
user.socket.emit("readChanLog", {
|
||||||
|
success: false,
|
||||||
|
data: "Channel log is only available to registered channels."
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var filterIp = user.global_rank < 255;
|
var filterIp = user.global_rank < 255;
|
||||||
this.readLog(filterIp, function (err, data) {
|
this.readLog(filterIp, function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -501,6 +922,9 @@ Channel.prototype.tryReadLog = function (user) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the last 100KiB of the channel's log file, masking IP addresses if desired
|
||||||
|
*/
|
||||||
Channel.prototype.readLog = function (filterIp, callback) {
|
Channel.prototype.readLog = function (filterIp, callback) {
|
||||||
var maxLen = 102400; // Limit to last 100KiB
|
var maxLen = 102400; // Limit to last 100KiB
|
||||||
var file = this.logger.filename;
|
var file = this.logger.filename;
|
||||||
|
|
Loading…
Reference in New Issue