blurts-server/ip-location-service.js

55 строки
1.9 KiB
JavaScript

"use strict";
const path = require("path");
const reader = require("@maxmind/geoip2-node").Reader;
const AppConstants = require("./app-constants");
let locationDb, timestamp;
async function openLocationDb() {
if (locationDb && isFresh()) return console.warn("Location database already open.");
try {
const dbPath = path.join(AppConstants.GEOIP_GEOLITE2_PATH, AppConstants.GEOIP_GEOLITE2_CITY_FILENAME);
locationDb = await reader.open(dbPath);
} catch (e) {
return console.warn("Could not open location database:", e.message);
}
timestamp = Date.now();
return true;
}
async function readLocationData(ip, locales) {
let locationArr;
if (!isFresh()) await openLocationDb();
try {
const data = locationDb.city(ip);
const countryName = data.country?.names[locales.find(locale => data.country?.names[locale])]; // find valid locale key and return its value
const cityName = data.city?.names[locales.find(locale => data.city?.names[locale])];
const subdivisionName = data.subdivisions?.[0].isoCode;
const subdivisionFiltered = /[A-z]{2,}/.test(subdivisionName) ? subdivisionName : null; // return strings that are 2 or more letters, or null (avoid unfamiliar subdivisions like `E` or `09`)
locationArr = [cityName, subdivisionFiltered, countryName].filter(str => str); // [city name, state code, country code] with non-null items.
} catch (e) {
return console.warn("Could not read location from database:", e.message);
}
return {
shortLocation: locationArr.slice(0, 2).join(", "), // shows the first two location values from the ones available
fullLocation: locationArr.join(", "), // shows up to three location values from the ones available
};
}
function isFresh() {
if (Date.now() - timestamp < 259200000) return true; // 1000ms * 60s * 60m * 24h * 3 elapsed time is less than 24hrs
return false;
}
module.exports = {
openLocationDb,
readLocationData,
};