/* ---------------------------------------------------------------------------- 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 . ------------------------------------------------------------------------- */ let url = '' const express = require('express') const bodyParser = require('body-parser') const busboy = require('connect-busboy') const fs = require('fs') const app = express() // const http = require('http') // const https = require('https') const logger = require('../../utils/logger.js') const utils = require('../../utils/utils.js') const actions = require('../../utils/actions.js') const recivedFiles = 'public/recivedfiles' const uloadFiles = 'public/f' const dataFile = 'public/data.json' const msgFile = 'stats/msgs' const motdFile = 'public/motd' const versionFile = 'public/version' let donateURL = '' try { donateURL = utils.ReadFile('./data/donateURL') } catch (e) { logger.Log('Couldnt read donate URL file!', logger.GetColor('red')) } app.set('view engine', 'ejs') app.set('views', [ './modules/qmining/views', './sharedViews' ]) app.use(express.static('public')) app.use(busboy({ limits: { fileSize: 10000 * 1024 * 1024 } })) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ limit: '5mb', extended: true })) app.use(bodyParser.json({ limit: '5mb' })) var data = actions.LoadJSON(dataFile) var version = '' var motd = '' function LoadVersion () { version = utils.ReadFile(versionFile) } function LoadMOTD () { motd = utils.ReadFile(motdFile) } function Load () { utils.WatchFile(motdFile, (newData) => { logger.Log(`Motd changed: ${newData.replace(/\/n/g, '')}`) LoadMOTD() }) utils.WatchFile(versionFile, (newData) => { logger.Log(`Version changed: ${newData.replace(/\/n/g, '')}`) LoadVersion() }) LoadVersion() LoadMOTD() } Load() // -------------------------------------------------------------- app.get('/', function (req, res) { // req.hostname let motd = '' try { motd = utils.ReadFile(motdFile) } catch (e) { } res.render('main', { siteurl: url, qa: actions.ProcessQA(), motd: motd }) res.end() }) app.get('/manual', function (req, res) { res.render('man') res.end() logger.LogReq(req) }) app.get('/legacy', function (req, res) { let qcount = data.Subjects.reduce((acc, currItem) => { acc += currItem.length return acc }, 0) let scount = data.length let grouped = data.Subjects.reduce((res, s) => { let sName = s.getSubjNameWithoutYear() if (sName) { if (!res[sName]) { res[sName] = [] } res[sName].push(s) } else { res.others.push(s) } return res }, { others: [] }) const ordered = {} Object.keys(grouped).sort().forEach((key) => { ordered[key] = grouped[key] }) res.render('alldata', { data: data, orderedData: ordered, scount: scount, qcount: qcount, siteurl: url }) logger.LogReq(req) }) app.post('/postfeedback', function (req, res) { res.redirect('back') logger.Log('New feedback message', logger.GetColor('bluebg'), true) utils.AppendToFile('\n\n' + logger.GetDateString() + ': ' + req.body.message_field, msgFile) }) app.get('/postfeedback', function (req, res) { res.redirect('/') }) app.get('/lred', function (req, res) { res.redirect('/legacy') res.end() logger.LogReq(req) }) app.get('/menuClick', function (req, res) { res.redirect('/') res.end() logger.LogReq(req) }) // all questions readable app.get('/allqr.txt', function (req, res) { res.set('Content-Type', 'text/plain') res.send(data.toString()) res.end() logger.LogReq(req) }) app.get('/greasy', function (req, res) { res.redirect('https://greasyfork.org/en/scripts/38999-moodle-elearning-kmooc-test-help') res.end() logger.LogReq(req) }) app.get('/install', function (req, res) { res.redirect(url + '/moodle-test-userscript/stable.user.js?install') res.end() logger.LogReq(req) }) app.get('/donate', function (req, res) { res.redirect(donateURL) res.end() logger.LogReq(req) }) app.get('/thanks', function (req, res) { res.render('thanks', { siteurl: url }) res.end() logger.LogReq(req) }) app.get('/classesgit', function (req, res) { res.redirect('https://gitlab.com/MrFry/question-classes') res.end() logger.LogReq(req) }) app.get('/scriptgit', function (req, res) { res.redirect('https://gitlab.com/MrFry/moodle-test-userscript') res.end() logger.LogReq(req) }) app.get('/servergit', function (req, res) { res.redirect('https://gitlab.com/MrFry/mrfrys-node-server') res.end() logger.LogReq(req) }) function UploadFile (req, res, path, next) { var fstream req.pipe(req.busboy) req.busboy.on('file', function (fieldname, file, filename) { logger.Log('Uploading: ' + filename, logger.GetColor('blue')) utils.CreatePath(path, true) let d = new Date() let fn = d.getHours() + '' + d.getMinutes() + '' + d.getSeconds() + '_' + filename fstream = fs.createWriteStream(path + '/' + fn) file.pipe(fstream) fstream.on('close', function () { logger.Log('Upload Finished of ' + path + '/' + fn, logger.GetColor('blue')) next(fn) }) fstream.on('error', function (err) { console.log(err) res.end('something bad happened :s') }) }) } app.route('/fosuploader').post(function (req, res, next) { UploadFile(req, res, uloadFiles, (fn) => { res.redirect('/f/' + fn) }) }) app.route('/badtestsender').post(function (req, res, next) { UploadFile(req, res, recivedFiles, (fn) => { res.render('uploaded') }) logger.LogReq(req) }) // ------------------------------------------------------------------------------------------- // API app.post('/isAdding', function (req, res) { logger.LogReq(req) // automatically saves to dataFile every n write let result = actions.ProcessIncomingRequest( req.body.datatoadd, data, { motd, version } ) res.json({ success: result !== -1, newQuestions: result }) }) app.get('/ask', function (req, res) { logger.LogReq(req) if (Object.keys(req.query).length === 0) { res.json({ message: `ask something! ?q=[question]&subj=[subject]&data=[question data]. 'subj' is optimal for faster result`, result: [], recievedData: JSON.stringify(req.query), success: false }) } else { if (req.query.q && req.query.data) { let subj = req.query.subj || '' let question try { question = decodeURIComponent(req.query.q) } catch (e) { console.err(req.query) throw e } let recData = {} try { recData = JSON.parse(req.query.data) } catch (e) { logger.Log(`Unable to parse recieved question data! '${req.query.data}'`, logger.GetColor('redbg')) } let r = data.Search(question, subj, recData) res.json({ result: r, success: true }) } else { res.json({ message: `Invalid question :(`, result: [], recievedData: JSON.stringify(req.query), success: false }) } } }) function getSimplreRes () { return { subjects: data.length, questions: data.Subjects.reduce((acc, subj) => { return acc + subj.length }, 0) } } function getDetailedRes () { return data.Subjects.map((subj) => { return { name: subj.Name, count: subj.length } }) } app.get('/datacount', function (req, res) { logger.LogReq(req) if (req.query.detailed === 'all') { res.json({ detailed: getDetailedRes(), simple: getSimplreRes() }) } else if (req.query.detailed) { res.json(getDetailedRes()) } else { res.json(getSimplreRes()) } }) app.get('/infos', function (req, res) { let result = {} if (req.query.subjinfo) { result.subjinfo = getSimplreRes() } if (req.query.version) { result.version = version } if (req.query.motd) { result.motd = motd } res.json(result) }) // ------------------------------------------------------------------------------------------- app.get('*', function (req, res) { res.status(404).render('404') }) app.post('*', function (req, res) { res.status(404).render('404') }) exports.app = app exports.setup = (x) => { url = x.url } logger.Log('Qmining module started', logger.GetColor('yellow'))