diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js index 0a5ebaa..6a6059b 100644 --- a/src/app/channel/media/queue.js +++ b/src/app/channel/media/queue.js @@ -131,6 +131,7 @@ class queue{ socket.on("lock", () => {this.toggleLock(socket)}); socket.on("goLive", (data) => {this.goLive(socket, data)}); socket.on("getStreamType", (data) => {this.getStreamType(socket)}); + socket.on("getArchive", (data) => {this.getArchive(socket, data)}); //If debug mode is enabled 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){ //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"))){ @@ -522,7 +566,7 @@ class queue{ //Pull the channel DB doc const chanDB = await channelModel.findOne({name:this.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 socket.emit("dumpQueue", { @@ -948,7 +992,7 @@ class queue{ //If broadcasting is enabled if(!noBroadcast){ //Broadcast the channel - this.broadcastQueue(chanDB); + this.broadcastQueue(); } }catch(err){ @@ -1238,7 +1282,7 @@ class queue{ await chanDB.save(); //Broadcast queue since we ended our media item early - this.broadcastQueue(chanDB); + this.broadcastQueue(); }catch(err){ loggerUtils.localExceptionHandler(err); } @@ -1384,7 +1428,7 @@ class queue{ } //broadcast queue using unsaved archive, run this before chanDB.save() for better responsiveness - this.broadcastQueue(chanDB); + this.broadcastQueue(); //Save our changes to the DB await chanDB.save(); @@ -1625,7 +1669,7 @@ class queue{ await this.scheduleMedia(newSched, null, chanDB); //Broadcast the queue now that everything is hunky dory - await this.broadcastQueue(chanDB); + await this.broadcastQueue(); }catch(err){ //Null out live remainder for the next stream this.liveRemainder = null; @@ -1799,71 +1843,49 @@ class 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 - 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 - * @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions * @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 - 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 - * @param {Mongoose.Document} chanDB - Pass through Channel Document to save on DB Transactions * @returns de-hydrated scehdule information */ - async prepQueue(chanDB){ + async prepQueue(){ 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 const yesterday = new Date(); //Make it yesterdays yesterday.setDate(yesterday.getDate() - 1); - //Get archive since yesterday - const archive = await this.getArchive(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]); - } + //Prep archive from yesterday + const archive = await this.prepArchive(yesterday); //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 }catch(err){ //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 * @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(chanDB.media.liveRemainder){ - let archive = await this.getArchive(); + let archive = await this.queryArchive(); //Iterate backwards through channel archive @@ -2005,15 +2052,17 @@ class queue{ /** * 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(startDate != null){ //Return archived media after start date return await archivedMediaModel.find({ 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 :) - startTime: mongoose.trusted({$gt: startDate.getTime()}) + startTime: mongoose.trusted({$gt: startDate.getTime(), $lt: endDate.getTime()}) }); //Otherwise }else{ diff --git a/src/app/channel/media/queueBroadcastManager.js b/src/app/channel/media/queueBroadcastManager.js index 7f8e319..f2ee20f 100644 --- a/src/app/channel/media/queueBroadcastManager.js +++ b/src/app/channel/media/queueBroadcastManager.js @@ -79,7 +79,7 @@ class queueBroadcastManager extends auxServer{ socket.join(socket.chan); //Send the queue down to our newly connected user - activeChannel.queue.emitQueue(chanDB, socket); + activeChannel.queue.emitQueue(socket); //Define listeners this.defineListeners(socket);