Cleaned up 'src/app/channel'
This commit is contained in:
parent
985f8a250f
commit
5b5f495853
|
|
@ -15,8 +15,69 @@ You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
module.exports = class{
|
module.exports = class{
|
||||||
constructor(name){
|
constructor(server, name){
|
||||||
|
this.server = server;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.userList = new Map();
|
this.userList = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleConnection(userDB, socket){
|
||||||
|
//get current user object from the userlist
|
||||||
|
var userObj = this.userList.get(userDB.user);
|
||||||
|
|
||||||
|
//If user is already connected
|
||||||
|
if(userObj){
|
||||||
|
//Add this socket on to the userobject
|
||||||
|
userObj.sockets.push(socket.id);
|
||||||
|
}else{
|
||||||
|
//if this is the first connection, initialize the userObject w/ the current socked id
|
||||||
|
userObj = {
|
||||||
|
id: userDB.id,
|
||||||
|
rank: userDB.rank,
|
||||||
|
flair: userDB.flair,
|
||||||
|
sockets: [socket.id]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set user entry in userlist
|
||||||
|
this.userList.set(userDB.user, userObj);
|
||||||
|
|
||||||
|
//if everything looks good, admit the connection to the channel
|
||||||
|
socket.join(socket.chan);
|
||||||
|
|
||||||
|
//Send out the userlist
|
||||||
|
this.broadcastUserList(socket.chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDisconnect(socket, reason){
|
||||||
|
//If we have more than one active connection
|
||||||
|
if(this.userList.get(socket.user.user).sockets.length > 1){
|
||||||
|
//temporarily store userObj
|
||||||
|
var userObj = this.userList.get(socket.user.user);
|
||||||
|
|
||||||
|
//Filter out disconnecting socket from socket list, and set as current socket list for user
|
||||||
|
userObj.sockets = userObj.sockets.filter((id) => {
|
||||||
|
return id != socket.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Update the userlist
|
||||||
|
this.userList.set(socket.user.user, userObj);
|
||||||
|
}else{
|
||||||
|
//If this is the last connection for this user, remove them from the userlist
|
||||||
|
this.userList.delete(socket.user.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
//and send out the filtered list
|
||||||
|
this.broadcastUserList(socket.chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
broadcastUserList(){
|
||||||
|
var userList = [];
|
||||||
|
|
||||||
|
this.userList.forEach((userObj, user) => {
|
||||||
|
userList.push(user);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.server.io.in(this.name).emit("user-list", userList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
const channelModel = require('../../schemas/channelSchema');
|
const channelModel = require('../../schemas/channelSchema');
|
||||||
const flairModel = require('../../schemas/flairSchema');
|
const flairModel = require('../../schemas/flairSchema');
|
||||||
const userModel = require('../../schemas/userSchema');
|
const userModel = require('../../schemas/userSchema');
|
||||||
|
const loggerUtils = require('../../utils/loggerUtils');
|
||||||
const activeChannel = require('./activeChannel');
|
const activeChannel = require('./activeChannel');
|
||||||
const chatHandler = require('./chatHandler');
|
const chatHandler = require('./chatHandler');
|
||||||
|
|
||||||
|
|
@ -40,111 +41,78 @@ module.exports = class{
|
||||||
//Prevent logged out connections and authenticate socket
|
//Prevent logged out connections and authenticate socket
|
||||||
if(socket.request.session.user != null){
|
if(socket.request.session.user != null){
|
||||||
try{
|
try{
|
||||||
//Find the user in the Database since the session won't store enough data to fulfill our needs :P
|
//Authenticate socket
|
||||||
const userDB = await userModel.findOne({user: socket.request.session.user.user});
|
const userDB = await this.authSocket(socket);
|
||||||
|
|
||||||
//Set socket user and channel values
|
//Get the active channel based on the socket
|
||||||
socket.user = {
|
var activeChan = await this.getActiveChan(socket);
|
||||||
id: userDB.id,
|
|
||||||
user: userDB.user,
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.chanName = socket.handshake.headers.referer.split('/c/')[1];
|
//Define listeners
|
||||||
|
this.defineListeners(socket);
|
||||||
//Check if channel exists
|
this.chatHandler.defineListeners(socket);
|
||||||
if(await channelModel.findOne({name: socket.chanName}) == null){
|
|
||||||
socket.disconnect("Channel does not exist!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if current channel is active
|
|
||||||
var activeChan = this.activeChannels.get(socket.chan);
|
|
||||||
if(!activeChan){
|
|
||||||
//If not, make it so
|
|
||||||
activeChan = new activeChannel(socket.chan);
|
|
||||||
this.activeChannels.set(socket.chan, activeChan);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if this user is already connected
|
|
||||||
if(activeChan.userList.get(socket.user.user)){
|
|
||||||
//get current list of socket connnections of selected user
|
|
||||||
var userObj = activeChan.userList.get(userDB.user);
|
|
||||||
//Add this one on
|
|
||||||
userObj.sockets.push(socket.id);
|
|
||||||
//Set the user back socket list back
|
|
||||||
activeChan.userList.set(userDB.user, userObj);
|
|
||||||
}else{
|
|
||||||
//if this is the first connection, initialize the socket array for this user
|
|
||||||
var userObj = {
|
|
||||||
id: userDB.id,
|
|
||||||
rank: userDB.rank,
|
|
||||||
flair: userDB.flair,
|
|
||||||
sockets: [socket.id]
|
|
||||||
}
|
|
||||||
|
|
||||||
activeChan.userList.set(userDB.user, userObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if everything looks good, admit the connection to the channel
|
|
||||||
socket.join(socket.chan);
|
|
||||||
|
|
||||||
//Send out the userlist
|
|
||||||
this.broadcastUserList(socket.chan);
|
|
||||||
|
|
||||||
|
//Connect the socket to it's given channel
|
||||||
|
activeChan.handleConnection(userDB, socket);
|
||||||
}catch(err){
|
}catch(err){
|
||||||
socket.disconnect("Server Error During Channel Connection Initialization");
|
//Flip a table if something fucks up
|
||||||
console.log(err);
|
return loggerUtils.socketCriticalExceptionHandler(socket, err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
//Toss out anon's
|
||||||
socket.disconnect("Unauthenticated");
|
socket.disconnect("Unauthenticated");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async authSocket(socket){
|
||||||
|
//Find the user in the Database since the session won't store enough data to fulfill our needs :P
|
||||||
|
const userDB = await userModel.findOne({user: socket.request.session.user.user});
|
||||||
|
|
||||||
|
if(userDB == null){
|
||||||
|
throw new Error("User not found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set socket user and channel values
|
||||||
|
socket.user = {
|
||||||
|
id: userDB.id,
|
||||||
|
user: userDB.user,
|
||||||
|
};
|
||||||
|
|
||||||
|
return userDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getActiveChan(socket){
|
||||||
|
socket.chan = socket.handshake.headers.referer.split('/c/')[1];
|
||||||
|
|
||||||
|
//Check if channel exists
|
||||||
|
if(await channelModel.findOne({name: socket.chan}) == null){
|
||||||
|
throw new Error("Channel not found!")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if current channel is active
|
||||||
|
var activeChan = this.activeChannels.get(socket.chan);
|
||||||
|
|
||||||
|
if(!activeChan){
|
||||||
|
//If not, make it so
|
||||||
|
activeChan = new activeChannel(this, socket.chan);
|
||||||
|
this.activeChannels.set(socket.chan, activeChan);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return whatever the active channel is (new or old)
|
||||||
|
return activeChan;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineListeners(socket){
|
||||||
//Socket Listeners
|
//Socket Listeners
|
||||||
socket.conn.on("close", (reason) => {
|
socket.conn.on("close", (reason) => {this.handleDisconnect(socket, reason)});
|
||||||
//Get active channel
|
|
||||||
var activeChan = this.activeChannels.get(socket.chan);
|
|
||||||
|
|
||||||
//If we have more than one active connection
|
|
||||||
if(activeChan.userList.get(socket.user.user).sockets.length > 1){
|
|
||||||
//temporarily store userObj
|
|
||||||
var userObj = activeChan.userList.get(socket.user.user);
|
|
||||||
|
|
||||||
//Filter out disconnecting socket from socket list, and set as current socket list for user
|
|
||||||
userObj.sockets = userObj.sockets.filter((id) => {
|
|
||||||
return id != socket.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
//Update the userlist
|
|
||||||
activeChan.userList.set(socket.user.user, userObj);
|
|
||||||
}else{
|
|
||||||
//If this is the last connection for this user, remove them from the userlist
|
|
||||||
activeChan.userList.delete(socket.user.user);
|
|
||||||
}
|
|
||||||
|
|
||||||
//and send out the filtered list
|
|
||||||
this.broadcastUserList(socket.chan);
|
|
||||||
});
|
|
||||||
|
|
||||||
//define chat listeners
|
|
||||||
this.chatHandler.defineListeners(socket);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcastUserList(chan){
|
handleDisconnect(socket, reason){
|
||||||
var activeChan = this.activeChannels.get(chan);
|
var activeChan = this.activeChannels.get(socket.chan);
|
||||||
var userList = [];
|
activeChan.handleDisconnect(socket, reason);
|
||||||
|
|
||||||
activeChan.userList.forEach((socketlist, user) => {
|
|
||||||
userList.push(user);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.io.in(chan).emit("user-list", userList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
socketToUser(socket){
|
getSocketInfo(socket){
|
||||||
const channel = this.activeChannels.get(socket.chan);
|
const channel = this.activeChannels.get(socket.chan);
|
||||||
return channel.userList.get(socket.user.user);
|
return channel.userList.get(socket.user.user);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,39 +28,42 @@ module.exports = class{
|
||||||
}
|
}
|
||||||
|
|
||||||
defineListeners(socket){
|
defineListeners(socket){
|
||||||
socket.on("chatMessage", (data) => {
|
socket.on("chatMessage", (data) => {this.relayChat(socket, data)});
|
||||||
//Trim and Sanatize for XSS
|
socket.on("setFlair", async (data) => {this.setFlair(socket, data)});
|
||||||
const msg = validator.trim(validator.escape(data.msg));
|
}
|
||||||
//make sure high is an int
|
|
||||||
const high = validator.toInt(data.high);
|
|
||||||
|
|
||||||
const user = this.server.socketToUser(socket);
|
relayChat(socket, data){
|
||||||
|
//Trim and Sanatize for XSS
|
||||||
|
const msg = validator.trim(validator.escape(data.msg));
|
||||||
|
//make sure high is an int
|
||||||
|
const high = validator.toInt(data.high);
|
||||||
|
|
||||||
//nuke the message if its empty or huge
|
const user = this.server.getSocketInfo(socket);
|
||||||
if(!validator.isLength(msg, {min: 1, max: 255})){
|
|
||||||
return;
|
//nuke the message if its empty or huge
|
||||||
|
if(!validator.isLength(msg, {min: 1, max: 255})){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//nuke the message if the high number is wrong
|
||||||
|
if(high < 0 || high > 10){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.server.io.in(socket.chan).emit("chatMessage", {user: socket.user.user, flair: user.flair, high, msg});
|
||||||
|
}
|
||||||
|
|
||||||
|
async setFlair(socket, data){
|
||||||
|
const userDB = await userModel.findOne({user: socket.user.user});
|
||||||
|
|
||||||
|
if(userDB){
|
||||||
|
try{
|
||||||
|
//We can take this data raw since our schema checks it against existing flairs, and mongoose sanatizes queries
|
||||||
|
userDB.flair = data.flair;
|
||||||
|
await userDB.save();
|
||||||
|
}catch(err){
|
||||||
|
return loggerUtils.socketExceptionHandler(socket, err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//nuke the message if the high number is wrong
|
|
||||||
if(high < 0 || high > 10){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.server.io.in(socket.chan).emit("chatMessage", {user: socket.user.user, flair: user.flair, high, msg});
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("setFlair", async (data) => {
|
|
||||||
const userDB = await userModel.findOne({user: socket.user.user});
|
|
||||||
|
|
||||||
if(userDB){
|
|
||||||
try{
|
|
||||||
//We can take this data raw since our schema checks it against existing flairs, and mongoose sanatizes queries
|
|
||||||
userDB.flair = data.flair;
|
|
||||||
await userDB.save();
|
|
||||||
}catch(err){
|
|
||||||
return loggerUtils.socketExceptionHandler(socket, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,3 +25,8 @@ module.exports.socketExceptionHandler = function(socket, err){
|
||||||
//if not yell at the browser for fucking up, and tell it what it did wrong.
|
//if not yell at the browser for fucking up, and tell it what it did wrong.
|
||||||
return socket.emit("error", {errors: [{type: "Caught Exception", msg: err.message, date: new Date()}]});
|
return socket.emit("error", {errors: [{type: "Caught Exception", msg: err.message, date: new Date()}]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports.socketCriticalExceptionHandler = function(socket, err){
|
||||||
|
//if not yell at the browser for fucking up, and tell it what it did wrong.
|
||||||
|
return socket.disconnect("error", {errors: [{type: "Caught Exception", msg: err.message, date: new Date()}]});
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue