Added server-side logic for requesting channel queue archives.

This commit is contained in:
rainbow napkin 2026-10-11 23:35:06 -04:00
parent d686cf540e
commit baf8255b2c
2 changed files with 99 additions and 50 deletions

View file

@ -131,6 +131,7 @@ class queue{
socket.on("lock", () => {this.toggleLock(socket)}); socket.on("lock", () => {this.toggleLock(socket)});
socket.on("goLive", (data) => {this.goLive(socket, data)}); socket.on("goLive", (data) => {this.goLive(socket, data)});
socket.on("getStreamType", (data) => {this.getStreamType(socket)}); socket.on("getStreamType", (data) => {this.getStreamType(socket)});
socket.on("getArchive", (data) => {this.getArchive(socket, data)});
//If debug mode is enabled //If debug mode is enabled
if(config.debug){ if(config.debug){
@ -510,6 +511,49 @@ class queue{
} }
} }
/**
* Returns current channel stream type upon request
* @param {Socket} socket - Socket we received the request from
* @param {Object} data - Event payload
*/
async getArchive(socket, data){
try{
//If we get an invalid start date
if(typeof data.startDate != "number" || data.startDate < 0){
//Bitch, moan, an' complain!
loggerUtils.socketErrorHandler(socket, "Invalid Start Date!", "validation");
//Yeetus-Deletus bitch
return;
}
//If we get an invalid start date
if(typeof data.endDate != "number" || data.endDate < 0){
//Bitch, moan, an' complain!
loggerUtils.socketErrorHandler(socket, "Invalid End Date!", "validation");
//Yeetus-Deletus bitch
return;
}
//Get the current channel from the database
const chanDB = await channelModel.findOne({name: socket.chan});
//If the user isn't allowed to read the schedule
if(!await chanDB.permCheck(socket.user, 'readSchedule')){
//Fuckin ignore em'
return;
}
//Create new date objects to represent range of data requested
const startDate = new Date(data.startDate);
const endDate = new Date(data.endDate);
//Grab archives from given range, and send them back to the requesting socket
socket.emit("archive", {archive: await this.prepArchive(startDate, endDate)});
}catch(err){
return loggerUtils.socketExceptionHandler(socket, err);
}
}
async dumpQueue(socket, data){ async dumpQueue(socket, data){
//If we somehow got here while config.debug is disabled, or the user isn't allowed to preform server-side debugging //If we somehow got here while config.debug is disabled, or the user isn't allowed to preform server-side debugging
if(!(config.debug && await permissionModel.permCheck(socket.user, "debug"))){ if(!(config.debug && await permissionModel.permCheck(socket.user, "debug"))){
@ -522,7 +566,7 @@ class queue{
//Pull the channel DB doc //Pull the channel DB doc
const chanDB = await channelModel.findOne({name:this.channel.name}); const chanDB = await channelModel.findOne({name:this.channel.name});
//Pull archived media by channel name //Pull archived media by channel name
const archived = await this.getArchive(); const archived = await this.queryArchive();
//Cook and emit a new object from all of the data //Cook and emit a new object from all of the data
socket.emit("dumpQueue", { socket.emit("dumpQueue", {
@ -948,7 +992,7 @@ class queue{
//If broadcasting is enabled //If broadcasting is enabled
if(!noBroadcast){ if(!noBroadcast){
//Broadcast the channel //Broadcast the channel
this.broadcastQueue(chanDB); this.broadcastQueue();
} }
}catch(err){ }catch(err){
@ -1238,7 +1282,7 @@ class queue{
await chanDB.save(); await chanDB.save();
//Broadcast queue since we ended our media item early //Broadcast queue since we ended our media item early
this.broadcastQueue(chanDB); this.broadcastQueue();
}catch(err){ }catch(err){
loggerUtils.localExceptionHandler(err); loggerUtils.localExceptionHandler(err);
} }
@ -1384,7 +1428,7 @@ class queue{
} }
//broadcast queue using unsaved archive, run this before chanDB.save() for better responsiveness //broadcast queue using unsaved archive, run this before chanDB.save() for better responsiveness
this.broadcastQueue(chanDB); this.broadcastQueue();
//Save our changes to the DB //Save our changes to the DB
await chanDB.save(); await chanDB.save();
@ -1625,7 +1669,7 @@ class queue{
await this.scheduleMedia(newSched, null, chanDB); await this.scheduleMedia(newSched, null, chanDB);
//Broadcast the queue now that everything is hunky dory //Broadcast the queue now that everything is hunky dory
await this.broadcastQueue(chanDB); await this.broadcastQueue();
}catch(err){ }catch(err){
//Null out live remainder for the next stream //Null out live remainder for the next stream
this.liveRemainder = null; this.liveRemainder = null;
@ -1799,71 +1843,49 @@ class queue{
/** /**
* Broadcasts channel queue * Broadcasts channel queue
* @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions
*/ */
async broadcastQueue(chanDB){ async broadcastQueue(){
//Broadcast queue to authenticated sockets within the channels room inside the protected 'queue-broadcast' namespace //Broadcast queue to authenticated sockets within the channels room inside the protected 'queue-broadcast' namespace
this.server.queueBroadcastManager.namespace.in(this.channel.name).emit('queue',{queue: await this.prepQueue(chanDB)}); this.server.queueBroadcastManager.namespace.in(this.channel.name).emit('queue',{queue: await this.prepQueue()});
} }
/** /**
* Broadcasts channel queue to a single socket * Broadcasts channel queue to a single socket
* @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions
* @param {Socket} socket - Socket to send queue to * @param {Socket} socket - Socket to send queue to
*/ */
async emitQueue(chanDB, socket){ async emitQueue(socket){
//Broadcast queue to authenticated sockets within the channels room inside the protected 'queue-broadcast' namespace //Broadcast queue to authenticated sockets within the channels room inside the protected 'queue-broadcast' namespace
socket.emit('queue',{queue: await this.prepQueue(chanDB)}); socket.emit('queue',{queue: await this.prepQueue()});
}
/**
* Broadcasts channel queue to a single socket
* @param {Date} startDate - Start date to pull archives from
* @param {Date} endDate - Start date to pull archives from
* @param {Socket} socket - Socket to send queue to
*/
async emitArchive(startDate, endDate, socket){
//Broadcast queue to authenticated sockets within the channels room inside the protected 'queue-broadcast' namespace
socket.emit('queue',{queue: await this.prepArchive(startDate, endDate)});
} }
/** /**
* Prepares channel queue for network transmission * Prepares channel queue for network transmission
* @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions
* @returns de-hydrated scehdule information * @returns de-hydrated scehdule information
*/ */
async prepQueue(chanDB){ async prepQueue(){
try{ try{
//If we didn't get handed a freebie
if(chanDB == null){
//Go out and get it done ourselves
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 rehydrating queue!`, "queue");
}
//Create an empty array to hold our schedule
let schedule = [];
//Get todays epoch //Get todays epoch
const yesterday = new Date(); const yesterday = new Date();
//Make it yesterdays //Make it yesterdays
yesterday.setDate(yesterday.getDate() - 1); yesterday.setDate(yesterday.getDate() - 1);
//Get archive since yesterday //Prep archive from yesterday
const archive = await this.getArchive(yesterday); const archive = await this.prepArchive(yesterday);
//Iterate through the channel archive backwards to save time
for(let mediaIndex = archive.length - 1; mediaIndex >= 0; mediaIndex--){
//Grab the current media record
let media = archive[mediaIndex].rehydrate();
//If we're sending out the live remainder during a live stream
if(this.liveRemainder != null && media.uuid.toString() == this.liveRemainder.uuid.toString()){
//Throw out the early end before sending it off, so it looks like it hasn't been cut off yet (smoke n mirrors :P)
media.earlyEnd = null;
}
//Add it to the temporary schedule array as if it where part of the actual schedule map
schedule.unshift([media.startTime, media]);
}
//Concatonate the actual schedule to the items we pulled out of the archive return it //Concatonate the actual schedule to the items we pulled out of the archive return it
return schedule.concat(Array.from(this.schedule)); return archive.concat(Array.from(this.schedule));
//If we can't get shit from the database //If we can't get shit from the database
}catch(err){ }catch(err){
//Complain //Complain
@ -1873,6 +1895,31 @@ class queue{
} }
} }
async prepArchive(startDate, endDate = new Date()){
//Define array to hold prepped archive objects
const preppedArchive = [];
//Get archive since yesterday
const archive = await this.queryArchive(startDate, endDate);
//Iterate through the channel archive backwards to save time
for(let mediaIndex = archive.length - 1; mediaIndex >= 0; mediaIndex--){
//Grab the current media record
let media = archive[mediaIndex].rehydrate();
//If we're sending out the live remainder during a live stream
if(this.liveRemainder != null && media.uuid.toString() == this.liveRemainder.uuid.toString()){
//Throw out the early end before sending it off, so it looks like it hasn't been cut off yet (smoke n mirrors :P)
media.earlyEnd = null;
}
//Add it to the temporary preppd archive array as if it where part of the actual schedule map
preppedArchive.unshift([media.startTime, media]);
}
return preppedArchive;
}
/** /**
* Rehydrates media schedule from DB * Rehydrates media schedule from DB
* @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions * @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions
@ -1946,7 +1993,7 @@ class queue{
//If we have a remainder from a livestream //If we have a remainder from a livestream
if(chanDB.media.liveRemainder){ if(chanDB.media.liveRemainder){
let archive = await this.getArchive(); let archive = await this.queryArchive();
//Iterate backwards through channel archive //Iterate backwards through channel archive
@ -2005,15 +2052,17 @@ class queue{
/** /**
* Get Channel Archive * Get Channel Archive
* @param {Date} startDate - Start of range to grab from
* @param {Date} endDate - End of range to grab from
*/ */
async getArchive(startDate){ async queryArchive(startDate, endDate = new Date()){
//If we provided a start date //If we provided a start date
if(startDate != null){ if(startDate != null){
//Return archived media after start date //Return archived media after start date
return await archivedMediaModel.find({ return await archivedMediaModel.find({
channel:this.channel._id, channel:this.channel._id,
//Prevent mongoose from attempting to sanatize and invalidate our query object, plus I think we can trust an epoch that came from server-side :) //Prevent mongoose from attempting to sanatize and invalidate our query object, plus I think we can trust an epoch that came from server-side :)
startTime: mongoose.trusted({$gt: startDate.getTime()}) startTime: mongoose.trusted({$gt: startDate.getTime(), $lt: endDate.getTime()})
}); });
//Otherwise //Otherwise
}else{ }else{

View file

@ -79,7 +79,7 @@ class queueBroadcastManager extends auxServer{
socket.join(socket.chan); socket.join(socket.chan);
//Send the queue down to our newly connected user //Send the queue down to our newly connected user
activeChannel.queue.emitQueue(chanDB, socket); activeChannel.queue.emitQueue(socket);
//Define listeners //Define listeners
this.defineListeners(socket); this.defineListeners(socket);