+
<% } %>
\ No newline at end of file
diff --git a/www/css/theme/the-network-classic.css b/www/css/theme/the-network-classic.css
index 1ccbee5..ae6e229 100644
--- a/www/css/theme/the-network-classic.css
+++ b/www/css/theme/the-network-classic.css
@@ -336,6 +336,14 @@ input.control-prompt, input.control-prompt:focus{
padding-right: 0.5em;
}
+.navbar-item.first{
+ margin-left: 0.25em;
+}
+
+.navbar-item-seperator.first{
+ display: none;
+}
+
/* index */
.channel-guide-entry{
background-color: var(--bg1);
diff --git a/www/js/channel/channel.js b/www/js/channel/channel.js
index 0782a38..f519cbe 100644
--- a/www/js/channel/channel.js
+++ b/www/js/channel/channel.js
@@ -145,11 +145,19 @@ class channel{
this.user.permMap.chan = new Map(data.user.permMap.chan);
//If we can read the schedule
- if(client.user.permMap.chan.get('readSchedule')){
+ if(this.user.permMap.chan.get('readSchedule')){
//Display the queue icon
this.chatBox.adminIcon.style.display = "";
}
+ //If we can manage the channel
+ if(this.user.permMap.chan.get('manageChannel')){
+ //Unhide the channel settings button
+ document.querySelector('.navbar-item#channel-settings-button-span').style.display = "";
+ //Annoyingly, there isn't a good way in html to set a links relative filepath to use the current 'file' as a directory
+ document.querySelector('.navbar-item#channel-settings-button-span a').href = `${document.URL}/settings`;
+ }
+
//Tell the chatbox to handle client info
//should it have its own event listener instead? Guess it's a stylistic choice :P
this.chatBox.handleClientInfo(data);
@@ -218,6 +226,17 @@ class channel{
return results;
}
+ insertSettingsIcon(){
+ const settingsIcon = document.createElement('i');
+ settingsIcon.classList.add('navbar-item', 'bi-projector-fill');
+ settingsIcon.id = "channel-settings-button";
+
+ //Insert settings icon into navbar
+ document.querySelector('.navbar-item#logout-button').insertAdjacentElement('beforebegin', settingsIcon);
+ //Insert icon seperator
+ settingsIcon.insertAdjacentText('afterend', ' - ');
+ }
+
/**
* Processes and applies default config on any unset settings
* @param {Boolean} force - Whether or not to forcefully reset already set settings
From 03fecaddc2cce2dc074e2648c9399f1ce35e9d89 Mon Sep 17 00:00:00 2001
From: rainbow napkin
Date: Sat, 17 Oct 2026 02:38:50 -0400
Subject: [PATCH 2/3] Centralized navbar template rendering property
definitions.
---
src/controllers/404Controller.js | 7 ++--
src/controllers/aboutController.js | 4 +--
src/controllers/adminPanelController.js | 7 ++--
src/controllers/channelController.js | 7 ++--
src/controllers/channelSettingsController.js | 17 ++++++---
src/controllers/emailChangeController.js | 13 +++----
src/controllers/hrtController.js | 8 ++---
src/controllers/indexController.js | 7 ++--
src/controllers/loginController.js | 13 +++----
src/controllers/migrateController.js | 7 ++--
src/controllers/navRender.js | 36 ++++++++++++++++++++
src/controllers/newChannelController.js | 7 ++--
src/controllers/passwordResetController.js | 9 ++---
src/controllers/profileController.js | 15 ++------
src/controllers/registerController.js | 7 ++--
src/controllers/streamInfoController.js | 8 ++---
16 files changed, 84 insertions(+), 88 deletions(-)
create mode 100644 src/controllers/navRender.js
diff --git a/src/controllers/404Controller.js b/src/controllers/404Controller.js
index 03f08aa..d1cb234 100644
--- a/src/controllers/404Controller.js
+++ b/src/controllers/404Controller.js
@@ -14,11 +14,8 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//Local Imports
-const csrfUtils = require('../utils/csrfUtils');
+const navRender = require('./navRender');
//register page functions
module.exports = async function(req, res){
@@ -26,5 +23,5 @@ module.exports = async function(req, res){
res.status(404);
//Render page
- return res.render('404', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, '404');
}
\ No newline at end of file
diff --git a/src/controllers/aboutController.js b/src/controllers/aboutController.js
index 11c6faf..a1f72b4 100644
--- a/src/controllers/aboutController.js
+++ b/src/controllers/aboutController.js
@@ -19,10 +19,10 @@ const config = require('../../config.json');
const package = require('../../package.json');
//Local Imports
-const csrfUtils = require('../utils/csrfUtils');
+const navRender = require('./navRender');
//register page functions
module.exports.get = async function(req, res){
//Render page
- return res.render('about', {aboutText: config.aboutText, instance: config.instanceName, links: config.links, user: req.session.user, version: package.canopyDisplayVersion, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'about', {aboutText: config.aboutText, version: package.canopyDisplayVersion});
}
\ No newline at end of file
diff --git a/src/controllers/adminPanelController.js b/src/controllers/adminPanelController.js
index 53c8f55..a27eba7 100644
--- a/src/controllers/adminPanelController.js
+++ b/src/controllers/adminPanelController.js
@@ -21,10 +21,10 @@ const config = require('../../config.json');
const validator = require('validator');//No express here, so regular validator it is!
//Local Imports
+const navRender = require('./navRender');
const {userModel} = require('../schemas/user/userSchema');
const permissionModel = require('../schemas/permissionSchema');
const channelModel = require('../schemas/channel/channelSchema');
-const csrfUtils = require('../utils/csrfUtils');
const {exceptionHandler, errorHandler} = require("../utils/loggerUtils");
//register page functions
@@ -41,14 +41,11 @@ module.exports.get = async function(req, res){
delete permList.__v;
//Render out the page
- return res.render('adminPanel', {
- instance: config.instanceName, links: config.links,
- user: req.session.user,
+ return navRender.render(req, res, 'adminPanel', {
rankEnum: permissionModel.rankEnum,
chanGuide: chanGuide,
userList: userList,
permList: permList,
- csrfToken: csrfUtils.generateToken(req),
unescape: validator.unescape
});
diff --git a/src/controllers/channelController.js b/src/controllers/channelController.js
index 1367a47..0ecd09d 100644
--- a/src/controllers/channelController.js
+++ b/src/controllers/channelController.js
@@ -14,13 +14,10 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//Local Imports
-const csrfUtils = require('../utils/csrfUtils');
+const navRender = require('./navRender');
//channel functions
module.exports.get = function(req, res){
- res.render('channel', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'channel');
}
\ No newline at end of file
diff --git a/src/controllers/channelSettingsController.js b/src/controllers/channelSettingsController.js
index 08503ca..f57ebbd 100644
--- a/src/controllers/channelSettingsController.js
+++ b/src/controllers/channelSettingsController.js
@@ -14,35 +14,42 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//NPM Imports
const validator = require('validator');//No express here, so regular validator it is!
//local imports
+const navRender = require('./navRender');
const channelModel = require('../schemas/channel/channelSchema');
const permissionModel = require('../schemas/permissionSchema');
-const csrfUtils = require('../utils/csrfUtils');
const {exceptionHandler, errorHandler} = require('../utils/loggerUtils');
//root index functions
module.exports.get = async function(req, res){
try{
+ //Get chan name and pull from DB
const chanName = (req.url.slice(1).replace('/settings',''));
const chanDB = await channelModel.findOne({name: chanName});
const reqRank = await chanDB.getChannelRank(req.session.user);
+ //gank user objects and stuffem into the rank list
await chanDB.populate("rankList.user");
//Take out the permissions doc id since we don't need it.
delete chanDB.permissions._doc._id;
+ //If the channel doesnt exist
if(chanDB == null){
+ //Pitch a fit
throw loggerUtils.exceptionSmith("Channel not found.", "queue");
}
- return res.render('channelSettings', {instance: config.instanceName, links: config.links, user: req.session.user, channel: chanDB, reqRank, rankEnum: permissionModel.rankEnum, csrfToken: csrfUtils.generateToken(req), unescape: validator.unescape});
+ //REnder dat bitch out
+ return navRender.render(req, res, 'channelSettings', {
+ channel: chanDB,
+ reqRank,
+ rankEnum: permissionModel.rankEnum,
+ unescape: validator.unescape
+ });
}catch(err){
return exceptionHandler(res, err);
}
diff --git a/src/controllers/emailChangeController.js b/src/controllers/emailChangeController.js
index 3085410..8df413f 100644
--- a/src/controllers/emailChangeController.js
+++ b/src/controllers/emailChangeController.js
@@ -14,15 +14,12 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//NPM Imports
const {validationResult, matchedData} = require('express-validator');
//local imports
+const navRender = require('./navRender');
const emailChangeModel = require('../schemas/user/emailChangeSchema');
-const csrfUtils = require('../utils/csrfUtils');
//gateway for resetting password
module.exports.get = async function(req, res){
@@ -40,18 +37,18 @@ module.exports.get = async function(req, res){
//If we have an invalid request
if(requestDB == null){
- return res.render('emailChange', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req), valid: false});
+ return navRender.render(req, res, 'emailChange', {valid: false});
}
//Speak of our success (don't wait for the emails to be sent)
- res.render('emailChange', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req), valid: true});
+ navRender.render(req, res, 'emailChange', {valid: true});
//Consume the request
await requestDB.consume();
}else{
- return res.render('emailChange', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req), valid: false});
+ return navRender.render(req, res, 'emailChange', {valid: false});
}
}catch(err){
- return res.render('emailChange', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req), valid: false});
+ return navRender.render(req, res, 'emailChange', {valid: false});
}
}
\ No newline at end of file
diff --git a/src/controllers/hrtController.js b/src/controllers/hrtController.js
index 6e4cbf4..9d26113 100644
--- a/src/controllers/hrtController.js
+++ b/src/controllers/hrtController.js
@@ -14,15 +14,11 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-const package = require('../../package.json');
-
//Local Imports
-const csrfUtils = require('../utils/csrfUtils');
+const navRender = require('./navRender');
//register page functions
module.exports.get = async function(req, res){
//Render page
- return res.render('hrt', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res,'hrt');
}
\ No newline at end of file
diff --git a/src/controllers/indexController.js b/src/controllers/indexController.js
index 3e30983..537656f 100644
--- a/src/controllers/indexController.js
+++ b/src/controllers/indexController.js
@@ -14,22 +14,19 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//NPM Imports
const validator = require('validator');//No express here, so regular validator it is!
//local imports
+const navRender = require('./navRender');
const channelModel = require('../schemas/channel/channelSchema');
-const csrfUtils = require('../utils/csrfUtils');
const {exceptionHandler, errorHandler} = require('../utils/loggerUtils');
//root index functions
module.exports.get = async function(req, res){
try{
const chanGuide = await channelModel.getChannelList();
- return res.render('index', {instance: config.instanceName, links: config.links, user: req.session.user, chanGuide: chanGuide, csrfToken: csrfUtils.generateToken(req), unescape: validator.unescape});
+ return navRender.render(req, res, 'index', {chanGuide: chanGuide, unescape: validator.unescape})
}catch(err){
return exceptionHandler(res, err);
}
diff --git a/src/controllers/loginController.js b/src/controllers/loginController.js
index 58fd64a..06aafea 100644
--- a/src/controllers/loginController.js
+++ b/src/controllers/loginController.js
@@ -14,16 +14,13 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//NPM Imports
const {validationResult, matchedData} = require('express-validator');
//Local Imports
+const navRender = require('./navRender');
const sessionUtils = require('../utils/sessionUtils');
const altchaUtils = require('../utils/altchaUtils');
-const csrfUtils = require('../utils/csrfUtils');
//register page functions
module.exports.get = async function(req, res){
@@ -45,7 +42,7 @@ module.exports.get = async function(req, res){
//if we have previous attempts for this user
if(attempts != null){
if(attempts.count > sessionUtils.maxAttempts){
- return res.render('lockedAccount', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'lockedAccount');
}
//If the users login's are being throttled
@@ -56,16 +53,16 @@ module.exports.get = async function(req, res){
const challenge = await altchaUtils.genCaptcha(difficulty, user);
//Render page
- return res.render('login', {instance: config.instanceName, links: config.links, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'login', {challenge});
}
//otherwise
}else{
//Render generic page
- return res.render('login', {instance: config.instanceName, links: config.links, user: req.session.user, challenge: null, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'login', {challenge: null});
}
//if we received invalid input
}else{
//Render pretend nothing happened, send out a generic page
- return res.render('login', {instance: config.instanceName, links: config.links, user: req.session.user, challenge: null, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'login', {challenge: null});
}
}
\ No newline at end of file
diff --git a/src/controllers/migrateController.js b/src/controllers/migrateController.js
index d069956..b386d86 100644
--- a/src/controllers/migrateController.js
+++ b/src/controllers/migrateController.js
@@ -14,12 +14,9 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//Local Imports
+const navRender = require('./navRender');
const altchaUtils = require('../utils/altchaUtils');
-const csrfUtils = require('../utils/csrfUtils');
//register page functions
module.exports.get = async function(req, res){
@@ -27,5 +24,5 @@ module.exports.get = async function(req, res){
const challenge = await altchaUtils.genCaptcha();
//Render page
- return res.render('migrate', {instance: config.instanceName, links: config.links, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'migrate', {challenge});
}
\ No newline at end of file
diff --git a/src/controllers/navRender.js b/src/controllers/navRender.js
new file mode 100644
index 0000000..53fc198
--- /dev/null
+++ b/src/controllers/navRender.js
@@ -0,0 +1,36 @@
+/*Canopy - The next generation of stoner streaming software
+Copyright (C) 2024-2026 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 .*/
+
+//Config
+const config = require('../../config.json');
+
+//Local Imports
+const csrfUtils = require('../utils/csrfUtils');
+
+/* You could make the argument this should be middleware that passes a properties object to user
+ But then I'd writing out all the other controllers properties as I am below, or worse. Not a great option.*/
+//Renders a given page with properties required for the navbar
+module.exports.render = async function(req, res, template, properties = {}){
+
+ //Set required properties on top of passed object
+ properties.instance = config.instanceName;
+ properties.links = config.links;
+ properties.user = req.session.user
+ properties.csrfToken = csrfUtils.generateToken(req)
+
+ //Render out template, passing given properties with navbar required properties added
+ return res.render(template, properties);
+}
\ No newline at end of file
diff --git a/src/controllers/newChannelController.js b/src/controllers/newChannelController.js
index 73101b0..224a5df 100644
--- a/src/controllers/newChannelController.js
+++ b/src/controllers/newChannelController.js
@@ -15,11 +15,8 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .*/
//Local Imports
+const navRender = require('./navRender');
const altchaUtils = require('../utils/altchaUtils');
-const csrfUtils = require('../utils/csrfUtils');
-
-//Config
-const config = require('../../config.json');
//root index functions
module.exports.get = async function(req, res){
@@ -27,5 +24,5 @@ module.exports.get = async function(req, res){
const challenge = await altchaUtils.genCaptcha();
//render the page
- return res.render('newChannel', {instance: config.instanceName, links: config.links, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'newChannel', {challenge});
}
\ No newline at end of file
diff --git a/src/controllers/passwordResetController.js b/src/controllers/passwordResetController.js
index 2aa81f4..b7b22f2 100644
--- a/src/controllers/passwordResetController.js
+++ b/src/controllers/passwordResetController.js
@@ -14,15 +14,12 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//npm imports
const {validationResult, matchedData} = require('express-validator');
//Local Imports
+const navRender = require('./navRender');
const altchaUtils = require('../utils/altchaUtils');
-const csrfUtils = require('../utils/csrfUtils');
//register page functions
module.exports.get = async function(req, res){
@@ -47,11 +44,11 @@ module.exports.get = async function(req, res){
*/
//Render page
- return res.render('passwordReset', {instance: config.instanceName, links: config.links, user: req.session.user, challenge, token, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'passwordReset', {challenge, token});
//If we didn't get a valid token
}else{
//otherwise render generic page
- return res.render('passwordReset', {instance: config.instanceName, links: config.links, user: req.session.user, challenge, token: null, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'passwordReset', {challenge, token: null});
}
}catch(err){
return exceptionHandler(res, err);
diff --git a/src/controllers/profileController.js b/src/controllers/profileController.js
index e35f195..cb7c846 100644
--- a/src/controllers/profileController.js
+++ b/src/controllers/profileController.js
@@ -15,17 +15,14 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .*/
//Local Imports
+const navRender = require('./navRender');
const {userModel} = require('../schemas/user/userSchema');
-const csrfUtils = require('../utils/csrfUtils');
const presenceUtils = require('../utils/presenceUtils');
const {exceptionHandler, errorHandler} = require('../utils/loggerUtils');
//NPM Imports
const validator = require('validator');//No express here, so regular validator it is!
-//Config
-const config = require('../../config.json');
-
//profile functions
module.exports.get = async function(req, res){
@@ -41,23 +38,17 @@ module.exports.get = async function(req, res){
//Pull presence (should be quick since everyone whos been on since last startup will be backed in RAM)
const presence = await presenceUtils.getPresence(profile.user);
- res.render('profile', {
- instance: config.instanceName, links: config.links,
- user: req.session.user,
+ navRender.render(req, res, 'profile', {
profile,
selfProfile,
presence,
- csrfToken: csrfUtils.generateToken(req),
unescape: validator.unescape
});
}else{
- res.render('profile', {
- instance: config.instanceName, links: config.links,
- user: req.session.user,
+ navRender.render(req, res, 'profile', {
profile: null,
selfProfile: false,
presence: null,
- csrfToken: csrfUtils.generateToken(req),
unescape: validator.unescape
});
}
diff --git a/src/controllers/registerController.js b/src/controllers/registerController.js
index f9b9d67..89c8aaa 100644
--- a/src/controllers/registerController.js
+++ b/src/controllers/registerController.js
@@ -14,12 +14,9 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-
//Local Imports
+const navRender = require('./navRender');
const altchaUtils = require('../utils/altchaUtils');
-const csrfUtils = require('../utils/csrfUtils');
//register page functions
module.exports.get = async function(req, res){
@@ -27,5 +24,5 @@ module.exports.get = async function(req, res){
const challenge = await altchaUtils.genCaptcha();
//Render page
- return res.render('register', {instance: config.instanceName, links: config.links, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'register', {challenge});
}
\ No newline at end of file
diff --git a/src/controllers/streamInfoController.js b/src/controllers/streamInfoController.js
index 22aef11..05644db 100644
--- a/src/controllers/streamInfoController.js
+++ b/src/controllers/streamInfoController.js
@@ -14,15 +14,11 @@ 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 .*/
-//Config
-const config = require('../../config.json');
-const package = require('../../package.json');
-
//Local Imports
-const csrfUtils = require('../utils/csrfUtils');
+const navRender = require('./navRender');
//register page functions
module.exports.get = async function(req, res){
//Render page
- return res.render('streamInfo', {instance: config.instanceName, links: config.links, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
+ return navRender.render(req, res, 'streamInfo');
}
\ No newline at end of file
From 05c1875158b06b5de132e69f9992dd71a407c1d1 Mon Sep 17 00:00:00 2001
From: rainbow napkin
Date: Sat, 17 Oct 2026 03:57:16 -0400
Subject: [PATCH 3/3] Finished re-working navbar
---
src/controllers/navRender.js | 2 ++
src/utils/presenceUtils.js | 22 ++++++++++++++++++++-
src/views/partial/navbar.ejs | 28 ++++++++++++++++++---------
www/css/global.css | 9 +++++++++
www/css/theme/the-network-classic.css | 3 ++-
5 files changed, 53 insertions(+), 11 deletions(-)
diff --git a/src/controllers/navRender.js b/src/controllers/navRender.js
index 53fc198..57dc8ca 100644
--- a/src/controllers/navRender.js
+++ b/src/controllers/navRender.js
@@ -19,6 +19,7 @@ const config = require('../../config.json');
//Local Imports
const csrfUtils = require('../utils/csrfUtils');
+const presenceUtils = require('../utils/presenceUtils');
/* You could make the argument this should be middleware that passes a properties object to user
But then I'd writing out all the other controllers properties as I am below, or worse. Not a great option.*/
@@ -30,6 +31,7 @@ module.exports.render = async function(req, res, template, properties = {}){
properties.links = config.links;
properties.user = req.session.user
properties.csrfToken = csrfUtils.generateToken(req)
+ properties.userCount = (await presenceUtils.getOnlineUsers()).length;
//Render out template, passing given properties with navbar required properties added
return res.render(template, properties);
diff --git a/src/utils/presenceUtils.js b/src/utils/presenceUtils.js
index 87acb97..35326ba 100644
--- a/src/utils/presenceUtils.js
+++ b/src/utils/presenceUtils.js
@@ -28,6 +28,26 @@ const tolerance = 2 * (60 * 1000);
//Defaults to five minutes
const offlineTimeout = 5 * (60 * 1000);
+module.exports.getOnlineUsers = async function(){
+ //Define array to hold list of online users
+ const users = [];
+
+ //Iterate through all users in the RAM-Backed activity map (only ones that would be online)
+ for(const key of Array.from(activityMap.keys())){
+ //Grab current user, should grab from ram since we're polling activityMap
+ const user = await module.exports.getPresence(key);
+
+ //If the user is online
+ if(user.status == "Streaming" || user.status == "Recently Active"){
+ //Addem' to da list
+ users.push(user);
+ }
+ }
+
+ //Return all found users
+ return users;
+}
+
module.exports.getPresence = async function(user, userDB){
//If we don't have a user
if(user == null || user == '' || user == 'Tokebot'){
@@ -44,7 +64,7 @@ module.exports.getPresence = async function(user, userDB){
//If we couldn't find anything in RAM
if(activity == null){
- //If we wheren't handed a free user doc
+ //If we wheren't handed a free user doc, and we're allowed to pull from DB
if(userDB == null){
//Pull one from the username
userDB = await userModel.findOne({user: user});
diff --git a/src/views/partial/navbar.ejs b/src/views/partial/navbar.ejs
index db80667..696805b 100644
--- a/src/views/partial/navbar.ejs
+++ b/src/views/partial/navbar.ejs
@@ -14,28 +14,33 @@ 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 . %>