From f95a0ae48c4dcd7c1e03b8a61de01d2ef3b1ddfd Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Sat, 25 Oct 2025 09:46:28 -0400 Subject: [PATCH 1/4] Added queue debugging. --- config.example.json | 1 + config.example.jsonc | 5 ++++ src/app/channel/media/queue.js | 49 ++++++++++++++++++++++++++++++++- src/schemas/permissionSchema.js | 6 ++++ src/server.js | 6 ++-- src/utils/configCheck.js | 5 ++++ 6 files changed, 68 insertions(+), 4 deletions(-) diff --git a/config.example.json b/config.example.json index 58445d8..6e7519f 100644 --- a/config.example.json +++ b/config.example.json @@ -8,6 +8,7 @@ "ytdlpPath": "/home/canopy/.local/pipx/venvs/yt-dlp/bin/yt-dlp", "migrate": false, "dropLegacyTokes": false, + "debug": false, "secrets":{ "passwordSecret": "CHANGE_ME", "rememberMeSecret": "CHANGE_ME", diff --git a/config.example.jsonc b/config.example.jsonc index 3f1bd0a..75d4591 100644 --- a/config.example.jsonc +++ b/config.example.jsonc @@ -24,6 +24,11 @@ //Requires migration to be disabled before it takes effect. //WARNING: this does NOT affect user toke counts, migrated or otherwise. Use carefully! "dropLegacyTokes": false, + //Enters the server into debug mode, allows specific commands to be emitted from the client-side dev console + //Usually to get the server to dump some sort of internal data for debugging purposes. + //Obviously, this means enabling this can have some gnar implications. + //Probably don't enable this on your production server unless you REALLY REALLY have to, and you probably don't. + "debug": false, //Server Secrets //Be careful with what you keep in secrets, you should use special chars, but test your deployment, as some chars may break account registration //An update to either kill the server and bitch about the issue in console is planned so it's not so confusing for new admins diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js index 8284420..8fa933f 100644 --- a/src/app/channel/media/queue.js +++ b/src/app/channel/media/queue.js @@ -18,10 +18,12 @@ along with this program. If not, see .*/ const validator = require('validator'); //Local imports +const config = require('../../../../config.json'); const queuedMedia = require('./queuedMedia'); const yanker = require('../../../utils/media/yanker'); const loggerUtils = require('../../../utils/loggerUtils'); const channelModel = require('../../../schemas/channel/channelSchema'); +const permissionModel = require('../../../schemas/permissionSchema'); /** * Object represneting a single channel's media queue @@ -114,6 +116,11 @@ class queue{ socket.on("move", (data) => {this.moveMedia(socket, data)}); socket.on("lock", () => {this.toggleLock(socket)}); socket.on("goLive", (data) => {this.goLive(socket, data)}); + + //If debug mode is enabled + if(config.debug){ + socket.on("dumpQueue", (data) => {this.dumpQueue(socket, data)}); + } } //--- USER FACING QUEUEING FUNCTIONS --- @@ -404,6 +411,44 @@ class queue{ } } + 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"))){ + //FUCKIN' CHEESE IT! + return; + } + + //If a full data dump was requested + if(data != null && data.full){ + //Pull the channel DB doc + const chanDB = await channelModel.findOne({name:this.channel.name}); + + //Cook and emit a new object from all of the data + socket.emit("dumpQueue", { + cache: { + schedule: Array.from(this.schedule), + nowPlaying: this.nowPlaying + }, + DB: { + schedule: chanDB.media.scheduled, + nowPlaying: chanDB.media.nowPlaying, + archived: chanDB.media.archived, + } + }); + + //DONE. + return; + } + + //Otherwise, just dump whats in RAM + socket.emit("dumpQueue", { + cache: { + schedule: Array.from(this.schedule), + nowPlaying: this.nowPlaying + } + }); + } + //--- INTERNAL USE ONLY QUEUEING FUNCTIONS --- /** * Clears and scheduling timers @@ -1788,7 +1833,9 @@ class queue{ chanDB.media.scheduled = newSched; //Save the DB - await chanDB.save(); + await chanDB.save() + + //End the media; //if something fucked up }catch(err){ diff --git a/src/schemas/permissionSchema.js b/src/schemas/permissionSchema.js index 108c888..322e8e2 100644 --- a/src/schemas/permissionSchema.js +++ b/src/schemas/permissionSchema.js @@ -100,6 +100,12 @@ const permissionSchema = new mongoose.Schema({ type: channelPermissionSchema, default: () => ({}) }, + debug: { + type: mongoose.SchemaTypes.String, + enum: rankEnum, + default: "admin", + required: true + }, }); //Statics diff --git a/src/server.js b/src/server.js index da30147..50dcda0 100644 --- a/src/server.js +++ b/src/server.js @@ -78,9 +78,6 @@ const config = require('../config.json'); const port = config.port; const dbUrl = `mongodb://${config.db.user}:${config.db.pass}@${config.db.address}:${config.db.port}/${config.db.database}`; -//Check for insecure config -configCheck.securityCheck(); - //Define express const app = express(); @@ -234,6 +231,9 @@ async function asyncKickStart(){ //Kick off scheduled-jobs scheduler.kickoff(); + //Check for insecure config + configCheck.securityCheck(); + //Increment launch counter await statModel.incrementLaunchCount(); diff --git a/src/utils/configCheck.js b/src/utils/configCheck.js index d979b32..411c8b8 100644 --- a/src/utils/configCheck.js +++ b/src/utils/configCheck.js @@ -74,4 +74,9 @@ module.exports.securityCheck = function(){ if(!validator.isStrongPassword(config.mail.pass) || config.mail.pass == "CHANGE_ME"){ loggerUtil.consoleWarn("Insecure Email Password! Change Email password!"); } + + //check debug mode + if(config.debug){ + loggerUtil.consoleWarn("Debug mode enabled! Understand the risks and security implications before enabling on production servers!"); + } } \ No newline at end of file From 37990ff8c31862db834a7555f706302188013da8 Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Sat, 25 Oct 2025 09:55:40 -0400 Subject: [PATCH 2/4] Traded bug with queue.end() being called as volatile from functions which handle their own DB save, in which stale item was left in cache, for a simple queue rending bug. --- src/app/channel/media/queue.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js index 8fa933f..ec44c81 100644 --- a/src/app/channel/media/queue.js +++ b/src/app/channel/media/queue.js @@ -1209,6 +1209,12 @@ class queue{ return this.endLivestream(wasPlaying, chanDB) } + + //Moved this from the block below to prevent accidental over-caching + //We may need to throw this into it's own conditional if it causes issues + //Take it out of the active schedule + this.schedule.delete(wasPlaying.startTime); + //If we're not in volatile mode and we're not ending a livestream if(!volatile){ //If we wheren't handed a channel @@ -1229,9 +1235,6 @@ class queue{ await chanDB.media.nowPlaying.deleteOne(); } - //Take it out of the active schedule - this.schedule.delete(wasPlaying.startTime); - //If archiving is enabled if(!noArchive){ //Add the item to the channel archive From 166e174397424f1c770d4feef6d579d1451142d9 Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Sat, 25 Oct 2025 09:56:24 -0400 Subject: [PATCH 3/4] comment --- src/app/channel/media/queue.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/channel/media/queue.js b/src/app/channel/media/queue.js index ec44c81..9bbaa01 100644 --- a/src/app/channel/media/queue.js +++ b/src/app/channel/media/queue.js @@ -1213,6 +1213,7 @@ class queue{ //Moved this from the block below to prevent accidental over-caching //We may need to throw this into it's own conditional if it causes issues //Take it out of the active schedule + //Ultimitaly though, if something is voltaile it should handle saving chanDB on its own, so this should be a non-issue this.schedule.delete(wasPlaying.startTime); //If we're not in volatile mode and we're not ending a livestream From 787846c7d6ec88efa478f3b9d30bba61dd61f60c Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Mon, 27 Oct 2025 19:29:07 -0400 Subject: [PATCH 4/4] Updated config example. --- config.example.json | 6 +++--- config.example.jsonc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config.example.json b/config.example.json index 6e7519f..5d8f957 100644 --- a/config.example.json +++ b/config.example.json @@ -1,9 +1,9 @@ { "instanceName": "Canopy", "verbose": false, - "port": 8080, - "proxied": false, - "protocol": "http", + "port": 8443, + "proxied": true, + "protocol": "https", "domain": "localhost", "ytdlpPath": "/home/canopy/.local/pipx/venvs/yt-dlp/bin/yt-dlp", "migrate": false, diff --git a/config.example.jsonc b/config.example.jsonc index 75d4591..f315d9a 100644 --- a/config.example.jsonc +++ b/config.example.jsonc @@ -6,9 +6,9 @@ //Scream about exceptions in the console "verbose": false, //Port to bind to (most linux/unix systems req root for ports below 1000, you should probably use nginx if you want port 80 or 443) - "port": 8080, + "port": 8443, //Lets the server know it's sitting behind a reverse-proxy - "proxied": false, + "proxied": true, //Protocol (either HTTP or HTTPS) "protocol": "http", //Domain the server is available at, used for server-side link generation