Refuctor channel related db functions

This commit is contained in:
calzoneman 2013-12-13 18:52:13 -06:00
parent db5dcf86f7
commit fe00fb8c83
3 changed files with 320 additions and 535 deletions

View File

@ -25,6 +25,7 @@ var $util = require("./utilities");
var AsyncQueue = require("./asyncqueue"); var AsyncQueue = require("./asyncqueue");
var ActionLog = require("./actionlog"); var ActionLog = require("./actionlog");
var InfoGetter = require("./get-info"); var InfoGetter = require("./get-info");
var db = require("./database");
var Channel = function(name) { var Channel = function(name) {
var self = this; var self = this;
@ -134,10 +135,10 @@ var Channel = function(name) {
self.ipkey += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[parseInt(Math.random() * 65)] self.ipkey += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[parseInt(Math.random() * 65)]
} }
Server.getServer().db.loadChannelData(self, function (err) { db.channels.load(self, function (err) {
if (err && err === "channel_dead") if (err)
return; return;
else if (!err || err === "channel_unregistered") else if (!err || err === "Channel is not registered")
self.dbloaded = true; self.dbloaded = true;
self.tryLoadDump(); self.tryLoadDump();
@ -411,8 +412,8 @@ Channel.prototype.tryRegister = function (user) {
}); });
} }
else { else {
self.server.db.registerChannel(self.name, user.name, db.channels.register(self.name, user.name,
function (err, res) { function (err, res) {
if(err) { if(err) {
user.socket.emit("registerChannel", { user.socket.emit("registerChannel", {
success: false, success: false,
@ -455,7 +456,7 @@ Channel.prototype.unregister = function (user) {
}); });
return; return;
} }
self.server.db.dropChannel(self.name, function (err, res) { db.channels.drop(self.name, function (err, res) {
if(err) { if(err) {
user.socket.emit("unregisterChannel", { user.socket.emit("unregisterChannel", {
success: false, success: false,
@ -472,7 +473,7 @@ Channel.prototype.unregister = function (user) {
Channel.prototype.getRank = function (name, callback) { Channel.prototype.getRank = function (name, callback) {
var self = this; var self = this;
self.server.db.getGlobalRank(name, function (err, global) { db.users.getGlobalRank(name, function (err, global) {
if (self.dead) if (self.dead)
return; return;
@ -486,8 +487,8 @@ Channel.prototype.getRank = function (name, callback) {
return; return;
} }
self.server.db.getChannelRank(self.name, name, db.channels.getRank(self.name, name,
function (err, rank) { function (err, rank) {
if(err) { if(err) {
callback(err, null); callback(err, null);
return; return;
@ -503,13 +504,13 @@ Channel.prototype.saveRank = function (user, callback) {
return; return;
if(!user.saverank) if(!user.saverank)
return; return;
this.server.db.setChannelRank(this.name, user.name, user.rank, callback); db.channels.setRank(this.name, user.name, user.rank, callback);
} }
Channel.prototype.saveInitialRank = function (user, callback) { Channel.prototype.saveInitialRank = function (user, callback) {
if(!this.registered) if(!this.registered)
return; return;
this.server.db.insertChannelRank(this.name, user.name, user.rank, callback); db.channels.newRank(this.name, user.name, user.rank, callback);
}; };
Channel.prototype.getIPRank = function (ip, callback) { Channel.prototype.getIPRank = function (ip, callback) {
@ -517,7 +518,7 @@ Channel.prototype.getIPRank = function (ip, callback) {
self.server.db.listAliases(ip, function (err, names) { self.server.db.listAliases(ip, function (err, names) {
if (self.dead) if (self.dead)
return; return;
self.server.db.listGlobalRanks(names, function (err, res) { db.users.getGlobalRanks(names, function (err, res) {
if(err) { if(err) {
callback(err, null); callback(err, null);
return; return;
@ -533,8 +534,8 @@ Channel.prototype.getIPRank = function (ip, callback) {
return; return;
} }
self.server.db.listChannelUserRanks(self.name, names, db.channels.getRanks(self.name, names,
function (err, res) { function (err, res) {
if (self.dead) if (self.dead)
return; return;
@ -564,7 +565,7 @@ Channel.prototype.cacheMedia = function(media) {
return; return;
} }
if(self.registered) { if(self.registered) {
self.server.db.addToLibrary(self.name, media); db.channels.addToLibrary(self.name, media);
} }
} }
@ -627,7 +628,7 @@ Channel.prototype.tryNameBan = function(actor, name) {
return; return;
} }
self.server.db.addChannelBan(self.name, "*", name, actor.name); db.channels.ban(self.name, "*", name, "", actor.name);
}); });
} }
@ -644,7 +645,7 @@ Channel.prototype.unbanName = function(actor, name) {
if (!self.registered) if (!self.registered)
return; return;
self.server.db.clearChannelNameBan(self.name, name, function (err, res) { db.channels.unbanName(self.name, name, function (err, res) {
if (self.dead) if (self.dead)
return; return;
@ -669,7 +670,7 @@ Channel.prototype.tryIPBan = function(actor, name, range) {
}); });
return; return;
} }
self.server.db.listIPsForName(name, function (err, ips) { db.listIPsForName(name, function (err, ips) {
if (self.dead) if (self.dead)
return; return;
@ -715,9 +716,8 @@ Channel.prototype.tryIPBan = function(actor, name, range) {
if(!self.registered) if(!self.registered)
return; return;
self.server.db.addChannelBan(self.name, ip, name, db.channels.ban(self.name, ip, name, "", actor.name,
actor.name, function (err, res) {
function (err, res) {
if (self.dead) if (self.dead)
return; return;
@ -761,7 +761,7 @@ Channel.prototype.unbanIP = function(actor, ip) {
return false; return false;
// Update database ban table // Update database ban table
self.server.db.clearChannelIPBan(self.name, ip); db.channels.unbanIP(self.name, ip);
} }
Channel.prototype.tryUnban = function(actor, data) { Channel.prototype.tryUnban = function(actor, data) {
@ -780,7 +780,7 @@ Channel.prototype.search = function(query, callback) {
callback([]); callback([]);
return; return;
} }
self.server.db.searchLibrary(self.name, query, function (err, res) { db.channels.searchLibrary(self.name, query, function (err, res) {
if(err) { if(err) {
res = []; res = [];
} }
@ -1032,7 +1032,7 @@ Channel.prototype.sendChatFilters = function(user) {
Channel.prototype.sendChannelRanks = function(user) { Channel.prototype.sendChannelRanks = function(user) {
if(user.rank >= 3 && this.registered) { if(user.rank >= 3 && this.registered) {
this.server.db.listChannelRanks(this.name, function (err, res) { db.channels.allRanks(this.name, function (err, res) {
if(err) { if(err) {
user.socket.emit("errorMsg", { user.socket.emit("errorMsg", {
msg: "Internal error: " + err msg: "Internal error: " + err
@ -1139,7 +1139,7 @@ Channel.prototype.broadcastNewUser = function(user) {
user.socket.emit("channelNotRegistered"); user.socket.emit("channelNotRegistered");
user.socket.emit("rank", user.rank); user.socket.emit("rank", user.rank);
} }
self.server.db.listAliases(user.ip, function (err, aliases) { db.listAliases(user.ip, function (err, aliases) {
if (self.dead) if (self.dead)
return; return;
@ -1605,8 +1605,8 @@ 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.db.getLibraryItem(self.name, data.id, db.getLibraryItem(self.name, data.id,
function (err, item) { function (err, item) {
if (self.dead) if (self.dead)
return; return;
@ -1765,8 +1765,8 @@ Channel.prototype.tryUncache = function(user, data) {
} }
if (!self.registered) if (!self.registered)
return; return;
self.server.db.removeFromLibrary(self.name, data.id, db.channels.deleteFromLibrary(self.name, data.id,
function (err, res) { function (err, res) {
if (self.dead) if (self.dead)
return; return;
@ -2507,8 +2507,8 @@ Channel.prototype.trySetRank = function(user, data) {
return; return;
if(rrank >= user.rank) if(rrank >= user.rank)
return; return;
self.server.db.setChannelRank(self.name, data.user, db.channels.setRank(self.name, data.user,
data.rank, function (err, res) { data.rank, function (err, res) {
if (self.dead) if (self.dead)
return; return;

View File

@ -32,6 +32,8 @@ module.exports.init = function (cfg) {
global_ipbans = {}; global_ipbans = {};
module.exports.users = require("./database/accounts"); module.exports.users = require("./database/accounts");
module.exports.users.init(); module.exports.users.init();
module.exports.channels = require("./database/channels");
module.exports.channels.init();
}; };
module.exports.query = function (query, sub, callback) { module.exports.query = function (query, sub, callback) {
@ -77,42 +79,6 @@ function blackHole() {
module.exports.oldinit = function () { module.exports.oldinit = function () {
var query; var query;
// Create channel table
query = ["CREATE TABLE IF NOT EXISTS `channels` (",
"`id` INT NOT NULL AUTO_INCREMENT,",
"`name` VARCHAR(255) NOT NULL,",
"`owner` VARCHAR(20) NOT NULL,",
"PRIMARY KEY(`id`))",
"ENGINE = MyISAM ",
"CHARACTER SET utf8;"].join("");
module.exports.query(query, function (err, res) {
if(err) {
Logger.errlog.log("! Failed to create channels table");
}
});
// Create registration table
query = ["CREATE TABLE IF NOT EXISTS `registrations` (",
"`id` INT NOT NULL AUTO_INCREMENT,",
"`uname` VARCHAR(20) NOT NULL,",
"`pw` VARCHAR(64) NOT NULL,",
"`global_rank` INT NOT NULL,",
"`session_hash` VARCHAR(64) NOT NULL,",
"`expire` BIGINT NOT NULL,",
"`profile_image` VARCHAR(255) NOT NULL,",
"`profile_text` TEXT NOT NULL,",
"`email` VARCHAR(255) NOT NULL,",
"PRIMARY KEY (`id`))",
"ENGINE = MyISAM ",
"CHARACTER SET utf8;"].join("");
module.exports.query(query, function (err, res) {
if(err) {
Logger.errlog.log("! Failed to create registration table");
}
});
// Create global bans table // Create global bans table
query = ["CREATE TABLE IF NOT EXISTS `global_bans` (", query = ["CREATE TABLE IF NOT EXISTS `global_bans` (",
"`ip` VARCHAR(15) NOT NULL,", "`ip` VARCHAR(15) NOT NULL,",
@ -285,470 +251,7 @@ module.exports.clearGlobalIPBan = function (ip, callback) {
/* END REGION */ /* END REGION */
/* REGION channels */
module.exports.loadChannelData = function (chan, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(chan.name)) {
callback("Invalid channel name", null);
return;
}
var query = "SELECT * FROM channels WHERE name=?";
module.exports.query(query, [chan.name], function (err, res) {
if(err) {
callback(err, null);
return;
}
if(res.length == 0) {
callback("channel_unregistered", null);
return;
}
if (chan.dead) {
callback("channel_dead", null);
return;
}
if(res[0].name != chan.name)
chan.name = res[0].name;
chan.registered = true;
// Load bans
query = "SELECT * FROM `chan_" + chan.name + "_bans`";
module.exports.query(query, function (err, res) {
if (chan.dead) {
callback("channel_dead", null);
return;
}
if(err) {
callback(err, null);
return;
}
for(var i in res) {
var r = res[i];
if(r.ip === "*")
chan.namebans[r.name] = r.banner;
else
chan.ipbans[r.ip] = [r.name, r.banner];
}
chan.logger.log("*** Loaded channel from database");
callback(null, true);
});
});
};
module.exports.setChannelRank = function (channame, name, rank, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "INSERT INTO `chan_" + channame + "_ranks` " +
"(name, rank) VALUES (?, ?) " +
"ON DUPLICATE KEY UPDATE rank=?";
module.exports.query(query, [name, rank, rank], callback);
};
module.exports.insertChannelRank = function (channame, name, rank, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "INSERT INTO `chan_" + channame + "_ranks` " +
"(name, rank) VALUES (?, ?) " +
"ON DUPLICATE KEY UPDATE rank=rank";
module.exports.query(query, [name, rank], callback);
};
module.exports.listChannelRanks = function (channame, callback) {
if(typeof callback !== "function")
return;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "SELECT * FROM `chan_" + channame + "_ranks` WHERE 1";
module.exports.query(query, callback);
};
module.exports.addToLibrary = function (channame, media, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name");
return;
}
var query = "INSERT INTO `chan_" + channame + "_library` " +
"(id, title, seconds, type) " +
"VALUES (?, ?, ?, ?) " +
"ON DUPLICATE KEY UPDATE id=id";
var params = [
media.id,
media.title,
media.seconds,
media.type
];
module.exports.query(query, params, callback);
};
module.exports.removeFromLibrary = function (channame, id, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "DELETE FROM `chan_" + channame + "_library` WHERE id=?";
module.exports.query(query, [id], callback);
};
module.exports.getLibraryItem = function (channame, id, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var m = id.match(/([\w-\/\.:]+)/);
if (m) {
id = m[1];
} else {
callback("Invalid ID", null);
return;
}
var query = "SELECT id, title, seconds, type FROM " +
"`chan_" + channame + "_library` WHERE id=?";
module.exports.query(query, [id], function (err, res) {
if(err) {
callback(err, null);
return;
}
callback(null, res.length > 0 ? res[0] : null);
});
};
module.exports.searchLibrary = function (channame, term, callback) {
if(typeof callback !== "function")
return;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "SELECT id, title, seconds, type FROM " +
"`chan_" + channame + "_library` WHERE title LIKE ?";
module.exports.query(query, ["%" + term + "%"], callback);
};
module.exports.addChannelBan = function (channame, ip, name, banBy,
callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "INSERT INTO `chan_" + channame + "_bans`" +
"(ip, name, banner) VALUES (?, ?, ?) " +
"ON DUPLICATE KEY UPDATE ip=ip";
module.exports.query(query, [ip, name, banBy], callback);
};
module.exports.clearChannelIPBan = function (channame, ip, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "DELETE FROM `chan_" + channame + "_bans` WHERE ip=?";
module.exports.query(query, [ip], callback);
};
module.exports.clearChannelNameBan = function (channame, name,
callback) {
if(typeof callback !== "function") {
callback = blackHole;
return;
}
var query = "DELETE FROM `chan_" + channame + "_bans` WHERE ip='*'" +
"AND name=?";
module.exports.query(query, [name], callback);
};
/* END REGION */
/* REGION Auth */ /* REGION Auth */
module.exports.isUsernameTaken = function (name, callback) {
if(typeof callback !== "function")
return;
var query = "SELECT id FROM registrations WHERE uname=?";
module.exports.query(query, [name], function (err, res) {
if(err) {
callback(err, null);
return;
}
callback(null, res.length > 0);
});
};
var regInProgress = {};
module.exports.registerUser = function (name, pw, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidUserName(name)) {
callback("Invalid username", null);
return;
}
if (regInProgress[name]) {
callback("Registration is already in progress", null);
return;
}
regInProgress[name] = true;
var postRegister = function (err, res) {
if(err) {
delete regInProgress[name];
callback(err, null);
return;
}
createLoginSession(name, function (err, hash) {
if(err) {
delete regInProgress[name];
// Don't confuse people into thinking the registration
// failed when it was the session that failed
callback(null, "");
return;
}
delete regInProgress[name];
callback(null, hash);
});
};
isUsernameTaken(name, function (err, taken) {
if(err) {
delete regInProgress[name];
callback(err, null);
return;
}
if(taken) {
delete regInProgress[name];
callback("Username already taken", null);
return;
}
bcrypt.hash(pw, 10, function (err, hash) {
if(err) {
delete regInProgress[name];
callback(err, null);
return;
}
var query = "INSERT INTO registrations VALUES " +
"(NULL, ?, ?, 1, '', 0, '', '', '')";
module.exports.query(query, [name, hash], postRegister);
});
});
};
module.exports.userLogin = function (name, pw, session, callback) {
if(typeof callback !== "function")
callback = blackHole;
var postLogin = function (err, row) {
if(err) {
callback(err, null);
return;
}
if(row.session_hash) {
callback(null, row);
return;
}
createLoginSession(name, function (err, hash) {
if(err) {
callback(err, null);
return;
}
row.session_hash = hash;
callback(null, row);
});
};
if(session) {
module.exports.userLoginSession(name, session, postLogin);
} else if(pw) {
module.exports.userLoginPassword(name, pw, postLogin);
} else {
callback("Invalid login", null);
}
};
module.exports.userLoginPassword = function (name, pw, callback) {
if(typeof callback !== "function")
callback = blackHole;
var query = "SELECT * FROM registrations WHERE uname=?";
module.exports.query(query, [name], function (err, res) {
if(err) {
callback(err, null);
return;
}
if(res.length == 0) {
callback("User does not exist", null);
return;
}
var row = res[0];
bcrypt.compare(pw, row.pw, function (err, valid) {
if(valid) {
// For security, erase the password field before returning
delete row["pw"];
row.session_hash = "";
callback(null, row);
return;
}
// Possibly could be a SHA256 hash from an *ancient* version
// of CyTube
var sha = hashlib.sha256(pw);
if(sha == row.pw) {
// Replace it
bcrypt.hash(pw, 10, function (err, hash) {
if(!err) {
module.exports.query("UPDATE registrations SET pw=? "+
"WHERE uname=?", [hash, name]);
}
});
// Remove password field before returning
delete row["pw"];
row.session_hash = "";
callback(null, row);
} else {
callback("Invalid username/password combination", null);
}
});
});
};
module.exports.userLoginSession = function (name, session, callback) {
if(typeof callback !== "function")
callback = blackHole;
var query = "SELECT * FROM registrations WHERE uname=? AND " +
"session_hash=?";
module.exports.query(query, [name, session], function (err, res) {
if(err) {
callback(err, null);
return;
}
if(res.length == 0) {
callback("Session expired", null);
return;
}
var row = res[0];
if(row.expire < Date.now()) {
callback("Session expired", null);
return;
}
callback(null, row);
});
};
module.exports.createLoginSession = function (name, callback) {
if(typeof callback !== "function")
callback = blackHole;
var salt = $util.randomSalt(32);
var hash = hashlib.sha256(salt + name);
var query = "UPDATE registrations SET session_hash=?, expire=? " +
"WHERE uname=?";
module.exports.query(query, [hash, Date.now() + 604800000, name],
function (err, res) {
if(err) {
callback(err, null);
return;
}
callback(null, hash);
});
};
module.exports.setUserPassword = function (name, pw, callback) {
if(typeof callback !== "function")
callback = blackHole;
bcrypt.hash(pw, 10, function (err, hash) {
if(err) {
callback(err, null);
return;
}
var query = "UPDATE registrations SET pw=? WHERE uname=?";
module.exports.query(query, [hash, name], callback);
});
};
module.exports.getGlobalRank = function (name, callback) { module.exports.getGlobalRank = function (name, callback) {
if(typeof callback !== "function") if(typeof callback !== "function")
return; return;

View File

@ -1,5 +1,5 @@
var db = require("../database"); var db = require("../database");
var $util = require("../utilities"); var valid = require("../utilities").isValidChannelName;
var blackHole = function () { }; var blackHole = function () { };
@ -19,7 +19,7 @@ function createLibraryTable(name, callback) {
db.query("CREATE TABLE `chan_" + name + "_library` (" + db.query("CREATE TABLE `chan_" + name + "_library` (" +
"`id` VARCHAR(255) NOT NULL," + "`id` VARCHAR(255) NOT NULL," +
"`title` VARCHAR(255) NOT NULL," + "`title` VARCHAR(255) NOT NULL," +
"`seconds` INT NOT NULL," "`seconds` INT NOT NULL," +
"`type` VARCHAR(2) NOT NULL," + "`type` VARCHAR(2) NOT NULL," +
"PRIMARY KEY (`id`))" + "PRIMARY KEY (`id`))" +
"CHARACTER SET utf8", callback); "CHARACTER SET utf8", callback);
@ -36,6 +36,10 @@ function createBansTable(name, callback) {
} }
function initTables(name, owner, callback) { function initTables(name, owner, callback) {
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
createRanksTable(name, function (err) { createRanksTable(name, function (err) {
if (err) { if (err) {
callback(err, null); callback(err, null);
@ -58,7 +62,7 @@ function initTables(name, owner, callback) {
callback(err, null); callback(err, null);
return; return;
} }
callback(null, true); callback(null, true);
}); });
}); });
@ -87,6 +91,11 @@ module.exports = {
return; return;
} }
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
dbutil.query("SELECT name FROM `channels` WHERE name=?", dbutil.query("SELECT name FROM `channels` WHERE name=?",
[name], [name],
function (err, rows) { function (err, rows) {
@ -106,6 +115,11 @@ module.exports = {
return; return;
} }
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
dbutil.query("SELECT * FROM `channels` WHERE name=?", dbutil.query("SELECT * FROM `channels` WHERE name=?",
[name], [name],
function (err, rows) { function (err, rows) {
@ -149,7 +163,7 @@ module.exports = {
return; return;
} }
if (!$util.isValidChannelName(name)) { if (!valid(name)) {
callback("Invalid channel name. Channel names may consist of 1-30 " + callback("Invalid channel name. Channel names may consist of 1-30 " +
"characters a-z, A-Z, 0-9, -, and _", null); "characters a-z, A-Z, 0-9, -, and _", null);
return; return;
@ -197,6 +211,11 @@ module.exports = {
callback = blackHole; callback = blackHole;
} }
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
dropTable("chan_" + name + "_ranks", function (err) { dropTable("chan_" + name + "_ranks", function (err) {
dropTable("chan_" + name + "_bans", function (e2) { dropTable("chan_" + name + "_bans", function (e2) {
if (err && e2) { if (err && e2) {
@ -221,7 +240,7 @@ module.exports = {
} }
callback(err, !Boolean(err)); callback(err, !Boolean(err));
} });
}); });
}); });
}); });
@ -246,6 +265,68 @@ module.exports = {
}); });
}, },
/**
* Loads the channel from the database
*/
load: function (chan, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan.name)) {
callback("Invalid channel name", null);
return;
}
db.query("SELECT * FROM `channels` WHERE name=?", chan.name, function (err, res) {
if (err) {
callback(err, null);
return;
}
if (res.length === 0) {
callback("Channel is not registered", null);
return;
}
if (chan.dead) {
callback("Channel is dead", null);
return;
}
// Note that before this line, chan.name might have a different capitalization
// than the database has stored. Update accordingly.
chan.name = res[0].name;
chan.canonical_name = chan.name.toLowerCase();
chan.registered = true;
// Load bans
db.query("SELECT * FROM `chan_" + chan.name + "_bans`", function (err, rows) {
if (chan.dead) {
callback("Channel is dead", null);
return;
}
if (err) {
callback(err, null);
return;
}
for (var i = 0; i < rows.length; i++) {
var r = rows[i];
if (r.ip === "*") {
chan.namebans[r.name] = r;
} else {
chan.ipbans[r.ip] = r;
}
}
chan.logger.log("*** Loaded channel from database");
callback(null, true);
});
});
},
/** /**
* Looks up a user's rank * Looks up a user's rank
*/ */
@ -254,6 +335,11 @@ module.exports = {
return; return;
} }
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE name=?", db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE name=?",
[name], [name],
function (err, rows) { function (err, rows) {
@ -279,6 +365,11 @@ module.exports = {
return; return;
} }
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
var replace = "(" + names.map(function () { return "?"; }).join(",") + ")"; var replace = "(" + names.map(function () { return "?"; }).join(",") + ")";
db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE name IN " + db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE name IN " +
replace, replace,
@ -291,4 +382,195 @@ module.exports = {
callback(null, rows); callback(null, rows);
}); });
}, },
/**
* Query all user ranks at once
*/
allRanks: function (chan, callback) {
if (typeof callback !== "function") {
return;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE 1", callback);
},
/**
* Updates a user's rank
*/
setRank: function (chan, name, rank, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("INSERT INTO `chan_" + chan + "_ranks` (name, rank) VALUES (?, ?) " +
"ON DUPLICATE KEY UPDATE rank=?", [name, rank, rank], callback);
},
/**
* Inserts a new user rank entry without clobbering an existing one
*/
newRank: function (chan, name, rank, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("INSERT INTO `chan_" + chan + "_ranks` (name, rank) VALUES (?, ?) " +
"ON DUPLICATE KEY UPDATE rank=rank", [name, rank], callback);
},
/**
* Removes a user's rank entry
*/
deleteRank: function (chan, name, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("DELETE FROM `chan_" + chan + "_ranks` WHERE name=?", [name], callback);
},
/**
* Adds a media item to the library
*/
addToLibrary: function (chan, media, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("INSERT INTO `chan_" + chan + "_library` (id, title, seconds, type) " +
"VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE id=id",
[media.id, media.title, media.seconds, media.type], callback);
},
/**
* Retrieves a media item from the library by id
*/
getLibraryItem: function (chan, id, callback) {
if (typeof callback !== "function") {
return;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("SELECT * FROM `chan_" + chan + "_library` WHERE id=?", [id],
function (err, rows) {
if (err) {
callback(err, null);
return;
}
if (rows.length === 0) {
callback("Item not in library", null);
} else {
callback(null, rows[0]);
}
});
},
/**
* Search the library by title
*/
searchLibrary: function (chan, search, callback) {
if (typeof callback !== "function") {
return;
}
db.query("SELECT * FROM `chan_" + chan + "_library` WHERE title LIKE ?",
["%" + search + "%"], callback);
},
/**
* Deletes a media item from the library
*/
deleteFromLibrary: function (chan, id, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("DELETE FROM `chan_" + chan + "_library` WHERE id=?", [id], callback);
},
/**
* Add a ban to the banlist
*/
ban: function (chan, ip, name, note, bannedby, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("INSERT INTO `chan_" + chan + "_bans` (ip, name, reason, bannedby) " +
"VALUES (?, ?, ?, ?)", [ip, name, reason, bannedby], callback);
},
/**
* Removes a ban from the banlist
*/
unbanName: function (chan, name, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("DELETE FROM `chan_" + chan + "_bans` WHERE ip='*' AND name=?",
[name], callback);
},
/**
* Removes a ban from the banlist
*/
unbanIP: function (chan, ip, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (!valid(chan)) {
callback("Invalid channel name", null);
return;
}
db.query("DELETE FROM `chan_" + chan + "_bans` WHERE ip=?",
[ip], callback);
}
}; };