channelManager now tracks all active connectedUser objects for a given user.
This commit is contained in:
parent
261dce7b29
commit
6222535c47
7 changed files with 160 additions and 24 deletions
|
|
@ -74,6 +74,7 @@ class activeChannel{
|
|||
* @param {Mongoose.Document} userDB - User Document Passthrough to save on DB Access
|
||||
* @param {Mongoose.Document} chanDB - Channnel Document Passthrough to save on DB Access
|
||||
* @param {Socket} socket - Requesting Socket
|
||||
* @returns {activeUser} active user object generated by the new connection
|
||||
*/
|
||||
async handleConnection(userDB, chanDB, socket){
|
||||
//get current user object from the userlist
|
||||
|
|
@ -104,10 +105,13 @@ class activeChannel{
|
|||
this.playlistHandler.defineListeners(socket);
|
||||
|
||||
//Hand off the connection initiation to it's user object
|
||||
await userObj.handleConnection(userDB, chanDB, socket)
|
||||
const activeUser = await userObj.handleConnection(userDB, chanDB, socket)
|
||||
|
||||
//Send out the userlist
|
||||
this.broadcastUserList(socket.chan);
|
||||
|
||||
//Return active user connection object for use by the channelManager object
|
||||
return activeUser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -115,11 +119,11 @@ class activeChannel{
|
|||
* @param {Socket} socket - Requesting Socket
|
||||
*/
|
||||
handleDisconnect(socket){
|
||||
//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);
|
||||
//temporarily store userObj
|
||||
let userObj = this.userList.get(socket.user.user);
|
||||
|
||||
//If we have more than one active connection
|
||||
if(userObj.sockets.length > 1){
|
||||
//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;
|
||||
|
|
@ -127,7 +131,11 @@ class activeChannel{
|
|||
|
||||
//Update the userlist
|
||||
this.userList.set(socket.user.user, userObj);
|
||||
//If this is the last one
|
||||
}else{
|
||||
//Tell the server to handle the disconnection of this user object
|
||||
this.server.handleUserDisconnect(userObj);
|
||||
|
||||
//If this is the last connection for this user, remove them from the userlist
|
||||
this.userList.delete(socket.user.user);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const chatHandler = require('./chatHandler');
|
|||
class channelManager{
|
||||
/**
|
||||
* Instantiates object containing global server-side channel conection management logic
|
||||
* @param {Server} io - Socket.io server instanced passed down from server.js
|
||||
* @param {Socket.io} io - Socket.io server instanced passed down from server.js
|
||||
*/
|
||||
constructor(io){
|
||||
/**
|
||||
|
|
@ -46,6 +46,11 @@ class channelManager{
|
|||
*/
|
||||
this.activeChannels = new Map;
|
||||
|
||||
/**
|
||||
* Map containing all active users. This may be redundant, however it improves preformance for user-specific inter-channel functionality
|
||||
*/
|
||||
this.activeUsers = new Map;
|
||||
|
||||
/**
|
||||
* Global Chat Handler Object
|
||||
*/
|
||||
|
|
@ -88,13 +93,48 @@ class channelManager{
|
|||
return;
|
||||
}
|
||||
|
||||
//Connection accepted past this point
|
||||
|
||||
//Define listeners for inter-channel classes
|
||||
this.defineListeners(socket);
|
||||
this.chatHandler.defineListeners(socket);
|
||||
|
||||
//Hand off the connection to it's given active channel object
|
||||
//Lil' hacky to pass chanDB like that, but why double up on DB calls?
|
||||
activeChan.handleConnection(userDB, chanDB, socket);
|
||||
const activeUser = await activeChan.handleConnection(userDB, chanDB, socket);
|
||||
|
||||
//Pull status from server-wide activeUsers map
|
||||
let status = this.activeUsers.get(activeUser.user);
|
||||
|
||||
//If this user isn't connected anywhere else
|
||||
if(status == null){
|
||||
//initiate the entry
|
||||
this.activeUsers.set(activeUser.user, [activeUser]);
|
||||
//otherwise
|
||||
}else{
|
||||
//Push user to array by default
|
||||
let pushUser = true;
|
||||
|
||||
//For each active connection within the status map
|
||||
for(let curUser of status){
|
||||
//If we're already listing this active user (we're splitting a user connection amongst several sockets)
|
||||
if(curUser.channel.name == activeUser.channel.name){
|
||||
//don't need to push it again
|
||||
pushUser = false;
|
||||
}
|
||||
}
|
||||
|
||||
//if the user is flagged as un-added
|
||||
if(pushUser){
|
||||
//Add their connection object into the status array we pulled
|
||||
status.push(activeUser);
|
||||
|
||||
//Set status entry to updated array
|
||||
this.activeUsers.set(activeUser.set, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
//Toss out anon's
|
||||
socket.emit("kick", {type: "disconnected", reason: "You must log-in to join this channel!"});
|
||||
|
|
@ -217,6 +257,34 @@ class channelManager{
|
|||
activeChan.handleDisconnect(socket, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a disconnection event for a single active user within a given channel (when all sockets disconnect)
|
||||
* @param {*} userObj
|
||||
*/
|
||||
handleUserDisconnect(userObj){
|
||||
//Create array to hold
|
||||
let stillConnected = [];
|
||||
|
||||
//Crawl through all known user connections
|
||||
this.crawlConnections(userObj.user, (curUser)=>{
|
||||
//If we have a matching username from a different channel
|
||||
if(curUser.user == userObj.user && userObj.channel.name != curUser.channel.name){
|
||||
//Keep current user
|
||||
stillConnected.push(curUser);
|
||||
}
|
||||
});
|
||||
|
||||
//If we have anyone left
|
||||
if(stillConnected.length > 0){
|
||||
//save the remainder to the status map, otherwise unset the value.
|
||||
this.activeUsers.set(userObj.user, stillConnected);
|
||||
//Otherwise
|
||||
}else{
|
||||
//Delete the user from the status map
|
||||
this.activeUsers.delete(userObj.user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls user information by socket
|
||||
* @param {Socket} socket - Socket to check
|
||||
|
|
@ -257,30 +325,28 @@ class channelManager{
|
|||
* @param {Function} cb - Callback function to run active connections of a given user against
|
||||
*/
|
||||
crawlConnections(user, cb){
|
||||
//For each channel
|
||||
this.activeChannels.forEach((channel) => {
|
||||
//Check and see if the user is connected
|
||||
const foundUser = channel.userList.get(user);
|
||||
//Pull connection list from status map
|
||||
const list = this.activeUsers.get(user);
|
||||
|
||||
//If we found a user and this channel hasn't been added to the list
|
||||
if(foundUser){
|
||||
cb(foundUser);
|
||||
//If we have active connections
|
||||
if(list != null){
|
||||
//For each connection
|
||||
for(let user of list){
|
||||
//Run the callback against it
|
||||
cb(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through connections by a given username, and runs them through a given callback function/method
|
||||
* This function is deprecated. Instead use channelManager.activeUsers.get(user)
|
||||
* @param {String} user - Username to crawl connections against
|
||||
* @param {Function} cb - Callback function to run active connections of a given user against
|
||||
*/
|
||||
getConnections(user){
|
||||
//Create a list to store our connections
|
||||
var connections = [];
|
||||
|
||||
//crawl through connections
|
||||
//this.crawlConnections(user,(foundUser)=>{connections.push(foundUser)});
|
||||
this.crawlConnections(user,(foundUser)=>{connections.push(foundUser)});
|
||||
const connections = this.activeUsers.get(user);
|
||||
|
||||
//return connects
|
||||
return connections;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ class connectedUser{
|
|||
* @param {Mongoose.Document} userDB - User Document Passthrough to save on DB Access
|
||||
* @param {Mongoose.Document} chanDB - Channnel Document Passthrough to save on DB Access
|
||||
* @param {Socket} socket - Requesting Socket
|
||||
* @returns {activeUser} active user object generated by the new connection
|
||||
*/
|
||||
async handleConnection(userDB, chanDB, socket){
|
||||
//send metadata to client
|
||||
|
|
@ -115,6 +116,10 @@ class connectedUser{
|
|||
//Tattoo hashed IP address to user account for seven days
|
||||
await userDB.tattooIPRecord(socket.handshake.address);
|
||||
}
|
||||
|
||||
|
||||
//Return active user object for use by activeChannel and channelManager objects
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
52
src/app/channel/message.js
Normal file
52
src/app/channel/message.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*Canopy - The next generation of stoner streaming software
|
||||
Copyright (C) 2024-2025 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/>.*/
|
||||
|
||||
/**
|
||||
* Class representing a single chat message
|
||||
*/
|
||||
class message{
|
||||
/**
|
||||
* Instantiates a chat message object
|
||||
* @param {connectedUser} sender - User who sent the message
|
||||
* @param {Array} recipients - Array of connected users who are supposed to receive the message
|
||||
* @param {String} msg - Contents of the message, with links replaced with numbered file-seperator markers
|
||||
* @param {Array} links - Array of URLs/Links included in the message.
|
||||
*/
|
||||
constructor(sender, recipients, msg, links){
|
||||
|
||||
/**
|
||||
* User who sent the message
|
||||
*/
|
||||
this.sender = sender;
|
||||
|
||||
/**
|
||||
* Array of strings containing usernames to send message to
|
||||
*/
|
||||
this.recipients = recipients;
|
||||
|
||||
/**
|
||||
* Contenst of the messages, with links replaced with numbered file-seperator markers
|
||||
*/
|
||||
this.msg = msg;
|
||||
|
||||
/**
|
||||
* Array of URLs/Links included in the message.
|
||||
*/
|
||||
this.links = links;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = message;
|
||||
Loading…
Add table
Add a link
Reference in a new issue