/* ---------------------------------------------------------------------------- Question Server GitLab: This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------- */ // package requires import express, { RequestHandler } from 'express' import fileUpload from 'express-fileupload' import type { Database } from 'better-sqlite3' import http from 'http' import https from 'https' // other requires import logger from '../../utils/logger' import utils from '../../utils/utils' import auth from '../../middlewares/auth.middleware' import { SetupData } from '../../server' import { DataFile, ModuleSpecificData, ModuleType, QuestionDb, Request, Submodule, } from '../../types/basicTypes' import { loadJSON } from '../../utils/actions' import { paths, publicDir } from '../../utils/files' import { initWorkerPool } from '../../worker/workerPool' // other paths const moduleName = 'API' // stuff gotten from server.js let userDB: Database let httpServer: http.Server let httpsServer: https.Server function GetApp(): ModuleType { const app = express() app.use( express.urlencoded({ limit: '10mb', extended: true, }) as RequestHandler ) app.use( express.json({ limit: '10mb', }) as RequestHandler ) app.set('view engine', 'ejs') app.set('views', ['./src/modules/api/views', './src/sharedViews']) app.use( auth({ userDB: userDB, }) ) app.use( fileUpload({ limits: { fileSize: 50 * 1024 * 1024 }, }) ) // ------------------------------------------------------------------------------------------- let rootRedirectURL = '' function reloadRootRedirectURL() { if (utils.FileExists(paths.rootRedirectToFile)) { rootRedirectURL = utils.ReadFile(paths.rootRedirectToFile).trim() } } const filesToWatch = [ { fname: paths.rootRedirectToFile, logMsg: 'Root redirect URL changed', action: reloadRootRedirectURL, }, ] function Load() { filesToWatch.forEach((ftw) => { if (utils.FileExists(ftw.fname)) { utils.WatchFile(ftw.fname, () => { logger.Log(ftw.logMsg) ftw.action() }) ftw.action() } }) } Load() // -------------------------------------------------------------- app.get('/', function (req: Request, res: any) { logger.LogReq(req) if (rootRedirectURL) { res.redirect(rootRedirectURL) } else { res.json({ msg: 'hi c:' }) } }) // ------------------------------------------------------------------------------------------- const dbsFile = publicDir + 'questionDbs.json' // FIXME: is dataFiles only a temp variable? does this cause any problems? if (!utils.FileExists(dbsFile)) { utils.WriteFile('[]', dbsFile) } const dataFiles: Array = utils.ReadJSON(dbsFile) let questionDbs: Array = loadJSON(dataFiles, publicDir) initWorkerPool(() => questionDbs) const submoduleDatas = setupSubModules(app, { getQuestionDbs: () => { return questionDbs }, setQuestionDbs: (newQdbs: QuestionDb[]) => { questionDbs = newQdbs }, dbsFile: dbsFile, }) // ------------------------------------------------------------------------------------------- app.use(express.static(publicDir)) // ------------------------------------------------------------------------------------------- function DailyAction() { submoduleDatas.forEach((data) => { if (data.dailyAction) { data.dailyAction() } }) } submoduleDatas.forEach((data) => { if (data.load) { data.load() } }) return { dailyAction: DailyAction, app: app, } } function setupSubModules( parentApp: express.Application, moduleSpecificData: ModuleSpecificData ): Submodule[] { const submoduleDir = './submodules/' const absolutePath = __dirname + '/' + submoduleDir if (!utils.FileExists(absolutePath)) { return null } const files = utils.ReadDir(absolutePath) const moduleDatas: Submodule[] = [] files.forEach((file) => { if (!file.endsWith('.js')) { return } const submodulePath = submoduleDir + file try { const mod = require(submodulePath).default // eslint-disable-line const loadedModData = mod.setup({ app: parentApp, userDB: userDB, moduleSpecificData: moduleSpecificData, httpServer: httpServer, httpsServer: httpsServer, }) moduleDatas.push(loadedModData || {}) } catch (e) { logger.Log(`Error loading submodule from ${submodulePath}`) console.error(e) } }) return moduleDatas } export default { name: moduleName, getApp: GetApp, setup: (data: SetupData): void => { userDB = data.userDB httpServer = data.httpServer httpsServer = data.httpsServer }, }