Full Data Update

This commit is contained in:
2026-07-17 21:17:18 -04:00
parent 3b3df1686c
commit 772415207e
6 changed files with 797 additions and 163 deletions
+2 -4
View File
@@ -8,7 +8,7 @@ This was a quick and dirty project, and will probably get some updates slowly in
```bash
npm i
node serve.js
node basicauth_serve.js
```
To use the endpoint, replace 'EMAIL' and 'PASSWORD' with your Haze Explr account details:
@@ -23,6 +23,4 @@ Then, make a request to the endpoint with the resulting string as the value of t
curl "http://localhost:3000/locations?auth=BASE64_ENCODED_STRING"
```
`basicauth_serve.js` does the same thing bus expects account details to be passed via basic HTTP auth, but does not work with QGIS.
This is from a limitation of express-basic-auth.
`adapt.js` converts url-passed auth credentials into the basicauth server, I will refactor these in the future to use a `.env` file and better coding standards.
+50
View File
@@ -0,0 +1,50 @@
// Adapt URL-passed auth into basic HTTP auth for QGIS compatibility.
const express = require('express');
const request = require('request');
const app = express();
const port = 8356;
const reqOpts = {
method: 'GET',
headers: {
Authorization: ''
},
url: 'http://localhost:8355',
timeout: 1200000 // 20 minutes
}
app.all('*', (req, res) => {
// Verify Inputs
if (!req.query.auth) {
res.status(401).send('Unauthorized');
return;
}
let hazePwHash = null;
let hazeUser = null;
if (req.query.auth) {
request({
...reqOpts,
url: reqOpts.url + req.baseUrl,
headers: {
Authorization: `Basic ${req.query.auth}`
}
}, (error, response, body) => {
if (error) {
res.status(500).send('Internal Server Error');
return;
} else if (response.statusCode !== 200) {
res.status(response.statusCode).send(body);
return;
} else {
res.setHeader('Content-Type', 'application/json');
res.send(body);
}
})
}
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
+243 -58
View File
@@ -1,4 +1,5 @@
const express = require('express');
const WebSocket = require('ws');
const auth = require('express-basic-auth');
const { createHash } = require('crypto');
@@ -40,6 +41,58 @@ const hazeTranslator = {
"Pathfinder",
"Trailblazer",
"Maven"
],
tag: [
"Vicious Dogs",
"Biohazard",
"Radioactive",
"Fence",
"Rats",
"Still Water",
"Barbed Wire",
"Fire",
"Flashlight Recommended",
"Climbing Rope Recommended",
"Boat",
"Electrical Hazard",
"Helmet Recommended",
"Boots Recommended",
"Falling Debris",
"Dust Mask Recommended",
"Asbestos",
"Extreme Temperature",
"Squatters",
"Risk of Violence or Crime",
"Emotional Distress",
"Landmines",
"Respirator Recommended",
"Active Security",
"No Trespassing Sign",
"Private Property Sign",
"Flood Risk",
"Locked",
"Dead Air",
"Unstable Structure",
"Black Mold",
"Ticks",
"Mosquitoes",
"Razor Wire",
"Fiberglass",
"Bears",
"Wolves",
"Wildlife",
"Broken Glass",
"Scorpions",
"Snakes",
"Venomous Spiders",
"Karens Present",
"Gloves Recommended",
"Boarded Up",
"Thorns",
"Dangerous Hights",
"Hazmat Suit Recommended",
"Heavy Overgrowth",
"Bats"
]
};
app.use(auth({
@@ -48,13 +101,15 @@ app.use(auth({
}
}));
app.all('/locations.geojson', (req, res) => {
// Assemble full Haze location data, can take a LONG time
app.all('/locations_full.geojson', (req, res) => {
// Verify Inputs
if ((!req.auth.user || !req.auth.password) && (!req.query.auth)) {
res.status(401).send('Unauthorized');
return;
}
// Query Haze API Websocket
// Setup local variables for request
let hazePwHash = null;
let hazeUser = null;
let hazeSocketCounter = 0;
@@ -71,8 +126,64 @@ app.all('/locations.geojson', (req, res) => {
hazePwHash = createHash('sha256').update(req.auth.password).digest('hex');
}
}
const haze = new WebSocket('wss://do.ecven.com:8120/explr');
const haze = new WebSocket('wss://do.ecven.com:8120/explr-mb');
let locations = [];
let failCounter = 0;
let queryComplete = false;
// Socket Message Handlers, defined here to use the local variables above
const sendComplete = () => {
if (!queryComplete) {
queryComplete = true;
haze.close();
let testTime = (new Date().getTime() - requestStartTime);
const countExported = locations.filter(location => location && location.completed).length;
console.log(`${(new Date().getTime() - requestStartTime)/1000}s | FAILS: ${failCounter} | TIMEOUT: ${testTime} | TOTAL LOCATIONS: ${locations.length} | EXPORTED: ${countExported} | TIMEDOUT: ${locations.length - countExported - failCounter}`);
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
...geoJsonTemplate,
features: locations.map(location => ({
type: "Feature",
geometry: {
type: "Point",
coordinates: [location['longitude'], location['latitude']]
},
properties: {
id: location['id'],
title: location['name'],
"marker-symbol": location['isUnconfirmedLocation'] === 1 ? "star-stroked" : "star",
author: location['author'] || '',
explored: location['isExplored'] || false,
confirmed: location['isConfirmed'] || false,
category: location['category'] || '',
level: location['level'] || '',
rating: location['rating'] || '',
difficulty: location['difficulty'] || '',
comments: location['comments'] || [],
querySuccess: location['completed']
}
}))
}));
}
}
const queryLocation = (index) => {
haze.send(locations[index]['requestQuery']);
setTimeout(() => {
if (locations[index]['completed'] === 0) {
console.log(`Timeout on ${locations[index]['id']}}`);
locations[index]['completed'] = -1; // mark as failed
failCounter++;
let nextIndex = locations.findIndex(location => location && location.completed === 0);
if (locations.every(location => location && location.completed !== 0) || nextIndex === -1) {
sendComplete();
} else {
queryLocation(nextIndex);
}
}
}, 10000);
}
// These are the socket event handlers, in order of expected use
haze.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
let haze_authToken = '', haze_username = '';
@@ -103,15 +214,9 @@ app.all('/locations.geojson', (req, res) => {
break;
case "getMyLocationsRequest_response":
if (data['body']['response'] === 1) {
// locations = data['body']['locations'].map(location => {
// return {
// id: location['id'],
// title: location['name'],
// completed: false
// };
// });
data['body']['locations'].forEach(location => {
locations[hazeSocketCounter++] = {
hazeSocketCounter++;
locations[hazeSocketCounter] = {
id: location['id'],
title: location['name'],
latitude: location['coordinates']['latitude'],
@@ -119,21 +224,17 @@ app.all('/locations.geojson', (req, res) => {
isExplored: location['explored'] > 0,
isConfirmed: location['isUnconfirmedLocation'] !== 1,
category: hazeTranslator.category[location['locationCategory']],
completed: false
}
});
// need to make the socketIDs dynamic and handle completed status before returning final payload
// FIX: Currently throwing response 2 "User does not have access to location."
locations.forEach((location, index) => {
if (location) {
haze.send(JSON.stringify({
rawBasicData: JSON.stringify(location),
requestQuery: JSON.stringify({
event: "getLocation_request",
body: locations.map(location => location.id),
socketMessageId: index
}));
body: [ location['id'] ],
socketMessageId: hazeSocketCounter
}),
completed: 0
}
});
queryLocation(locations.findIndex(location => location && location.completed === 0));
} else {
console.dir(data);
res.status(500).send('Failed to retrieve locations');
@@ -143,14 +244,29 @@ app.all('/locations.geojson', (req, res) => {
break;
case "getLocation_response":
if (data['body']['response'] === 1) {
let locationTags = {};
data['body']['location']['locationRating']['ratingItemsList'].map(tag => {
locationTags[hazeTranslator.tag[tag['id']] ? hazeTranslator.tag[tag['id']] : tag['id']] = tag['count'];
});
locations[data['socketMessageId']] = {
...locations[data['socketMessageId']],
completed: true,
completed: 1,
author: `${data['body']['location']['submittorUserDatas']['username']} (${data['body']['location']['submittorUserDatas']['email']})`,
rating: hazeTranslator.rating[data['body']['location']['locationRating']['overallRating']],
difficulty: hazeTranslator.difficulty[data['body']['location']['locationRating']['difficultyRating']],
level: hazeTranslator.level[data['body']['location']['locationRating']['levelRating']],
// TODO: use body.location.locationRating.ratingItemsList for location tags
tags: locationTags,
images: [
... data['body']['location']['gallery'].map(image => ({
id: image['id'],
mimetype: `image/${image['mediaType']}`,
author: `${image['uploaderData']['username']} (${image['uploaderData']['email']})`,
url: image['url'],
thumbnail: image['thumbnailUrl'],
likes: image['likes'],
date: image['uploadDate'],
}))
],
comments: data['body']['location']['locationCommentsAndCommunityVotes'].map(comment => ({
id: comment['id'],
text: comment['comment'],
@@ -158,43 +274,111 @@ app.all('/locations.geojson', (req, res) => {
author: comment['submittor']['username'],
}))
};
let testTime = (new Date().getTime() - requestStartTime) > 30000; // 30s timeout
if (locations.every(location => location && location.completed) || testTime) {
res.setHeader('Content-Type', 'application/json');
haze.close();
res.end(JSON.stringify({
...geoJsonTemplate,
features: locations.map(location => ({
type: "Feature",
geometry: {
type: "Point",
coordinates: [location['longitude'], location['latitude']]
},
properties: {
id: location['id'],
title: location['name'],
"marker-symbol": location['isUnconfirmedLocation'] === 1 ? "star-stroked" : "star",
author: location['author'] || '',
explored: location['isExplored'] || false,
confirmed: location['isConfirmed'] || false,
category: location['category'] || '',
level: location['level'] || '',
rating: location['rating'] || '',
difficulty: location['difficulty'] || '',
comments: location['comments'] || [],
querySuccess: location['completed']
}
}))
}));
}
} else {
console.dir(data);
// res.status(500).send('Failed to retrieve locations');
// haze.close();
// res.end();
console.log(`Failure on ${locations[data['socketMessageId']]['id']}: ${data['body']['responseDetails']}`);
locations[data['socketMessageId']]['completed'] = -1; // mark as failed
failCounter++;
}
// Completion Check and increment
let nextIndex = locations.findIndex(location => location && location.completed === 0);
if (locations.every(location => location && location.completed !== 0) || nextIndex === -1) {
sendComplete();
} else {
queryLocation(nextIndex);
}
break;
case "ping":
console.log('Ping received from Haze API');
break;
default:
console.log(JSON.stringify(data, null, 2));
res.status(500).send('Unexpected response from Haze API');
haze.close();
res.end();
}
});
});
// Original API, for only listing locations with minimal data
app.all('/locations.geojson', (req, res) => {
// Verify Inputs
if ((!req.auth.user || !req.auth.password) && (!req.query.auth)) {
res.status(401).send('Unauthorized');
return;
}
// Query Haze API Websocket
let hazePwHash = null;
let hazeUser = null;
if (req.query.auth) {
let paramAuth = Buffer.from(req.query.auth, 'base64').toString('utf-8');
hawUser = paramAuth.split(":")[0];
hazePwHash = paramAuth.split(":")[1];
} else {
hazeUser = req.auth.user;
if (/\b[A-Fa-f0-9]{64}\b/.test(req.auth.password)) {
hazePwHash = req.auth.password;
} else {
hazePwHash = createHash('sha256').update(req.auth.password).digest('hex');
}
}
const haze = new WebSocket('wss://do.ecven.com:8120/explr');
haze.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
let haze_authToken = '', haze_username = '';
switch (data['event']) {
case "connected":
haze.send(JSON.stringify({
"event": "authenticateAccount_request",
"body": [
{
"password": hazePwHash,
"email": hazeUser
}
],
"socketMessageId": 0
}));
break;
case "authenticateAccount_response":
if (data['body']['response'] === 1) {
haze_authToken = data['body']['authToken'];
haze_username = data['body']['username'];
haze.send('{"event": "getMyLocationsRequest_request","body": [{"higlightImages": true}],"socketMessageId": 0}');
} else {
console.dir(req.query);
res.status(401).json({ ...data, password: req.auth.password });
haze.close();
res.end();
}
break;
case "getMyLocationsRequest_response":
if (data['body']['response'] === 1) {
const hazeLocations = data['body']['locations'].map(location => {
return {
type: "Feature",
geometry: {
type: "Point",
coordinates: [location['coordinates']['longitude'], location['coordinates']['latitude']]
},
properties: {
id: location['id'],
title: location['name'],
"marker-symbol": location['isUnconfirmedLocation'] === 1 ? "star-stroked" : "star",
}
}
});
res.setHeader('Content-Type', 'application/json');
haze.close();
res.end(JSON.stringify({
...geonJsonTemplate,
features: hazeLocations
}));
} else {
console.dir(data);
res.status(500).send('Failed to retrieve locations');
haze.close();
res.end();
}
break;
default:
console.dir(data);
res.status(500).send('Unexpected response from Haze API');
@@ -204,6 +388,7 @@ app.all('/locations.geojson', (req, res) => {
});
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
+499 -1
View File
@@ -11,7 +11,9 @@
"dependencies": {
"crypto": "^1.0.1",
"express": "^5.2.1",
"express-basic-auth": "^1.2.1"
"express-basic-auth": "^1.2.1",
"request": "^2.88.2",
"ws": "^8.21.1"
}
},
"node_modules/accepts": {
@@ -27,6 +29,61 @@
"node": ">= 0.6"
}
},
"node_modules/ajv": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
"integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"license": "MIT",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"license": "MIT",
"engines": {
"node": ">=0.8"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
"license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/aws4": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
"license": "MIT"
},
"node_modules/basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
@@ -39,6 +96,15 @@
"node": ">= 0.8"
}
},
"node_modules/bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"license": "BSD-3-Clause",
"dependencies": {
"tweetnacl": "^0.14.3"
}
},
"node_modules/body-parser": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
@@ -101,6 +167,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
"license": "Apache-2.0"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/content-disposition": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
@@ -141,6 +225,12 @@
"node": ">=6.6.0"
}
},
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"license": "MIT"
},
"node_modules/crypto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
@@ -148,6 +238,18 @@
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.",
"license": "ISC"
},
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -165,6 +267,15 @@
}
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -188,6 +299,16 @@
"node": ">= 0.4"
}
},
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
"license": "MIT",
"dependencies": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -300,6 +421,33 @@
"basic-auth": "^2.0.1"
}
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
"engines": [
"node >=0.6.0"
],
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"license": "MIT"
},
"node_modules/finalhandler": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
@@ -321,6 +469,50 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
"license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/form-data/node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/form-data/node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -385,6 +577,15 @@
"node": ">= 0.4"
}
},
"node_modules/getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -397,6 +598,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
"license": "ISC",
"engines": {
"node": ">=4"
}
},
"node_modules/har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"deprecated": "this library is no longer supported",
"license": "MIT",
"dependencies": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -441,6 +665,21 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
},
"engines": {
"node": ">=0.8",
"npm": ">=1.3.7"
}
},
"node_modules/iconv-lite": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
@@ -478,6 +717,57 @@
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
"license": "MIT"
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
"license": "MIT"
},
"node_modules/jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
"license": "MIT"
},
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
"license": "(AFL-2.1 OR BSD-3-Clause)"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"license": "MIT"
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"license": "ISC"
},
"node_modules/jsprim": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
"license": "MIT",
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
},
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -548,6 +838,15 @@
"node": ">= 0.6"
}
},
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -600,6 +899,12 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
"license": "MIT"
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -613,6 +918,27 @@
"node": ">= 0.10"
}
},
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
"license": "MIT",
"dependencies": {
"punycode": "^2.3.1"
},
"funding": {
"url": "https://github.com/sponsors/lupomontero"
}
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
@@ -652,6 +978,68 @@
"node": ">= 0.10"
}
},
"node_modules/request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
"license": "Apache-2.0",
"dependencies": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/request/node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/request/node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/request/node_modules/qs": {
"version": "6.5.5",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz",
"integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.6"
}
},
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
@@ -803,6 +1191,31 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sshpk": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
"license": "MIT",
"dependencies": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
@@ -821,6 +1234,37 @@
"node": ">=0.6"
}
},
"node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"license": "BSD-3-Clause",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
"license": "Unlicense"
},
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -844,6 +1288,25 @@
"node": ">= 0.8"
}
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
}
},
"node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
"license": "MIT",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -853,11 +1316,46 @@
"node": ">= 0.8"
}
},
"node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"engines": [
"node >=0.6.0"
],
"license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/ws": {
"version": "8.21.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz",
"integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
+3 -1
View File
@@ -16,6 +16,8 @@
"dependencies": {
"crypto": "^1.0.1",
"express": "^5.2.1",
"express-basic-auth": "^1.2.1"
"express-basic-auth": "^1.2.1",
"request": "^2.88.2",
"ws": "^8.21.1"
}
}
-99
View File
@@ -1,99 +0,0 @@
const express = require('express');
const { createHash } = require('crypto');
const app = express();
const port = 8356;
const geonJsonTemplate = {
type: "FeatureCollection",
features: [],
"marker-symbol-images": {
"star": "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 640'><path opacity='.4' fill='currentColor' d='M160 263.7L160 512C160 520.8 167.2 528 176 528L261.9 528L231.6 479.9C227.2 473 228.8 463.9 235.2 458.8L320 391.5L261.9 315.4C250.6 300.6 269.3 281.8 284.2 292.9L399.4 379.1C407.8 385.4 408 397.9 399.8 404.4L320 467.8L357.9 528L464 528C472.8 528 480 520.8 480 512L480 263.7L320 120.2L160 263.7z'/><path fill='currentColor' d='M336 70.1C326.9 61.9 313.1 61.9 304 70.1L72 278.1C62.1 286.9 61.3 302.1 70.2 312C79.1 321.9 94.2 322.7 104.1 313.8L112.1 306.6L112.1 511.9C112.1 547.2 140.8 575.9 176.1 575.9L464.1 575.9C499.4 575.9 528.1 547.2 528.1 511.9L528.1 306.6L536.1 313.8C546 322.6 561.1 321.8 570 312C578.9 302.2 578 287 568.2 278.1L528.2 242.2L528.2 152C528.2 138.7 517.5 128 504.2 128C490.9 128 480.2 138.7 480.2 152L480.2 199.2L336.2 70.1zM480 263.7L480 512C480 520.8 472.8 528 464 528L357.9 528L320 467.8L399.7 404.5C407.9 398 407.7 385.4 399.3 379.2L284.2 293C269.3 281.9 250.6 300.8 261.9 315.5L320 391.6L235.2 458.9C228.8 464 227.3 473.1 231.6 480L261.9 528.1L176 528.1C167.2 528.1 160 520.9 160 512.1L160 263.7L320 120.2L480 263.7z'/></svg>",
"star-stroked": "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'><path fill='currentColor' d='M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32zm73.8 149.3c7.9-22.3 29.1-37.3 52.8-37.3l58.3 0c34.9 0 63.1 28.3 63.1 63.1 0 22.6-12.1 43.5-31.7 54.8L248 280.4c-.2 13-10.9 23.6-24 23.6-13.3 0-24-10.7-24-24l0-13.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1 0-8.4-6.8-15.1-15.1-15.1l-58.3 0c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM192 368a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zM48 104a24 24 0 1 1 48 0 24 24 0 1 1 -48 0zM376 80a24 24 0 1 1 0 48 24 24 0 1 1 0-48zM48 408a24 24 0 1 1 48 0 24 24 0 1 1 -48 0zm328-24a24 24 0 1 1 0 48 24 24 0 1 1 0-48z'/></svg>"
}
};
app.all('/locations.geojson', (req, res) => {
// Verify Inputs
if (!req.query.auth) {
res.status(401).send('Unauthorized');
return;
}
// Query Haze API Websocket
let hazePwHash = null;
let hazeUser = null;
if (req.query.auth) {
let paramAuth = Buffer.from(req.query.auth, 'base64').toString('utf-8').replaceAll('\n', '');
hazeUser = paramAuth.split(":")[0];
hazePwHash = paramAuth.split(":")[1];
}
const haze = new WebSocket('wss://do.ecven.com:8120/explr');
haze.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
let haze_authToken = '', haze_username = '';
switch (data['event']) {
case "connected":
let pld = {
"event": "authenticateAccount_request",
"body": [
{
"password": hazePwHash,
"email": hazeUser
}
],
"socketMessageId": 0
};
haze.send(JSON.stringify(pld));
break;
case "authenticateAccount_response":
if (data['body']['response'] === 1) {
haze_authToken = data['body']['authToken'];
haze_username = data['body']['username'];
haze.send('{"event": "getMyLocationsRequest_request","body": [{"higlightImages": true}],"socketMessageId": 0}');
} else {
console.dir(req.query);
res.status(401).json({ ...data, password: req.query.auth });
haze.close();
res.end();
}
break;
case "getMyLocationsRequest_response":
if (data['body']['response'] === 1) {
const hazeLocations = data['body']['locations'].map(location => {
return {
type: "Feature",
geometry: {
type: "Point",
coordinates: [location['coordinates']['longitude'], location['coordinates']['latitude']]
},
properties: {
id: location['id'],
title: location['name'],
"marker-symbol": location['isUnconfirmedLocation'] === 1 ? "star-stroked" : "star",
}
}
});
res.setHeader('Content-Type', 'application/json');
haze.close();
res.end(JSON.stringify({
...geonJsonTemplate,
features: hazeLocations
}));
} else {
console.dir(data);
res.status(500).send('Failed to retrieve locations');
haze.close();
res.end();
}
break;
default:
console.dir(data);
res.status(500).send('Unexpected response from Haze API');
haze.close();
res.end();
}
});
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});