2014-01-06 01:42:09 +00:00
|
|
|
var Logger = require("./logger");
|
2013-10-11 21:31:40 +00:00
|
|
|
var Server = require("./server");
|
2014-01-06 01:42:09 +00:00
|
|
|
var util = require("./utilities");
|
|
|
|
var MakeEmitter = require("./emitter");
|
2014-01-06 15:55:12 +00:00
|
|
|
var db = require("./database");
|
|
|
|
var InfoGetter = require("./get-info");
|
2014-01-22 23:11:26 +00:00
|
|
|
var Config = require("./config");
|
2014-01-30 03:50:45 +00:00
|
|
|
var ACP = require("./acp");
|
2014-01-06 01:42:09 +00:00
|
|
|
|
|
|
|
function User(socket) {
|
|
|
|
var self = this;
|
|
|
|
MakeEmitter(self);
|
|
|
|
self.socket = socket;
|
|
|
|
self.ip = socket._ip;
|
|
|
|
self.loggedIn = false;
|
|
|
|
self.loggingIn = false;
|
|
|
|
self.rank = -1;
|
|
|
|
self.global_rank = -1;
|
|
|
|
self.channel = null;
|
|
|
|
self.name = "";
|
|
|
|
self.canonicalName = "";
|
|
|
|
self.profile = {
|
2013-05-13 00:41:02 +00:00
|
|
|
image: "",
|
|
|
|
text: ""
|
|
|
|
};
|
2014-01-06 01:42:09 +00:00
|
|
|
self.meta = {
|
|
|
|
afk: false,
|
|
|
|
muted: false,
|
|
|
|
smuted: false,
|
|
|
|
aliases: []
|
|
|
|
};
|
|
|
|
self.queueLimiter = util.newRateLimiter();
|
|
|
|
self.chatLimiter = util.newRateLimiter();
|
|
|
|
self.awaytimer = false;
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
self.socket.once("initChannelCallbacks", function () {
|
|
|
|
self.initChannelCallbacks();
|
|
|
|
});
|
|
|
|
|
2014-02-02 18:41:41 +00:00
|
|
|
self.socket.once("initUserPLCallbacks", function () {
|
|
|
|
self.initUserPLCallbacks();
|
|
|
|
});
|
|
|
|
|
2014-01-30 03:50:45 +00:00
|
|
|
self.socket.once("initACP", function () {
|
|
|
|
self.whenLoggedIn(function () {
|
|
|
|
if (self.global_rank >= 255) {
|
|
|
|
ACP.init(self);
|
|
|
|
} else {
|
|
|
|
self.kick("Attempted initACP from non privileged user. This incident " +
|
|
|
|
"will be reported.");
|
|
|
|
Logger.eventlog.log("[acp] Attempted initACP from socket client " +
|
|
|
|
self.name + "@" + self.ip);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-01-06 15:55:12 +00:00
|
|
|
self.socket.on("login", function (data) {
|
|
|
|
data = (typeof data === "object") ? data : {};
|
|
|
|
|
|
|
|
var name = data.name;
|
|
|
|
if (typeof name !== "string") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var pw = data.pw || "";
|
|
|
|
if (typeof pw !== "string") {
|
|
|
|
pw = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pw) {
|
|
|
|
self.guestLogin(name);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
var announcement = Server.getServer().announcement;
|
|
|
|
if (announcement != null) {
|
|
|
|
self.socket.emit("announcement", announcement);
|
2013-03-20 18:35:06 +00:00
|
|
|
}
|
2014-01-26 06:13:33 +00:00
|
|
|
|
|
|
|
self.on("login", function () {
|
|
|
|
db.recordVisit(self.ip, self.name);
|
|
|
|
db.users.getProfile(self.name, function (err, profile) {
|
|
|
|
if (!err) {
|
|
|
|
self.profile = profile;
|
|
|
|
if (self.inChannel()) {
|
|
|
|
self.channel.sendUserProfile(self.channel.users, self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2014-01-31 05:02:58 +00:00
|
|
|
|
|
|
|
if (self.global_rank >= 255) {
|
|
|
|
self.initAdminCallbacks();
|
|
|
|
}
|
2014-01-26 06:13:33 +00:00
|
|
|
});
|
2014-01-06 01:42:09 +00:00
|
|
|
}
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
/**
|
|
|
|
* Checks whether the user is in a valid channel
|
|
|
|
*/
|
2013-09-18 23:27:42 +00:00
|
|
|
User.prototype.inChannel = function () {
|
2014-01-06 01:42:09 +00:00
|
|
|
return this.channel != null && !this.channel.dead;
|
2013-11-25 22:20:15 +00:00
|
|
|
};
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
/**
|
|
|
|
* Changes a user's AFK status, updating the channel voteskip if necessary
|
|
|
|
*/
|
2013-07-28 21:58:22 +00:00
|
|
|
User.prototype.setAFK = function (afk) {
|
2014-01-06 01:42:09 +00:00
|
|
|
if (!this.inChannel()) {
|
2013-07-28 21:58:22 +00:00
|
|
|
return;
|
2014-01-06 01:42:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.meta.afk === afk) {
|
2013-08-01 19:12:57 +00:00
|
|
|
return;
|
2014-01-06 01:42:09 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 02:18:00 +00:00
|
|
|
this.meta.afk = afk;
|
|
|
|
|
2013-07-28 21:58:22 +00:00
|
|
|
var chan = this.channel;
|
2013-09-26 18:29:36 +00:00
|
|
|
if (afk) {
|
2014-01-06 01:42:09 +00:00
|
|
|
if (chan.voteskip) {
|
2013-08-07 17:11:58 +00:00
|
|
|
chan.voteskip.unvote(this.ip);
|
2014-01-06 01:42:09 +00:00
|
|
|
}
|
2013-09-12 03:16:56 +00:00
|
|
|
} else {
|
2013-08-01 13:39:10 +00:00
|
|
|
this.autoAFK();
|
2013-07-28 21:58:22 +00:00
|
|
|
}
|
2014-01-06 01:42:09 +00:00
|
|
|
|
2013-08-01 13:39:10 +00:00
|
|
|
chan.checkVoteskipPass();
|
2013-08-01 19:12:57 +00:00
|
|
|
chan.sendAll("setAFK", {
|
|
|
|
name: this.name,
|
|
|
|
afk: afk
|
|
|
|
});
|
2013-09-26 18:29:36 +00:00
|
|
|
};
|
2013-07-28 21:58:22 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
/**
|
|
|
|
* Sets a timer to automatically mark the user as AFK after
|
|
|
|
* a period of inactivity
|
|
|
|
*/
|
2013-07-28 21:58:22 +00:00
|
|
|
User.prototype.autoAFK = function () {
|
2013-09-26 18:29:36 +00:00
|
|
|
var self = this;
|
2014-01-06 01:42:09 +00:00
|
|
|
if (self.awaytimer) {
|
2013-09-26 18:29:36 +00:00
|
|
|
clearTimeout(self.awaytimer);
|
2014-01-06 01:42:09 +00:00
|
|
|
}
|
2013-07-28 21:58:22 +00:00
|
|
|
|
2013-11-30 03:09:19 +00:00
|
|
|
if (!self.inChannel()) {
|
2013-07-28 21:58:22 +00:00
|
|
|
return;
|
2013-11-30 03:09:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var timeout = parseFloat(self.channel.opts.afk_timeout);
|
2014-01-06 01:42:09 +00:00
|
|
|
if (isNaN(timeout) || timeout <= 0) {
|
2013-11-30 03:09:19 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-07-28 21:58:22 +00:00
|
|
|
|
2013-09-26 18:29:36 +00:00
|
|
|
self.awaytimer = setTimeout(function () {
|
|
|
|
self.setAFK(true);
|
2013-11-30 03:09:19 +00:00
|
|
|
}, timeout * 1000);
|
2013-09-26 18:29:36 +00:00
|
|
|
};
|
2013-07-28 21:58:22 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
/**
|
|
|
|
* Sends a kick message and disconnects the user
|
|
|
|
*/
|
2013-10-12 23:59:50 +00:00
|
|
|
User.prototype.kick = function (reason) {
|
|
|
|
this.socket.emit("kick", { reason: reason });
|
|
|
|
this.socket.disconnect(true);
|
|
|
|
};
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
/**
|
|
|
|
* Initializes socket message callbacks for a channel user
|
|
|
|
*/
|
|
|
|
User.prototype.initChannelCallbacks = function () {
|
2013-08-18 17:21:34 +00:00
|
|
|
var self = this;
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
// Verifies datatype before calling a function
|
|
|
|
// Passes a default value if the typecheck fails
|
|
|
|
var typecheck = function (type, def, fn) {
|
|
|
|
return function (data) {
|
|
|
|
if (typeof data !== type) {
|
|
|
|
fn(def);
|
|
|
|
} else {
|
|
|
|
fn(data);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
2013-09-08 04:40:25 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
// Verify that the user is in a channel, and that the passed data is an Object
|
|
|
|
var wrapTypecheck = function (msg, fn) {
|
|
|
|
self.socket.on(msg, typecheck("object", {}, function (data) {
|
|
|
|
if (self.inChannel()) {
|
|
|
|
fn(data);
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
};
|
2013-09-08 04:40:25 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
// Verify that the user is in a channel, but don't typecheck the data
|
|
|
|
var wrap = function (msg, fn) {
|
|
|
|
self.socket.on(msg, function (data) {
|
|
|
|
if (self.inChannel()) {
|
|
|
|
fn(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
self.socket.on("disconnect", function () {
|
|
|
|
if (self.awaytimer) {
|
|
|
|
clearTimeout(self.awaytimer);
|
2013-02-16 05:02:42 +00:00
|
|
|
}
|
|
|
|
|
2013-09-26 18:29:36 +00:00
|
|
|
if (self.inChannel()) {
|
2014-01-06 15:55:12 +00:00
|
|
|
self.channel.part(self);
|
2013-06-05 15:40:59 +00:00
|
|
|
}
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-05 15:40:59 +00:00
|
|
|
|
2014-01-26 03:29:56 +00:00
|
|
|
self.socket.once("joinChannel", typecheck("object", {}, function (data) {
|
2014-01-25 23:44:32 +00:00
|
|
|
if (self.inChannel()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
if (typeof data.name !== "string") {
|
|
|
|
return;
|
2013-05-21 16:17:01 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
if (!util.isValidChannelName(data.name)) {
|
|
|
|
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 _"
|
|
|
|
});
|
|
|
|
self.kick("Invalid channel name");
|
|
|
|
return;
|
2013-02-16 05:02:42 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
data.name = data.name.toLowerCase();
|
|
|
|
var chan = Server.getServer().getChannel(data.name);
|
2014-01-26 03:29:56 +00:00
|
|
|
chan.preJoin(self, data.pw);
|
2014-01-06 01:42:09 +00:00
|
|
|
}));
|
2013-04-18 16:42:07 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("assignLeader", function (data) {
|
|
|
|
self.channel.handleChangeLeader(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setChannelRank", function (data) {
|
|
|
|
self.channel.handleSetRank(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-17 19:05:45 +00:00
|
|
|
|
2014-01-12 05:55:52 +00:00
|
|
|
wrapTypecheck("unban", function (data) {
|
|
|
|
self.channel.handleUnban(self, data);
|
|
|
|
});
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("chatMsg", function (data) {
|
|
|
|
if (typeof data.msg !== "string") {
|
|
|
|
return;
|
2013-02-16 05:02:42 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
if (data.msg.indexOf("/afk") !== 0) {
|
|
|
|
self.setAFK(false);
|
|
|
|
self.autoAFK();
|
2013-05-04 22:54:28 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
self.channel.handleChat(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2014-02-15 07:40:14 +00:00
|
|
|
|
|
|
|
wrapTypecheck("pm", function (data) {
|
|
|
|
if (typeof data.msg !== "string" || typeof data.to !== "string") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.channel.handlePm(self, data);
|
|
|
|
});
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("newPoll", function (data) {
|
2014-01-08 16:52:00 +00:00
|
|
|
self.channel.handleOpenPoll(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-27 16:48:36 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("vote", function (data) {
|
2014-01-08 16:52:00 +00:00
|
|
|
self.channel.handlePollVote(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("closePoll", function () {
|
|
|
|
self.channel.handleClosePoll(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-03-28 23:51:08 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("playerReady", function () {
|
|
|
|
self.channel.sendMediaUpdate([self]);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("requestPlaylist", function () {
|
|
|
|
self.channel.sendPlaylist([self]);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-22 20:37:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("queue", function (data) {
|
|
|
|
self.channel.handleQueue(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-22 20:37:42 +00:00
|
|
|
|
2014-02-02 18:41:41 +00:00
|
|
|
wrapTypecheck("queuePlaylist", function (data) {
|
|
|
|
self.channel.handleQueuePlaylist(self, data);
|
|
|
|
});
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setTemp", function (data) {
|
|
|
|
self.channel.handleSetTemp(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-03-16 20:39:58 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("moveMedia", function (data) {
|
|
|
|
self.channel.handleMove(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-14 06:52:56 +00:00
|
|
|
wrap("delete", function (data) {
|
2014-01-06 01:42:09 +00:00
|
|
|
self.channel.handleDelete(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("uncache", function (data) {
|
|
|
|
self.channel.handleUncache(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-03-16 21:49:58 +00:00
|
|
|
|
2014-01-14 06:52:56 +00:00
|
|
|
wrap("jumpTo", function (data) {
|
|
|
|
self.channel.handleJumpTo(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-03-16 21:49:58 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("playNext", function () {
|
|
|
|
self.channel.handlePlayNext(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-03-17 17:14:34 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("clearPlaylist", function () {
|
|
|
|
self.channel.handleClear(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-05-13 19:41:29 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("shufflePlaylist", function () {
|
|
|
|
self.channel.handleShuffle(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-03-31 19:27:54 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("togglePlaylistLock", function () {
|
|
|
|
self.channel.handleToggleLock(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-05-22 19:38:16 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("mediaUpdate", function (data) {
|
2014-01-27 22:44:22 +00:00
|
|
|
self.channel.handleUpdate(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-05-15 15:34:27 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("searchMedia", function (data) {
|
|
|
|
if (typeof data.query !== "string") {
|
|
|
|
return;
|
2013-05-15 15:34:27 +00:00
|
|
|
}
|
2014-01-06 01:42:09 +00:00
|
|
|
data.query = data.query.substring(0, 255);
|
2013-05-15 15:34:27 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
var searchYT = function () {
|
|
|
|
InfoGetter.Getters.ytSearch(data.query.split(" "), function (e, vids) {
|
|
|
|
if (!e) {
|
|
|
|
self.socket.emit("searchResults", {
|
|
|
|
source: "yt",
|
|
|
|
results: vids
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2013-06-18 15:51:42 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
if (data.source === "yt") {
|
|
|
|
searchYT();
|
|
|
|
} else {
|
|
|
|
self.channel.search(data.query, function (vids) {
|
|
|
|
if (vids.length === 0) {
|
|
|
|
searchYT();
|
|
|
|
} else {
|
|
|
|
self.socket.emit("searchResults", {
|
|
|
|
source: "library",
|
|
|
|
results: vids
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2013-06-18 15:51:42 +00:00
|
|
|
}
|
|
|
|
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-01 21:02:09 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setOptions", function (data) {
|
|
|
|
self.channel.handleUpdateOptions(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-19 19:50:08 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setPermissions", function (data) {
|
|
|
|
self.channel.handleSetPermissions(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-18 03:57:29 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setChannelCSS", function (data) {
|
|
|
|
self.channel.handleSetCSS(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-18 04:26:44 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setChannelJS", function (data) {
|
|
|
|
self.channel.handleSetJS(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-23 18:47:09 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("setMotd", function (data) {
|
2014-01-16 17:53:34 +00:00
|
|
|
self.channel.handleSetMotd(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-04-29 23:59:51 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("updateFilter", function (data) {
|
|
|
|
self.channel.handleUpdateFilter(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-05-13 00:41:02 +00:00
|
|
|
|
2014-01-19 07:45:20 +00:00
|
|
|
wrap("importFilters", function (data) {
|
|
|
|
self.channel.handleImportFilters(self, data);
|
|
|
|
});
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
// REMOVE FILTER
|
|
|
|
// https://www.youtube.com/watch?v=SxUU3zncVmI
|
|
|
|
wrapTypecheck("removeFilter", function (data) {
|
|
|
|
self.channel.handleRemoveFilter(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-01 15:59:04 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrapTypecheck("moveFilter", function (data) {
|
|
|
|
self.channel.handleMoveFilter(self, data);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-01 19:42:08 +00:00
|
|
|
|
2014-02-13 05:33:42 +00:00
|
|
|
wrapTypecheck("updateEmote", function (data) {
|
|
|
|
self.channel.handleUpdateEmote(self, data);
|
|
|
|
});
|
|
|
|
|
|
|
|
wrap("importEmotes", function (data) {
|
|
|
|
self.channel.handleImportEmotes(self, data);
|
|
|
|
});
|
|
|
|
|
|
|
|
wrapTypecheck("removeEmote", function (data) {
|
|
|
|
self.channel.handleRemoveEmote(self, data);
|
|
|
|
});
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("requestBanlist", function () {
|
|
|
|
self.channel.sendBanlist([self]);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-01 20:56:23 +00:00
|
|
|
|
2014-01-09 02:12:02 +00:00
|
|
|
wrap("requestChannelRanks", function () {
|
|
|
|
self.channel.sendChannelRanks([self]);
|
|
|
|
});
|
|
|
|
|
2014-01-16 17:53:34 +00:00
|
|
|
wrap("requestChatFilters", function () {
|
2014-01-06 01:42:09 +00:00
|
|
|
self.channel.sendChatFilters([self]);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-06-20 23:45:21 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("voteskip", function () {
|
|
|
|
self.channel.handleVoteskip(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2013-08-06 18:20:47 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
wrap("readChanLog", function () {
|
|
|
|
self.channel.handleReadLog(self);
|
2013-08-18 17:21:34 +00:00
|
|
|
});
|
2014-01-06 01:42:09 +00:00
|
|
|
};
|
2013-06-23 14:25:49 +00:00
|
|
|
|
2014-01-31 05:02:58 +00:00
|
|
|
User.prototype.initAdminCallbacks = function () {
|
|
|
|
var self = this;
|
|
|
|
self.socket.on("borrow-rank", function (rank) {
|
|
|
|
if (self.inChannel()) {
|
|
|
|
if (typeof rank !== "number") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rank > self.global_rank) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rank === 255 && self.global_rank > 255) {
|
|
|
|
rank = self.global_rank;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.rank = rank;
|
|
|
|
self.socket.emit("rank", rank);
|
|
|
|
self.channel.sendAll("setUserRank", {
|
|
|
|
name: self.name,
|
|
|
|
rank: rank
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
User.prototype.whenLoggedIn = function (fn) {
|
|
|
|
if (this.loggedIn) {
|
|
|
|
fn();
|
|
|
|
} else {
|
|
|
|
this.once("login", fn);
|
|
|
|
}
|
2013-09-26 18:29:36 +00:00
|
|
|
};
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2013-05-03 03:13:46 +00:00
|
|
|
var lastguestlogin = {};
|
2013-09-26 18:18:37 +00:00
|
|
|
User.prototype.guestLogin = function (name) {
|
2013-08-17 20:54:23 +00:00
|
|
|
var self = this;
|
2013-09-26 18:18:37 +00:00
|
|
|
|
|
|
|
if (self.ip in lastguestlogin) {
|
2014-01-06 01:42:09 +00:00
|
|
|
var diff = (Date.now() - lastguestlogin[self.ip]) / 1000;
|
2014-01-22 23:11:26 +00:00
|
|
|
if (diff < Config.get("guest-login-delay")) {
|
2013-08-17 20:54:23 +00:00
|
|
|
self.socket.emit("login", {
|
|
|
|
success: false,
|
2014-01-06 01:42:09 +00:00
|
|
|
error: "Guest logins are restricted to one per IP address per " +
|
2014-01-22 23:11:26 +00:00
|
|
|
Config.get("guest-login-delay") + " seconds."
|
2013-08-17 20:54:23 +00:00
|
|
|
});
|
2014-01-06 01:42:09 +00:00
|
|
|
return;
|
2013-08-17 20:54:23 +00:00
|
|
|
}
|
2013-09-26 18:18:37 +00:00
|
|
|
}
|
2013-08-17 20:54:23 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
if (!util.isValidUserName(name)) {
|
2013-09-26 18:18:37 +00:00
|
|
|
self.socket.emit("login", {
|
|
|
|
success: false,
|
2014-01-06 01:42:09 +00:00
|
|
|
error: "Invalid username. Usernames must be 1-20 characters long and " +
|
|
|
|
"consist only of characters a-z, A-Z, 0-9, -, _, and accented " +
|
|
|
|
"letters."
|
2013-09-26 18:18:37 +00:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2013-08-17 20:54:23 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
// Prevent duplicate logins
|
2013-09-26 18:18:37 +00:00
|
|
|
self.loggingIn = true;
|
2014-01-06 01:42:09 +00:00
|
|
|
db.users.isUsernameTaken(name, function (err, taken) {
|
2013-09-26 18:18:37 +00:00
|
|
|
self.loggingIn = false;
|
2013-09-26 18:29:36 +00:00
|
|
|
if (err) {
|
2013-09-26 18:18:37 +00:00
|
|
|
self.socket.emit("login", {
|
|
|
|
success: false,
|
2014-01-06 01:42:09 +00:00
|
|
|
error: err
|
2013-09-26 18:18:37 +00:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2013-08-17 20:54:23 +00:00
|
|
|
|
2013-09-26 18:29:36 +00:00
|
|
|
if (taken) {
|
2013-08-17 20:54:23 +00:00
|
|
|
self.socket.emit("login", {
|
2013-09-26 18:18:37 +00:00
|
|
|
success: false,
|
2014-01-06 01:42:09 +00:00
|
|
|
error: "That username is registered."
|
2013-02-16 05:02:42 +00:00
|
|
|
});
|
2013-09-26 18:18:37 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-09-26 18:29:36 +00:00
|
|
|
if (self.inChannel()) {
|
2014-01-06 01:42:09 +00:00
|
|
|
var nameLower = name.toLowerCase();
|
|
|
|
for (var i = 0; i < self.channel.users.length; i++) {
|
|
|
|
if (self.channel.users[i].name.toLowerCase() === nameLower) {
|
2013-09-26 18:18:37 +00:00
|
|
|
self.socket.emit("login", {
|
|
|
|
success: false,
|
2014-01-06 01:42:09 +00:00
|
|
|
error: "That name is already in use on this channel."
|
2013-09-26 18:18:37 +00:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2013-06-19 21:54:27 +00:00
|
|
|
}
|
2013-09-26 18:18:37 +00:00
|
|
|
}
|
2014-01-06 01:42:09 +00:00
|
|
|
|
|
|
|
// Login succeeded
|
2013-09-26 18:18:37 +00:00
|
|
|
lastguestlogin[self.ip] = Date.now();
|
|
|
|
self.rank = 0;
|
2014-01-06 01:42:09 +00:00
|
|
|
self.global_rank = 0;
|
|
|
|
self.socket.emit("rank", 0);
|
2013-09-26 18:18:37 +00:00
|
|
|
self.name = name;
|
2014-01-06 01:42:09 +00:00
|
|
|
self.loggedIn = true;
|
2013-09-26 18:18:37 +00:00
|
|
|
self.socket.emit("login", {
|
|
|
|
success: true,
|
2014-01-19 02:18:00 +00:00
|
|
|
name: name,
|
|
|
|
guest: true
|
2013-08-17 23:51:10 +00:00
|
|
|
});
|
2014-01-06 01:42:09 +00:00
|
|
|
|
|
|
|
// TODO you shouldn't be able to guest login without being in a channel
|
2013-09-26 18:29:36 +00:00
|
|
|
if (self.inChannel()) {
|
2013-09-26 18:18:37 +00:00
|
|
|
self.channel.logger.log(self.ip + " signed in as " + name);
|
|
|
|
}
|
2013-09-26 18:29:36 +00:00
|
|
|
|
2014-01-06 01:42:09 +00:00
|
|
|
self.emit("login");
|
|
|
|
});
|
2013-09-26 18:29:36 +00:00
|
|
|
};
|
2013-02-16 05:02:42 +00:00
|
|
|
|
2014-02-02 18:41:41 +00:00
|
|
|
User.prototype.initUserPLCallbacks = function () {
|
|
|
|
require("./userplaylists").init(this);
|
|
|
|
};
|
|
|
|
|
2013-07-16 03:01:12 +00:00
|
|
|
module.exports = User;
|