commit b42bfeae23f1a1c332eb843025e980aafc67db66 Author: YourFriendlyNeighborhoodDealer <3167982-YourFriendlyNeighborhoodDealer@users.noreply.gitlab.com> Date: Wed Nov 21 15:01:21 2018 +0100 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..8491e40 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +Question server + +Install: + npm install connect-busboy ejs express-layout querystring express + +some stuff maybe missing diff --git a/actions.js b/actions.js new file mode 100755 index 0000000..db3264f --- /dev/null +++ b/actions.js @@ -0,0 +1,213 @@ +module.exports = { + ProcessIncomingRequest: ProcessIncomingRequest, + CheckData: CheckData +}; + +var recievedFile = "stats/recieved"; +var publicFile = "public/data/public"; +var staticFile = "public/data/static"; +var manFile = "public/man.html"; + +var logger = require('./logger.js'); +var utils = require('./utils.js'); + +function Process(d, file) { + logger.Log("[PCES]: File: " + file); + + try { + + if (d.data.split("\n").length > 1) { + var oldFile = utils.ReadFile(file); + var newFile = oldFile + "\n+" + d.data; + + var newRes = CheckData(newFile); + var oldRes = CheckData(oldFile); + + if (newRes.count > 0) + logger.Log("[NLOD]: new file result: " + newRes.count); + else + logger.Log("[NLOD]: new file NLOD error, " + newRes.log, logger.GetColor("redbg"), true); + + if (oldRes.count > 0) + logger.Log("[NLOD]: old public result: " + oldRes.count); + else + logger.Log("[NLOD]: old public NLOD error, " + oldRes.log, logger.GetColor("redbg"), true); + + utils.WriteFile(newFile, file); + logger.Log("[NLOD]: New data written to: " + file); + + return newRes.count - oldRes.count; + } else + logger.Log("[PCES]: No new data."); + + } catch (e) { + Beep(); + logger.Log("[ERR ]: Error at processing data! File: " + file, logger.GetColor("redbg")); + logger.Log(e.toString(), logger.GetColor("redbg")); + } +} + +function ProcessIncomingRequest(data) { + + if (data == undefined) { + logger.Log("[PCES]: Recieved data is undefined!", logger.GetColor("redbg")); + return; + } + + var d = SetupData(data); + + logger.Log("[PCES]: Processing data: " + d.subj + " (" + d.type + ")"); + if (d.subj == undefined){ + logger.Log(JSON.stringify(d), logger.GetColor("red")); + return; + } + + var newItems = 0; + + /*if (d.type == 0) // -> safe, static + newItems = Process(d, staticFile); + else if (d.type == 1) // -> unsafe, public + newItems = Process(d, publicFile); + else { // -> error, or old client + logger.Log("[PCES]: Old client..."); + Process(d, publicFile); + Process(d, staticFile); + }*/ + var newPubItems = Process(d, publicFile); + var newStatItems = Process(d, staticFile); + + utils.AppendToFile(logger.GetDateString() + "\n" + d.data, recievedFile); + PrintNewCount(d, newPubItems, publicFile); + PrintNewCount(d, newStatItems, staticFile); +} + +function PrintNewCount(d, newItems, file) { + if (newItems > 0) { + var count = 0; + var splitted = d.alldata.split("\n"); + for (var i = 0; i < splitted.length; i++) + if (splitted[i].startsWith("?")) + count++; + logger.Log("[NEW ]: " + file + " All / New: " + count + " / " + newItems, logger.GetColor("cyan")); + } +} + +function SetupData(data) { + var pdata = data.split("<#>"); + if (pdata.length <= 0) + throw "No data recieved!"; + var d = {}; // parsed data + for (var i = 0; i < pdata.length; i++) { + var td = pdata[i].split("<=>"); + if (td.length == 2) + d[td[0]] = td[1]; + else + throw "Invalid parameter recieved!"; + } + return d; +} + +function CheckData(data) { + try { + var presult = NLoad(data); + return presult; + } catch (e) { + logger.Log("[NLOD]: NLOD error, " + e.toString(), logger.GetColor("redbg"), true); + return { + count: -1, + log: [e.toString()] + }; + } +} + +function NLoad(resource) { + var resultLog = []; + var count = -1; + var allCount = 0; + if (resource == undefined) + throw "A megadott adat undefined!"; + resource = resource.split("\n"); // splitting by enters + if (resource.length == 1) + throw "A megadott adat nem sorokból áll!"; + var data = []; // initializing data declared at the begining + + function AddNewSubj(name) // adds a new subject to the data + { + data.push({ + "questions": [] + }); // ads aa new object, with an empty array in it + GetCurrSubj().name = name; // sets the name for it + GetCurrSubj().count = 0; // setting count to default + // setting if its active only if its undefined, otherwise previous user setting shouldt be overwritten + } + + function AddItem() // adds an item to the last subjects questions + { + GetCurrSubj().count++; + allCount++; // incrementing all count + GetCurrSubj().questions.push({}); // adding a new empty object to the last item in the data + } + + function GetLastItem() // returns the last item of the last item of data + { + var q = GetCurrSubj().questions.length; // questions length + return GetCurrSubj().questions[q - 1]; + } + + function GetCurrSubj() { + return data[data.length - 1]; + } + + // ? : question + // ! : answer + // > : image JSON data + // + : subject name + + // checking for name + for (var j = 0; j < resource.length; j++) // goes through resources + { + if (resource[j][0] == '+') // if there is a name identifier + { + break; // breaks, couse there will be a name + } + if (resource[j][0] == '?' || resource[j][0] == '!' || resource[j][0] == '>') // if it begins with another identifier: + { + AddNewSubj("NONAME"); // there is no name (for the first question at least), so setting it noname. + break; + } + // else it does nothing, continues to check + } + var jumped = 0; // the amount of lines it processed + for (var i = 0; i < resource.length; i += jumped) // gouing through the resource + { + jumped = 0; // resetting it to 0 + var currRawDataQ = resource[i]; // current question + var currRawDataA = resource[i + 1]; // current answer + var currRawDataI = resource[i + 2]; // current image + if (currRawDataQ != undefined && currRawDataQ[0] == '?' && currRawDataA != undefined && + currRawDataA[0] == '!') // if the current line is ? and the next is ! its a data + { + AddItem(); + GetLastItem().q = currRawDataQ.substr(1); + GetLastItem().a = currRawDataA.substr(1); + jumped += 2; + if (currRawDataI != undefined && currRawDataI[0] == '>') { + GetLastItem().i = currRawDataI.substr(1); + jumped++; + } + } else if (currRawDataQ[0] == '+') // if its a new subject + { + AddNewSubj(currRawDataQ.substr(1)); + jumped++; + } else { + // this should be invalid question order + resultLog.push("Warning @ line " + i + ":" + currRawDataQ + " " + currRawDataA + " " + + currRawDataI); + jumped++; + } + } // end of parsing all data + return { + count: allCount, + log: resultLog + }; +} diff --git a/logger.js b/logger.js new file mode 100644 index 0000000..8d95105 --- /dev/null +++ b/logger.js @@ -0,0 +1,46 @@ +module.exports = { + GetDateString: GetDateString, + Log: Log, + GetColor: GetColor +}; + +var utils = require('./utils.js'); +const nlogFile = "stats/nlogs"; + +function GetDateString() { + var m = new Date(); + return m.getFullYear() + "/" + + ("0" + (m.getMonth() + 1)).slice(-2) + "/" + + ("0" + m.getDate()).slice(-2) + " " + + ("0" + m.getHours()).slice(-2) + ":" + + ("0" + m.getMinutes()).slice(-2) + ":" + + ("0" + m.getSeconds()).slice(-2); +} + +function Log(s, c, b) { + if (c != undefined) + console.log(c, GetDateString() + "> " + s); + else + console.log(GetDateString() + "> " + s); + + if (b) + utils.Beep(); + utils.AppendToFile(GetDateString() + "> " + s, nlogFile); +} + +function GetColor(c) { + if (c == "redbg") + return '\x1b[41m%s\x1b[0m'; + if (c == "bluebg") + return '\x1b[44m%s\x1b[0m'; + if (c == "red") + return '\x1b[31m%s\x1b[0m'; + if (c == "green") + return '\x1b[32m%s\x1b[0m'; + if (c == "yellow") + return '\x1b[33m%s\x1b[0m'; + if (c == "blue") + return '\x1b[34m%s\x1b[0m'; + if (c == "cyan") + return '\x1b[36m%s\x1b[0m'; +} diff --git a/server.js b/server.js new file mode 100755 index 0000000..831b7c6 --- /dev/null +++ b/server.js @@ -0,0 +1,252 @@ +var express = require('express'); +var bodyParser = require('body-parser'); +var busboy = require('connect-busboy'); +var fs = require('fs'); +var app = express(); + +var logger = require('./logger.js'); +var utils = require('./utils.js'); +var actions = require('./actions.js'); +var stat = require('./stat.js'); + +var bodyParser = require('body-parser'); + +const recivedFiles = "public/recivedfiles"; +const publicFile = "public/data/public"; +const staticFile = "public/data/static"; +const countFile = "public/data/count"; +const manFile = "public/man.html"; +const simpOutFile = "public/simplified"; +const inputFile = "stats/inputs"; +const msgFile = "stats/msgs"; +const logFile = "stats/logs"; +const port = 8080; + +var highlights = ["public", "static", "manual", "isgetting", "postfeedback", + "postquestions" +]; + +try { + var stdin = process.openStdin(); + stdin.addListener("data", function(d) { + var input = d.toString().trim(); + + if (input == "hello") + console.log("hello, messages: \n" + newMessages); + if (input == "clear" || input == "c") + console.clear(); + + }); +} catch (e) { + console.log("Failed to open STDIN"); + console.log(e); +} + +var newMessages = ""; + +app.set('view engine', 'ejs'); +app.use(function(req, res, next) { + var ip = req.headers['cf-connecting-ip'] || req.connection.remoteAddress; + if (req.headers['cf-connecting-ip']) { + next(); + } else { + res.status(404); + res.end(); + logger.Log("[BLOCK]: " + req.connection.remoteAddress + " blocked, " + req.url, logger.GetColor("redbg")); + } +}); +app.use(function(req, res, next) { + res.on('finish', function() { + if (res.statusCode != 404 && req.connection.remoteAddress != "::1") + Log(req); + else + Log(req, true); + }); + stat.Inc(req.url); + next(); +}); +app.use(express.static('public')); +app.use(busboy({ + limits: { + fileSize: 10 * 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) { + res.render('main', { + pdata: utils.ReadFile(publicFile), + sdata: utils.ReadFile(staticFile) + }); + res.end(); +}); + +app.get('/manual', function(req, res) { + res.write(utils.ReadFile(manFile)); + res.end(); +}); + +app.get('/public', function(req, res) { + res.write(utils.ReadFile(publicFile)); + res.end(); +}); + +app.get('/static', function(req, res) { + res.write(utils.ReadFile(staticFile)); + res.end(); +}); + +app.post('/postquestions', function(req, res) { + //res.redirect('back'); + var log = "Questions posted! "; + if (req.body.data_field == undefined) { + res.render('submitted', { + log: [], + msg: "Nincsen beküldött adat!" + }); + log += "Sent data is undefined! "; + + } else { + try { + utils.AppendToFile("\n" + logger.GetDateString() + "\n" + req.body.data_field, inputFile); + } catch (e) { + console.log(e); + } + var r = actions.CheckData(req.body.data_field); + if (r.count > 0) { + var c = utils.ReadFile(countFile); + if (parseInt(c) >= r.count) { + res.render('submitted', { + log: r.log, + msg: "Amit beküldtél kevesebb, vagy ugyanannyi kérdést tartalmaz! Az új kérdéseidet az eredeti végére másold! " + + "Új: " + r.count + " vs régi: " + c + }); + log += "Sent data contains less questions: " + r.count + ", "; + + } else { + res.render('submitted', { + log: r.log, + msg: "Sikeres frissítés! + " + (r.count - parseInt(c)) + + " új kérdés beküldve. néhány üzenet:" + }); + utils.WriteFile(req.body.data_field, publicFile); + utils.WriteFile(r.count.toString(), countFile); + utils.WriteBackup(); + log += "Wrote to file. "; + } + log += "Prev count : " + parseInt(c) + ", "; + + } else { + res.render('submitted', { + log: r.log, + msg: "A fordító nem bírta értelmezni az elküldött adatokat! Ellenőrizd a kimenetet, és az elküldött adatokat." + }); + log += "Could't parse data! "; + } + log += "NLOAD result: " + r.count; + } + logger.Log(log, logger.GetColor("blue")); +}); + +app.get('/postquestions', function(req, res) { + res.render('main', { + pdata: utils.ReadFile(publicFile), + sdata: utils.ReadFile(staticFile) + }); +}); + +app.post('/postfeedback', function(req, res) { + res.redirect('back'); + newMessages += "\n" + req.body.message_field; + logger.Log("[UMSG]: " + req.body.message_field, logger.GetColor("bluebg"), true); + utils.AppendToFile(logger.GetDateString() + ": " + req.body.message_field, msgFile); +}); + +app.get('/postfeedback', function(req, res) { + res.render('main', { + pdata: utils.ReadFile(publicFile), + sdata: utils.ReadFile(staticFile) + }); +}); + +app.post('/isAdding', function(req, res) { + res.end('OK'); + actions.ProcessIncomingRequest(req.body.datatoadd); + utils.WriteBackup(); +}); + +app.get('/sanityCheck', function(req, res) { + res.end('Hello guys'); +}); + +app.route('/badtestsender').post(function(req, res, next) { + var fstream; + req.pipe(req.busboy); + req.busboy.on('file', function(fieldname, file, filename) { + logger.Log("[UPL]: Uploading: " + filename, logger.GetColor("blue")); + + fstream = fs.createWriteStream(recivedFiles + "/" + filename + " | " + Date().toString()); + file.pipe(fstream); + fstream.on('close', function() { + logger.Log("[UPL]: Upload Finished of " + filename, logger.GetColor("blue")); + res.render("uploaded"); + }); + fstream.on('error', function(err) { + console.log("ERROR:" + err); + res.end("file uploaded"); + }); + }); +}); + +app.get('/sanityCheck', function(req, res) { + res.end('Uploaded :) go back now'); +}); + +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); + Log(req, true); +}); + +stat.Load(); +app.listen(port); +logger.Log("[START]: Server listening on port " + port + "..."); + +function Log(req, toFile) { + try { + var ip = req.headers['cf-connecting-ip'] || req.connection.remoteAddress; + var logEntry = "[RSND]: " + ip + ", " + req.headers['user-agent'] + + " " + req.method + " " + req.url; + var color = logger.GetColor("green"); + for (var i = 0; i < highlights.length; i++) + if (req.url.toLowerCase().includes(highlights[i])) { + color = logger.GetColor("blue"); + break; + } + if (req.url.toLowerCase().includes("isadding")) + color = logger.GetColor("yellow"); + if (!toFile) { + logger.Log(logEntry, color); + } else { + utils.AppendToFile(logger.GetDateString() + ": " + logEntry + "\n\t" + JSON.stringify(req.headers) + + "\n\t" + JSON.stringify(req + .body) + "\n", logFile); + } + + } catch (e) { + logger.Log("Error at logging lol", logger.GetColor("redbg"), true); + } +} diff --git a/stat.js b/stat.js new file mode 100755 index 0000000..f5b4492 --- /dev/null +++ b/stat.js @@ -0,0 +1,46 @@ +module.exports = { + Inc: Inc, + Load: Load +}; + +var utils = require('./utils.js'); +var logger = require('./logger.js'); + +const statFile = "stats/stats"; +const writeInterval = 10; + +var data = {}; +var writes = 0; + +function Load() { + try { + var prevData = utils.ReadFile(statFile); + data = JSON.parse(prevData); + } catch (e) { + logger.Log("[STAT]: Error at loading logs!", logger.GetColor("redbg")); + console.log(e); + } +} + +function Inc(value) { + if (value.startsWith("/?")) + value = "/"; + if (data[value] == undefined) + data[value] = 0; + data[value]++; + Save(); +} + +function Save() { + writes++; + if (writes == writeInterval) { + try { + utils.WriteFile(JSON.stringify(data), statFile); + writes = 0; + // logger.Log("[STAT] Stats wrote."); + } catch (e) { + logger.Log("[STAT]: Error at writing logs!", logger.GetColor("redbg")); + console.log(e); + } + } +} diff --git a/todos b/todos new file mode 100644 index 0000000..7d3e8f5 --- /dev/null +++ b/todos @@ -0,0 +1,2 @@ +make init function that + creates directory and file structure diff --git a/views/404.ejs b/views/404.ejs new file mode 100644 index 0000000..07cd9f6 --- /dev/null +++ b/views/404.ejs @@ -0,0 +1,17 @@ + + + + + + +

404

+ + +
+ + diff --git a/views/main.ejs b/views/main.ejs new file mode 100755 index 0000000..75bb336 --- /dev/null +++ b/views/main.ejs @@ -0,0 +1,79 @@ + + + + + + + + + +

+

+Script +greasyforkon +| +Manual +

+ + + + + + +
+ +
+ + + +
+ +
+ +
+ + + +
+ + + + +
+
+ +
Észrevételek: (közeledő teszt miatti kérdés-karbantartás, bug, feature vagy egyéb dolog, ami + nyomja a lelked)
+ + + + +

+Weboldal aljára rakom ki a választ általában. +
+ +
+Hibát kiváltó teszt feltöltése +
+ +
+ + +
+ +

+Ha egy kérdésre mindig helytelenül talál választ a userscript (vagy egyéb hibát észlelsz), akkor +azon az oldalon nyomj egy ctrl-s -t. Ez lementi a weboldalt úgy ahogy van egy mappába, és egy html +fájlba. Ezt a kettőt ha berakod egy .zip-be, és ide feltöltöd, akkor ránézek mi lehet a hiba, és +kijavítom. Max 10 MB! + Ha több, elég a .html. +
+ + diff --git a/views/submitted.ejs b/views/submitted.ejs new file mode 100755 index 0000000..f4bef83 --- /dev/null +++ b/views/submitted.ejs @@ -0,0 +1,25 @@ + + + +

+<%=msg%> +

+

+ + +

+Log: +

+Érdemes átnézni, lehetséges hibák vannak benne. +

+<%for(var i=0; i + <%= log[i] %> +
+<%}%> + +
+ + Vissza + + + diff --git a/views/uploaded.ejs b/views/uploaded.ejs new file mode 100755 index 0000000..bef1509 --- /dev/null +++ b/views/uploaded.ejs @@ -0,0 +1,18 @@ + + + + + + +fájl feltöltve! +

+Vagy nem, who knows? +

+
Ha 10 mega alatt van, akkor nagy esélyel feltöltve tho
+ Vissza + + +