320 lines
12 KiB
TypeScript
320 lines
12 KiB
TypeScript
|
module.exports = function (app, enabMods, con, otherContext) {
|
||
|
const wc = require('pp-which-country');
|
||
|
const _ = require("underscore");
|
||
|
const libs = require("../libs/metaHandler.lib");
|
||
|
const jLib = require("../libs/jsonHand.lib");
|
||
|
const stringify = require('safe-stable-stringify')
|
||
|
const mailValidator = require("deep-email-validator")
|
||
|
const tools = require("../functions");
|
||
|
|
||
|
// Returns all installed and non-limited modules
|
||
|
app.get("/api/allModules", function (req, res) {
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
|
||
|
const allModules = [];
|
||
|
// Loop though all modules and sort all interesting ones into `allModules`
|
||
|
for (let i = 0; i < enabMods.length; i++) {
|
||
|
if (enabMods[i].getModuleMeta().limited == false) {
|
||
|
allModules.push(enabMods[i].getModuleMeta());
|
||
|
}
|
||
|
}
|
||
|
// Return all modules
|
||
|
res.send(allModules);
|
||
|
});
|
||
|
|
||
|
// Returns all tags with usages amounts
|
||
|
app.get("/api/allTags", function (req, res) {
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
|
||
|
|
||
|
// Return all tags
|
||
|
const allTags = otherContext.tags
|
||
|
//allTags = allTags.sort(function(a,b) { return parseInt(a.z) - parseInt(b.z) } );
|
||
|
const response = []
|
||
|
for (const key in allTags) {
|
||
|
if (allTags.hasOwnProperty(key)) {
|
||
|
console.log(`${key}: ${allTags[key]}`);
|
||
|
response.push({key: key, amount: allTags[key]})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
res.send(response);
|
||
|
});
|
||
|
|
||
|
// The report API endpoint
|
||
|
app.get("/api/internal/report", function (req, res) {
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
// First check if all needed parameters are set
|
||
|
const point_id = req.query.point_id;
|
||
|
const mail = req.query.mail;
|
||
|
const reason = req.query.reason;
|
||
|
if (!point_id || !mail || !reason) {
|
||
|
res.send(JSON.stringify({
|
||
|
"status": "error",
|
||
|
"message": "Missing parameters"
|
||
|
}));
|
||
|
} else {
|
||
|
// Check if the point_id is valid
|
||
|
const splited = point_id.split("_");
|
||
|
if (splited.length != 2) {
|
||
|
res.send(JSON.stringify({
|
||
|
"status": "error",
|
||
|
"message": "Invalid point_id"
|
||
|
}));
|
||
|
} else {
|
||
|
let isValid = false;
|
||
|
for (let i = 0; i < enabMods.length; i++) {
|
||
|
if (enabMods[i].getModuleMeta().exactName == splited[0] && enabMods[i].getModuleMeta().limited == false) {
|
||
|
isValid = true;
|
||
|
}
|
||
|
}
|
||
|
if (isValid) {
|
||
|
// Check if the mail is valid
|
||
|
const mailValidationRes = mailValidator.validate({ email: mail, validateSMTP: false, validateTypo: false });
|
||
|
mailValidationRes.then(function (resp) {
|
||
|
if (resp.valid) {
|
||
|
const sqlQuery = "INSERT INTO `reports` (`point_id`, `mail`, `comment`) VALUES (?, ? , ?);";
|
||
|
con.query(sqlQuery, [point_id, mail, reason], function (err, rows, fields) {
|
||
|
tools.handleMysqlErrors(err, "API");
|
||
|
res.send(JSON.stringify({
|
||
|
"status": "success",
|
||
|
"message": "Report sent"
|
||
|
}));
|
||
|
});
|
||
|
|
||
|
} else {
|
||
|
res.send(JSON.stringify({
|
||
|
"status": "error",
|
||
|
"message": "Invalid mail",
|
||
|
"cause": resp
|
||
|
}));
|
||
|
}
|
||
|
})
|
||
|
|
||
|
} else {
|
||
|
res.send(JSON.stringify({
|
||
|
"status": "error",
|
||
|
"message": "Invalid point_id"
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
|
||
|
app.get("/api/retrieve", function (req, res) {
|
||
|
// Make sure all parameters are there
|
||
|
if (
|
||
|
req.query.uid != undefined
|
||
|
) {
|
||
|
// All parameters are there
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
|
||
|
const uid = req.query.uid;
|
||
|
let result = undefined;
|
||
|
console.warn("Retrieving data for UID: " + uid);
|
||
|
// Go thorugh all modules and find the one which should handle the request
|
||
|
for (let i = 0; i < enabMods.length; i++) {
|
||
|
if (enabMods[i].getModuleMeta().exactName == uid.split("_")[0] && enabMods[i].getModuleMeta().limited == false) {
|
||
|
|
||
|
result = enabMods[i].queryItem(uid);
|
||
|
console.warn("Found module: " + enabMods[i].getModuleMeta().exactName + " with result: " + result);
|
||
|
}
|
||
|
}
|
||
|
// Because DBs are slow the module only returns a Promise and we have to wait for it
|
||
|
Promise.all([result]).then(function (results) { res.send(results) });
|
||
|
} else {
|
||
|
// A parameter is missing
|
||
|
res.status(400);
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
|
||
|
}
|
||
|
});
|
||
|
|
||
|
app.get("/api/getPOI", function (req, res) {
|
||
|
// All parameters are there
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
// Check if the bounds are valid so `lat;lng` is present
|
||
|
// First check if the `;` is present and .split() returns an array with 2 elements
|
||
|
const boundNorthEast = req.query.boundingEast.split(";");
|
||
|
const boundSouthWest = req.query.boundingWest.split(";");
|
||
|
let filterdModules = [];
|
||
|
if (boundNorthEast.length == 2 && boundSouthWest.length == 2) {
|
||
|
// Length is valid. Now check if the values are numbers and they are not infinte
|
||
|
if (_.isFinite(boundNorthEast[0]) && _.isFinite(boundNorthEast[1]) && _.isFinite(boundSouthWest[0]) && _.isFinite(boundSouthWest[1])) {
|
||
|
// Values are valid
|
||
|
const boundNorthEastLat = parseFloat(boundNorthEast[0]);
|
||
|
const boundNorthEastLng = parseFloat(boundNorthEast[1]);
|
||
|
const boundNorthEastLatLng = { lat: boundNorthEastLat, lng: boundNorthEastLng };
|
||
|
const boundSouthWestLat = parseFloat(boundSouthWest[0]);
|
||
|
const boundSouthWestLng = parseFloat(boundSouthWest[1]);
|
||
|
const boundSouthWestLatLng = { lat: boundSouthWestLat, lng: boundSouthWestLng };
|
||
|
// Get the country of both edges
|
||
|
// If the country is diffrent, set the country to *
|
||
|
const countryNorthEast = wc([boundNorthEastLng, boundNorthEastLat]);
|
||
|
let countrySouthWest = wc([boundSouthWestLng, boundSouthWestLat]);
|
||
|
if (countryNorthEast != countrySouthWest) {
|
||
|
// Country is the same
|
||
|
countrySouthWest = "*";
|
||
|
}
|
||
|
|
||
|
// Get all POIs in the given bounds
|
||
|
const usefullMods = []
|
||
|
for (let i = 0; i < enabMods.length; i++) {
|
||
|
const meta = enabMods[i].getModuleMeta()
|
||
|
// Is the country in the module's country list? Or is it "*"? Or did the system decide is doesnt matter
|
||
|
if ((meta.country.indexOf(countrySouthWest) > -1 || meta.country[0] == "*" || countrySouthWest == "*") && meta.limited == false) {
|
||
|
usefullMods.push(enabMods[i])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// JSON filter
|
||
|
if (jLib.IsJsonString(req.query.filter)) {
|
||
|
const jsonData = JSON.parse(req.query.filter);
|
||
|
filterdModules = usefullMods.filter(function (elm) {
|
||
|
// Loops through all elements in a list and lets you decide if weather to keep 'em or not
|
||
|
let amount = 0;
|
||
|
for (const fId in jsonData.filters) {
|
||
|
// Do this is each provided filter
|
||
|
const fi = jsonData.filters[fId]; // Gets the current filters name
|
||
|
switch (fi[0]) {
|
||
|
case "tag":
|
||
|
if (jsonData.conjunction == "OR") {
|
||
|
if (libs.returnTags(elm).includes(fi[1])) {
|
||
|
return elm;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
if (libs.returnTags(elm).includes(fi[1])) {
|
||
|
amount++;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case "country":
|
||
|
if (jsonData.conjunction == "OR") {
|
||
|
if (libs.returnCountries(elm).includes(fi[1])) {
|
||
|
return elm;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
if (libs.returnCountries(elm).includes(fi[1])) {
|
||
|
amount++;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case "source":
|
||
|
if (jsonData.conjunction == "OR") {
|
||
|
if (elm.getModuleMeta().exactName == fi[1]) {
|
||
|
return elm;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
if (elm.getModuleMeta().exactName == fi[1]) {
|
||
|
amount++;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (jsonData.conjunction == "AND") {
|
||
|
if (amount == jsonData.filters.length) {
|
||
|
return elm;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
} else { // No filtering
|
||
|
filterdModules = enabMods;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Create all promises
|
||
|
const allProms = []; // A list for all promises
|
||
|
for (let i = 0; i < filterdModules.length; i++) {
|
||
|
const module = filterdModules[i];
|
||
|
const temp = module.queryData(boundNorthEastLatLng, boundSouthWestLatLng, true); // Returns a promise of the results, because DBs are slowwwww
|
||
|
allProms.push(temp); // Put the promises into a list
|
||
|
}
|
||
|
|
||
|
// Wait for all promises and return them
|
||
|
Promise.all(allProms).then(function (result) {
|
||
|
const allResultsInOne = []
|
||
|
for (let i = 0; i < result.length; i++) {
|
||
|
for (let d = 0; d < result[i].length; d++) {
|
||
|
allResultsInOne.push(result[i][d])
|
||
|
}
|
||
|
}
|
||
|
res.send(stringify(allResultsInOne));
|
||
|
}).catch(function (error) {
|
||
|
console.error(error)
|
||
|
res.status(500).send(error); // We should probably not do this in a PROD env but FIXME: Only in DEV env
|
||
|
});
|
||
|
} else {
|
||
|
// Values are not valid
|
||
|
res.status(400);
|
||
|
res.send(JSON.stringify({ state: "Failed", message: "Bounding box is not valid" }));
|
||
|
return (0);
|
||
|
}
|
||
|
} else {
|
||
|
res.send(
|
||
|
JSON.stringify({ state: "Failed", message: "Invalid arguments" })
|
||
|
);
|
||
|
res.status(400);
|
||
|
return;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
app.get("/api/getPOILocations", function (req, res) {
|
||
|
// Make sure all parameters are there
|
||
|
|
||
|
// All parameters are there
|
||
|
res.setHeader("Content-Type", "application/json");
|
||
|
if (_.isFinite(req.query.lat) && _.isFinite(req.query.lng) && _.isFinite(req.query.radius)) {
|
||
|
const lng = parseFloat(req.query.lng);
|
||
|
const lat = parseFloat(req.query.lat);
|
||
|
const radius = parseFloat(req.query.radius);
|
||
|
|
||
|
// Filter by usefull modules
|
||
|
const country = wc([lng, lat]); // Find out which country is at this location
|
||
|
const usefullMods = [];
|
||
|
// Go through all modules and find all fiting ones
|
||
|
for (let i = 0; i < enabMods.length; i++) {
|
||
|
const meta = enabMods[i].getModuleMeta()
|
||
|
if ((meta.country.indexOf(country) > -1 || meta.country[0] == "*") && meta.limited == false) {
|
||
|
usefullMods.push(enabMods[i])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const allProms = [];
|
||
|
for (let i = 0; i < usefullMods.length; i++) {
|
||
|
const module = usefullMods[i]
|
||
|
const temp = module.queryData(lat, lng, radius) // Returns a promise of the results
|
||
|
allProms.push(temp)
|
||
|
}
|
||
|
|
||
|
// Wait for all promises to be resolved
|
||
|
Promise.all(allProms).then(function (result) {
|
||
|
const allResultsInOne = []
|
||
|
for (let i = 0; i < result.length; i++) {
|
||
|
for (let d = 0; d < result[i].length; d++) {
|
||
|
allResultsInOne.push(result[i][d])
|
||
|
}
|
||
|
}
|
||
|
res.send(allResultsInOne);
|
||
|
}).catch(function (error) {
|
||
|
console.error(error)
|
||
|
res.status(500).send(error); // TODO: again only do it in DEV envs
|
||
|
});
|
||
|
} else {
|
||
|
res.send(
|
||
|
JSON.stringify({ state: "Failed", message: "Invalid arguments" })
|
||
|
);
|
||
|
res.status(400);
|
||
|
return;
|
||
|
}
|
||
|
});
|
||
|
}
|