/*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 .*/ //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); //tooltip app.use('/tooltip', tooltipRouter); //Bot-Ready app.use('/api', apiRouter); //Static File Server //Serve client-side libraries app.use('/lib/bootstrap-icons',express.static(path.join(__dirname, '../node_modules/bootstrap-icons'))); //Icon set app.use('/lib/altcha',express.static(path.join(__dirname, '../node_modules/altcha/dist_external'))); //Self-Hosted PoW-based Captcha app.use('/lib/hls.js',express.static(path.join(__dirname, '../node_modules/hls.js/dist'))); //HLS Media Handler //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}`); });