diff --git a/src/app/channel/activeChannel.js b/src/app/channel/activeChannel.js
index 7eb1091..62f03f4 100644
--- a/src/app/channel/activeChannel.js
+++ b/src/app/channel/activeChannel.js
@@ -19,6 +19,7 @@ const connectedUser = require('./connectedUser');
const queue = require('./media/queue');
const flairModel = require('../../schemas/flairSchema');
const permissionModel = require('../../schemas/permissionSchema');
+const channelModel = require('../../schemas/channel/channelSchema');
module.exports = class{
constructor(server, chanDB){
@@ -27,7 +28,7 @@ module.exports = class{
this.tokeCommands = chanDB.tokeCommands;
//Keeping these in a map was originally a vestige but it's more preformant than an array or object so :P
this.userList = new Map();
- this.queue = new queue(server, this);
+ this.queue = new queue(server, chanDB, this);
}
async handleConnection(userDB, chanDB, socket){
diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js
index 1b14147..fcc2bb1 100644
--- a/src/app/channel/media/queue.js
+++ b/src/app/channel/media/queue.js
@@ -24,7 +24,7 @@ const loggerUtils = require('../../../utils/loggerUtils');
const channelModel = require('../../../schemas/channel/channelSchema');
module.exports = class{
- constructor(server, channel){
+ constructor(server, chanDB, channel){
//Set server
this.server = server
//Set channel
@@ -47,6 +47,9 @@ module.exports = class{
//create boolean to hold schedule lock
this.locked = false;
+
+ //Rehydrate channel queue from database
+ this.rehydrateQueue(chanDB);
}
defineListeners(socket){
@@ -441,8 +444,8 @@ module.exports = class{
return false;
}
- //If the item has already started and it's not being forced
- if((mediaObj.startTime < new Date().getTime())){
+ //If the item has already started
+ if((mediaObj.startTime < new Date().getTime()) && !force){
//Set time stamp to existing timestamp plus the difference between the orginal start-date and now
mediaObj.startTimeStamp = mediaObj.startTimeStamp + ((new Date().getTime() - mediaObj.startTime) / 1000)
//Start the item now
@@ -493,7 +496,7 @@ module.exports = class{
return mediaObj;
}
- start(mediaObj, timestamp = mediaObj.startTimeStamp){
+ async start(mediaObj, timestamp = mediaObj.startTimeStamp){
//Silently end the media
this.end(true);
@@ -503,6 +506,19 @@ module.exports = class{
//Set current playing media
this.nowPlaying = mediaObj;
+ try{
+ //Get our channel
+ const chanDB = await channelModel.findOne({name: this.channel.name});
+
+ //Set the now playing queued media document
+ chanDB.media.nowPlaying = mediaObj;
+
+ //Save the channel
+ await chanDB.save();
+ }catch(err){
+ loggerUtils.localExceptionHandler(err);
+ }
+
//Send play signal out to the channel
this.sendMedia();
@@ -655,4 +671,31 @@ module.exports = class{
broadcastQueue(){
this.server.io.in(this.channel.name).emit('queue',{queue: Array.from(this.schedule)})
}
+
+ async rehydrateQueue(chanDB){
+ 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 new Error(`Unable to find channel document ${this.channel.name} while rehydrating queue!`);
+ }
+
+ //Rehydrate the currently playing item
+ const wasPlaying = chanDB.media.nowPlaying.rehydrate();
+
+ //Schedule it
+ this.scheduleMedia(wasPlaying, null, true);
+
+ //if something fucked up
+ }catch(err){
+ //bitch about it in the server console
+ loggerUtils.localExceptionHandler(err);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/app/channel/media/queuedMedia.js b/src/app/channel/media/queuedMedia.js
index 99b6a5a..7cc2994 100644
--- a/src/app/channel/media/queuedMedia.js
+++ b/src/app/channel/media/queuedMedia.js
@@ -18,7 +18,7 @@ along with this program. If not, see .*/
const media = require('./media');
module.exports = class extends media{
- constructor(title, fileName, url, id, type, duration, startTime, startTimeStamp){
+ constructor(title, fileName, url, id, type, duration, startTime, startTimeStamp, earlyEnd, uuid){
//Call derived constructor
super(title, fileName, url, id, type, duration);
//Set media start time
@@ -27,10 +27,17 @@ module.exports = class extends media{
this.startTimeStamp = startTimeStamp;
//Create empty variable to hold early end if media is stopped early
this.earlyEnd = null;
+ //Set status for discriminator key
+ this.status = 'queued';
- //Generate id unique to this specific entry of this specific file within this specific channel's queue
- //That way even if we have six copies of the same video queued, we can still uniquely idenitify each instance
- this.genUUID();
+ //If we have a null uuid (can't use default argument because of 'this')
+ if(uuid == null){
+ //Generate id unique to this specific entry of this specific file within this specific channel's queue
+ //That way even if we have six copies of the same video queued, we can still uniquely idenitify each instance
+ this.genUUID();
+ }else{
+ this.uuid = uuid;
+ }
}
//statics
diff --git a/src/schemas/channel/channelSchema.js b/src/schemas/channel/channelSchema.js
index dbac81b..0ae5b7a 100644
--- a/src/schemas/channel/channelSchema.js
+++ b/src/schemas/channel/channelSchema.js
@@ -29,6 +29,7 @@ const emoteModel = require('../emoteSchema');
//DB Schemas
const channelPermissionSchema = require('./channelPermissionSchema');
const channelBanSchema = require('./channelBanSchema');
+const queuedMediaSchema = require('./media/queuedMediaSchema');
//Utils
const { exceptionHandler, errorHandler } = require('../../utils/loggerUtils');
@@ -98,6 +99,11 @@ const channelSchema = new mongoose.Schema({
default: emoteModel.typeEnum[0]
}
}],
+ media: {
+ nowPlaying: queuedMediaSchema,
+ scheduled: [queuedMediaSchema],
+ archived: [queuedMediaSchema],
+ },
//Thankfully we don't have to keep track of alts, ips, or deleted users so this should be a lot easier than site-wide bans :P
banList: [channelBanSchema]
});
diff --git a/src/schemas/channel/media/mediaSchema.js b/src/schemas/channel/media/mediaSchema.js
index 7454dc3..c1d1f4d 100644
--- a/src/schemas/channel/media/mediaSchema.js
+++ b/src/schemas/channel/media/mediaSchema.js
@@ -42,6 +42,10 @@ const mediaSchema = new mongoose.Schema({
type: mongoose.SchemaTypes.Number,
required: true,
},
-});
+},
+{
+ discriminatorKey: 'status'
+}
+);
module.exports = mediaSchema;
\ No newline at end of file
diff --git a/src/schemas/channel/media/queuedMediaSchema.js b/src/schemas/channel/media/queuedMediaSchema.js
index fbf0a3e..eef12d5 100644
--- a/src/schemas/channel/media/queuedMediaSchema.js
+++ b/src/schemas/channel/media/queuedMediaSchema.js
@@ -19,16 +19,44 @@ const {mongoose} = require('mongoose');
//Local Imports
const mediaSchema = require('./mediaSchema');
+const queuedMedia = require('../../../app/channel/media/queuedMedia');
const queuedProperties = new mongoose.Schema({
startTime: {
type: mongoose.SchemaTypes.Number,
required: true,
},
+ startTimeStamp: {
+ type: mongoose.SchemaTypes.Number,
+ required: false,
+ },
+ earlyEnd: {
+ type: mongoose.SchemaTypes.Number,
+ required: false,
+ },
uuid: {
type: mongoose.SchemaTypes.UUID,
required: true,
}
+},
+{
+ discriminatorKey: 'status'
});
-module.exports = mediaSchema.descriminiator('queued', queuedProperties);
\ No newline at end of file
+//methods
+queuedProperties.methods.rehydrate = function(){
+ return new queuedMedia(
+ this.title,
+ this.fileName,
+ this.url,
+ this.id,
+ this.type,
+ this.duration,
+ this.startTime,
+ this.startTimeStamp,
+ this.earlyEnd,
+ this.uuid.toString()
+ );
+}
+
+module.exports = mediaSchema.discriminator('queued', queuedProperties);
\ No newline at end of file
diff --git a/src/utils/loggerUtils.js b/src/utils/loggerUtils.js
index a82b336..e8033df 100644
--- a/src/utils/loggerUtils.js
+++ b/src/utils/loggerUtils.js
@@ -26,12 +26,17 @@ module.exports.errorHandler = function(res, msg, type = "Generic", status = 400)
}
}
-module.exports.exceptionHandler = function(res, err){
+module.exports.localExceptionHandler = function(err){
//If we're being verbose
if(config.verbose){
//Log the error
console.log(err)
}
+}
+
+module.exports.exceptionHandler = function(res, err){
+ //Locally handle the exception
+ module.exports.localExceptionHandler(err);
//if not yell at the browser for fucking up, and tell it what it did wrong.
module.exports.errorHandler(res, err.message, "Caught Exception");
@@ -42,11 +47,8 @@ module.exports.socketErrorHandler = function(socket, msg, type = "Generic"){
}
module.exports.socketExceptionHandler = function(socket, err){
- //If we're being verbose
- if(config.verbose){
- //Log the error
- console.log(err)
- }
+ //Locally handle the exception
+ module.exports.localExceptionHandler(err);
//if not yell at the browser for fucking up, and tell it what it did wrong.
return module.exports.socketErrorHandler(socket, err.msg, "Caught Exception");
diff --git a/src/views/partial/popup/changePassword.ejs b/src/views/partial/popup/changePassword.ejs
index 76abca8..b726362 100644
--- a/src/views/partial/popup/changePassword.ejs
+++ b/src/views/partial/popup/changePassword.ejs
@@ -16,8 +16,8 @@ along with this program. If not, see . %>
Update Password
-
Enter new email and current password below:
-
-
-
+
Enter new and confirm current password below:
+
+
+
\ No newline at end of file
diff --git a/www/js/channel/panels/queuePanel.js b/www/js/channel/panels/queuePanel.js
index 65349ab..264d1e0 100644
--- a/www/js/channel/panels/queuePanel.js
+++ b/www/js/channel/panels/queuePanel.js
@@ -80,8 +80,10 @@ class queuePanel extends panelObj{
defineListeners(){
//Render queue when we receive a new copy of the queue data from the server
- this.client.socket.on("clientMetadata", (data) => {this.renderQueue();});
- this.client.socket.on("queue", (data) => {this.renderQueue();});
+ this.client.socket.on("clientMetadata", () => {this.renderQueue();});
+ this.client.socket.on("queue", () => {this.renderQueue();});
+ this.client.socket.on("start", () => {this.renderQueue();});
+ this.client.socket.on("end", () => {this.renderQueue();});
this.client.socket.on("lock", this.handleScheduleLock.bind(this));
this.client.socket.on("error", this.handleQueueError.bind(this));
}
@@ -415,6 +417,12 @@ class queuePanel extends panelObj{
}
clearQueue(){
+ //If we have no body
+ if(this.ownerDoc.body == null){
+ //We have bigger issues
+ return;
+ }
+
//Clear out queue container
this.queueContainer.innerHTML = '';;
//Clear out queue marker container
diff --git a/www/js/profile.js b/www/js/profile.js
index a2aae0e..7cc1e85 100644
--- a/www/js/profile.js
+++ b/www/js/profile.js
@@ -227,7 +227,7 @@ class accountSettingsButton{
class changeEmailPopup{
constructor(){
- this.popup = new canopyUXUtils.popup("changeEmail", true, this.asyncConstructor.bind(this), this.asyncConstructor);
+ this.popup = new canopyUXUtils.popup("changeEmail", true, this.asyncConstructor.bind(this));
}
asyncConstructor(){
@@ -251,7 +251,7 @@ class changeEmailPopup{
class changePasswordPopup{
constructor(){
- this.popup = new canopyUXUtils.popup("changePassword", true, this.asyncConstructor.bind(this), this.asyncConstructor);
+ this.popup = new canopyUXUtils.popup("changePassword", true, this.asyncConstructor.bind(this));
}
asyncConstructor(){