Added schedule locking and day jumping on scroll lock.
This commit is contained in:
parent
c83ca63f9a
commit
44dd613ea3
8 changed files with 221 additions and 125 deletions
|
|
@ -139,8 +139,11 @@ module.exports = class{
|
|||
//Get schedule as a temporary array
|
||||
const queue = Array.from(this.channel.queue.schedule);
|
||||
|
||||
//Get schedule lock status
|
||||
const queueLock = this.channel.queue.locked;
|
||||
|
||||
//Send off the metadata to our user's clients
|
||||
this.emit("clientMetadata", {user: userObj, flairList, queue});
|
||||
this.emit("clientMetadata", {user: userObj, flairList, queue, queueLock});
|
||||
}
|
||||
|
||||
async sendSiteEmotes(){
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ const validator = require('validator');
|
|||
const queuedMedia = require('./queuedMedia');
|
||||
const yanker = require('../../../utils/media/yanker');
|
||||
const loggerUtils = require('../../../utils/loggerUtils');
|
||||
const channelModel = require('../../../schemas/channel/channelSchema');
|
||||
|
||||
module.exports = class{
|
||||
constructor(server, channel){
|
||||
|
|
@ -43,145 +44,182 @@ module.exports = class{
|
|||
this.nextTimer = null;
|
||||
//Create variable to hold currently playing media object
|
||||
this.nowPlaying = null;
|
||||
|
||||
//create boolean to hold schedule lock
|
||||
this.locked = false;
|
||||
}
|
||||
|
||||
defineListeners(socket){
|
||||
socket.on("queue", (data) => {this.queueURL(socket, data)});
|
||||
socket.on("delete", (data => {this.deleteMedia(socket, data)}));
|
||||
socket.on("move", (data => {this.moveMedia(socket, data)}));
|
||||
socket.on("clear", (data => {this.deleteRange(socket, data)}));
|
||||
socket.on("delete", (data) => {this.deleteMedia(socket, data)});
|
||||
socket.on("move", (data) => {this.moveMedia(socket, data)});
|
||||
socket.on("clear", (data) => {this.deleteRange(socket, data)});
|
||||
socket.on("lock", (data) => {this.toggleLock(socket)});
|
||||
}
|
||||
|
||||
|
||||
async queueURL(socket, data){
|
||||
try{
|
||||
//Set url
|
||||
var url = data.url;
|
||||
//Get the current channel from the database
|
||||
const chanDB = await channelModel.findOne({name: socket.chan});
|
||||
|
||||
//If we where given a bad URL
|
||||
if(!validator.isURL(url)){
|
||||
//Attempt to fix the situation by encoding it
|
||||
url = encodeURI(url);
|
||||
if((!this.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin')){
|
||||
try{
|
||||
//Set url
|
||||
var url = data.url;
|
||||
|
||||
//If it's still bad
|
||||
//If we where given a bad URL
|
||||
if(!validator.isURL(url)){
|
||||
//Attempt to fix the situation by encoding it
|
||||
url = encodeURI(url);
|
||||
|
||||
//If it's still bad
|
||||
if(!validator.isURL(url)){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad URL!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//If the title is too long
|
||||
if(!validator.isLength(data.title, {max:30})){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad URL!", "validation");
|
||||
loggerUtils.socketErrorHandler(socket, "Title too long!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Set title
|
||||
const title = validator.escape(validator.trim(data.title));
|
||||
//set start
|
||||
var start = data.start;
|
||||
|
||||
//If the title is too long
|
||||
if(!validator.isLength(data.title, {max:30})){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Title too long!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
//Set title
|
||||
const title = validator.escape(validator.trim(data.title));
|
||||
//set start
|
||||
var start = data.start;
|
||||
|
||||
//If start time isn't an integer after the current epoch
|
||||
if(start != null &&!validator.isInt(String(start), (new Date().getTime()))){
|
||||
//Null out time to tell the later parts of the function to start it now
|
||||
start = null;
|
||||
}
|
||||
|
||||
//Pull media list
|
||||
const mediaList = await yanker.yankMedia(url, title);
|
||||
|
||||
//If we didn't find any media
|
||||
if(mediaList == null || mediaList.length <= 0){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "No media found!", "queue");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
//If we have an invalid time
|
||||
if(start == null || start < (new Date).getTime()){
|
||||
//Get last item from schedule
|
||||
const lastItem = (Array.from(this.schedule)[this.schedule.size - 1]);
|
||||
|
||||
//if we have a last item
|
||||
if(lastItem != null){
|
||||
//Throw it on five ms after the last item
|
||||
start = lastItem[1].startTime + (lastItem[1].duration * 1000) + 5;
|
||||
//If start time isn't an integer after the current epoch
|
||||
if(start != null &&!validator.isInt(String(start), (new Date().getTime()))){
|
||||
//Null out time to tell the later parts of the function to start it now
|
||||
start = null;
|
||||
}
|
||||
}
|
||||
|
||||
//Queue the first media object given
|
||||
this.queueMedia(mediaList[0], start, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
//Pull media list
|
||||
const mediaList = await yanker.yankMedia(url, title);
|
||||
|
||||
//If we didn't find any media
|
||||
if(mediaList == null || mediaList.length <= 0){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "No media found!", "queue");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
//If we have an invalid time
|
||||
if(start == null || start < (new Date).getTime()){
|
||||
//Get last item from schedule
|
||||
const lastItem = (Array.from(this.schedule)[this.schedule.size - 1]);
|
||||
|
||||
//if we have a last item
|
||||
if(lastItem != null){
|
||||
//Throw it on five ms after the last item
|
||||
start = lastItem[1].startTime + (lastItem[1].duration * 1000) + 5;
|
||||
}
|
||||
}
|
||||
|
||||
//Queue the first media object given
|
||||
this.queueMedia(mediaList[0], start, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deleteRange(socket, data){
|
||||
try{
|
||||
//If start time isn't an integer
|
||||
if(data.start != null && !validator.isInt(String(data.start))){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad start date!", "queue");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
async deleteRange(socket, data){
|
||||
//Get the current channel from the database
|
||||
const chanDB = await channelModel.findOne({name: socket.chan});
|
||||
|
||||
//If end time isn't an integer
|
||||
if(data.end != null && !validator.isInt(String(data.end))){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad end date!", "queue");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
if((!this.locked && await chanDB.permCheck(socket.user, 'clearSchedule')) || await chanDB.permCheck(socket.user, 'scheduleAdmin')){
|
||||
try{
|
||||
//If start time isn't an integer
|
||||
if(data.start != null && !validator.isInt(String(data.start))){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad start date!", "queue");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeRange(data.start, data.end, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
//If end time isn't an integer
|
||||
if(data.end != null && !validator.isInt(String(data.end))){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad end date!", "queue");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeRange(data.start, data.end, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deleteMedia(socket, data){
|
||||
try{
|
||||
//If we don't have a valid UUID
|
||||
if(!validator.isUUID(data.uuid)){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad UUID!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
async deleteMedia(socket, data){
|
||||
//Get the current channel from the database
|
||||
const chanDB = await channelModel.findOne({name: socket.chan});
|
||||
|
||||
//Remove media by UUID
|
||||
this.removeMedia(data.uuid, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
if((!this.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin')){
|
||||
try{
|
||||
//If we don't have a valid UUID
|
||||
if(!validator.isUUID(data.uuid)){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad UUID!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
//Remove media by UUID
|
||||
this.removeMedia(data.uuid, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moveMedia(socket, data){
|
||||
try{
|
||||
//If we don't have a valid UUID
|
||||
if(!validator.isUUID(data.uuid)){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad UUID!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
async moveMedia(socket, data){
|
||||
//Get the current channel from the database
|
||||
const chanDB = await channelModel.findOne({name: socket.chan});
|
||||
|
||||
//If start time isn't an integer after the current epoch
|
||||
if(data.start != null && !validator.isInt(String(data.start))){
|
||||
//Null out time to tell the later parts of the function to start it now
|
||||
data.start = undefined;
|
||||
}
|
||||
if((!this.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin')){
|
||||
try{
|
||||
//If we don't have a valid UUID
|
||||
if(!validator.isUUID(data.uuid)){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Bad UUID!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
//Move media by UUID
|
||||
this.rescheduleMedia(data.uuid, data.start, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
//If start time isn't an integer after the current epoch
|
||||
if(data.start != null && !validator.isInt(String(data.start))){
|
||||
//Null out time to tell the later parts of the function to start it now
|
||||
data.start = undefined;
|
||||
}
|
||||
|
||||
//Move media by UUID
|
||||
this.rescheduleMedia(data.uuid, data.start, socket);
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async toggleLock(socket){
|
||||
//Get the current channel from the database
|
||||
const chanDB = await channelModel.findOne({name: socket.chan});
|
||||
|
||||
//If the user is a schedule admin
|
||||
if(await chanDB.permCheck(socket.user, 'scheduleAdmin')){
|
||||
//Toggle the schedule lock
|
||||
this.locked = !this.locked;
|
||||
|
||||
//Update schedule lock status for everyone in the channel
|
||||
this.server.io.in(this.channel.name).emit("lock", {locked: this.locked});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,24 @@ const channelPermissionSchema = new mongoose.Schema({
|
|||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
scheduleMedia: {
|
||||
type: mongoose.SchemaTypes.String,
|
||||
enum: rankEnum,
|
||||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
clearSchedule:{
|
||||
type: mongoose.SchemaTypes.String,
|
||||
enum: rankEnum,
|
||||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
scheduleAdmin:{
|
||||
type: mongoose.SchemaTypes.String,
|
||||
enum: rankEnum,
|
||||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
deleteChannel: {
|
||||
type: mongoose.SchemaTypes.String,
|
||||
enum: rankEnum,
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
|||
<div id="queue-panel-layout-controller">
|
||||
<div id="queue-controls">
|
||||
<div id="queue-control-buttons">
|
||||
<button id="queue-add-media"><i class="bi-plus-lg"></i></button>
|
||||
<button id="queue-search-media"><i class="bi-search"></i></button>
|
||||
<button id="queue-add-media" class="bi-plus-lg"></button>
|
||||
<button id="queue-search-media" class="bi-search"></button>
|
||||
<button id="queue-scroll-lock" class="positive-button"><i class="bi-clock-fill"></i><i class="bi-arrows-expand"></i></button>
|
||||
<button id="queue-date"><i class="bi-calendar-fill"></i></button>
|
||||
<button id="queue-playlists"><i class="bi-list"></i></button>
|
||||
<button id="queue-clear" class="danger-button"><i class="bi-trash-fill"></i></button>
|
||||
<button id="queue-lock" class="positive-button"><i class="bi-unlock-fill"></i></button>
|
||||
<button id="queue-date" class="bi-calendar-fill"></button>
|
||||
<button id="queue-playlists" class="bi-list"></button>
|
||||
<button id="queue-clear" class="danger-button bi-trash-fill"></button>
|
||||
<button id="queue-lock" class="positive-button bi-unlock-fill"></button>
|
||||
</div>
|
||||
<div id="queue-control-date" style="display: none">
|
||||
<i class="bi-caret-left" id="queue-control-date-decrement"></i>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue