diff --git a/.gitignore b/.gitignore
index 88e898a..76cfb45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,5 +9,4 @@ chatexamples.txt
server.cert
server.key
www/nonfree/*
-migration/*
-www/hrt.zip
\ No newline at end of file
+migration/*
\ No newline at end of file
diff --git a/README.md b/README.md
index a61d209..3be348e 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Canopy
-0.1-Alpha (Panama Red) - Hotfix 3
+0.4-INDEV
=========
Canopy - /ˈkæ.nə.pi/:
diff --git a/config.example.json b/config.example.json
index 7b869b3..5d8f957 100644
--- a/config.example.json
+++ b/config.example.json
@@ -34,10 +34,5 @@
"address": "toke@42069.weed",
"pass": "CHANGE_ME"
},
- "links":{
- "About": "/about",
- "Code": "https://git.ourfore.st/rainbownapkin/canopy",
- "HRT": "/hrt"
- },
"aboutText":"ourfore.st is the one and only original canopy instance. Setup, ran, and administered by rainbownapkin herself. This site exists to provide a featureful, preformant, and comfy replacement for the TTN community."
}
\ No newline at end of file
diff --git a/config.example.jsonc b/config.example.jsonc
index 3669d09..f315d9a 100644
--- a/config.example.jsonc
+++ b/config.example.jsonc
@@ -65,12 +65,6 @@
"address": "toke@42069.weed",
"pass": "CHANGE_ME"
},
- //Provides customizable links for navbar
- "links":{
- "About": "/about",
- "Code": "https://git.ourfore.st/rainbownapkin/canopy",
- "HRT": "/hrt"
- },
//Fills the 'about ${instanceName}' section on the /about page, lets users know about your specific instance
"aboutText":"ourfore.st is the one and only original canopy instance. Setup, ran, and administered by rainbownapkin herself. This site exists to provide a featureful, preformant, and comfy replacement for the TTN community."
}
\ No newline at end of file
diff --git a/package.json b/package.json
index 54af4f0..0076162 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,13 @@
{
- "name": "canopy-of-alpha",
- "version": "0.1.3",
- "canopyDisplayVersion": "0.1-Alpha (Panama Red) - Hotfix 3",
+ "name": "canopy-of-indev",
+ "version": "0.4",
"license": "AGPL-3.0-only",
"dependencies": {
"@braintree/sanitize-url": "^7.1.1",
- "altcha": "^2.3.0",
+ "altcha": "^1.0.7",
"altcha-lib": "^1.2.0",
"argon2": "^0.44.0",
- "bcrypt": "^6.0.0",
+ "bcrypt": "^5.1.1",
"bootstrap-icons": "^1.11.3",
"connect-mongo": "^5.1.0",
"cookie-parser": "^1.4.7",
@@ -20,8 +19,8 @@
"hls.js": "^1.6.2",
"mongoose": "^8.4.3",
"node-cron": "^3.0.3",
- "nodemailer": "^8.0.7",
- "socket.io": "^4.2.0",
+ "nodemailer": "^7.0.9",
+ "socket.io": "^4.8.1",
"youtube-dl-exec": "^3.0.20"
},
"scripts": {
diff --git a/src/app/channel/chatHandler.js b/src/app/channel/chatHandler.js
index 218f561..bc1e751 100644
--- a/src/app/channel/chatHandler.js
+++ b/src/app/channel/chatHandler.js
@@ -212,12 +212,6 @@ class chatHandler{
* @param {chat} chat - Chat Object representing the message to broadcast to the given channel
*/
relayChatObject(chan, chat){
- //If we have an empty chat
- if(chat.msg.length <= 0){
- //Drop it
- return;
- }
-
//Send out chat
this.server.io.in(chan).emit("chatMessage", chat);
diff --git a/src/app/channel/tokebot.js b/src/app/channel/tokebot.js
index 52743eb..6e41471 100644
--- a/src/app/channel/tokebot.js
+++ b/src/app/channel/tokebot.js
@@ -148,15 +148,6 @@ class tokebot{
//Add the toking user to the tokers map
this.tokers.set(commandObj.socket.user.user, commandObj.argumentArray[0].toLowerCase());
-
- if(this.tokeCounter <= 3){
- //Drop the toke timer
- clearTimeout(this.tokeTimer);
- //Roll the toke counter back to 3
- this.tokeCounter = 3;
- //Re-start the toke timer
- this.tokeTimer = setTimeout(this.countdown.bind(this), 1000);
- }
//If the user is already in the toke
}else{
//Tell them to fuck off
@@ -219,7 +210,7 @@ class tokebot{
//Decrement toke time
this.tokeCounter--;
//try again in another second
- this.tokeTimer = setTimeout(this.countdown.bind(this), 1000);
+ this.tokeTimer = setTimeout(this.countdown.bind(this), 1000)
}
/**
diff --git a/src/app/chatPreprocessor.js b/src/app/chatPreprocessor.js
index dc3d4bd..a4331ab 100644
--- a/src/app/chatPreprocessor.js
+++ b/src/app/chatPreprocessor.js
@@ -57,7 +57,7 @@ class chatPreprocessor{
//If we don't pass sanatization/validation turn this car around
if(!this.sanatizeCommand(commandObj)){
- return false;
+ return;
}
//split the command
diff --git a/src/controllers/404Controller.js b/src/controllers/404Controller.js
index 3e7a4e0..471ea16 100644
--- a/src/controllers/404Controller.js
+++ b/src/controllers/404Controller.js
@@ -26,5 +26,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 res.render('404', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
}
\ No newline at end of file
diff --git a/src/controllers/aboutController.js b/src/controllers/aboutController.js
index 249e931..2b32b84 100644
--- a/src/controllers/aboutController.js
+++ b/src/controllers/aboutController.js
@@ -16,7 +16,6 @@ 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');
@@ -24,5 +23,5 @@ const csrfUtils = require('../utils/csrfUtils');
//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 res.render('about', {aboutText: config.aboutText, instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
}
\ No newline at end of file
diff --git a/src/controllers/adminPanelController.js b/src/controllers/adminPanelController.js
index 6ecdaee..ca1a74c 100644
--- a/src/controllers/adminPanelController.js
+++ b/src/controllers/adminPanelController.js
@@ -42,7 +42,7 @@ module.exports.get = async function(req, res){
//Render out the page
return res.render('adminPanel', {
- instance: config.instanceName, links: config.links,
+ instance: config.instanceName,
user: req.session.user,
rankEnum: permissionModel.rankEnum,
chanGuide: chanGuide,
diff --git a/src/controllers/api/account/deleteController.js b/src/controllers/api/account/deleteController.js
index 0552da7..94b9cdf 100644
--- a/src/controllers/api/account/deleteController.js
+++ b/src/controllers/api/account/deleteController.js
@@ -33,14 +33,17 @@ module.exports.post = async function(req, res){
const data = matchedData(req);
//make sure we're not bullshitting ourselves here.
- if(user == null || user.user == null){
- return errorHandler(res, 'You must be logged in to delete your account!', 'unauthorized');
+ if(user == null){
+ res.status(400);
+ return res.send('Invalid Session! Cannot delete account while logged out!');
}
- const userDB = await userModel.findOne({user: user.user});
+ const userDB = await userModel.findOne(user);
+
if(!userDB){
- return errorHandler(res, 'User not found!', 'unauthorized');
+ res.status(400);
+ return res.send('Invalid User! Account must exist in order to delete!');
}
await userDB.nuke(data.pass);
diff --git a/src/controllers/api/account/emailChangeRequestController.js b/src/controllers/api/account/emailChangeRequestController.js
index 3108ab6..4791ba2 100644
--- a/src/controllers/api/account/emailChangeRequestController.js
+++ b/src/controllers/api/account/emailChangeRequestController.js
@@ -60,7 +60,7 @@ module.exports.post = async function(req, res){
//Look through DB and migration cache for existing email
- const existingDB = await userModel.findOne({email: new RegExp(`^${email}$`, 'i')});
+ const existingDB = await userModel.findOne({email: new RegExp(email, 'i')});
const needsMigration = userModel.migrationCache.emails.includes(email.toLowerCase());
//If the email is in use
diff --git a/src/controllers/api/account/loginController.js b/src/controllers/api/account/loginController.js
index be8685b..d509342 100644
--- a/src/controllers/api/account/loginController.js
+++ b/src/controllers/api/account/loginController.js
@@ -90,7 +90,7 @@ module.exports.post = async function(req, res){
const {user, pass} = matchedData(req);
//Look for the username in the migration DB
- const migrationDB = await migrationModel.findOne({user: new RegExp(`^${user}$`, 'i')});
+ const migrationDB = await migrationModel.findOne({user});
//If we found a migration profile
if(migrationDB != null){
diff --git a/src/controllers/api/account/updateController.js b/src/controllers/api/account/updateController.js
index bb3fd3f..befca96 100644
--- a/src/controllers/api/account/updateController.js
+++ b/src/controllers/api/account/updateController.js
@@ -46,13 +46,7 @@ module.exports.post = async function(req, res){
const {field, change} = data;
const {user} = req.session;
- //If the user is null
- if(user == null || user.user == null){
- //BEFORE YOU BREAK MY HEART!!!
- return errorHandler(res, 'You must be logged in to preform this action!', 'unauthorized');
- }
-
- const userDB = await userModel.findOne({user: user.user});
+ const userDB = await userModel.findOne(user);
const update = {};
@@ -92,7 +86,8 @@ module.exports.post = async function(req, res){
res.status(200);
return res.send(update);
}else{
- return errorHandler(res, 'User not found!', 'unauthorized');
+ res.status(400);
+ return res.send({errors: [{msg:"User not found!"}]});
}
}else{
res.status(400);
diff --git a/src/controllers/channelController.js b/src/controllers/channelController.js
index fef37a7..dd27fcd 100644
--- a/src/controllers/channelController.js
+++ b/src/controllers/channelController.js
@@ -22,5 +22,5 @@ const csrfUtils = require('../utils/csrfUtils');
//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)});
+ res.render('channel', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
}
\ No newline at end of file
diff --git a/src/controllers/channelSettingsController.js b/src/controllers/channelSettingsController.js
index 3559503..e310773 100644
--- a/src/controllers/channelSettingsController.js
+++ b/src/controllers/channelSettingsController.js
@@ -42,7 +42,7 @@ module.exports.get = async function(req, res){
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});
+ return res.render('channelSettings', {instance: config.instanceName, user: req.session.user, channel: chanDB, reqRank, rankEnum: permissionModel.rankEnum, csrfToken: csrfUtils.generateToken(req), unescape: validator.unescape});
}catch(err){
return exceptionHandler(res, err);
}
diff --git a/src/controllers/emailChangeController.js b/src/controllers/emailChangeController.js
index 6b0b99d..fb9cabd 100644
--- a/src/controllers/emailChangeController.js
+++ b/src/controllers/emailChangeController.js
@@ -40,18 +40,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 res.render('emailChange', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req), 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});
+ res.render('emailChange', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req), 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 res.render('emailChange', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req), 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 res.render('emailChange', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req), valid: false});
}
}
\ No newline at end of file
diff --git a/src/controllers/hrtController.js b/src/controllers/hrtController.js
deleted file mode 100644
index 7b1b920..0000000
--- a/src/controllers/hrtController.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*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 .*/
-
-//Config
-const config = require('../../config.json');
-const package = require('../../package.json');
-
-//Local Imports
-const csrfUtils = require('../utils/csrfUtils');
-
-//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)});
-}
\ No newline at end of file
diff --git a/src/controllers/indexController.js b/src/controllers/indexController.js
index a06cfec..30e9682 100644
--- a/src/controllers/indexController.js
+++ b/src/controllers/indexController.js
@@ -29,7 +29,7 @@ const {exceptionHandler, errorHandler} = require('../utils/loggerUtils');
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 res.render('index', {instance: config.instanceName, user: req.session.user, chanGuide: chanGuide, csrfToken: csrfUtils.generateToken(req), unescape: validator.unescape});
}catch(err){
return exceptionHandler(res, err);
}
diff --git a/src/controllers/loginController.js b/src/controllers/loginController.js
index ffa5fc8..a25d316 100644
--- a/src/controllers/loginController.js
+++ b/src/controllers/loginController.js
@@ -45,7 +45,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 res.render('lockedAccount', {instance: config.instanceName, user: req.session.user, csrfToken: csrfUtils.generateToken(req)});
}
//If the users login's are being throttled
@@ -56,16 +56,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 res.render('login', {instance: config.instanceName, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
}
//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 res.render('login', {instance: config.instanceName, user: req.session.user, challenge: null, csrfToken: csrfUtils.generateToken(req)});
}
//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 res.render('login', {instance: config.instanceName, user: req.session.user, challenge: null, csrfToken: csrfUtils.generateToken(req)});
}
}
\ No newline at end of file
diff --git a/src/controllers/migrateController.js b/src/controllers/migrateController.js
index a46d3b2..ea82e5e 100644
--- a/src/controllers/migrateController.js
+++ b/src/controllers/migrateController.js
@@ -27,5 +27,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 res.render('migrate', {instance: config.instanceName, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
}
\ No newline at end of file
diff --git a/src/controllers/newChannelController.js b/src/controllers/newChannelController.js
index 233c99a..ee77166 100644
--- a/src/controllers/newChannelController.js
+++ b/src/controllers/newChannelController.js
@@ -27,5 +27,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 res.render('newChannel', {instance: config.instanceName, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
}
\ No newline at end of file
diff --git a/src/controllers/panel/popoutContainerController.js b/src/controllers/panel/popoutContainerController.js
index 619cf18..6993f9e 100644
--- a/src/controllers/panel/popoutContainerController.js
+++ b/src/controllers/panel/popoutContainerController.js
@@ -19,5 +19,5 @@ const config = require('../../../config.json');
//popout panel container functions
module.exports.get = async function(req, res){
- res.render('popoutContainer', {instance: config.instanceName, links: config.links});
+ res.render('popoutContainer', {instance: config.instanceName});
}
\ No newline at end of file
diff --git a/src/controllers/passwordResetController.js b/src/controllers/passwordResetController.js
index 5fd392c..1d47fae 100644
--- a/src/controllers/passwordResetController.js
+++ b/src/controllers/passwordResetController.js
@@ -47,11 +47,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 res.render('passwordReset', {instance: config.instanceName, user: req.session.user, challenge, token, csrfToken: csrfUtils.generateToken(req)});
//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 res.render('passwordReset', {instance: config.instanceName, user: req.session.user, challenge, token: null, csrfToken: csrfUtils.generateToken(req)});
}
}catch(err){
return exceptionHandler(res, err);
diff --git a/src/controllers/profileController.js b/src/controllers/profileController.js
index df5b9c2..67d1895 100644
--- a/src/controllers/profileController.js
+++ b/src/controllers/profileController.js
@@ -42,7 +42,7 @@ module.exports.get = async function(req, res){
const presence = await presenceUtils.getPresence(profile.user);
res.render('profile', {
- instance: config.instanceName, links: config.links,
+ instance: config.instanceName,
user: req.session.user,
profile,
selfProfile,
@@ -52,7 +52,7 @@ module.exports.get = async function(req, res){
});
}else{
res.render('profile', {
- instance: config.instanceName, links: config.links,
+ instance: config.instanceName,
user: req.session.user,
profile: null,
selfProfile: false,
diff --git a/src/controllers/registerController.js b/src/controllers/registerController.js
index 9f2eb14..91fb5b0 100644
--- a/src/controllers/registerController.js
+++ b/src/controllers/registerController.js
@@ -27,5 +27,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 res.render('register', {instance: config.instanceName, user: req.session.user, challenge, csrfToken: csrfUtils.generateToken(req)});
}
\ No newline at end of file
diff --git a/src/routers/hrtRouter.js b/src/routers/hrtRouter.js
deleted file mode 100644
index bcf314b..0000000
--- a/src/routers/hrtRouter.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*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 .*/
-
-//npm imports
-const { Router } = require('express');
-
-
-//local imports
-const hrtController = require("../controllers/hrtController");
-const presenceUtils = require("../utils/presenceUtils");
-
-//globals
-const router = Router();
-
-//Use presence middleware
-router.use(presenceUtils.presenceMiddleware);
-
-//routing functions
-router.get('/', hrtController.get);
-
-module.exports = router;
diff --git a/src/schemas/emoteSchema.js b/src/schemas/emoteSchema.js
index 8a35dc5..c059a0c 100644
--- a/src/schemas/emoteSchema.js
+++ b/src/schemas/emoteSchema.js
@@ -51,11 +51,8 @@ const emoteSchema = new mongoose.Schema({
* Post-Save function, ensures all new emotes are broadcastes to actively connected clients
*/
emoteSchema.post('save', async function (next){
- //Ensure the channel manager is actually up
- if(server.channelManager != null){
- //broadcast updated emotes
- server.channelManager.broadcastSiteEmotes();
- }
+ //broadcast updated emotes
+ server.channelManager.broadcastSiteEmotes();
});
/**
diff --git a/src/schemas/tokebot/tokeCommandSchema.js b/src/schemas/tokebot/tokeCommandSchema.js
index 635f487..892b7d0 100644
--- a/src/schemas/tokebot/tokeCommandSchema.js
+++ b/src/schemas/tokebot/tokeCommandSchema.js
@@ -36,20 +36,15 @@ const tokeCommandSchema = new mongoose.Schema({
* Pre-Save middleware, ensures tokebot receives all new toke commands
*/
tokeCommandSchema.pre('save', async function (next){
- //if the channel manager, chat handler, and chat post-processor are all loaded up...
+ //if the command was changed
if(this.isModified("command")){
- if(server.channelManager != null &&
- server.channelManager.chatHandler != null &&
- server.channelManager.chatHandler.chatPreprocessor != null){
+ //Get server tokebot object
+ const tokebot = server.channelManager.chatHandler.chatPreprocessor.tokebot;
- //Get server tokebot object
- const tokebot = server.channelManager.chatHandler.chatPreprocessor.tokebot;
-
- //If tokebot is up and running
- if(tokebot != null && tokebot.tokeCommands != null){
- //Pop the command on to the end
- tokebot.tokeCommands.push(this.command);
- }
+ //If tokebot is up and running
+ if(tokebot != null && tokebot.tokeCommands != null){
+ //Pop the command on to the end
+ tokebot.tokeCommands.push(this.command);
}
}
diff --git a/src/schemas/user/migrationSchema.js b/src/schemas/user/migrationSchema.js
index 4e61ce0..c17ed51 100644
--- a/src/schemas/user/migrationSchema.js
+++ b/src/schemas/user/migrationSchema.js
@@ -217,22 +217,13 @@ migrationSchema.statics.ingestLegacyUser = async function(rawProfile){
return;
}
- //Pull rank, dropping over-ranked users down to current enum length
- let rank = Math.min(Math.max(0, profileArray[3]), permissionModel.rankEnum.length - 1);
-
- //If this user was a mod on the old site
- if(rank == 2){
- //Set them up as a mod here
- rank = permissionModel.rankEnum.length - 2;
- }
-
//Create migration profile object from scraped info
const migrationProfile = new this({
user: profileArray[1],
pass: profileArray[2],
//Clamp rank to 0 and the max setting allowed by the rank enum
- rank,
+ rank: Math.min(Math.max(0, profileArray[3]), permissionModel.rankEnum.length - 1),
email: validator.normalizeEmail(profileArray[4]),
date: profileArray[7],
})
@@ -323,7 +314,7 @@ migrationSchema.statics.buildMigrationCache = async function(){
migrationSchema.statics.consumeByUsername = async function(ip, migration){
//Pull migration doc by case-insensitive username
- const migrationDB = await this.findOne({user: new RegExp(`^${migration.user}$`, 'i')});
+ const migrationDB = await this.findOne({user: new RegExp(migration.user, 'i')});
//If we have no migration document
if(migrationDB == null){
diff --git a/src/schemas/user/userSchema.js b/src/schemas/user/userSchema.js
index 783b241..41dfcda 100644
--- a/src/schemas/user/userSchema.js
+++ b/src/schemas/user/userSchema.js
@@ -256,13 +256,13 @@ userSchema.statics.register = async function(userObj, ip){
//Check password confirmation matches
if(pass == passConfirm){
//Setup user query
- let userQuery = {user: new RegExp(`^${user}$`, 'i')};
+ let userQuery = {user: new RegExp(user, 'i')};
//If we have an email
if(email != null && email != ""){
userQuery = {$or: [
userQuery,
- {email: new RegExp(`^${email}$`, 'i')}
+ {email: new RegExp(email, 'i')}
]};
}
@@ -319,7 +319,7 @@ userSchema.statics.authenticate = async function(user, pass, failLine = "Bad Use
}
//get the user if it exists
- const userDB = await this.findOne({ user: new RegExp(`^${user}$`, 'i')});
+ const userDB = await this.findOne({ user: new RegExp(user, 'i')});
//if not scream and shout
if(!userDB){
diff --git a/src/server.js b/src/server.js
index 228d555..50dcda0 100644
--- a/src/server.js
+++ b/src/server.js
@@ -55,7 +55,6 @@ const fileNotFoundController = require('./controllers/404Controller');
//Humie-Friendly
const indexRouter = require('./routers/indexRouter');
const aboutRouter = require('./routers/aboutRouter');
-const hrtRouter = require('./routers/hrtRouter');
const registerRouter = require('./routers/registerRouter');
const loginRouter = require('./routers/loginRouter');
const profileRouter = require('./routers/profileRouter');
@@ -76,7 +75,6 @@ const apiRouter = require('./routers/apiRouter');
//Define Config variables
const config = require('../config.json');
-const package = require('../package.json');
const port = config.port;
const dbUrl = `mongodb://${config.db.user}:${config.db.pass}@${config.db.address}:${config.db.port}/${config.db.database}`;
@@ -180,7 +178,6 @@ app.use(sessionUtils.rememberMeMiddleware);
//Humie-Friendly
app.use('/', indexRouter);
app.use('/about', aboutRouter);
-app.use('/hrt', hrtRouter);
app.use('/register', registerRouter);
app.use('/login', loginRouter);
app.use('/profile', profileRouter);
@@ -211,7 +208,7 @@ Might be better if she kicked off everything at once, and ran a while loop to ch
This runs once at server startup, and most startups will run fairly quickly so... Not worth it?*/
async function asyncKickStart(){
//Lettum fuckin' know wassup
- console.log(`${config.instanceName}(Powered by Canopy ${package.canopyDisplayVersion}) is booting up!`);
+ console.log(`${config.instanceName}(Powered by Canopy) is booting up!`);
//Run legacy migration
await migrationModel.ingestLegacyDump();
diff --git a/src/utils/linkUtils.js b/src/utils/linkUtils.js
index 76b8e45..9e85870 100644
--- a/src/utils/linkUtils.js
+++ b/src/utils/linkUtils.js
@@ -14,9 +14,6 @@ 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!
const {sanitizeUrl} = require("@braintree/sanitize-url");
@@ -35,15 +32,6 @@ module.exports.cache = new Map();
module.exports.markLink = async function(dirtyLink){
const link = sanitizeUrl(dirtyLink);
- //If this link is referencing this web server
- if(link.match(new RegExp(`^${config.protocol}://${config.domain}`)) != null){
- //Lazily return it as a good link, since we know it'll at least return a good 404 page XP
- return {
- link,
- type: "link"
- }
- }
-
//Check link cache for the requested link
const cachedLink = module.exports.cache.get(link);
@@ -117,4 +105,4 @@ module.exports.markLink = async function(dirtyLink){
//return the link
return linkObj;
-}
+}
\ No newline at end of file
diff --git a/src/utils/media/yanker.js b/src/utils/media/yanker.js
index cb6697b..2dff869 100644
--- a/src/utils/media/yanker.js
+++ b/src/utils/media/yanker.js
@@ -131,7 +131,7 @@ module.exports.getMediaType = async function(dirtyURL){
}
//If we have link to a resource from archive.org
- if(match = url.match(/archive\.org\/(?:details|download)\/(.+)/)){
+ if(match = url.match(/archive\.org\/(?:details|download)\/([a-zA-Z0-9\/._-\s\%]+)/)){
//return internet archive upload id and filepath
return {
type: "ia",
diff --git a/src/views/about.ejs b/src/views/about.ejs
index cebfc35..8842ff0 100644
--- a/src/views/about.ejs
+++ b/src/views/about.ejs
@@ -40,8 +40,6 @@ along with this program. If not, see . %>
it was decided that the original cytube fork, fore.st, had been run past it's prime. In summer/fall 2024, work began on a
replacement. The resulting software became Canopy, which was
first used to run the ourfore.st instance in late 2025.
-
-
Canopy Ver: <%= version %>
- <%- include('partial/navbar', {user}); %>
-
-
Bowie's DIY HRT Archive
-
-
- This page is an attempt at putting together everything I know about DIY HRT.
-
- So far I have used Homebrew Sublingual Oil from Open Gate Labs with great results, and have received a small batch of raw estradoil from Dragon Ordnance.
-
- I am currently in the process of figuring out brewing my own sublingual oil.
-
-
- This page is not intended to be a replacement for professional medical advice, merely an attempt at harm reduction for my friends.
- It should be used at most as a starting point for research. Everyone's HRT experience, and really transition, are unique and individual journeys.
- Take the time to do the best research you can, to make sure you're starting and continuing yours correctly.
-
-
- Much love, and remember to take your meds!
-
- -rainbownapkin <3
-
-
-
-
diff --git a/src/views/hrt.ejs b/src/views/hrt.ejs
deleted file mode 100644
index 8777403..0000000
--- a/src/views/hrt.ejs
+++ /dev/null
@@ -1,56 +0,0 @@
-<%# 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 . %>
-
-
-