diff --git a/main.js b/main.js index 20430b5..c4ec696 100644 --- a/main.js +++ b/main.js @@ -1,8 +1,169 @@ -const express = require('express') -const vhost = require('vhost') +/* ---------------------------------------------------------------------------- -express() - .use(vhost('qmining.frylabs.net', require('./server.js').app)) - .use(vhost('frylabs.net', require('./server.js').app)) -// .use(vhost('sync.mysite.com', require('/path/to/sync').app)) - .listen(8080) + 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 . + + ------------------------------------------------------------------------- */ + +const startHTTPS = true +const siteUrl = 'https://qmining.tk' // http(s)//asd.basd +const ircURL = 'https://kiwiirc.com/nextclient/irc.sub.fm/#qmining' + +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('./logger.js') +const utils = require('./utils.js') +const actions = require('./actions.js') +const stat = require('./stat.js') + +const listedFiles = './public/files' +const recivedFiles = 'public/recivedfiles' +const uloadFiles = 'public/f' +const staticFile = 'public/data/static' +const dataFile = 'public/data.json' +const msgFile = 'stats/msgs' + +// https://certbot.eff.org/ +const privkeyFile = '/etc/letsencrypt/live/qmining.tk/privkey.pem' +const fullchainFile = '/etc/letsencrypt/live/qmining.tk/fullchain.pem' +const chainFile = '/etc/letsencrypt/live/qmining.tk/chain.pem' + +var certsLoaded = false +if (startHTTPS && utils.FileExists(privkeyFile) && utils.FileExists(fullchainFile) && utils.FileExists( + chainFile)) { + try { + const key = fs.readFileSync(privkeyFile, 'utf8') + const cert = fs.readFileSync(fullchainFile, 'utf8') + const ca = fs.readFileSync(chainFile, 'utf8') + var certs = { + key: key, + cert: cert, + ca: ca + } + certsLoaded = true + } catch (e) { + logger.Log('Error loading cert files!', logger.GetColor('redbg')) + } +} + +app.set('view engine', 'ejs') +app.use(function (req, res, next) { + res.on('finish', function () { + logger.LogReq(req, true, res.statusCode) + if (res.statusCode !== 404) { stat.LogStat(req.url) } + }) + next() +}) +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' +})) + +// -------------------------------------------------------------- + +app.get('/', function (req, res) { + // req.hostname + + //res.render() + res.end('henlo') +}) + +// ----------------------------------------------------------------------------------------------- + +app.get('/stuff*', function (req, res) { + let curr = listedFiles + '/' + req.url.substring('/stuff/'.length, req.url.length).split('?')[0] + let relPath = curr.substring('./public/files'.length, curr.length) + + if (relPath[relPath.length - 1] !== '/') { relPath += '/' } + + let t = relPath.split('/') + let prevDir = '' + for (let i = 0; i < t.length - 2; i++) { prevDir += t[i] + '/' } + + // curr = curr.replace(/\//g, "/"); + // relPath = relPath.replace(/\//g, "/"); + + logger.LogReq(req) + + if (fs.lstatSync(curr).isDirectory()) { + if (curr[curr.length - 1] !== '/') { curr += '/' } + + let f = [] + + fs.readdirSync(curr).forEach((item) => { + if (item[0] !== '.') { + let res = { name: item } + let stats = fs.statSync(curr + '/' + item) + + let fileSizeInBytes = stats['size'] + res.size = Math.round(fileSizeInBytes / 1000000) + + res.path = relPath + if (res.path[res.path.length - 1] !== '/') { res.path += '/' } + res.path += item + + res.mtime = stats['mtime'].toLocaleString() + + f.push(res) + } + }) + + res.render('folders', { + folders: f, + dirname: relPath, + prevDir + }) + } else { + let fileStream = fs.createReadStream(curr) + fileStream.pipe(res) + } +}) + +// ----------------------------------------------------------------------------------------------- + +app.get('*', function (req, res) { + res.render('404') + res.status(404) + // utils.AppendToFile(logger.GetDateString() + ": " + "404 GET", logFile); +}) + +app.post('*', function (req, res) { + res.status(404) + // utils.AppendToFile(logger.GetDateString() + ": " + "404 POST", logFile); +}) + +var msg = '' +stat.Load() + +exports.app = app + +logger.Log('Main module started', logger.GetColor('yellow')) diff --git a/package.json b/package.json new file mode 100644 index 0000000..3471a4b --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "node-ejs", + "main": "server.js", + "dependencies": { + "connect-busboy": "0.0.2", + "ejs": "^1.0.0", + "express": "^4.6.1", + "express-ejs-layouts": "^1.1.0", + "vhost": "^3.0.2" + } +} diff --git a/qmining.js b/qmining.js new file mode 100644 index 0000000..a2bbf7c --- /dev/null +++ b/qmining.js @@ -0,0 +1,265 @@ +/* ---------------------------------------------------------------------------- + + 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 . + + ------------------------------------------------------------------------- */ + +const startHTTPS = true +const siteUrl = 'https://qmining.tk' // http(s)//asd.basd +const ircURL = 'https://kiwiirc.com/nextclient/irc.sub.fm/#qmining' + +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('./logger.js') +const utils = require('./utils.js') +const actions = require('./actions.js') +const stat = require('./stat.js') + +const listedFiles = './public/files' +const recivedFiles = 'public/recivedfiles' +const uloadFiles = 'public/f' +const staticFile = 'public/data/static' +const dataFile = 'public/data.json' +const msgFile = 'stats/msgs' + +// https://certbot.eff.org/ +const privkeyFile = '/etc/letsencrypt/live/qmining.tk/privkey.pem' +const fullchainFile = '/etc/letsencrypt/live/qmining.tk/fullchain.pem' +const chainFile = '/etc/letsencrypt/live/qmining.tk/chain.pem' + +var certsLoaded = false +if (startHTTPS && utils.FileExists(privkeyFile) && utils.FileExists(fullchainFile) && utils.FileExists( + chainFile)) { + try { + const key = fs.readFileSync(privkeyFile, 'utf8') + const cert = fs.readFileSync(fullchainFile, 'utf8') + const ca = fs.readFileSync(chainFile, 'utf8') + var certs = { + key: key, + cert: cert, + ca: ca + } + certsLoaded = true + } catch (e) { + logger.Log('Error loading cert files!', logger.GetColor('redbg')) + } +} + +app.set('view engine', 'ejs') +app.use(function (req, res, next) { + res.on('finish', function () { + logger.LogReq(req, true, res.statusCode) + if (res.statusCode !== 404) { stat.LogStat(req.url) } + }) + next() +}) +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' +})) + +// -------------------------------------------------------------- + +app.get('/', function (req, res) { + // req.hostname + + res.render('main', { + siteurl: siteUrl, + qa: actions.ProcessQA() + }) + res.end() +}) + +app.get('/sio', function (req, res) { + res.render('uload') + res.end() +}) + +app.get('/manual', function (req, res) { + res.render('man') + res.end() + logger.LogReq(req) +}) + +app.get('/public', function (req, res) { + var response = '@Plz update :)' + response += utils.ReadFile(staticFile) + res.write(response) + res.end() +}) + +app.get('/static', function (req, res) { + var response = '@Plz update :)' + response += utils.ReadFile(staticFile) + res.write(response) + res.end() +}) + +app.get('/legacy', function (req, res) { + var f = utils.ReadFile(dataFile) + var d = actions.LoadJSON(f) + let qcount = 0 + for (let i = 0; i < d.length; i++) { qcount += d.Subjects[i].length } + let scount = d.length + + res.render('alldata', { + data: d, + scount: scount, + qcount: qcount, + siteurl: siteUrl + }) + + 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) { + // TODO: res.redirect("/"); or if needs this anyways, becouse /postfeedback post handler already + // redirects + res.render('main', { + sdata: utils.ReadFile(staticFile) + }) +}) + +app.post('/isAdding', function (req, res) { + res.end('OK') + logger.LogReq(req) + actions.ProcessIncomingRequest(req.body.datatoadd) + utils.WriteBackup() +}) + +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) +}) + +app.get('/irc', function (req, res) { + res.redirect(ircURL) + res.end() + logger.LogReq(req) +}) + +// all questions readable +app.get('/allqr', function (req, res) { + var f = utils.ReadFile(dataFile) + var d = actions.LoadJSON(f) + + res.render('allqr', { + d: d.toString().split('\n') + }) + 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('/scriptgit', function (req, res) { + res.redirect('https://gitlab.com/YourFriendlyNeighborhoodDealer/moodle-test-userscript') + res.end() + logger.LogReq(req) +}) + +app.get('/servergit', function (req, res) { + res.redirect('https://gitlab.com/YourFriendlyNeighborhoodDealer/question-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) +}) + +app.get('*', function (req, res) { + res.render('404') + res.status(404) + // utils.AppendToFile(logger.GetDateString() + ": " + "404 GET", logFile); +}) + +app.post('*', function (req, res) { + res.status(404) + // utils.AppendToFile(logger.GetDateString() + ": " + "404 POST", logFile); +}) + +var msg = '' +stat.Load() + +exports.app = app + +logger.Log('Qmining module started', logger.GetColor('yellow')) diff --git a/server.js b/server.js index 071fa78..77a2846 100644 --- a/server.js +++ b/server.js @@ -1,335 +1,19 @@ -/* ---------------------------------------------------------------------------- - - 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 . - - ------------------------------------------------------------------------- */ - -const startHTTPS = true -const siteUrl = 'https://qmining.tk' // http(s)//asd.basd -const ircURL = 'https://kiwiirc.com/nextclient/irc.sub.fm/#qmining' - 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 vhost = require('vhost') const logger = require('./logger.js') -const utils = require('./utils.js') -const actions = require('./actions.js') -const stat = require('./stat.js') -const listedFiles = './public/files' -const recivedFiles = 'public/recivedfiles' -const uloadFiles = 'public/f' -const staticFile = 'public/data/static' -const dataFile = 'public/data.json' -const msgFile = 'stats/msgs' - -// https://certbot.eff.org/ -const privkeyFile = '/etc/letsencrypt/live/qmining.tk/privkey.pem' -const fullchainFile = '/etc/letsencrypt/live/qmining.tk/fullchain.pem' -const chainFile = '/etc/letsencrypt/live/qmining.tk/chain.pem' - -var certsLoaded = false -if (startHTTPS && utils.FileExists(privkeyFile) && utils.FileExists(fullchainFile) && utils.FileExists( - chainFile)) { - try { - const key = fs.readFileSync(privkeyFile, 'utf8') - const cert = fs.readFileSync(fullchainFile, 'utf8') - const ca = fs.readFileSync(chainFile, 'utf8') - var certs = { - key: key, - cert: cert, - ca: ca - } - certsLoaded = true - } catch (e) { - logger.Log('Error loading cert files!', logger.GetColor('redbg')) - } -} +const qmining = require('./qmining.js').app +const main = require('./main.js').app const port = 8080 -const httpsPort = 8443 -app.set('view engine', 'ejs') -app.use(function (req, res, next) { - res.on('finish', function () { - logger.LogReq(req, true, res.statusCode) - if (res.statusCode !== 404) { stat.LogStat(req.url) } - }) - next() -}) -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' -})) +express() + .use(vhost('qmining.frylabs.net', qmining)) + .use(vhost('frylabs.net', main)) + .use(vhost('qmining.tk', qmining)) + .listen(port) -// -------------------------------------------------------------- -app.get('/', function (req, res) { - // req.hostname - - res.render('main', { - siteurl: siteUrl, - qa: actions.ProcessQA() - }) - res.end() -}) - -app.get('/sio', function (req, res) { - res.render('uload') - res.end() -}) - -app.get('/manual', function (req, res) { - res.render('man') - res.end() - logger.LogReq(req) -}) - -app.get('/public', function (req, res) { - var response = '@Plz update :)' - response += utils.ReadFile(staticFile) - res.write(response) - res.end() -}) - -app.get('/static', function (req, res) { - var response = '@Plz update :)' - response += utils.ReadFile(staticFile) - res.write(response) - res.end() -}) - -app.get('/legacy', function (req, res) { - var f = utils.ReadFile(dataFile) - var d = actions.LoadJSON(f) - let qcount = 0 - for (let i = 0; i < d.length; i++) { qcount += d.Subjects[i].length } - let scount = d.length - - res.render('alldata', { - data: d, - scount: scount, - qcount: qcount, - siteurl: siteUrl - }) - - 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) { - // TODO: res.redirect("/"); or if needs this anyways, becouse /postfeedback post handler already - // redirects - res.render('main', { - sdata: utils.ReadFile(staticFile) - }) -}) - -app.post('/isAdding', function (req, res) { - res.end('OK') - logger.LogReq(req) - actions.ProcessIncomingRequest(req.body.datatoadd) - utils.WriteBackup() -}) - -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) -}) - -app.get('/irc', function (req, res) { - res.redirect(ircURL) - res.end() - logger.LogReq(req) -}) - -// all questions readable -app.get('/allqr', function (req, res) { - var f = utils.ReadFile(dataFile) - var d = actions.LoadJSON(f) - - res.render('allqr', { - d: d.toString().split('\n') - }) - 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('/scriptgit', function (req, res) { - res.redirect('https://gitlab.com/YourFriendlyNeighborhoodDealer/moodle-test-userscript') - res.end() - logger.LogReq(req) -}) - -app.get('/servergit', function (req, res) { - res.redirect('https://gitlab.com/YourFriendlyNeighborhoodDealer/question-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) -}) - -// ----------------------------------------------------------------------------------------------- - -app.get('/stuff*', function (req, res) { - let curr = listedFiles + '/' + req.url.substring('/stuff/'.length, req.url.length).split('?')[0] - let relPath = curr.substring('./public/files'.length, curr.length) - - if (relPath[relPath.length - 1] !== '/') { relPath += '/' } - - let t = relPath.split('/') - let prevDir = '' - for (let i = 0; i < t.length - 2; i++) { prevDir += t[i] + '/' } - - // curr = curr.replace(/\//g, "/"); - // relPath = relPath.replace(/\//g, "/"); - - logger.LogReq(req) - - if (fs.lstatSync(curr).isDirectory()) { - if (curr[curr.length - 1] !== '/') { curr += '/' } - - let f = [] - - fs.readdirSync(curr).forEach((item) => { - if (item[0] !== '.') { - let res = { name: item } - let stats = fs.statSync(curr + '/' + item) - - let fileSizeInBytes = stats['size'] - res.size = Math.round(fileSizeInBytes / 1000000) - - res.path = relPath - if (res.path[res.path.length - 1] !== '/') { res.path += '/' } - res.path += item - - res.mtime = stats['mtime'].toLocaleString() - - f.push(res) - } - }) - - res.render('folders', { - folders: f, - dirname: relPath, - prevDir - }) - } else { - let fileStream = fs.createReadStream(curr) - fileStream.pipe(res) - } -}) - -// ----------------------------------------------------------------------------------------------- - -app.get('*', function (req, res) { - res.render('404') - res.status(404) - // utils.AppendToFile(logger.GetDateString() + ": " + "404 GET", logFile); -}) - -app.post('*', function (req, res) { - res.status(404) - // utils.AppendToFile(logger.GetDateString() + ": " + "404 POST", logFile); -}) - -var msg = '' -stat.Load() - -// const httpServer = http.createServer(app) -// httpServer.listen(port) - -exports.app = app - -msg += 'Server listening on port ' + port + ' (http)' - -// if (startHTTPS && certsLoaded) { -// const httpsServer = https.createServer(certs, app) -// httpsServer.listen(httpsPort) -// msg += ', and ' + httpsPort + ' (https)...' -// } else { -// logger.Log('Cert files does not exists, starting http only!', logger.GetColor('redbg')) -// } - -logger.Log(msg, logger.GetColor('yellow')) logger.Log('Node version: ' + process.version) +logger.Log('Listening on port: ' + port) +