commit 21200894219806e6fe609c0d5d15f5c4e9d0c39e Author: Utopiah Date: Mon May 8 11:50:45 2023 +0200 idea diff --git a/index.js b/index.js new file mode 100644 index 0000000..dab84a2 --- /dev/null +++ b/index.js @@ -0,0 +1,123 @@ +const http = require("http"); +const fs = require("fs"); +const path = require("path"); +const express = require("express"); // could be good to replace with code, no dep + +const port = process.env.PORT || 7788; +const configFilePath = path.resolve(__dirname, "config.json") +const usageFilePath = path.resolve(__dirname, "usage.json") +process.title = 'onhygi' + +// didn't work on its own with ^C nor killall +process.on('beforeExit', _ => { console.log('trying to save before exit') }); +// process.on('exit', _ => { console.log('trying to save on exit') }); + +// catching signals and do something before exit +['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT', + 'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM' +].forEach(function (sig) { + process.on(sig, function () { + terminator(sig); + console.log('signal: ' + sig); + }); +}); + +function terminator(sig) { + if (typeof sig === "string") { + console.log('Received %s - terminating server app ...', sig); + console.log('trying to save on exit') + fs.writeFileSync(usageFilePath, JSON.stringify( usage )) + process.exit(1); + } + console.log('Node server stopped.'); +} +// from https://stackoverflow.com/a/40574758/1442164 + +var usage = {} +if (fs.existsSync( usageFilePath ) ){ + console.log('found usage file') + usage = JSON.parse( fs.readFileSync(usageFilePath).toString() ) +} +console.log('past usage', usage) + +// does not apply in a P2P fashion, must rely on local configuration here config.json +let quota = [ + {id:"ownhome", pattern:/.*fabien\.benetou\.fr.*/, perHour:10, perDay:200}, + {id:"twitter",pattern:/.*twitter\.com.*/,perHour:1,perDay:12}, + {id:"proton",pattern:/.*proton\.me.*/,perHour:6,perDay:12}, + {id:"yt",pattern:/.*youtube\.com.*/,perHour:1,perDay:12}, + {id:"linkedin",pattern:/.*linkedin\.com.*/,perHour:1,perDay:12}, + {id:"reddit",pattern:/.*reddit\.com.*/,perHour:1,perDay:12}, + {id:"element",pattern:/.*element\.io.*/,perHour:1,perDay:12}, + {id:"discord",pattern:/.*discord\.com.*/,perHour:1,perDay:12}, +] +// could also check on time, e.g not before 7am nor after 10pm as done via tridactyl now + +if (fs.existsSync( configFilePath ) ){ + const configurationFromFile = JSON.parse( fs.readFileSync( configFilePath ).toString() ) + console.log('found quota file') + quota = configurationFromFile +} +console.log('quota', quota) +quota.map( rule => { if (typeof usage[rule.id] == 'undefined') usage[rule.id] = [] } ) + +// Setup and configure Express http server. +const app = express(); + +// CORS +app.use(function(req, res, next) { + res.header("Access-Control-Allow-Origin", "*"); + res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); + next(); +}); + +app.get('/', (req, res) => { + res.json( quota ) +}) + +app.get('/check', (req, res) => { + console.log('starting check') + if (!req.query.url) { + res.sendStatus(400); + console.log('no url found') + return; + } + let matched = false + quota.map( rule => { + if ( req.query.url.match( rule.pattern ) ){ + matched = true + console.log('match on', rule.id) + let now = Date.now()/1000 + usage[rule.id].push( now ) + if ( usage[rule.id].filter( t => t>now-60*60).length > rule.perHour ){ + res.json( { passed: false, msg: 'over quota per hour' } ) + return + } + if ( usage[rule.id].filter( t => t>now-60*60*24).length > rule.perDay ){ + res.json( { passed: false, msg: 'over quota per day' } ) + return + } + res.json( { passed: true, msg: 'within quota' } ) + return // returns from map, not get + } + }) + if (!matched) { + res.json( { passed: true, msg: 'no quota' } ) + console.log('no match') + } + // otherwise assume response already sent +}) + +/* +const privateKey = fs.readFileSync("naf-key.pem", "utf8"); +const certificate = fs.readFileSync("naf.pem", "utf8"); +const credentials = { key: privateKey, cert: certificate }; +const webServer = https.createServer(credentials, app); +*/ + +// Start Express http server +const webServer = http.createServer(app); +// Listen on port +webServer.listen(port, () => { + console.log("listening on http://localhost:" + port); +});