Start refactoring database channels

This commit is contained in:
calzoneman 2013-12-13 11:18:50 -06:00
parent a14363a845
commit db5dcf86f7
2 changed files with 294 additions and 189 deletions

View File

@ -287,104 +287,6 @@ module.exports.clearGlobalIPBan = function (ip, callback) {
/* REGION channels */
module.exports.searchChannel = function (field, value, callback) {
if(typeof callback !== "function")
return;
var query = "SELECT * FROM channels WHERE ";
if(field === "owner")
query += "owner LIKE ?";
else if(field === "name")
query += "name LIKE ?";
module.exports.query(query, ["%" + value + "%"], callback);
};
module.exports.channelExists = function (name, callback) {
if(typeof callback !== "function")
return;
if(!$util.isValidChannelName(name)) {
callback("Invalid channel name", null);
return;
}
var query = "SELECT name FROM channels WHERE name=?";
module.exports.query(query, [name], function (err, res) {
callback(err, res.length > 0);
});
};
module.exports.registerChannel = function (name, owner, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(name)) {
callback("Invalid channel name", null);
return;
}
// Messy, but I can't think of a better async solution atm
var query = "SELECT * FROM channels WHERE name=?";
module.exports.query(query, [name], function (err, res) {
if(!err && res.length > 0) {
callback("Channel already exists", null);
return;
}
// Library table
query = ["CREATE TABLE `chan_" + name + "_library` (",
"`id` VARCHAR(255) NOT NULL,",
"`title` VARCHAR(255) NOT NULL,",
"`seconds` INT NOT NULL,",
"`type` VARCHAR(2) NOT NULL,",
"PRIMARY KEY (`id`))",
"ENGINE = MyISAM ",
"CHARACTER SET utf8;"].join("");
module.exports.query(query, function (err, res) {
if(err) {
callback(err, null);
return;
}
// Rank table
query = ["CREATE TABLE `chan_" + name + "_ranks` (",
"`name` VARCHAR(32) NOT NULL,",
"`rank` INT NOT NULL,",
"UNIQUE (`name`))",
"ENGINE = MyISAM ",
"CHARACTER SET utf8;"].join("");
module.exports.query(query, function (err, res) {
if(err) {
callback(err, null);
return;
}
// Ban table
query = ["CREATE TABLE `chan_" + name + "_bans` (",
"`ip` VARCHAR(15) NOT NULL,",
"`name` VARCHAR(32) NOT NULL,",
"`banner` VARCHAR(32) NOT NULL,",
"PRIMARY KEY (`ip`, `name`))",
"ENGINE = MyISAM ",
"CHARACTER SET utf8;"].join("");
module.exports.query(query, function (err, res) {
if(err) {
callback(err, null);
return;
}
query = "INSERT INTO channels VALUES (NULL, ?, ?)";
module.exports.query(query, [name, owner], function (err, res) {
callback(err, res);
});
});
});
});
});
};
module.exports.loadChannelData = function (chan, callback) {
if(typeof callback !== "function")
callback = blackHole;
@ -443,97 +345,6 @@ module.exports.loadChannelData = function (chan, callback) {
});
};
module.exports.dropChannel = function (name, callback) {
if(typeof callback !== "function")
callback = blackHole;
if(!$util.isValidChannelName(name)) {
callback("Invalid channel name", null);
return;
}
var query = "DROP TABLE `chan_?_bans`,`chan_?_ranks`,`chan_?_library`"
.replace(/\?/g, name);
module.exports.query(query, function (err, res) {
if(err) {
Logger.errlog.log("! Failed to drop channel tables for "+name);
callback(err, null);
return;
}
query = "DELETE FROM channels WHERE name=?";
module.exports.query(query, [name], function (err, res) {
callback(err, res);
if(err) {
Logger.errlog.log("! Failed to delete channel "+name);
}
});
});
};
module.exports.getChannelRank = function (channame, name, callback) {
if(typeof callback !== "function")
return;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
var query = "SELECT name, rank FROM `chan_" + channame + "_ranks`" +
"WHERE name=?";
module.exports.query(query, [name], function (err, res) {
if(err) {
Logger.errlog.log("! Failed to lookup " + channame + " ranks");
callback(err, null);
return;
}
if(res.length == 0)
callback(null, 0);
else
callback(null, res[0].rank);
});
};
module.exports.listChannelUserRanks = function (channame, names,
callback) {
if(typeof callback !== "function")
return;
if(!$util.isValidChannelName(channame)) {
callback("Invalid channel name", null);
return;
}
if(typeof names === "string")
names = [names];
// Build the query template (?, ?, ?, ?, ...)
var nlist = [];
for(var i in names)
nlist.push("?");
nlist = "(" + nlist.join(",") + ")";
var query = "SELECT name, rank FROM `chan_" + channame + "_ranks`" +
"WHERE name IN " + nlist;
module.exports.query(query, names, function (err, res) {
if(err) {
Logger.errlog.log("! Failed to lookup " + channame + " ranks");
callback(err, null);
return;
}
for(var i in res)
res[i] = res[i].rank;
callback(null, res);
});
};
module.exports.setChannelRank = function (channame, name, rank, callback) {
if(typeof callback !== "function")
callback = blackHole;

294
lib/database/channels.js Normal file
View File

@ -0,0 +1,294 @@
var db = require("../database");
var $util = require("../utilities");
var blackHole = function () { };
function dropTable(name, callback) {
db.query("DROP TABLE `" + name + "`");
}
function createRanksTable(name, callback) {
db.query("CREATE TABLE `chan_" + name + "_ranks` (" +
"`name` VARCHAR(20) NOT NULL," +
"`rank` INT NOT NULL," +
"PRIMARY KEY (`name`)) " +
"CHARACTER SET utf8", callback);
}
function createLibraryTable(name, callback) {
db.query("CREATE TABLE `chan_" + name + "_library` (" +
"`id` VARCHAR(255) NOT NULL," +
"`title` VARCHAR(255) NOT NULL," +
"`seconds` INT NOT NULL,"
"`type` VARCHAR(2) NOT NULL," +
"PRIMARY KEY (`id`))" +
"CHARACTER SET utf8", callback);
}
function createBansTable(name, callback) {
db.query("CREATE TABLE `chan_" + name + "_bans` (" +
"`ip` VARCHAR(39) NOT NULL," +
"`name` VARCHAR(20) NOT NULL," +
"`bannedby` VARCHAR(20) NOT NULL," +
"`reason` VARCHAR(255) NOT NULL," +
"PRIMARY KEY (`ip`, `name`))" +
"CHARACTER SET utf8", callback);
}
function initTables(name, owner, callback) {
createRanksTable(name, function (err) {
if (err) {
callback(err, null);
return;
}
// TODO add owner to ranks table
createLibraryTable(name, function (err) {
if (err) {
dropTable("chan_" + name + "_ranks");
callback(err, null);
return;
}
createBansTable(name, function (err) {
if (err) {
dropTable("chan_" + name + "_ranks");
dropTable("chan_" + name + "_library");
callback(err, null);
return;
}
callback(null, true);
});
});
});
}
module.exports = {
/**
* Initialize the channels table
*/
init: function () {
db.query("CREATE TABLE IF NOT EXISTS `channels` (" +
"`id` INT NOT NULL AUTO_INCREMENT," +
"`name` VARCHAR(30) NOT NULL," +
"`owner` VARCHAR(20) NOT NULL," +
"`time` BIGINT NOT NULL," +
"PRIMARY KEY (`id`), INDEX(`name`), INDEX(`owner`))" +
"CHARACTER SET utf8");
},
/**
* Checks if the given channel name is registered
*/
isChannelTaken: function (name, callback) {
if (typeof callback !== "function") {
return;
}
dbutil.query("SELECT name FROM `channels` WHERE name=?",
[name],
function (err, rows) {
if (err) {
callback(err, true);
return;
}
callback(null, rows.length > 0);
});
},
/**
* Looks up a channel
*/
lookup: function (name, callback) {
if (typeof callback !== "function") {
return;
}
dbutil.query("SELECT * FROM `channels` WHERE name=?",
[name],
function (err, rows) {
if (err) {
callback(err, null);
return;
}
callback(null, rows);
});
},
/**
* Searches for a channel
*/
search: function (name, callback) {
if (typeof callback !== "function") {
return;
}
dbutil.query("SELECT * FROM `channels` WHERE name LIKE ?",
["%" + name + "%"],
function (err, rows) {
if (err) {
callback(err, null);
return;
}
callback(null, rows);
});
},
/**
* Validates and registers a new channel
*/
register: function (name, owner, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
if (typeof name !== "string" || typeof owner !== "string") {
callback("Name and owner are required for channel registration", null);
return;
}
if (!$util.isValidChannelName(name)) {
callback("Invalid channel name. Channel names may consist of 1-30 " +
"characters a-z, A-Z, 0-9, -, and _", null);
return;
}
module.exports.isChannelTaken(name, function (err, taken) {
if (err) {
callback(err, null);
return;
}
if (taken) {
callback("Channel name " + name + " is already taken", null);
return;
}
dbutil.query("INSERT INTO `channels` " +
"(`name`, `owner`, `time`) VALUES (?, ?, ?)",
[name, owner, Date.now()],
function (err, res) {
if (err) {
callback(err, null);
return;
}
initTables(name, owner, function (err, res) {
if (err) {
dbutil.query("DELETE FROM `channels` WHERE name=?", [name]);
callback(err, null);
return;
}
callback(null, {
name: name
});
});
});
});
},
/**
* Unregisters a channel
*/
drop: function (name, callback) {
if (typeof callback !== "function") {
callback = blackHole;
}
dropTable("chan_" + name + "_ranks", function (err) {
dropTable("chan_" + name + "_bans", function (e2) {
if (err && e2) {
err += "\n" + e2;
} else if (e2) {
err = e2;
}
dropTable("chan_" + name + "_library", function (e3) {
if (err && e3) {
err += "\n" + e3;
} else if (e3) {
err = e3;
}
db.query("DELETE FROM `channels` WHERE name=?", [name],
function (e4) {
if (err && e4) {
err += "\n" + e4;
} else if (e4) {
err = e4;
}
callback(err, !Boolean(err));
}
});
});
});
},
/**
* Looks up channels registered by a given user
*/
listUserChannels: function (owner, callback) {
if (typeof callback !== "function") {
return;
}
db.query("SELECT * FROM `channels` WHERE owner=?", [owner],
function (err, res) {
if (err) {
callback(err, []);
return;
}
callback(err, res);
});
},
/**
* Looks up a user's rank
*/
getRank: function (chan, name, callback) {
if (typeof callback !== "function") {
return;
}
db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE name=?",
[name],
function (err, rows) {
if (err) {
callback(err, 1);
return;
}
if (rows.length === 0) {
callback(null, 1);
return;
}
callback(null, rows[0].rank);
});
},
/**
* Looks up multiple users' ranks at once
*/
getRanks: function (chan, names, callback) {
if (typeof callback !== "function") {
return;
}
var replace = "(" + names.map(function () { return "?"; }).join(",") + ")";
db.query("SELECT name,rank FROM `chan_" + chan + "_ranks` WHERE name IN " +
replace,
function (err, rows) {
if (err) {
callback(err, []);
return;
}
callback(null, rows);
});
},
};