Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a live check for the twitch proxy #522

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 78 additions & 78 deletions apps/twitch-proxy/server.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
const express = require("express");
const express = require('express');
const app = express();
const cors = require("cors")();
const cors = require('cors')();

const log = require("./utilities/logger");
const config = require("./config");
const log = require('./utilities/logger');
const config = require('./config');

const outReqLimiter = require("./utilities/outbound-reqs-limiter");
const blacklist = require("./utilities/blacklist");
const { validate, validateLegacy } = require("./utilities/req-validate");
const outReqLimiter = require('./utilities/outbound-reqs-limiter');
const blacklist = require('./utilities/blacklist');
const { validate, validateLegacy } = require('./utilities/req-validate');

if (!config.serveStaticData) {
var Datastore = require("@seald-io/nedb");
var Datastore = require('@seald-io/nedb');
var db = new Datastore({ filename: config.db.dbPath });
db.loadDatabase();

if (config.db.enableCompaction) {
db.persistence.setAutocompactionInterval(config.db.compactionMillisecs);
}

db.ensureIndex({ fieldName: "query" }, function(err) {
if (err) log.error(err, "unable to set db index");
db.ensureIndex({ fieldName: 'query' }, function (err) {
if (err) log.error(err, 'unable to set db index');
});

var dbMware = function(db) {
return function(req, res, next) {
var dbMware = function (db) {
return function (req, res, next) {
req.db = db;
next();
};
};

var cacheCheck = function() {
var cacheCheck = function () {
var d = Date.now();
var ets = config.db.dataExpirationSecs;
log.info("cache expiration check");
log.info('cache expiration check');
db.remove(
{
createdAt: {
Expand All @@ -48,29 +48,33 @@ if (!config.serveStaticData) {

app.use(dbMware(db));

var request = require("request");
var request = require('request');
var reqOptions = {
method: "GET",
method: 'GET',
headers: {
"Client-ID": config.twitchCID,
"Authorization": `Bearer ${config.accessTOKEN}`
'Client-ID': config.twitchCID,
Authorization: `Bearer ${config.accessTOKEN}`
}
};
}

app.enable("trust proxy");
app.enable('trust proxy');

app.get("/", function(req, res) {
res.sendFile(__dirname + "/views/index.html");
app.get('/', function (req, res) {
res.sendFile(__dirname + '/views/index.html');
});

app.get("/helix/:route", cors, blacklist, validate, function(req, res, next) {
if (config.serveStaticData) return next("route");
app.get('/status/ping', (req, res) => {
res.status(200).send({ msg: 'pong' });
});

app.get('/helix/:route', cors, blacklist, validate, function (req, res, next) {
if (config.serveStaticData) return next('route');
var route = req.params.route;
var qs = req.query;
const query =
route + Object.keys(qs).reduce((a, q) => `${a}:${q}=${qs[q]}`, "");
req.db.findOne({ query }, function(err, dbCache) {
route + Object.keys(qs).reduce((a, q) => `${a}:${q}=${qs[q]}`, '');
req.db.findOne({ query }, function (err, dbCache) {
// if data is cached return it
if (err) return next(err);
if (dbCache) {
Expand All @@ -79,11 +83,11 @@ app.get("/helix/:route", cors, blacklist, validate, function(req, res, next) {
} else {
// get data from twitch api, store and serve it
if (outReqLimiter(req))
return next({ status: 429, message: "outbound rate limiter" });
return next({ status: 429, message: 'outbound rate limiter' });

reqOptions.url = `${config.baseApiUrl}/helix/${route}`;
reqOptions.qs = qs;
request(reqOptions, function(err, response, body) {
request(reqOptions, function (err, response, body) {
if (err) return next(err);
log.info(`${query} - new - "${req.headers.referer}" - ${req.ip}`);
var cacheItem = {
Expand All @@ -94,7 +98,7 @@ app.get("/helix/:route", cors, blacklist, validate, function(req, res, next) {
createdAt: Date.now()
};

req.db.insert(cacheItem, function(err) {
req.db.insert(cacheItem, function (err) {
if (err) return next(err);
res.json(cacheItem.data);
});
Expand All @@ -103,16 +107,16 @@ app.get("/helix/:route", cors, blacklist, validate, function(req, res, next) {
});
});

const staticHandler = require("./utilities/static-data-handler");
app.get("/helix/:route", cors, blacklist, validate, function(req, res, next) {
const staticHandler = require('./utilities/static-data-handler');
app.get('/helix/:route', cors, blacklist, validate, function (req, res, next) {
const {
params: { route },
query,
headers: { referer },
ip
} = req;
const _q =
route + Object.keys(query).reduce((a, q) => `${a}:${q}=${query[q]}`, "");
route + Object.keys(query).reduce((a, q) => `${a}:${q}=${query[q]}`, '');
log.info(`${_q} - static - "${referer}" - ${ip}`);
const data = staticHandler(route, query);
if (data) {
Expand All @@ -131,84 +135,80 @@ const sendData = (req, res, data, err) => {
res.status(stat).json(err || data);
}
};
const getLegacyAPIDAta = require("./utilities/legacy-data-handler");
app.get("/twitch-api/:type/:name", blacklist, cors, validateLegacy, function(
req,
res,
next
) {
const {
params: { type, name },
headers: { referer },
ip
} = req;
log.info(`${type}/${name} - static (kraken) - "${referer}" - ${ip}`);

var data = getLegacyAPIDAta(req.params.type, req.params.name);

if (data) {
setTimeout(() => sendData(req, res, data), 1000);
} else {
log.warn(
`${type}/${name} - static (kraken) not found - "${referer}" - ${ip}`
);
next();
const getLegacyAPIDAta = require('./utilities/legacy-data-handler');
app.get(
'/twitch-api/:type/:name',
blacklist,
cors,
validateLegacy,
function (req, res, next) {
const {
params: { type, name },
headers: { referer },
ip
} = req;
log.info(`${type}/${name} - static (kraken) - "${referer}" - ${ip}`);

var data = getLegacyAPIDAta(req.params.type, req.params.name);

if (data) {
setTimeout(() => sendData(req, res, data), 1000);
} else {
log.warn(
`${type}/${name} - static (kraken) not found - "${referer}" - ${ip}`
);
next();
}
}
});
);

var fs = require("fs");
app.get("/reset-db", function(req, res, next) {
var fs = require('fs');
app.get('/reset-db', function (req, res, next) {
if (process.env.ADMIN_PWD && req.query.pwd === process.env.ADMIN_PWD) {
try {
fs.unlinkSync(__dirname + "/.data/db");
fs.unlinkSync(__dirname + '/.data/db');
} catch (e) {
return next(e);
}
res.type("txt").send("OK");
res.type('txt').send('OK');
} else {
res
.type("txt")
.status(401)
.send("Unauthorized");
res.type('txt').status(401).send('Unauthorized');
}
});

const {
updateStaticData,
updateLegacyStaticData
} = require("./static-data/update");
app.get("/update-static", async (req, res, next) => {
} = require('./static-data/update');
app.get('/update-static', async (req, res, next) => {
const { pwd, type } = req.query;
if (process.env.ADMIN_PWD && pwd === process.env.ADMIN_PWD) {
const isLegacy = type === "legacy";
const isLegacy = type === 'legacy';
let _update = isLegacy ? updateLegacyStaticData : updateStaticData;
log.info(`updating static data${isLegacy ? " (legacy)" : ""}...`);
log.info(`updating static data${isLegacy ? ' (legacy)' : ''}...`);
try {
await _update();
log.info(`update static data${isLegacy ? " (legacy)" : ""} OK`);
res.type("text").send("OK");
log.info(`update static data${isLegacy ? ' (legacy)' : ''} OK`);
res.type('text').send('OK');
} catch (err) {
return next(err);
}
} else {
res
.type("txt")
.status(401)
.send("Unauthorized");
res.type('txt').status(401).send('Unauthorized');
}
});

app.use(function(req, res) {
sendData(req, res, null, { status: 404, error: "not found" });
app.use(function (req, res) {
sendData(req, res, null, { status: 404, error: 'not found' });
});

app.use(function(err, req, res) {
app.use(function (err, req, res) {
log.error(`!! ${err.message || err.msg || err.error}`);
err.status = err.status || 500;
err.error = err.error || "internal server error";
err.error = err.error || 'internal server error';
sendData(req, res, null, err);
});

app.listen(config.port, function() {
log.info("fcc twitch proxy listening on port " + config.port);
app.listen(config.port, function () {
log.info('fcc twitch proxy listening on port ' + config.port);
});
Loading