/*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 .*/ /** * Class for handling incoming Private Messages for the entire client */ class pmHandler{ /** * Instantiates a new Private Message Handler object * @param {channel} client - Parent client Management Object */ constructor(client){ /** * Parent client management object */ this.client = client; /** * PM Icon in the main chat bar */ this.pmIcon = document.querySelector('#chat-panel-pm-icon'); /** * List of PM Sessions */ this.seshList = new Map(); this.defineListeners(); this.setupInput(); } /** * Defines network related event listeners for PM Handler */ defineListeners(){ this.client.pmSocket.on("message", this.handlePM.bind(this)); this.client.pmSocket.on("sent", this.handlePM.bind(this)); } /** * Defines inpet related event listeners for PM handler */ setupInput(){ this.pmIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new pmPanel(client))}); } /** * Handles received Private Messages from the PM service on the server, organizing it into the proper session from the sesh list * Or creating a new sesh where a matching one does not a exist * @param {object} data - Private Message data from the server */ handlePM(data){ //Store whether or not current message has been consumed by an existing sesh let consumed = false; const nameObj = pmHandler.genSeshName(data); //Create members array from scratch to avoid changing the input data for further processing const members = nameObj.recipients; //For each existing sesh for(const seshEntry of this.seshList){ //Pull sesh object from map entry const sesh = seshEntry[1]; //If currently checked sesh ID matches calculated message sesh id if(sesh.id == nameObj.name){ //Dump collected message into the matching session sesh.messages.push(data); //Add sesh to sesh map this.seshList.set(sesh.id, sesh); //Let the rest of the method know that we've consumed this message consumed = true; } } //If we made it through the loop without consuming the message if(!consumed){ //Generate a new sesh const sesh = new pmSesh(data, client); //Add it to the sesh list this.seshList.set(sesh.id, sesh); } } static genSeshName(message){ const recipients = []; //Manually iterate through recipients for(const member of message.recipients){ //check to make sure we're not adding ourselves if(member != client.user.user){ //Copy relevant array members by value instead of reference recipients.push(member); } } //If this wasn't our message if(message.user != client.user.user){ //Push sender onto members list recipients.push(message.user); } //Sort recipients recipients.sort(); return { name: recipients.join(', '), recipients } } } /** * Class which represents an existing Private Messaging session between two or more users */ class pmSesh{ /** * Instatiates a new pmSession object * @param {Object} message - Initial Private Message object from server that initiated the session */ constructor(message, client){ /** * Parent client management object */ this.client = client; const nameObj = pmHandler.genSeshName(message); /** * Members of session excluding the currently logged in user */ this.recipients = nameObj.recipients /** * Name of the chat sesh, named after out-going recipients */ this.id = nameObj.name; /** * Array containing all session messages */ this.messages = (message.msg == "" || message.msg == null) ? [] : [message]; } }