canopy/src/app/channel/channelManager.js
2024-11-20 06:54:44 -05:00

119 lines
3.9 KiB
JavaScript

/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024 Rainbownapkin and the TTN Community
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
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/>.*/
//Local Imports
const channelModel = require('../../schemas/channelSchema');
const flairModel = require('../../schemas/flairSchema');
const userModel = require('../../schemas/userSchema');
const loggerUtils = require('../../utils/loggerUtils');
const activeChannel = require('./activeChannel');
const chatHandler = require('./chatHandler');
module.exports = class{
constructor(io){
//Set the socket.io server
this.io = io;
//Load
this.activeChannels = new Map;
//Load server components
this.chatHandler = new chatHandler(this);
//Handle connections from socket.io
io.on("connection", this.handleConnection.bind(this) );
}
async handleConnection(socket){
//Prevent logged out connections and authenticate socket
if(socket.request.session.user != null){
try{
//Authenticate socket
const userDB = await this.authSocket(socket);
//Get the active channel based on the socket
var activeChan = await this.getActiveChan(socket);
//Define listeners
this.defineListeners(socket);
this.chatHandler.defineListeners(socket);
//Connect the socket to it's given channel
activeChan.handleConnection(userDB, socket);
}catch(err){
//Flip a table if something fucks up
return loggerUtils.socketCriticalExceptionHandler(socket, err);
}
}else{
//Toss out anon's
socket.disconnect("Unauthenticated");
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.conn.on("close", (reason) => {this.handleDisconnect(socket, reason)});
}
handleDisconnect(socket, reason){
var activeChan = this.activeChannels.get(socket.chan);
activeChan.handleDisconnect(socket, reason);
}
getSocketInfo(socket){
const channel = this.activeChannels.get(socket.chan);
return channel.userList.get(socket.user.user);
}
}