canopy/src/server.js

206 lines
6.2 KiB
JavaScript

/*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 <https://www.gnu.org/licenses/>.*/
//Define global crypto variable for altcha
globalThis.crypto = require('node:crypto').webcrypto;
//Define NODE imports
const https = require('https');
const fs = require('fs');
//Define NPM imports
const express = require('express');
const session = require('express-session');
const {createServer } = require('http');
const { Server } = require('socket.io');
const path = require('path');
const mongoStore = require('connect-mongo');
const mongoose = require('mongoose');
//Define Local Imports
//Application
const channelManager = require('./app/channel/channelManager');
//Util
const configCheck = require('./utils/configCheck');
const scheduler = require('./utils/scheduler');
const {errorMiddleware} = require('./utils/loggerUtils');
//DB Model
const statModel = require('./schemas/statSchema');
const flairModel = require('./schemas/flairSchema');
const emoteModel = require('./schemas/emoteSchema');
const tokeCommandModel = require('./schemas/tokebot/tokeCommandSchema');
//Controller
const fileNotFoundController = require('./controllers/404Controller');
//Router
//Humie-Friendly
const indexRouter = require('./routers/indexRouter');
const registerRouter = require('./routers/registerRouter');
const loginRouter = require('./routers/loginRouter');
const profileRouter = require('./routers/profileRouter');
const adminPanelRouter = require('./routers/adminPanelRouter');
const channelRouter = require('./routers/channelRouter');
const newChannelRouter = require('./routers/newChannelRouter');
const passwordResetRouter = require('./routers/passwordResetRouter');
const emailChangeRouter = require('./routers/emailChangeController');
//Panel
const panelRouter = require('./routers/panelRouter');
//Popup
const popupRouter = require('./routers/popupRouter');
//Tooltip
const tooltipRouter = require('./routers/tooltipRouter');
//Api
const apiRouter = require('./routers/apiRouter');
//Define Config variables
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();
//Define session-store (exported so we can kill sessions from user schema)
module.exports.store = mongoStore.create({mongoUrl: dbUrl});
//define sessionMiddleware
const sessionMiddleware = session({
secret: config.sessionSecret,
resave: false,
saveUninitialized: false,
store: module.exports.store
});
//Declare web server
let webServer = null;
//If we're using HTTPS
if(config.protocol.toLowerCase() == "https"){
try{
//Read key/cert files and store contents
const httpsOptions = {
key: fs.readFileSync(config.ssl.key),
cert: fs.readFileSync(config.ssl.cert)
};
//Start HTTPS Server
webServer = https.createServer(httpsOptions, app);
}catch(err){
//If the error has a path
if(err.path != null && err.path != ""){
//Tell the user to fix their shit
console.log(`Error opening key/cert file: ${err.path}`);
//Otherwise
}else{
//Shit our pants
console.log("Unknown error occured while starting HTTPS server! Bailing out!");
console.log(err);
}
//and run for the hills
process.exit();
}
//Otherwise
}else{
//Default to HTTP
webServer = createServer(app)
}
const io = new Server(webServer, {});
//Connect mongoose to the database
mongoose.set("sanitizeFilter", true).connect(dbUrl).then(() => {
console.log("Connected to DB");
}).catch((err) => {
console.error("Unable to connecto to DB: ");
console.error(err);
process.exit();
});
//Set View Engine
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
//Middlware
//Enable Express
app.use(express.json());
//app.use(express.urlencoded());
//Enable Express-Sessions
app.use(sessionMiddleware);
//Enable Express-Session w/ Socket.IO
io.engine.use(sessionMiddleware);
//Routes
//Humie-Friendly
app.use('/', indexRouter);
app.use('/register', registerRouter);
app.use('/login', loginRouter);
app.use('/profile', profileRouter);
app.use('/adminPanel', adminPanelRouter);
app.use('/c', channelRouter);
app.use('/newChannel', newChannelRouter);
app.use('/passwordReset', passwordResetRouter);
app.use('/emailChange', emailChangeRouter);
//Panel
app.use('/panel', panelRouter);
//Popup
app.use('/popup', popupRouter);
//tooltip
app.use('/tooltip', tooltipRouter);
//Bot-Ready
app.use('/api', apiRouter);
//Static File Server
//Serve bootstrap icons
app.use('/lib/bootstrap-icons',express.static(path.join(__dirname, '../node_modules/bootstrap-icons')));
app.use('/lib/altcha',express.static(path.join(__dirname, '../node_modules/altcha/dist_external')));
//Server public 'www' folder
app.use(express.static(path.join(__dirname, '../www')));
//Handle error checking
app.use(errorMiddleware);
//Basic 404 handler
app.use(fileNotFoundController);
//Increment launch counter
statModel.incrementLaunchCount();
//Load default flairs
flairModel.loadDefaults();
//Load default emotes
emoteModel.loadDefaults();
//Load default toke commands
tokeCommandModel.loadDefaults();
//Kick off scheduled-jobs
scheduler.kickoff();
//Hand over general-namespace socket.io connections to the channel manager
module.exports.channelManager = new channelManager(io)
//Listen Function
webServer.listen(port, () => {
console.log(`Opening port ${port}`);
});