/*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 .*/ const config = require('../../../config.json'); const channelModel = require('../../schemas/channel/channelSchema'); /** * Class representing a stored chat buffer */ class chatBuffer{ /** * Instantiates a new chat buffer for a given channel * @param {channelManager} server - Parent Server Object * @param {Mongoose.Document} chanDB - chanDB to rehydrate buffer from * @param {activeChannel} channel - Parent Channel Object */ constructor(server, chanDB, channel){ //Grab parent server and chan objects this.server = server; this.channel = channel; //If we have no chanDB.chatBuffer if(chanDB == null || chanDB.chatBuffer == null){ //Create RAM-based buffer array this.buffer = []; //Otherwise }else{ //Pull buffer from DB this.buffer = chanDB.chatBuffer; } //Create variables to hold timers for deciding when to write RAM buffer to DB //Goes off 'this.inactivityDelay' seconds after the last chat was sent, assuming it isn't interrupted by new chats this.inactivityTimer = null; this.inactivityDelay = 10; //Goes off 'this.busyDelay' minutes after the first chat message in the current volley of messages. Get's cancelled before being called if this.inactivityTimer goes off. this.busyTimer = null; this.busyDelay = 5; } /** * Adds a given chat to the chat buffer in RAM and sets any appropriate timers for DB transactions * @param {chat} chat - Chat object to commit to buffer */ push(chat){ //push chat into RAM buffer this.buffer.push(chat); //clear existing inactivity timer clearTimeout(this.inactivityTimer); //reset inactivity timer this.inactivityTimer = setTimeout(this.handleInactivity.bind(this), 1000 * this.inactivityDelay); //If busy timer is unset if(this.busyTimer == null){ this.busyTimer = setTimeout(this.handleBusyRoom.bind(this), 1000 * 60 * this.busyDelay); } } /** * Removes the oldest item from the chat buffer * * Was originally created in-case we needed to trigger timing functions * * Left here since it seems like good form anywho, since this would be a private, or at least protected member in another language */ shift(){ this.buffer.shift(); } /** * Called after 10 seconds of chat room inactivity */ handleInactivity(){ this.saveDB(`${this.inactivityDelay} seconds of inactivity.`); } /** * Called after 5 minutes of solid activity */ handleBusyRoom(){ this.saveDB(`${this.busyDelay} minutes of activity.`); } /** * Saves RAM-Based buffer to Channel Document in DB * @param {String} reason - Reason for DB save, formatted as 'x minutes/seconds of in/activity', used for logging purposes * @param {Mongoose.Document} chanDB - Channel Doc to work with, can be left empty for method to auto-find through channel name. */ async saveDB(reason, chanDB){ //clear existing timers clearTimeout(this.inactivityTimer); clearTimeout(this.busyTimer); this.inactivityTimer = null; this.busyTimer = null; //if the server is in screamy boi mode if(config.verbose){ //This should eventually be replaced by a per-channel logging feature that provides access to chan admins via web front-end console.log(`Saving chat buffer to channel ${this.channel.name} after ${reason}.`); } //If we wheren't handed a channel if(chanDB == null){ //Now that everything is clean, we can take our time with the DB :P chanDB = await channelModel.findOne({name:this.channel.name}); } //If we couldn't find the channel if(chanDB == null){ //FUCK throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while saving chat buffer!`, "chat"); } //Set chan doc buffer to RAM buffer chanDB.chatBuffer = this.buffer; //save chan doc to DB. await chanDB.save(); } } module.exports = chatBuffer;