commit
89f4da20c5
169
acp.js
169
acp.js
|
@ -9,10 +9,11 @@ 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.
|
||||
*/
|
||||
|
||||
var Auth = require("./auth");
|
||||
var ActionLog = require("./actionlog");
|
||||
var Logger = require("./logger");
|
||||
|
||||
module.exports = function (Server) {
|
||||
var db = Server.db;
|
||||
var ActionLog = Server.actionlog;
|
||||
return {
|
||||
init: function(user) {
|
||||
ActionLog.record(user.ip, user.name, "acp-init");
|
||||
|
@ -28,118 +29,84 @@ module.exports = function (Server) {
|
|||
});
|
||||
|
||||
user.socket.on("acp-global-ban", function(data) {
|
||||
ActionLog.record(user.ip, user.name, "acp-global-ban", data.ip);
|
||||
Server.db.globalBanIP(data.ip, data.note);
|
||||
user.socket.emit("acp-global-banlist", Server.db.refreshGlobalBans());
|
||||
ActionLog.record(user.ip, user.name, "acp-global-ban", data.ip);
|
||||
db.setGlobalIPBan(data.ip, data.note, function (err, res) {
|
||||
db.listGlobalIPBans(function (err, res) {
|
||||
res = res || [];
|
||||
user.socket.emit("acp-global-banlist", res);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.on("acp-global-unban", function(ip) {
|
||||
ActionLog.record(user.ip, user.name, "acp-global-unban", ip);
|
||||
Server.db.globalUnbanIP(ip);
|
||||
user.socket.emit("acp-global-banlist", Server.db.refreshGlobalBans());
|
||||
db.clearGlobalIPBan(ip, function (err, res) {
|
||||
db.listGlobalIPBans(function (err, res) {
|
||||
res = res || [];
|
||||
user.socket.emit("acp-global-banlist", res);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.emit("acp-global-banlist", Server.db.refreshGlobalBans());
|
||||
db.listGlobalIPBans(function (err, res) {
|
||||
res = res || [];
|
||||
user.socket.emit("acp-global-banlist", res);
|
||||
});
|
||||
|
||||
user.socket.on("acp-lookup-user", function(name) {
|
||||
var db = Server.db.getConnection();
|
||||
if(!db) {
|
||||
return;
|
||||
}
|
||||
|
||||
var query = Server.db.createQuery(
|
||||
"SELECT id,uname,global_rank,profile_image,profile_text,email FROM registrations WHERE uname LIKE ?",
|
||||
["%"+name+"%"]
|
||||
);
|
||||
|
||||
var res = db.querySync(query);
|
||||
if(!res)
|
||||
return;
|
||||
|
||||
var rows = res.fetchAllSync();
|
||||
user.socket.emit("acp-userdata", rows);
|
||||
db.searchUser(name, function (err, res) {
|
||||
res = res || [];
|
||||
user.socket.emit("acp-userdata", res);
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.on("acp-lookup-channel", function (data) {
|
||||
var db = Server.db.getConnection();
|
||||
if(!db) {
|
||||
return;
|
||||
}
|
||||
|
||||
var query;
|
||||
if(data.field === "owner") {
|
||||
query = Server.db.createQuery(
|
||||
"SELECT * FROM channels WHERE owner LIKE ?",
|
||||
["%" + data.value + "%"]
|
||||
);
|
||||
} else if (data.field === "name") {
|
||||
query = Server.db.createQuery(
|
||||
"SELECT * FROM channels WHERE name LIKE ?",
|
||||
["%" + data.value + "%"]
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
var results = db.querySync(query);
|
||||
if(!results)
|
||||
return;
|
||||
|
||||
var rows = results.fetchAllSync();
|
||||
user.socket.emit("acp-channeldata", rows);
|
||||
db.searchChannel(data.field, data.value, function (e, res) {
|
||||
res = res || [];
|
||||
user.socket.emit("acp-channeldata", res);
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.on("acp-reset-password", function(data) {
|
||||
if(Auth.getGlobalRank(data.name) >= user.global_rank)
|
||||
return;
|
||||
try {
|
||||
var hash = Server.db.generatePasswordReset(user.ip, data.name, data.email);
|
||||
ActionLog.record(user.ip, user.name, "acp-reset-password", data.name);
|
||||
}
|
||||
catch(e) {
|
||||
user.socket.emit("acp-reset-password", {
|
||||
success: false,
|
||||
error: e
|
||||
});
|
||||
return;
|
||||
}
|
||||
if(hash) {
|
||||
user.socket.emit("acp-reset-password", {
|
||||
success: true,
|
||||
hash: hash
|
||||
});
|
||||
}
|
||||
else {
|
||||
user.socket.emit("acp-reset-password", {
|
||||
success: false,
|
||||
error: "Reset failed"
|
||||
});
|
||||
}
|
||||
db.getGlobalRank(data.name, function (err, rank) {
|
||||
if(err || rank >= user.global_rank)
|
||||
return;
|
||||
|
||||
db.genPasswordReset(user.ip, data.name, data.email,
|
||||
function (err, hash) {
|
||||
var pkt = {
|
||||
success: !err
|
||||
};
|
||||
|
||||
if(err) {
|
||||
pkt.error = err;
|
||||
} else {
|
||||
pkt.hash = hash;
|
||||
}
|
||||
|
||||
user.socket.emit("acp-reset-password", pkt);
|
||||
ActionLog.record(user.ip, user.name,
|
||||
"acp-reset-password", data.name);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.on("acp-set-rank", function(data) {
|
||||
if(data.rank < 1 || data.rank >= user.global_rank)
|
||||
return;
|
||||
|
||||
if(Auth.getGlobalRank(data.name) >= user.global_rank)
|
||||
return;
|
||||
db.getGlobalRank(data.name, function (err, rank) {
|
||||
if(err || rank >= user.global_rank)
|
||||
return;
|
||||
|
||||
var db = Server.db.getConnection();
|
||||
if(!db)
|
||||
return;
|
||||
|
||||
ActionLog.record(user.ip, user.name, "acp-set-rank", data);
|
||||
var query = Server.db.createQuery(
|
||||
"UPDATE registrations SET global_rank=? WHERE uname=?",
|
||||
[data.rank, data.name]
|
||||
);
|
||||
|
||||
var res = db.querySync(query);
|
||||
if(!res)
|
||||
return;
|
||||
|
||||
user.socket.emit("acp-set-rank", data);
|
||||
db.setGlobalRank(data.name, data.rank,
|
||||
function (err, res) {
|
||||
ActionLog.record(user.ip, user.name, "acp-set-rank",
|
||||
data);
|
||||
if(!err)
|
||||
user.socket.emit("acp-set-rank", data);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.on("acp-list-loaded", function() {
|
||||
|
@ -180,9 +147,10 @@ module.exports = function (Server) {
|
|||
});
|
||||
|
||||
user.socket.on("acp-actionlog-list", function () {
|
||||
user.socket.emit("acp-actionlog-list",
|
||||
ActionLog.getLogTypes()
|
||||
);
|
||||
ActionLog.listActionTypes(function (err, types) {
|
||||
if(!err)
|
||||
user.socket.emit("acp-actionlog-list", types);
|
||||
});
|
||||
});
|
||||
|
||||
user.socket.on("acp-actionlog-clear", function(data) {
|
||||
|
@ -196,13 +164,10 @@ module.exports = function (Server) {
|
|||
});
|
||||
|
||||
user.socket.on("acp-view-stats", function () {
|
||||
var db = Server.db.getConnection();
|
||||
if(!db)
|
||||
return;
|
||||
var query = "SELECT * FROM stats ORDER BY time ASC";
|
||||
var results = db.querySync(query);
|
||||
if(results)
|
||||
user.socket.emit("acp-view-stats", results.fetchAllSync());
|
||||
db.listStats(function (err, res) {
|
||||
if(!err)
|
||||
user.socket.emit("acp-view-stats", res);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
181
actionlog.js
181
actionlog.js
|
@ -9,143 +9,50 @@ 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.
|
||||
*/
|
||||
|
||||
var Database = require("./database");
|
||||
var Logger = require("./logger");
|
||||
|
||||
exports.record = function(ip, name, action, args) {
|
||||
if(typeof args === "undefined" || args === null) {
|
||||
args = "";
|
||||
} else {
|
||||
try {
|
||||
args = JSON.stringify(args);
|
||||
} catch(e) {
|
||||
args = "";
|
||||
module.exports = function (Server) {
|
||||
var db = Server.db;
|
||||
return {
|
||||
record: function (ip, name, action, args) {
|
||||
if(!args)
|
||||
args = "";
|
||||
else {
|
||||
try {
|
||||
args = JSON.stringify(args);
|
||||
} catch(e) {
|
||||
args = "";
|
||||
}
|
||||
}
|
||||
|
||||
db.recordAction(ip, name, action, args);
|
||||
},
|
||||
|
||||
clear: function (actions) {
|
||||
db.clearActions(actions);
|
||||
},
|
||||
|
||||
clearOne: function (item) {
|
||||
db.clearSingleAction(item);
|
||||
},
|
||||
|
||||
throttleRegistrations: function (ip, callback) {
|
||||
db.recentRegistrationCount(ip, function (err, count) {
|
||||
if(err) {
|
||||
callback(err, null);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, count > 4);
|
||||
});
|
||||
},
|
||||
|
||||
listActionTypes: function (callback) {
|
||||
db.listActionTypes(callback);
|
||||
},
|
||||
|
||||
listActions: function (types, callback) {
|
||||
db.listActions(types, callback);
|
||||
}
|
||||
}
|
||||
|
||||
var db = Database.getConnection();
|
||||
if(!db)
|
||||
return false;
|
||||
|
||||
var query = Database.createQuery(
|
||||
"INSERT INTO actionlog (ip, name, action, args, time) "+
|
||||
"VALUES (?, ?, ?, ?, ?)",
|
||||
[ip, name, action, args, Date.now()]
|
||||
);
|
||||
|
||||
var result = db.querySync(query);
|
||||
if(!result) {
|
||||
Logger.errlog.log("! Failed to record action");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.clear = function(actions) {
|
||||
var db = Database.getConnection();
|
||||
if(!db)
|
||||
return false;
|
||||
|
||||
var list = new Array(actions.length);
|
||||
for(var i = 0; i < actions.length; i++)
|
||||
list[i] = "?";
|
||||
|
||||
var query = Database.createQuery(
|
||||
"DELETE FROM actionlog WHERE action IN ("+
|
||||
list.join(",")+
|
||||
")",
|
||||
actions
|
||||
);
|
||||
|
||||
var result = db.querySync(query);
|
||||
if(!result) {
|
||||
Logger.errlog.log("! Failed to clear action log");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.clearOne = function(e) {
|
||||
var db = Database.getConnection();
|
||||
if(!db)
|
||||
return false;
|
||||
|
||||
var query = Database.createQuery(
|
||||
"DELETE FROM actionlog WHERE ip=? AND time=?",
|
||||
[e.ip, e.time]
|
||||
);
|
||||
|
||||
var result = db.querySync(query);
|
||||
if(!result) {
|
||||
Logger.errlog.log("! Failed to clear action log");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.tooManyRegistrations = function (ip) {
|
||||
var db = Database.getConnection();
|
||||
if(!db)
|
||||
return true;
|
||||
|
||||
var query = Database.createQuery(
|
||||
"SELECT * FROM actionlog WHERE ip=? AND action='register-success'"+
|
||||
"AND time > ?",
|
||||
[ip, Date.now() - 48 * 3600 * 1000]
|
||||
);
|
||||
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
Logger.errlog.log("! Failed to check tooManyRegistrations");
|
||||
return true;
|
||||
}
|
||||
|
||||
var rows = results.fetchAllSync();
|
||||
// TODO Config value for this
|
||||
return rows.length > 4;
|
||||
}
|
||||
|
||||
exports.getLogTypes = function () {
|
||||
var db = Database.getConnection();
|
||||
if(!db)
|
||||
return false;
|
||||
|
||||
var query = "SELECT DISTINCT action FROM actionlog";
|
||||
var result = db.querySync(query);
|
||||
if(!result) {
|
||||
Logger.errlog.log("! Failed to read action log");
|
||||
return [];
|
||||
}
|
||||
|
||||
result = result.fetchAllSync();
|
||||
var actions = [];
|
||||
for(var i in result)
|
||||
actions.push(result[i].action);
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
exports.readLog = function (actions) {
|
||||
var db = Database.getConnection();
|
||||
if(!db)
|
||||
return false;
|
||||
|
||||
var query = "SELECT * FROM actionlog";
|
||||
if(actions !== undefined) {
|
||||
var list = new Array(actions.length);
|
||||
for(var i in actions)
|
||||
list[i] = "?";
|
||||
list = list.join(",");
|
||||
query += Database.createQuery(
|
||||
" WHERE action IN ("+list+")",
|
||||
actions
|
||||
);
|
||||
}
|
||||
var result = db.querySync(query);
|
||||
if(!result) {
|
||||
Logger.errlog.log("! Failed to read action log");
|
||||
return [];
|
||||
}
|
||||
|
||||
return result.fetchAllSync();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
226
auth.js
226
auth.js
|
@ -1,226 +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.
|
||||
*/
|
||||
|
||||
var mysql = require("mysql-libmysqlclient");
|
||||
var Database = require("./database.js");
|
||||
var bcrypt = require("bcrypt");
|
||||
var hashlib = require("node_hash");
|
||||
var Logger = require("./logger.js");
|
||||
|
||||
// Check if a name is taken
|
||||
exports.isRegistered = function(name) {
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
throw "Database failure";
|
||||
}
|
||||
var query = Database.createQuery(
|
||||
"SELECT * FROM `registrations` WHERE uname=?",
|
||||
[name]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var rows = results.fetchAllSync();
|
||||
return rows.length > 0;
|
||||
}
|
||||
|
||||
// Check if a name is valid
|
||||
// Valid names are 1-20 characters, alphanumeric and underscores
|
||||
exports.validateName = function(name) {
|
||||
if(name.length > 20)
|
||||
return false;
|
||||
const VALID_REGEX = /^[a-zA-Z0-9_]+$/;
|
||||
return name.match(VALID_REGEX) != null;
|
||||
}
|
||||
|
||||
// Try to register a new account
|
||||
exports.register = function(name, pw) {
|
||||
if(!exports.validateName(name))
|
||||
return false;
|
||||
if(exports.isRegistered(name))
|
||||
return false;
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var hash = bcrypt.hashSync(pw, 10);
|
||||
var query = Database.createQuery(
|
||||
["INSERT INTO `registrations` VALUES ",
|
||||
"(NULL, ?, ?, 1, '', 0, '', '', '')"].join(""),
|
||||
[name, hash]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
if(results) {
|
||||
return exports.createSession(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exports.login = function(name, pw, session) {
|
||||
if(session) {
|
||||
var res = exports.loginSession(name, session);
|
||||
if(res) {
|
||||
return res;
|
||||
}
|
||||
else if(!pw) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var row = exports.loginPassword(name, pw);
|
||||
if(row) {
|
||||
var hash = exports.createSession(name);
|
||||
row.session_hash = hash;
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to login
|
||||
exports.loginPassword = function(name, pw) {
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
throw "Database failure";
|
||||
}
|
||||
var query = Database.createQuery(
|
||||
"SELECT * FROM `registrations` WHERE uname=?",
|
||||
[name]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
return false;
|
||||
}
|
||||
var rows = results.fetchAllSync();
|
||||
if(rows.length > 0) {
|
||||
try {
|
||||
if(bcrypt.compareSync(pw, rows[0].pw)) {
|
||||
return rows[0];
|
||||
}
|
||||
else {
|
||||
// Check if the sha256 is in the database
|
||||
// If so, migrate to bcrypt
|
||||
var sha256 = hashlib.sha256(pw);
|
||||
if(sha256 == rows[0].pw) {
|
||||
var newhash = bcrypt.hashSync(pw, 10);
|
||||
var query = Database.createQuery(
|
||||
["UPDATE `registrations` SET pw=?",
|
||||
"WHERE uname=?"].join(""),
|
||||
[newhash, name]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
Logger.errlog.log("Failed to migrate password! user=" + name);
|
||||
return false;
|
||||
}
|
||||
return rows[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
Logger.errlog.log("Auth.login fail");
|
||||
Logger.errlog.log(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exports.createSession = function(name) {
|
||||
var salt = sessionSalt();
|
||||
var hash = hashlib.sha256(salt + name);
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
throw "Database failure";
|
||||
}
|
||||
var query = Database.createQuery(
|
||||
["UPDATE `registrations` SET ",
|
||||
"`session_hash`=?,",
|
||||
"`expire`=? ",
|
||||
"WHERE uname=?"].join(""),
|
||||
[hash, Date.now() + 604800000, name]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
return results ? hash : false;
|
||||
}
|
||||
|
||||
exports.loginSession = function(name, hash) {
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
throw "Database failure";
|
||||
}
|
||||
var query = Database.createQuery(
|
||||
"SELECT * FROM `registrations` WHERE `uname`=?",
|
||||
[name]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
return false;
|
||||
}
|
||||
var rows = results.fetchAllSync();
|
||||
if(rows.length != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var dbhash = rows[0].session_hash;
|
||||
if(hash != dbhash) {
|
||||
return false;
|
||||
}
|
||||
var timeout = rows[0].expire;
|
||||
if(timeout < new Date().getTime()) {
|
||||
return false;
|
||||
}
|
||||
return rows[0];
|
||||
}
|
||||
|
||||
function sessionSalt() {
|
||||
var chars = "abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
+ "0123456789!@#$%^&*_+=~";
|
||||
var salt = [];
|
||||
for(var i = 0; i < 32; i++) {
|
||||
salt.push(chars[parseInt(Math.random()*chars.length)]);
|
||||
}
|
||||
return salt.join('');
|
||||
}
|
||||
|
||||
exports.setUserPassword = function(name, pw) {
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
return false;
|
||||
}
|
||||
var hash = bcrypt.hashSync(pw, 10);
|
||||
var query = Database.createQuery(
|
||||
"UPDATE `registrations` SET `pw`=? WHERE `uname`=?",
|
||||
[hash, name]
|
||||
);
|
||||
var result = db.querySync(query);
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.getGlobalRank = function(name) {
|
||||
var db = Database.getConnection();
|
||||
if(!db) {
|
||||
return false;
|
||||
}
|
||||
var query = Database.createQuery(
|
||||
"SELECT * FROM `registrations` WHERE `uname`=?",
|
||||
[name]
|
||||
);
|
||||
var results = db.querySync(query);
|
||||
if(!results) {
|
||||
return 0;
|
||||
}
|
||||
var rows = results.fetchAllSync();
|
||||
if(rows.length > 0) {
|
||||
return rows[0].global_rank;
|
||||
}
|
||||
return 0;
|
||||
}
|
932
channel.js
932
channel.js
File diff suppressed because it is too large
Load diff
|
@ -145,10 +145,21 @@ function handleUnmute(chan, user, args) {
|
|||
function handleKick(chan, user, args) {
|
||||
if(chan.hasPermission(user, "kick") && args.length > 0) {
|
||||
args[0] = args[0].toLowerCase();
|
||||
if(args[0] == user.name.toLowerCase()) {
|
||||
user.socket.emit("costanza", {
|
||||
msg: "Kicking yourself?"
|
||||
});
|
||||
return;
|
||||
}
|
||||
var kickee;
|
||||
for(var i = 0; i < chan.users.length; i++) {
|
||||
if(chan.users[i].name.toLowerCase() == args[0] &&
|
||||
chan.getRank(chan.users[i].name) < user.rank) {
|
||||
if(chan.users[i].name.toLowerCase() == args[0]) {
|
||||
if(chan.users[i].rank >= user.rank) {
|
||||
user.socket.emit("errorMsg", {
|
||||
msg: "You don't have permission to kick " + args[0]
|
||||
});
|
||||
return;
|
||||
}
|
||||
kickee = chan.users[i];
|
||||
break;
|
||||
}
|
||||
|
|
13
config.js
13
config.js
|
@ -42,17 +42,14 @@ var defaults = {
|
|||
}
|
||||
|
||||
function save(cfg, file) {
|
||||
if(!cfg.loaded)
|
||||
return;
|
||||
var x = {};
|
||||
for(var k in cfg) {
|
||||
if(k !== "nodemailer")
|
||||
if(k !== "nodemailer" && k !== "loaded")
|
||||
x[k] = cfg[k];
|
||||
}
|
||||
fs.writeFile(file, JSON.stringify(x, null, 4), function (err) {
|
||||
if(err) {
|
||||
Logger.errlog.log("Failed to save config");
|
||||
Logger.errlog.log(err);
|
||||
}
|
||||
});
|
||||
fs.writeFileSync(file, JSON.stringify(x, null, 4));
|
||||
}
|
||||
|
||||
exports.load = function (Server, file, callback) {
|
||||
|
@ -92,6 +89,8 @@ exports.load = function (Server, file, callback) {
|
|||
);
|
||||
}
|
||||
|
||||
cfg["loaded"] = true;
|
||||
|
||||
save(cfg, file);
|
||||
Server.cfg = cfg;
|
||||
callback();
|
||||
|
|
2090
database.js
2090
database.js
File diff suppressed because it is too large
Load diff
|
@ -2,14 +2,14 @@
|
|||
"author": "Calvin Montgomery",
|
||||
"name": "CyTube",
|
||||
"description": "Online media synchronizer and chat",
|
||||
"version": "2.3.3",
|
||||
"version": "2.4.0",
|
||||
"repository": {
|
||||
"url": "http://github.com/calzoneman/sync"
|
||||
},
|
||||
"dependencies": {
|
||||
"socket.io": ">=0.9",
|
||||
"express": ">=3.2",
|
||||
"mysql-libmysqlclient": "*",
|
||||
"mysql": "2.0.0-alpha8",
|
||||
"node_hash": "*",
|
||||
"bcrypt": "*",
|
||||
"nodemailer": "*",
|
||||
|
|
32
server.js
32
server.js
|
@ -6,7 +6,7 @@ var Logger = require("./logger");
|
|||
var Channel = require("./channel");
|
||||
var User = require("./user");
|
||||
|
||||
const VERSION = "2.3.3";
|
||||
const VERSION = "2.4.0";
|
||||
|
||||
function getIP(req) {
|
||||
var raw = req.connection.remoteAddress;
|
||||
|
@ -74,6 +74,7 @@ var Server = {
|
|||
ips: {},
|
||||
acp: null,
|
||||
httpaccess: null,
|
||||
actionlog: null,
|
||||
logHTTP: function (req, status) {
|
||||
if(status === undefined)
|
||||
status = 200;
|
||||
|
@ -89,8 +90,14 @@ var Server = {
|
|||
this.httpaccess.log([ipstr, req.method, url, status, req.headers["user-agent"]].join(" "));
|
||||
},
|
||||
init: function () {
|
||||
// init database
|
||||
var Database = require("./database");
|
||||
this.db = new Database(this.cfg);
|
||||
this.db.init();
|
||||
this.actionlog = require("./actionlog")(this);
|
||||
this.httpaccess = new Logger.Logger("httpaccess.log");
|
||||
this.app = express();
|
||||
this.app.use(express.bodyParser());
|
||||
// channel path
|
||||
this.app.get("/r/:channel(*)", function (req, res, next) {
|
||||
var c = req.params.channel;
|
||||
|
@ -105,10 +112,12 @@ var Server = {
|
|||
|
||||
// api path
|
||||
this.api = require("./api")(this);
|
||||
/*
|
||||
this.app.get("/api/:apireq(*)", function (req, res, next) {
|
||||
this.logHTTP(req);
|
||||
this.api.handle(req.url.substring(5), req, res);
|
||||
}.bind(this));
|
||||
*/
|
||||
|
||||
this.app.get("/", function (req, res, next) {
|
||||
this.logHTTP(req);
|
||||
|
@ -167,14 +176,15 @@ var Server = {
|
|||
this.io.sockets.on("connection", function (socket) {
|
||||
var ip = getSocketIP(socket);
|
||||
socket._ip = ip;
|
||||
if(this.db.checkGlobalBan(ip)) {
|
||||
Logger.syslog.log("Disconnecting " + ip + " - gbanned");
|
||||
socket.emit("kick", {
|
||||
reason: "You're globally banned."
|
||||
});
|
||||
socket.disconnect(true);
|
||||
return;
|
||||
}
|
||||
this.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 () {
|
||||
this.ips[ip]--;
|
||||
|
@ -197,10 +207,6 @@ var Server = {
|
|||
new User(socket, this);
|
||||
}.bind(this));
|
||||
|
||||
// init database
|
||||
this.db = require("./database");
|
||||
this.db.setup(Server.cfg);
|
||||
this.db.init();
|
||||
|
||||
// init ACP
|
||||
this.acp = require("./acp")(this);
|
||||
|
|
28
stats.js
28
stats.js
|
@ -15,6 +15,7 @@ const STAT_INTERVAL = 60 * 60 * 1000;
|
|||
const STAT_EXPIRE = 24 * STAT_INTERVAL;
|
||||
|
||||
module.exports = function (Server) {
|
||||
var db = Server.db;
|
||||
setInterval(function () {
|
||||
var chancount = Server.channels.length;
|
||||
var usercount = 0;
|
||||
|
@ -24,29 +25,8 @@ module.exports = function (Server) {
|
|||
|
||||
var mem = process.memoryUsage().rss;
|
||||
|
||||
var db = Server.db.getConnection();
|
||||
if(!db)
|
||||
return;
|
||||
|
||||
var query = Server.db.createQuery(
|
||||
"INSERT INTO stats VALUES (?, ?, ?, ?)",
|
||||
[Date.now(), usercount, chancount, mem]
|
||||
);
|
||||
|
||||
if(!db.querySync(query)) {
|
||||
Logger.errlog.log("! Failed to record stats");
|
||||
Logger.errlog.log(query);
|
||||
}
|
||||
|
||||
query = Server.db.createQuery(
|
||||
"DELETE FROM stats WHERE time<?",
|
||||
[Date.now() - STAT_EXPIRE]
|
||||
);
|
||||
|
||||
if(!db.querySync(query)) {
|
||||
Logger.errlog.log("! Failed to prune stats");
|
||||
Logger.errlog.log(query);
|
||||
}
|
||||
|
||||
db.addStatPoint(Date.now(), usercount, chancount, mem, function () {
|
||||
db.pruneStats(Date.now() - STAT_EXPIRE);
|
||||
});
|
||||
}, STAT_INTERVAL);
|
||||
}
|
||||
|
|
803
user.js
803
user.js
|
@ -10,11 +10,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||
*/
|
||||
|
||||
var Rank = require("./rank.js");
|
||||
var Auth = require("./auth.js");
|
||||
var Channel = require("./channel.js").Channel;
|
||||
var formatTime = require("./media.js").formatTime;
|
||||
var Logger = require("./logger.js");
|
||||
var ActionLog = require("./actionlog");
|
||||
var $util = require("./utilities");
|
||||
|
||||
// Represents a client connected via socket.io
|
||||
var User = function(socket, Server) {
|
||||
|
@ -118,365 +117,350 @@ User.prototype.autoAFK = function () {
|
|||
}
|
||||
|
||||
User.prototype.initCallbacks = function() {
|
||||
this.socket.on("disconnect", function() {
|
||||
this.awaytimer && clearTimeout(this.awaytimer);
|
||||
if(this.channel != null)
|
||||
this.channel.userLeave(this);
|
||||
}.bind(this));
|
||||
var self = this;
|
||||
self.socket.on("disconnect", function() {
|
||||
self.awaytimer && clearTimeout(self.awaytimer);
|
||||
if(self.channel != null)
|
||||
self.channel.userLeave(self);
|
||||
});
|
||||
|
||||
this.socket.on("joinChannel", function(data) {
|
||||
if(this.channel != null)
|
||||
self.socket.on("joinChannel", function(data) {
|
||||
if(self.channel != null)
|
||||
return;
|
||||
if(typeof data.name != "string")
|
||||
return;
|
||||
if(!data.name.match(/^[\w-_]{1,30}$/)) {
|
||||
this.socket.emit("errorMsg", {
|
||||
self.socket.emit("errorMsg", {
|
||||
msg: "Invalid channel name. Channel names may consist of"+
|
||||
" 1-30 characters in the set a-z, A-Z, 0-9, -, and _"
|
||||
});
|
||||
this.socket.emit("kick", {
|
||||
self.socket.emit("kick", {
|
||||
reason: "Bad channel name"
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
data.name = data.name.toLowerCase();
|
||||
this.channel = this.server.getChannel(data.name);
|
||||
if(this.loggedIn) {
|
||||
var chanrank = this.channel.getRank(this.name);
|
||||
if(chanrank > this.rank) {
|
||||
this.rank = chanrank;
|
||||
}
|
||||
self.channel = self.server.getChannel(data.name);
|
||||
if(self.loggedIn) {
|
||||
self.channel.getRank(self.name, function (err, rank) {
|
||||
if(!err && rank > self.rank)
|
||||
self.rank = rank;
|
||||
});
|
||||
}
|
||||
this.channel.userJoin(this);
|
||||
}.bind(this));
|
||||
self.channel.userJoin(self);
|
||||
});
|
||||
|
||||
this.socket.on("login", function(data) {
|
||||
self.socket.on("login", function(data) {
|
||||
var name = data.name || "";
|
||||
var pw = data.pw || "";
|
||||
var session = data.session || "";
|
||||
if(pw.length > 100)
|
||||
pw = pw.substring(0, 100);
|
||||
if(this.name == "")
|
||||
this.login(name, pw, session);
|
||||
}.bind(this));
|
||||
if(self.name == "")
|
||||
self.login(name, pw, session);
|
||||
});
|
||||
|
||||
this.socket.on("assignLeader", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryChangeLeader(this, data);
|
||||
self.socket.on("assignLeader", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryChangeLeader(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("promote", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryPromoteUser(this, data);
|
||||
self.socket.on("promote", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryPromoteUser(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("demote", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryDemoteUser(this, data);
|
||||
self.socket.on("demote", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryDemoteUser(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("setChannelRank", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.trySetRank(this, data);
|
||||
self.socket.on("setChannelRank", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.trySetRank(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("banName", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.banName(this, data.name || "");
|
||||
self.socket.on("banName", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.banName(self, data.name || "");
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("banIP", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryIPBan(this, data);
|
||||
self.socket.on("banIP", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryIPBan(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("unban", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUnban(this, data);
|
||||
self.socket.on("unban", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUnban(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("chatMsg", function(data) {
|
||||
if(this.channel != null) {
|
||||
self.socket.on("chatMsg", function(data) {
|
||||
if(self.channel != null) {
|
||||
if(data.msg.indexOf("/afk") != 0) {
|
||||
this.setAFK(false);
|
||||
this.autoAFK();
|
||||
self.setAFK(false);
|
||||
self.autoAFK();
|
||||
}
|
||||
this.channel.tryChat(this, data);
|
||||
self.channel.tryChat(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("newPoll", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryOpenPoll(this, data);
|
||||
self.socket.on("newPoll", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryOpenPoll(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("playerReady", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.sendMediaUpdate(this);
|
||||
self.socket.on("playerReady", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.sendMediaUpdate(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("requestPlaylist", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.sendPlaylist(this);
|
||||
self.socket.on("requestPlaylist", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.sendPlaylist(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("queue", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryQueue(this, data);
|
||||
self.socket.on("queue", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryQueue(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("setTemp", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.trySetTemp(this, data);
|
||||
self.socket.on("setTemp", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.trySetTemp(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("delete", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryDequeue(this, data);
|
||||
self.socket.on("delete", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryDequeue(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("uncache", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUncache(this, data);
|
||||
self.socket.on("uncache", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUncache(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("moveMedia", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryMove(this, data);
|
||||
self.socket.on("moveMedia", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryMove(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("jumpTo", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryJumpTo(this, data);
|
||||
self.socket.on("jumpTo", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryJumpTo(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("playNext", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryPlayNext(this);
|
||||
self.socket.on("playNext", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryPlayNext(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("clearPlaylist", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryClearqueue(this);
|
||||
self.socket.on("clearPlaylist", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryClearqueue(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("shufflePlaylist", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryShufflequeue(this);
|
||||
self.socket.on("shufflePlaylist", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryShufflequeue(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("togglePlaylistLock", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryToggleLock(this);
|
||||
self.socket.on("togglePlaylistLock", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryToggleLock(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("mediaUpdate", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUpdate(this, data);
|
||||
self.socket.on("mediaUpdate", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUpdate(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("searchMedia", function(data) {
|
||||
if(this.channel != null) {
|
||||
self.socket.on("searchMedia", function(data) {
|
||||
if(self.channel != null) {
|
||||
if(data.source == "yt") {
|
||||
var callback = function(vids) {
|
||||
this.socket.emit("searchResults", {
|
||||
var searchfn = self.server.infogetter.Getters["ytSearch"];
|
||||
searchfn(data.query.split(" "), function (e, vids) {
|
||||
if(!e) {
|
||||
self.socket.emit("searchResults", {
|
||||
results: vids
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
self.channel.search(data.query, function (vids) {
|
||||
self.socket.emit("searchResults", {
|
||||
results: vids
|
||||
});
|
||||
}.bind(this);
|
||||
this.channel.search(data.query, callback);
|
||||
}
|
||||
else {
|
||||
this.socket.emit("searchResults", {
|
||||
results: this.channel.search(data.query)
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("closePoll", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryClosePoll(this);
|
||||
self.socket.on("closePoll", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryClosePoll(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("vote", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryVote(this, data);
|
||||
self.socket.on("vote", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryVote(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("registerChannel", function(data) {
|
||||
if(this.channel == null) {
|
||||
this.socket.emit("channelRegistration", {
|
||||
self.socket.on("registerChannel", function(data) {
|
||||
if(self.channel == null) {
|
||||
self.socket.emit("channelRegistration", {
|
||||
success: false,
|
||||
error: "You're not in any channel!"
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.channel.tryRegister(this);
|
||||
self.channel.tryRegister(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("unregisterChannel", function() {
|
||||
if(this.channel == null) {
|
||||
self.socket.on("unregisterChannel", function() {
|
||||
if(self.channel == null) {
|
||||
return;
|
||||
}
|
||||
if(!this.channel.registered) {
|
||||
this.socket.emit("unregisterChannel", {
|
||||
success: false,
|
||||
error: "This channel is already unregistered"
|
||||
});
|
||||
}
|
||||
else if(this.rank < 10) {
|
||||
this.socket.emit("unregisterChannel", {
|
||||
success: false,
|
||||
error: "You don't have permission to unregister"
|
||||
});
|
||||
}
|
||||
else if(this.channel.unregister()) {
|
||||
this.socket.emit("unregisterChannel", {
|
||||
success: true
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.socket.emit("unregisterChannel", {
|
||||
success: false,
|
||||
error: "Unregistration failed. Please see a site admin if this continues."
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
self.channel.unregister(self);
|
||||
});
|
||||
|
||||
this.socket.on("setOptions", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUpdateOptions(this, data);
|
||||
self.socket.on("setOptions", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUpdateOptions(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("setPermissions", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUpdatePermissions(this, data);
|
||||
self.socket.on("setPermissions", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUpdatePermissions(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("setChannelCSS", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.trySetCSS(this, data);
|
||||
self.socket.on("setChannelCSS", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.trySetCSS(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("setChannelJS", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.trySetJS(this, data);
|
||||
self.socket.on("setChannelJS", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.trySetJS(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("updateFilter", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUpdateFilter(this, data);
|
||||
self.socket.on("updateFilter", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUpdateFilter(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("removeFilter", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryRemoveFilter(this, data);
|
||||
self.socket.on("removeFilter", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryRemoveFilter(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("moveFilter", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryMoveFilter(this, data);
|
||||
self.socket.on("moveFilter", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryMoveFilter(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("setMotd", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryUpdateMotd(this, data);
|
||||
self.socket.on("setMotd", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryUpdateMotd(self, data);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("requestLoginHistory", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.sendLoginHistory(this);
|
||||
self.socket.on("requestLoginHistory", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.sendLoginHistory(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("requestBanlist", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.sendBanlist(this);
|
||||
self.socket.on("requestBanlist", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.sendBanlist(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("requestChatFilters", function() {
|
||||
if(this.channel != null) {
|
||||
this.channel.sendChatFilters(this);
|
||||
self.socket.on("requestChatFilters", function() {
|
||||
if(self.channel != null) {
|
||||
self.channel.sendChatFilters(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("requestChannelRanks", function() {
|
||||
if(this.channel != null) {
|
||||
if(this.noflood("requestChannelRanks", 0.25))
|
||||
self.socket.on("requestChannelRanks", function() {
|
||||
if(self.channel != null) {
|
||||
if(self.noflood("requestChannelRanks", 0.25))
|
||||
return;
|
||||
this.channel.sendChannelRanks(this);
|
||||
self.channel.sendChannelRanks(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("voteskip", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryVoteskip(this);
|
||||
self.socket.on("voteskip", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryVoteskip(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("listPlaylists", function(data) {
|
||||
if(this.name == "" || this.rank < 1) {
|
||||
this.socket.emit("listPlaylists", {
|
||||
self.socket.on("listPlaylists", function(data) {
|
||||
if(self.name == "" || self.rank < 1) {
|
||||
self.socket.emit("listPlaylists", {
|
||||
pllist: [],
|
||||
error: "You must be logged in to manage playlists"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var list = this.server.db.getUserPlaylists(this.name);
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
list[i].time = formatTime(list[i].time);
|
||||
}
|
||||
this.socket.emit("listPlaylists", {
|
||||
pllist: list,
|
||||
self.server.db.listUserPlaylists(self.name, function (err, list) {
|
||||
if(err)
|
||||
list = [];
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
list[i].time = formatTime(list[i].time);
|
||||
}
|
||||
self.socket.emit("listPlaylists", {
|
||||
pllist: list,
|
||||
});
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("savePlaylist", function(data) {
|
||||
if(this.rank < 1) {
|
||||
this.socket.emit("savePlaylist", {
|
||||
self.socket.on("savePlaylist", function(data) {
|
||||
if(self.rank < 1) {
|
||||
self.socket.emit("savePlaylist", {
|
||||
success: false,
|
||||
error: "You must be logged in to manage playlists"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.channel == null) {
|
||||
this.socket.emit("savePlaylist", {
|
||||
if(self.channel == null) {
|
||||
self.socket.emit("savePlaylist", {
|
||||
success: false,
|
||||
error: "Not in a channel"
|
||||
});
|
||||
|
@ -487,79 +471,100 @@ User.prototype.initCallbacks = function() {
|
|||
return;
|
||||
}
|
||||
|
||||
var pl = this.channel.playlist.items.toArray();
|
||||
var result = this.server.db.saveUserPlaylist(pl, this.name, data.name);
|
||||
this.socket.emit("savePlaylist", {
|
||||
success: result,
|
||||
error: result ? false : "Unknown"
|
||||
});
|
||||
var list = this.server.db.getUserPlaylists(this.name);
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
list[i].time = formatTime(list[i].time);
|
||||
}
|
||||
this.socket.emit("listPlaylists", {
|
||||
pllist: list,
|
||||
});
|
||||
}.bind(this));
|
||||
var pl = self.channel.playlist.items.toArray();
|
||||
self.server.db.saveUserPlaylist(pl, self.name, data.name,
|
||||
function (err, res) {
|
||||
if(err) {
|
||||
self.socket.emit("savePlaylist", {
|
||||
success: false,
|
||||
error: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
self.socket.emit("savePlaylist", {
|
||||
success: true
|
||||
});
|
||||
|
||||
this.socket.on("queuePlaylist", function(data) {
|
||||
if(this.channel != null) {
|
||||
this.channel.tryQueuePlaylist(this, data);
|
||||
}
|
||||
}.bind(this));
|
||||
self.server.db.listUserPlaylists(self.name,
|
||||
function (err, list) {
|
||||
if(err)
|
||||
list = [];
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
list[i].time = formatTime(list[i].time);
|
||||
}
|
||||
self.socket.emit("listPlaylists", {
|
||||
pllist: list,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.socket.on("deletePlaylist", function(data) {
|
||||
self.socket.on("queuePlaylist", function(data) {
|
||||
if(self.channel != null) {
|
||||
self.channel.tryQueuePlaylist(self, data);
|
||||
}
|
||||
});
|
||||
|
||||
self.socket.on("deletePlaylist", function(data) {
|
||||
if(typeof data.name != "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.server.db.deleteUserPlaylist(this.name, data.name);
|
||||
var list = this.server.db.getUserPlaylists(this.name);
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
list[i].time = formatTime(list[i].time);
|
||||
}
|
||||
this.socket.emit("listPlaylists", {
|
||||
pllist: list,
|
||||
self.server.db.deleteUserPlaylist(self.name, data.name,
|
||||
function () {
|
||||
self.server.db.listUserPlaylists(self.name,
|
||||
function (err, list) {
|
||||
if(err)
|
||||
list = [];
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
list[i].time = formatTime(list[i].time);
|
||||
}
|
||||
self.socket.emit("listPlaylists", {
|
||||
pllist: list,
|
||||
});
|
||||
});
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("readChanLog", function () {
|
||||
if(this.channel !== null) {
|
||||
this.channel.tryReadLog(this);
|
||||
self.socket.on("readChanLog", function () {
|
||||
if(self.channel !== null) {
|
||||
self.channel.tryReadLog(self);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
this.socket.on("acp-init", function() {
|
||||
if(this.global_rank >= Rank.Siteadmin)
|
||||
this.server.acp.init(this);
|
||||
}.bind(this));
|
||||
self.socket.on("acp-init", function() {
|
||||
if(self.global_rank >= Rank.Siteadmin)
|
||||
self.server.acp.init(self);
|
||||
});
|
||||
|
||||
this.socket.on("borrow-rank", function(rank) {
|
||||
if(this.global_rank < 255)
|
||||
self.socket.on("borrow-rank", function(rank) {
|
||||
if(self.global_rank < 255)
|
||||
return;
|
||||
if(rank > this.global_rank)
|
||||
if(rank > self.global_rank)
|
||||
return;
|
||||
|
||||
this.rank = rank;
|
||||
this.socket.emit("rank", rank);
|
||||
if(this.channel != null)
|
||||
this.channel.broadcastUserUpdate(this);
|
||||
self.rank = rank;
|
||||
self.socket.emit("rank", rank);
|
||||
if(self.channel != null)
|
||||
self.channel.broadcastUserUpdate(self);
|
||||
|
||||
}.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
var lastguestlogin = {};
|
||||
// Attempt to login
|
||||
User.prototype.login = function(name, pw, session) {
|
||||
var self = this;
|
||||
// No password => try guest login
|
||||
if(pw == "" && session == "") {
|
||||
if(this.ip in lastguestlogin) {
|
||||
var diff = (Date.now() - lastguestlogin[this.ip])/1000;
|
||||
if(diff < this.server.cfg["guest-login-delay"]) {
|
||||
this.socket.emit("login", {
|
||||
if(self.ip in lastguestlogin) {
|
||||
var diff = (Date.now() - lastguestlogin[self.ip])/1000;
|
||||
if(diff < self.server.cfg["guest-login-delay"]) {
|
||||
self.socket.emit("login", {
|
||||
success: false,
|
||||
error: ["Guest logins are restricted to one per ",
|
||||
this.server.cfg["guest-login-delay"]
|
||||
self.server.cfg["guest-login-delay"]
|
||||
+ " seconds per IP. ",
|
||||
"This restriction does not apply to registered users."
|
||||
].join("")
|
||||
|
@ -567,149 +572,111 @@ User.prototype.login = function(name, pw, session) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Sorry bud, can't take that name
|
||||
if(Auth.isRegistered(name)) {
|
||||
this.socket.emit("login", {
|
||||
success: false,
|
||||
error: "That username is already taken"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
// YOUR ARGUMENT IS INVALID
|
||||
else if(!Auth.validateName(name)) {
|
||||
this.socket.emit("login", {
|
||||
success: false,
|
||||
error: "Invalid username. Usernames must be 1-20 characters long and consist only of alphanumeric characters and underscores"
|
||||
});
|
||||
}
|
||||
else {
|
||||
if(this.channel != null) {
|
||||
for(var i = 0; i < this.channel.users.length; i++) {
|
||||
if(this.channel.users[i].name == name) {
|
||||
this.socket.emit("login", {
|
||||
success: false,
|
||||
error: "That name is already taken on this channel"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastguestlogin[this.ip] = Date.now();
|
||||
this.rank = Rank.Guest;
|
||||
Logger.syslog.log(this.ip + " signed in as " + name);
|
||||
this.server.db.recordVisit(this.ip, name);
|
||||
this.name = name;
|
||||
this.loggedIn = false;
|
||||
this.socket.emit("login", {
|
||||
success: true,
|
||||
name: name
|
||||
});
|
||||
this.socket.emit("rank", this.rank);
|
||||
if(this.channel != null) {
|
||||
this.channel.logger.log(this.ip + " signed in as " + name);
|
||||
this.channel.broadcastNewUser(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
this.socket.emit("login", {
|
||||
if(!$util.isValidUserName(name)) {
|
||||
self.socket.emit("login", {
|
||||
success: false,
|
||||
error: e
|
||||
error: "Invalid username. Usernames must be 1-20 characters long and consist only of alphanumeric characters and underscores"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var row;
|
||||
if((row = Auth.login(name, pw, session))) {
|
||||
if(this.channel != null) {
|
||||
for(var i = 0; i < this.channel.users.length; i++) {
|
||||
if(this.channel.users[i].name == name) {
|
||||
this.channel.kick(this.channel.users[i], "Duplicate login");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.global_rank >= 255)
|
||||
ActionLog.record(this.ip, name, "login-success");
|
||||
this.loggedIn = true;
|
||||
this.socket.emit("login", {
|
||||
success: true,
|
||||
session: row.session_hash,
|
||||
name: name
|
||||
});
|
||||
Logger.syslog.log(this.ip + " logged in as " + name);
|
||||
this.server.db.recordVisit(this.ip, name);
|
||||
this.profile = {
|
||||
image: row.profile_image,
|
||||
text: row.profile_text
|
||||
};
|
||||
var chanrank = (this.channel != null) ? this.channel.getRank(name)
|
||||
: Rank.Guest;
|
||||
var rank = (chanrank > row.global_rank) ? chanrank
|
||||
: row.global_rank;
|
||||
this.rank = (this.rank > rank) ? this.rank : rank;
|
||||
this.global_rank = row.global_rank;
|
||||
this.socket.emit("rank", this.rank);
|
||||
this.name = name;
|
||||
if(this.channel != null) {
|
||||
this.channel.logger.log(this.ip + " logged in as " + name);
|
||||
this.channel.broadcastNewUser(this);
|
||||
}
|
||||
}
|
||||
// Wrong password
|
||||
else {
|
||||
ActionLog.record(this.ip, this.name, "login-failure");
|
||||
this.socket.emit("login", {
|
||||
success: false,
|
||||
error: "Invalid session"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
this.socket.emit("login", {
|
||||
success: false,
|
||||
error: e
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to register a user account
|
||||
User.prototype.register = function(name, pw) {
|
||||
if(pw == "") {
|
||||
// Sorry bud, password required
|
||||
this.socket.emit("register", {
|
||||
success: false,
|
||||
error: "You must provide a password"
|
||||
self.server.db.isUsernameTaken(name, function (err, taken) {
|
||||
if(err) {
|
||||
self.socket.emit("login", {
|
||||
success: false,
|
||||
error: "Internal error: " + err
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(taken) {
|
||||
self.socket.emit("login", {
|
||||
success: false,
|
||||
error: "That username is taken"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(self.channel != null) {
|
||||
for(var i = 0; i < self.channel.users.length; i++) {
|
||||
if(self.channel.users[i].name == name) {
|
||||
self.socket.emit("login", {
|
||||
success: false,
|
||||
error: "That name is already taken on self channel"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastguestlogin[self.ip] = Date.now();
|
||||
self.rank = Rank.Guest;
|
||||
Logger.syslog.log(self.ip + " signed in as " + name);
|
||||
self.server.db.recordVisit(self.ip, name);
|
||||
self.name = name;
|
||||
self.loggedIn = false;
|
||||
self.socket.emit("login", {
|
||||
success: true,
|
||||
name: name
|
||||
});
|
||||
self.socket.emit("rank", self.rank);
|
||||
if(self.channel != null) {
|
||||
self.channel.logger.log(self.ip + " signed in as " + name);
|
||||
self.channel.broadcastNewUser(self);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else if(Auth.isRegistered(name)) {
|
||||
this.socket.emit("register", {
|
||||
success: false,
|
||||
error: "That username is already taken"
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else if(!Auth.validateName(name)) {
|
||||
this.socket.emit("register", {
|
||||
success: false,
|
||||
error: "Invalid username. Usernames must be 1-20 characters long and consist only of alphanumeric characters and underscores"
|
||||
});
|
||||
}
|
||||
else if(Auth.register(name, pw)) {
|
||||
console.log(this.ip + " registered " + name);
|
||||
this.socket.emit("register", {
|
||||
success: true
|
||||
});
|
||||
this.login(name, pw);
|
||||
}
|
||||
else {
|
||||
this.socket.emit("register", {
|
||||
success: false,
|
||||
error: "[](/ppshrug) Registration Failed."
|
||||
} else {
|
||||
self.server.db.userLogin(name, pw, session, function (err, row) {
|
||||
if(err) {
|
||||
self.server.actionlog.record(self.ip, name, "login-failure");
|
||||
self.socket.emit("login", {
|
||||
success: false,
|
||||
error: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
if(self.channel != null) {
|
||||
for(var i = 0; i < self.channel.users.length; i++) {
|
||||
if(self.channel.users[i].name.toLowerCase() == name.toLowerCase()) {
|
||||
self.channel.kick(self.channel.users[i], "Duplicate login");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(self.global_rank >= 255)
|
||||
self.server.actionlog.record(self.ip, name, "login-success");
|
||||
self.loggedIn = true;
|
||||
self.socket.emit("login", {
|
||||
success: true,
|
||||
session: row.session_hash,
|
||||
name: name
|
||||
});
|
||||
Logger.syslog.log(self.ip + " logged in as " + name);
|
||||
self.server.db.recordVisit(self.ip, name);
|
||||
self.profile = {
|
||||
image: row.profile_image,
|
||||
text: row.profile_text
|
||||
};
|
||||
self.global_rank = row.global_rank;
|
||||
var afterRankLookup = function () {
|
||||
self.socket.emit("rank", self.rank);
|
||||
self.name = name;
|
||||
if(self.channel != null) {
|
||||
self.channel.logger.log(self.ip + " logged in as " +
|
||||
name);
|
||||
self.channel.broadcastNewUser(self);
|
||||
}
|
||||
};
|
||||
if(self.channel !== null) {
|
||||
self.channel.getRank(name, function (err, rank) {
|
||||
if(!err)
|
||||
self.rank = rank;
|
||||
else
|
||||
self.rank = self.global_rank;
|
||||
afterRankLookup();
|
||||
});
|
||||
} else {
|
||||
self.rank = self.global_rank;
|
||||
afterRankLookup();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
29
utilities.js
Normal file
29
utilities.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
module.exports = {
|
||||
isValidChannelName: function (name) {
|
||||
return name.match(/^[\w-_]{1,30}$/);
|
||||
},
|
||||
|
||||
isValidUserName: function (name) {
|
||||
return name.match(/^[\w-_]{1,20}$/);
|
||||
},
|
||||
|
||||
randomSalt: function (length) {
|
||||
var chars = "abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
+ "0123456789!@#$%^&*_+=~";
|
||||
var salt = [];
|
||||
for(var i = 0; i < length; i++) {
|
||||
salt.push(chars[parseInt(Math.random()*chars.length)]);
|
||||
}
|
||||
return salt.join('');
|
||||
},
|
||||
|
||||
maskIP: function (ip) {
|
||||
if(ip.match(/^\d+\.\d+\.\d+\.\d+$/)) {
|
||||
// standard 32 bit IP
|
||||
return ip.replace(/\d+\.\d+\.(\d+\.\d+)/, "x.x.$1");
|
||||
} else if(ip.match(/^\d+\.\d+\.\d+/)) {
|
||||
// /24 range
|
||||
return ip.replace(/\d+\.\d+\.(\d+)/, "x.x.$1.*");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -9,19 +9,44 @@ 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
So, it turns out that $.post causes Firefox to use a GET request
|
||||
on cross-site requests. What the hell? I'd understand if they just
|
||||
made it error instead, but why give me chicken tenders if I ordered a
|
||||
cheeseburger and act like everything's peachy?
|
||||
*/
|
||||
function postJSON(url, data, callback) {
|
||||
$.ajax(url, {
|
||||
method: "POST",
|
||||
crossDomain: true,
|
||||
data: data,
|
||||
success: function (data) {
|
||||
try {
|
||||
data = data.substring(data.indexOf("{"));
|
||||
data = data.substring(0, data.lastIndexOf("}") + 1);
|
||||
data = JSON.parse(data);
|
||||
callback(data);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
dataType: "text"
|
||||
});
|
||||
}
|
||||
|
||||
var uname = readCookie("cytube_uname") || "";
|
||||
var session = readCookie("cytube_session") || "";
|
||||
var api = WEB_URL + "/api/json/";
|
||||
var loggedin = false;
|
||||
|
||||
if(uname && session) {
|
||||
var loginstr = "name=" + encodeURIComponent(uname)
|
||||
+ "&session=" + session;
|
||||
var url = api + "login?" + loginstr + "&callback=?";
|
||||
$.getJSON(url, function(data) {
|
||||
if(data.success) {
|
||||
var data = {
|
||||
name: uname,
|
||||
session: session
|
||||
};
|
||||
postJSON(WEB_URL + "/api/login?callback=?", data, function (data) {
|
||||
console.log(data);
|
||||
if(data.success)
|
||||
onLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -57,7 +82,8 @@ $("#email").click(makeTabCallback("#email", "#changeemailpane"));
|
|||
$("#profile").click(makeTabCallback("#profile", "#profilepane"));
|
||||
$("#profile").click(function() {
|
||||
if(uname != "") {
|
||||
$.getJSON(api + "getprofile?name=" + encodeURIComponent(uname) + "&callback=?", function(data) {
|
||||
$.getJSON(WEB_URL+"/api/users/"+uname+"/profile?callback=?",
|
||||
function (data) {
|
||||
if(data.success) {
|
||||
$("#profiletext").val(data.profile_text);
|
||||
$("#profileimg").val(data.profile_image);
|
||||
|
@ -82,8 +108,10 @@ $("#channels").click(function () {
|
|||
return;
|
||||
}
|
||||
|
||||
$.getJSON(api + "listuserchannels?name=" + encodeURIComponent(uname) +
|
||||
"&session=" + session + "&callback=?", function(data) {
|
||||
var auth = "name=" + encodeURIComponent(uname) + "&session=" +
|
||||
encodeURIComponent(session);
|
||||
$.getJSON(WEB_URL+"/api/account/mychannels?"+auth+"&callback=?",
|
||||
function (data) {
|
||||
$("#channellist tbody").remove();
|
||||
data.channels.forEach(function (chan) {
|
||||
var tr = $("<tr/>").appendTo($("#channellist"));
|
||||
|
@ -134,12 +162,12 @@ $("#registerbtn").click(function() {
|
|||
}
|
||||
|
||||
// Input valid, try registering
|
||||
var url = api + "register?" + [
|
||||
"name=" + encodeURIComponent(name),
|
||||
"pw=" + encodeURIComponent(pw)
|
||||
].join("&") + "&callback=?";
|
||||
|
||||
$.getJSON(url, function(data) {
|
||||
var data = {
|
||||
name: name,
|
||||
pw: pw
|
||||
};
|
||||
|
||||
postJSON(WEB_URL + "/api/register?callback=?", data, function (data) {
|
||||
if(data.success) {
|
||||
uname = name;
|
||||
session = data.session;
|
||||
|
@ -170,10 +198,12 @@ $("#loginbtn").click(function() {
|
|||
return;
|
||||
}
|
||||
uname = $("#loginusername").val();
|
||||
var loginstr = "name=" + encodeURIComponent(uname)
|
||||
+ "&pw=" + encodeURIComponent($("#loginpw").val());
|
||||
var url = api + "login?" + loginstr + "&callback=?";
|
||||
$.getJSON(url, function(data) {
|
||||
var data = {
|
||||
name: uname,
|
||||
pw: $("#loginpw").val()
|
||||
};
|
||||
|
||||
postJSON(WEB_URL+"/api/login?callback=?", data, function(data) {
|
||||
if(data.success) {
|
||||
session = data.session;
|
||||
onLogin();
|
||||
|
@ -230,12 +260,13 @@ $("#cpwbtn").click(function() {
|
|||
}
|
||||
|
||||
// Input valid, try changing password
|
||||
var url = api + "changepass?" + [
|
||||
"name=" + encodeURIComponent(name),
|
||||
"oldpw=" + encodeURIComponent(oldpw),
|
||||
"newpw=" + encodeURIComponent(newpw)
|
||||
].join("&") + "&callback=?";
|
||||
$.getJSON(url, function(data) {
|
||||
var data = {
|
||||
name: name,
|
||||
oldpw: oldpw,
|
||||
newpw: newpw
|
||||
};
|
||||
postJSON(WEB_URL + "/api/account/passwordchange?callback=?", data,
|
||||
function (data) {
|
||||
if(data.success) {
|
||||
$("<div/>").addClass("alert alert-success")
|
||||
.text("Password changed.")
|
||||
|
@ -266,7 +297,7 @@ $("#cebtn").click(function() {
|
|||
return;
|
||||
}
|
||||
|
||||
if(!email.match(/^[a-z0-9_\.]+@[a-z0-9_\.]+[a-z]+$/)) {
|
||||
if(!email.match(/^[\w_\.]+@[\w_\.]+[a-zA-Z]+$/)) {
|
||||
$("<div/>").addClass("alert alert-error")
|
||||
.text("Invalid email")
|
||||
.insertAfter($("#ceemail").parent().parent());
|
||||
|
@ -282,12 +313,13 @@ $("#cebtn").click(function() {
|
|||
return;
|
||||
}
|
||||
|
||||
var url = api + "setemail?" + [
|
||||
"name=" + encodeURIComponent(name),
|
||||
"pw=" + encodeURIComponent(pw),
|
||||
"email=" + encodeURIComponent(email)
|
||||
].join("&") + "&callback=?";
|
||||
$.getJSON(url, function(data) {
|
||||
var data = {
|
||||
name: name,
|
||||
pw: pw,
|
||||
email: email
|
||||
};
|
||||
postJSON(WEB_URL + "/api/account/email?callback=?", data,
|
||||
function (data) {
|
||||
if(data.success) {
|
||||
$("<div/>").addClass("alert alert-success")
|
||||
.text("Email updated")
|
||||
|
@ -312,11 +344,12 @@ $("#rpbtn").click(function() {
|
|||
var name = $("#rpusername").val();
|
||||
var email = $("#rpemail").val();
|
||||
|
||||
var url = api + "resetpass?" + [
|
||||
"name=" + encodeURIComponent(name),
|
||||
"email=" + encodeURIComponent(email)
|
||||
].join("&") + "&callback=?";
|
||||
$.getJSON(url, function(data) {
|
||||
var data = {
|
||||
name: name,
|
||||
email: email
|
||||
};
|
||||
postJSON(WEB_URL + "/api/account/passwordreset?callback=?", data,
|
||||
function (data) {
|
||||
$("#rpbtn").text("Send Reset");
|
||||
if(data.success) {
|
||||
$("<div/>").addClass("alert alert-success")
|
||||
|
@ -336,20 +369,16 @@ $("#profilesave").click(function() {
|
|||
$("#profilepane").find(".alert-error").remove();
|
||||
$("#profilepane").find(".alert-success").remove();
|
||||
var img = $("#profileimg").val();
|
||||
/*
|
||||
img = escape(img).replace(/\//g, "%2F")
|
||||
.replace(/&/g, "%26")
|
||||
.replace(/=/g, "%3D")
|
||||
.replace(/\?/g, "%3F");
|
||||
*/
|
||||
var url = api + "setprofile?" + [
|
||||
"name=" + encodeURIComponent(uname),
|
||||
"session=" + session,
|
||||
"profile_image=" + encodeURIComponent(img),
|
||||
"profile_text=" + encodeURIComponent($("#profiletext").val())
|
||||
].join("&") + "&callback=?";
|
||||
var text = $("#profiletext").val();
|
||||
var data = {
|
||||
name: uname,
|
||||
session: session,
|
||||
profile_image: img,
|
||||
profile_text: text
|
||||
};
|
||||
|
||||
$.getJSON(url, function(data) {
|
||||
postJSON(WEB_URL+"/api/account/profile?callback=?", data,
|
||||
function (data) {
|
||||
if(data.success) {
|
||||
$("<div/>").addClass("alert alert-success")
|
||||
.text("Profile updated.")
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
var BASE = WEB_URL + "/api/json/";
|
||||
var AUTH = "";
|
||||
var NO_WEBSOCKETS = false;
|
||||
|
||||
|
@ -156,20 +155,21 @@ function reverseLog() {
|
|||
$("#log_reverse").click(reverseLog);
|
||||
|
||||
function getSyslog() {
|
||||
$.ajax(WEB_URL+"/api/plain/readlog?type=sys&"+AUTH).done(function(data) {
|
||||
$.ajax(WEB_URL+"/api/logging/syslog?"+AUTH).done(function(data) {
|
||||
$("#log").text(data);
|
||||
});
|
||||
}
|
||||
$("#syslog").click(getSyslog);
|
||||
function getErrlog() {
|
||||
$.ajax(WEB_URL+"/api/plain/readlog?type=err&"+AUTH).done(function(data) {
|
||||
$.ajax(WEB_URL+"/api/logging/errorlog?"+AUTH).done(function(data) {
|
||||
$("#log").text(data);
|
||||
});
|
||||
}
|
||||
$("#errlog").click(getErrlog);
|
||||
function getActionLog() {
|
||||
var types = "&actions=" + $("#actionlog_filter").val().join(",");
|
||||
$.getJSON(WEB_URL+"/api/json/readactionlog?"+AUTH+types+"&callback=?").done(function(entries) {
|
||||
$.getJSON(WEB_URL+"/api/logging/actionlog?"+AUTH+types+"&callback=?")
|
||||
.done(function(entries) {
|
||||
var tbl = $("#actionlog table");
|
||||
entries.forEach(function (e) {
|
||||
e.time = parseInt(e.time);
|
||||
|
@ -217,7 +217,8 @@ function getActionLog() {
|
|||
}
|
||||
function getChanlog() {
|
||||
var chan = $("#channame").val();
|
||||
$.ajax(WEB_URL+"/api/plain/readlog?type=channel&channel="+chan+"&"+AUTH).done(function(data) {
|
||||
$.ajax(WEB_URL+"/api/logging/channels/"+chan+"?"+AUTH)
|
||||
.done(function(data) {
|
||||
$("#log").text(data);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||
Callbacks = {
|
||||
|
||||
error: function (reason) {
|
||||
// Don't show the error for when the server goes down
|
||||
if(reason && reason.returnValue === true)
|
||||
return;
|
||||
|
||||
var d = $("<div/>").addClass("alert alert-error span12")
|
||||
.appendTo($("#announcements"));
|
||||
$("<h3/>").text("Uh-oh!").appendTo(d);
|
||||
|
@ -74,6 +78,33 @@ Callbacks = {
|
|||
alert(data.msg);
|
||||
},
|
||||
|
||||
costanza: function (data) {
|
||||
hidePlayer();
|
||||
$("#costanza-modal").modal("hide");
|
||||
var modal = $("<div/>").addClass("modal hide fade")
|
||||
.attr("id", "costanza-modal")
|
||||
.appendTo($("body"));
|
||||
|
||||
|
||||
var body = $("<div/>").addClass("modal-body").appendTo(modal);
|
||||
$("<button/>").addClass("close")
|
||||
.attr("data-dismiss", "modal")
|
||||
.attr("data-hidden", "true")
|
||||
.html("×")
|
||||
.appendTo(body);
|
||||
$("<img/>").attr("src", "http://i0.kym-cdn.com/entries/icons/original/000/005/498/1300044776986.jpg")
|
||||
.appendTo(body);
|
||||
|
||||
$("<strong/>").text(data.msg).appendTo(body);
|
||||
|
||||
modal.on("hidden", function () {
|
||||
modal.remove();
|
||||
unhidePlayer();
|
||||
});
|
||||
|
||||
modal.modal();
|
||||
},
|
||||
|
||||
announcement: function(data) {
|
||||
$("#announcements").html("");
|
||||
makeAlert(data.title, data.text)
|
||||
|
@ -572,7 +603,7 @@ Callbacks = {
|
|||
|
||||
login: function(data) {
|
||||
if(!data.success) {
|
||||
if(data.error != "Invalid session") {
|
||||
if(data.error != "Session expired") {
|
||||
alert(data.error);
|
||||
}
|
||||
}
|
||||
|
@ -696,6 +727,7 @@ Callbacks = {
|
|||
|
||||
/* REGION Playlist Stuff */
|
||||
playlist: function(data) {
|
||||
PL_QUEUED_ACTIONS = [];
|
||||
// Clear the playlist first
|
||||
var q = $("#queue");
|
||||
q.html("");
|
||||
|
|
|
@ -1,200 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CyTube</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="A free, open source synchtube replacement">
|
||||
<meta name="author" content="Calvin 'calzoneman' Montgomery">
|
||||
|
||||
<link href="./assets/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="./assets/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
<link href="./assets/css/ytsync.css" rel="stylesheet" id="defaultcss">
|
||||
<link href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 60px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<!-- begin navbar -->
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="brand" href="index.html">CyTube</a>
|
||||
<ul class="nav">
|
||||
<li class="active"><a href="index.html">Home</a></li>
|
||||
<li><a href="help.html">Help</a></li>
|
||||
<li><a href="account.html">Account</a></li>
|
||||
<li><a href="javascript:void(0)" id="optlink">Options</a></li>
|
||||
</ul>
|
||||
<div class="navbar-form pull-right" id="loginform">
|
||||
<input type="text" id="guestname" placeholder="Name">
|
||||
<button class="btn" id="guestlogin">Guest Login</button>
|
||||
<button class="btn" id="login">Login/Register</button>
|
||||
</div>
|
||||
<div class="navbar-form pull-right" id="logoutform" style="display: none;">
|
||||
<span id="welcome"></span>
|
||||
<button class="btn" id="logout">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end navbar -->
|
||||
<!-- begin main page -->
|
||||
<div class="container" id="mainpage">
|
||||
<!-- top row (MOTD, drink count) -->
|
||||
<div class="row-fluid" id="toprow">
|
||||
<div class="well span12" id="motd">
|
||||
</div>
|
||||
<div class="span12" id="drinkbar">
|
||||
<h1 id="drinkcount"></h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- announcement area -->
|
||||
<div class="row-fluid" id="announcements">
|
||||
</div>
|
||||
<!-- main row -->
|
||||
<div class="row" id="main">
|
||||
<!-- chat container -->
|
||||
<div class="span5" id="chatwrap">
|
||||
<!-- user count -->
|
||||
<div id="usercountwrap" class="pointer">
|
||||
<i class="icon-chevron-up pull-left" id="userlisttoggle" title="Show/Hide Userlist"></i>
|
||||
<p id="usercount">Not connected</p>
|
||||
</div>
|
||||
<!-- userlist -->
|
||||
<div id="userlist">
|
||||
</div>
|
||||
<!-- message buffer -->
|
||||
<div id="messagebuffer">
|
||||
</div>
|
||||
<!-- chat input -->
|
||||
<input type="text" id="chatline" maxlength="240" class="span5">
|
||||
</div>
|
||||
<!-- video container -->
|
||||
<div class="span7" id="videowrap">
|
||||
<!-- current video display -->
|
||||
<p id="currenttitle">Nothing playing</p>
|
||||
<!-- video frame -->
|
||||
<div id="ytapiplayer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- playlist row -->
|
||||
<div class="row" id="playlistrow">
|
||||
<!-- left pane - Library + user playlists -->
|
||||
<div class="span5" id="leftpane-outer">
|
||||
<div class="row-fluid" id="leftpane-inner">
|
||||
<!-- poll container -->
|
||||
<div class="span12" id="pollwrap">
|
||||
<!-- new poll controls -->
|
||||
<button class="btn btn-primary btn-small" id="newpollbtn">New Poll</button>
|
||||
</div>
|
||||
<!-- library search -->
|
||||
<div class="span12 pointer" id="librarytoggle">
|
||||
<i class="icon-chevron-down pull-left"></i>
|
||||
<p>Show Library</p>
|
||||
</div>
|
||||
<div id="librarywrap">
|
||||
<div class="span7" id="querywrap">
|
||||
<input type="text" id="library_query" class="input-block-level" placeholder="Search Query">
|
||||
</div>
|
||||
<div class="span5 btn-group" id="searchbtns">
|
||||
<button class="btn" id="library_search">Library</button>
|
||||
<button class="btn" id="youtube_search">YouTube</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- user playlists -->
|
||||
<div class="span12 pointer" id="userpltoggle">
|
||||
<i class="icon-chevron-down pull-left"></i>
|
||||
<p>Show Playlist Manager</p>
|
||||
</div>
|
||||
<div id="userplaylistwrap">
|
||||
<div class="span7">
|
||||
<input type="text" id="userpl_name" class="input-block-level" placeholder="Playlist Name">
|
||||
</div>
|
||||
<div class="span5">
|
||||
<button class="btn btn-block" id="userpl_save">Save Playlist</button>
|
||||
</div>
|
||||
<ul class="span12" id="userpl_list">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- right pane - channel playlist -->
|
||||
<div class="span7" id="rightpane-outer">
|
||||
<div class="row-fluid" id="rightpane-inner">
|
||||
<!-- account for left pane having the poll buffer -->
|
||||
<div class="span12" id="queue_align"></div>
|
||||
<!-- playlist controls -->
|
||||
<div class="span12 pointer" id="playlisttoggle">
|
||||
<i class="icon-chevron-down pull-left"></i>
|
||||
<p>Show Playlist Controls</p>
|
||||
</div>
|
||||
<div id="playlist_controls">
|
||||
<div class="span8">
|
||||
<input type="text" id="mediaurl" class="input-block-level" placeholder="Media URL">
|
||||
</div>
|
||||
<div class="span4 btn-group">
|
||||
<button class="btn" id="queue_next">Next</button>
|
||||
<button class="btn" id="queue_end">End</button>
|
||||
</div>
|
||||
<div id="extended_controls" class="span12">
|
||||
<button class="btn btn-danger btn-block" id="qlockbtn">Unlock Queue</button>
|
||||
<button class="btn btn-block" id="getplaylist">Get Playlist URLs</button>
|
||||
<button class="btn btn-block" id="clearplaylist">Clear Playlist</button>
|
||||
<button class="btn btn-block" id="shuffleplaylist">Shuffle Playlist</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- video queue -->
|
||||
<ul class="span12 videolist" id="queue">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="push"></div>
|
||||
<div id="sitefooter">
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<p class="muted">
|
||||
CyTube Software Copyright © 2013 Calvin Montgomery · Available for free on <a href="http://github.com/calzoneman/sync">GitHub</a> ·
|
||||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5Y7PUVVGVSEWG&lc=US&item_name=CyTube¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted">Donate</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="./assets/js/jquery.js"></script>
|
||||
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
|
||||
<!-- My Javascript -->
|
||||
<script src="./assets/js/data.js"></script>
|
||||
<script src="./assets/js/util.js"></script>
|
||||
<script src="./assets/js/ui.js"></script>
|
||||
<script src="./assets/js/callbacks.js"></script>
|
||||
<!--
|
||||
<script src="./assets/js/iourl.js"></script>
|
||||
<script src="./assets/js/notwebsocket.js"></script>
|
||||
<script src="./assets/js/media.js"></script>
|
||||
<script src="./assets/js/functions.js"></script>
|
||||
<script src="./assets/js/client.js"></script>
|
||||
<script src="./assets/js/callbacks.js"></script>
|
||||
-->
|
||||
<!-- APIs -->
|
||||
<!--
|
||||
<script src="http://api.dmcdn.net/all.js"></script>
|
||||
<script src="http://jwpsrv.com/library/QouFCLBMEeKC+CIACpYGxA.js"></script>
|
||||
<script src="./assets/js/sc.js"></script>
|
||||
<script src="./assets/js/froogaloop.min.js"></script>
|
||||
<script src="./assets/js/swf.js"></script>
|
||||
-->
|
||||
<!-- Third party -->
|
||||
<script src="./assets/js/bootstrap.js"></script>
|
||||
<script src="./assets/js/bootstrap-transition.js"></script>
|
||||
<script src="./assets/js/bootstrap-modal.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -247,12 +247,12 @@
|
|||
<script src="./assets/js/ui.js"></script>
|
||||
<script src="./assets/js/callbacks.js"></script>
|
||||
<!-- APIs -->
|
||||
<script src="http://www.youtube.com/iframe_api"></script>
|
||||
<script src="http://api.dmcdn.net/all.js"></script>
|
||||
<script src="http://jwpsrv.com/library/QouFCLBMEeKC+CIACpYGxA.js"></script>
|
||||
<script src="./assets/js/sc.js"></script>
|
||||
<script src="./assets/js/froogaloop.min.js"></script>
|
||||
<script src="./assets/js/swf.js"></script>
|
||||
<script defer src="http://www.youtube.com/iframe_api"></script>
|
||||
<script defer src="http://api.dmcdn.net/all.js"></script>
|
||||
<script defer src="http://jwpsrv.com/library/QouFCLBMEeKC+CIACpYGxA.js"></script>
|
||||
<script defer src="./assets/js/sc.js"></script>
|
||||
<script defer src="./assets/js/froogaloop.min.js"></script>
|
||||
<script defer src="./assets/js/swf.js"></script>
|
||||
<!-- Third party -->
|
||||
<script src="./assets/js/bootstrap.js"></script>
|
||||
<script src="./assets/js/bootstrap-transition.js"></script>
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CyTube</title>
|
||||
<link href="assets/css/bootstrap.css" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
#channeldata td, #channeldata th {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table id="channeldata" class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Channel</th>
|
||||
<th>Connected</th>
|
||||
<th>Playing</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<script src="assets/js/jquery.js" type="text/javascript"></script>
|
||||
<script src="assets/js/iourl.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
var p = document.location + "";
|
||||
var host = p.replace("http://", "");
|
||||
if(host.indexOf("/") != -1) {
|
||||
host = host.substring(0, host.indexOf("/"));
|
||||
}
|
||||
if(p.indexOf("?") != -1) {
|
||||
p = p.substring(p.indexOf("?")+1);
|
||||
}
|
||||
$.getJSON(IO_URL+"/api/json/channeldata?"+p+"&callback=?", function(data) {
|
||||
if(data.error) {
|
||||
return;
|
||||
}
|
||||
$("#channeldata").find("tbody").remove();
|
||||
for(var i = 0; i < data.length; i++) {
|
||||
var d = data[i];
|
||||
var tr = $("<tr/>").appendTo($("#channeldata"));
|
||||
var name = $("<td/>").appendTo(tr);
|
||||
$("<a/>").attr("href", host + "/r/" + d.name)
|
||||
.text(d.name)
|
||||
.appendTo(name);
|
||||
$("<td/>").text(d.usercount || 0).appendTo(tr);
|
||||
$("<td/>").text(d.title || "-").appendTo(tr);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -130,7 +130,8 @@
|
|||
return entry;
|
||||
}
|
||||
function refresh() {
|
||||
$.getJSON(WEB_URL+"/api/json/listloaded?filter=public&callback=?", function(data) {
|
||||
$.getJSON(WEB_URL+"/api/allchannels/public?callback=?",
|
||||
function(data) {
|
||||
$("#channeldata").find("tbody").remove();
|
||||
data.sort(function(a, b) {
|
||||
var x = a.usercount;
|
||||
|
|
|
@ -37,6 +37,30 @@
|
|||
<script src="assets/js/jquery.js" type="text/javascript"></script>
|
||||
<script src="assets/js/iourl.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*
|
||||
So, it turns out that $.post causes Firefox to use a GET request
|
||||
on cross-site requests. What the hell? I'd understand if they just
|
||||
made it error instead, but why give me chicken tenders if I ordered a
|
||||
cheeseburger and act like everything's peachy?
|
||||
*/
|
||||
function postJSON(url, data, callback) {
|
||||
$.ajax(url, {
|
||||
method: "POST",
|
||||
crossDomain: true,
|
||||
data: data,
|
||||
success: function (data) {
|
||||
try {
|
||||
data = data.substring(data.indexOf("{"));
|
||||
data = data.substring(0, data.lastIndexOf("}") + 1);
|
||||
data = JSON.parse(data);
|
||||
callback(data);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
dataType: "text"
|
||||
});
|
||||
}
|
||||
function readCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(";");
|
||||
|
@ -66,9 +90,11 @@
|
|||
window.addEventListener("message", respond, false);
|
||||
|
||||
$("#login").click(function() {
|
||||
var u = encodeURIComponent($("#username").val());
|
||||
var p = encodeURIComponent($("#pw").val());
|
||||
$.getJSON(WEB_URL+"/api/json/login?name="+u+"&pw="+p+"&callback=?", function(data) {
|
||||
var data = {
|
||||
name: $("#username").val(),
|
||||
pw: $("#pw").val()
|
||||
};
|
||||
postJSON(WEB_URL+"/api/login", data, function (data) {
|
||||
data.uname = $("#username").val();
|
||||
source.postMessage("cytube-login:"+JSON.stringify(data), document.location);
|
||||
});
|
||||
|
|
|
@ -71,7 +71,8 @@
|
|||
hash = loc.substring(loc.indexOf("?") + 1);
|
||||
})();
|
||||
|
||||
var url = WEB_URL+"/api/json/recoverpw?hash="+hash+"&callback=?";
|
||||
var url = WEB_URL+"/api/account/passwordrecover?hash="+hash+
|
||||
"&callback=?";
|
||||
$.getJSON(url, function(data) {
|
||||
if(data.success) {
|
||||
$("<div/>").addClass("alert alert-success")
|
||||
|
|
Loading…
Reference in a new issue