diff --git a/README.md b/README.md
index ac1f39c..75720ec 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@ Canopy
======
-
+
diff --git a/src/app/auxServer.js b/src/app/auxServer.js
index 3a66337..2779dbf 100644
--- a/src/app/auxServer.js
+++ b/src/app/auxServer.js
@@ -51,21 +51,30 @@ class auxServer{
* Handles global server-side initialization for new connections to aux server
* @param {Socket} socket - Requesting Socket
*/
- async handleConnection(socket){
+ async handleConnection(socket, lite = true){
try{
+ //Define empty value to hold result
+ let result = null;
+
//ensure unbanned ip and valid CSRF token
if(!(await socketUtils.validateSocket(socket))){
socket.disconnect();
- return false;
+ return null;
+ }
+
+ if(lite){
+ result = await socketUtils.authSocketLite(socket);
+ }else{
+ result = await socketUtils.authSocket(socket);
}
//If the socket wasn't authorized
- if(await socketUtils.authSocketLite(socket) == null){
+ if(result == null){
socket.disconnect();
- return false;
+ return null;
}
- return true;
+ return result;
}catch(err){
//Flip a table if something fucks up
return loggerUtils.socketCriticalExceptionHandler(socket, err);
diff --git a/src/app/channel/channelManager.js b/src/app/channel/channelManager.js
index 289c227..e9223f1 100644
--- a/src/app/channel/channelManager.js
+++ b/src/app/channel/channelManager.js
@@ -25,6 +25,7 @@ const loggerUtils = require('../../utils/loggerUtils');
const presenceUtils = require('../../utils/presenceUtils');
const activeChannel = require('./activeChannel');
const chatHandler = require('./chatHandler');
+const queueBroadcastManager = require('./media/queueBroadcastManager');
/**
* Class containing global server-side channel connection management logic
@@ -55,6 +56,16 @@ class channelManager{
*/
this.chatHandler = new chatHandler(this);
+ /**
+ * Global Chat Handler Object
+ */
+ this.chatHandler = new chatHandler(this);
+
+ /**
+ * Global Auxiliary Server for Authenticated Queue Metadata Brodcasting
+ */
+ this.queueBroadcastManager = new queueBroadcastManager(this.io, this)
+
//Handle connections from socket.io
io.on("connection", this.handleConnection.bind(this) );
}
@@ -152,7 +163,7 @@ class channelManager{
* @returns {Object} Object containing users active channel name and channel document object
*/
async getActiveChan(socket){
- socket.chan = socket.handshake.headers.referer.split('/c/')[1].split('/')[0];
+ socket.chan = socketUtils.getChannelName(socket);
const chanDB = (await channelModel.findOne({name: socket.chan}));
//Check if channel exists
diff --git a/src/app/channel/media/queueBroadcastManager.js b/src/app/channel/media/queueBroadcastManager.js
new file mode 100644
index 0000000..c72a1c3
--- /dev/null
+++ b/src/app/channel/media/queueBroadcastManager.js
@@ -0,0 +1,82 @@
+/*Canopy - The next generation of stoner streaming software
+Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .*/
+
+//local includes
+const auxServer = require("../../auxServer");
+const socketUtils = require("../../../utils/socketUtils")
+const loggerUtils = require("../../../utils/loggerUtils");
+const channelModel = require("../../../schemas/channel/channelSchema");
+
+/**
+ * Class containg global server-side private message relay logic
+ *
+ * Exists to make broadcasting channel queues to groups of authenticated users with the 'read-queue' perm as painless as possible,
+ * reducing DB call/perm checks to just connection time, and not requireing any out-of-library user iteration at broadcast time.
+ *
+ * Calls to modify and write to the schedule are still handled by the main namespace
+ * This is both for it's ease of access to the rest of the channel logic, but also to keep this class as small as possible.
+ */
+class queueBroadcastManager extends auxServer{
+ /**
+ * Instantiates object containing global server-side channel schedule broadcasting subsystem
+ * @param {Socket.io} io - Socket.io server instanced passed down from server.js
+ * @param {channelManager} chanServer - Sister channel management server object
+ */
+ constructor(io, chanServer){
+ super(io, chanServer, "/queue-broadcast");
+ }
+
+ /**
+ * Handles global server-side initialization for new connections to the queue broadcast subsystem
+ * @param {Socket} socket - Requesting Socket
+ */
+ async handleConnection(socket){
+ //Check if we're properly authorized
+ const userObj = await super.handleConnection(socket);
+
+ //If we're un-authorized
+ if(userObj == null){
+ //Drop the connection
+ return;
+ }
+
+ //Set socket channel value
+ socket.chan = socketUtils.getChannelName(socket);
+ //Pull channel DB
+ const chanDB = (await channelModel.findOne({name: socket.chan}));
+
+ //If the user is connecting from an invalid channel
+ if(chanDB == null){
+ //Drop the connection
+ return;
+ }
+
+ //If the user is allowed to read the schedule
+ if(await chanDB.permCheck(socket.user, 'readSchedule')){
+ //Throw the user into the channels room within the queue-broadcast instance
+ socket.join(socket.chan);
+
+ //Define listeners
+ this.defineListeners(socket);
+ }
+ }
+
+ defineListeners(socket){
+ super.defineListeners(socket);
+ }
+}
+
+module.exports = queueBroadcastManager;
\ No newline at end of file
diff --git a/src/app/pm/pmHandler.js b/src/app/pm/pmHandler.js
index 5e16ffc..10c505e 100644
--- a/src/app/pm/pmHandler.js
+++ b/src/app/pm/pmHandler.js
@@ -19,6 +19,7 @@ const auxServer = require('../auxServer');
const chatPreprocessor = require('../chatPreprocessor');
const loggerUtils = require("../../utils/loggerUtils");
const message = require("./message");
+const socketUtils = require("../../utils/socketUtils");
/**
* Class containg global server-side private message relay logic
@@ -41,10 +42,10 @@ class pmHandler extends auxServer{
*/
async handleConnection(socket){
//Check if we're properly authorized
- const authorized = await super.handleConnection(socket, "${user}");
+ const authorized = await super.handleConnection(socket);
//If we're authorized
- if(authorized){
+ if(authorized != null){
//Throw the user into their own unique channel
socket.join(socket.user.user);
diff --git a/src/schemas/channel/channelPermissionSchema.js b/src/schemas/channel/channelPermissionSchema.js
index bdd709e..1916efd 100644
--- a/src/schemas/channel/channelPermissionSchema.js
+++ b/src/schemas/channel/channelPermissionSchema.js
@@ -89,6 +89,12 @@ const channelPermissionSchema = new mongoose.Schema({
default: "admin",
required: true
},
+ readSchedule: {
+ type: mongoose.SchemaTypes.String,
+ enum: rankEnum,
+ default: "admin",
+ required: true
+ },
scheduleMedia: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
diff --git a/src/utils/socketUtils.js b/src/utils/socketUtils.js
index 765ea02..8b538df 100644
--- a/src/utils/socketUtils.js
+++ b/src/utils/socketUtils.js
@@ -98,4 +98,8 @@ module.exports.authSocket = async function(socket){
};
return userDB;
+}
+
+module.exports.getChannelName = function(socket){
+ return socket.handshake.headers.referer.split('/c/')[1].split('/')[0];
}
\ No newline at end of file
diff --git a/www/js/channel/channel.js b/www/js/channel/channel.js
index 9198ee1..e63a8a0 100644
--- a/www/js/channel/channel.js
+++ b/www/js/channel/channel.js
@@ -67,6 +67,10 @@ class channel{
//Freak out any weirdos who take a peek in the dev console for shits n gigs
console.log("👁️👄👁️ ℬℴ𝓊𝓃𝒿ℴ𝓊𝓇.");
+ //Preach the good word about software which is Free as in Freedom
+ console.log(`Did you know Canopy, the software that runs '${utils.ux.getInstanceName()}' is software that is free as in freedom AND free weed?`);
+ console.log("This means you can read/modify/redistribute the code, run your own server, and even contribute back!");
+ console.log("https://git.ourfore.st/rainbownapkin/canopy");
}
/**
@@ -81,6 +85,7 @@ class channel{
};
this.socket = io(clientOptions);
+ this.queueBroadcastSocket = io("/queue-broadcast", clientOptions);
this.pmSocket = io("/pm", clientOptions);
}
diff --git a/www/js/utils.js b/www/js/utils.js
index 2db077a..1c25aeb 100644
--- a/www/js/utils.js
+++ b/www/js/utils.js
@@ -50,6 +50,10 @@ class canopyUXUtils{
constructor(){
}
+ getInstanceName(){
+ return document.querySelector("#instance-title a").innerText;
+ }
+
async awaitNextFrame(){
//return a new promise
return new Promise((resolve)=>{