geoip_from_cities
Version:
Find the lattitude and longitude from a locally cached cities.json as opposed to google geoip which has limits of 2500 requests per day.
110 lines (82 loc) • 3.23 kB
JavaScript
/*! geoip_from_cities 2.2.0 (b884907) | https://gitlab.com/rioadvancement/geoip_from_cities */
var geoip_from_cities = (function () {
'use strict';
// Copyright 2018 Rio Advancement Inc
const R = require('ramda');
const cities = require('cities.json');
const _fromCity = city => {
return city.name + ", " + city.country;
};
const _fromString = (city, country) => {
return city + ", " + country;
};
// Group function that groups the cities json by the format as below
// 'City name, Country' : [{ its lattitue data }]
//
const byCityWithCountry = R.groupBy(function(city){
return _fromCity(city)
});
// Apply the byCityWithCountry groupBy function with the cities data
// The locations has the transformed data.
// Examples
// 'Delhi, IN': [{"country":"IN","name":"New Delhi","lat":"28.63576","lng":"77.22445"}]
//
const locations = byCityWithCountry(cities);
// Only store the keys of the locations
//
const locationKeys = R.keys(locations);
// A scoped cached, that stored the cached results.
let cachedLocations = {};
class RioGeo {
constructor () { }
// Given a city and country name, return
// multiple cities + countries combo found.
// This is an opinionated function for Rio.
// This works in the way that when an user types
// "NEW" + US => The multiple cities starting with NEW + US
// must be sent back.
locateCity(city, country) {
const uCity = city.toUpperCase();
const uCountry = country.toUpperCase();
const isLike = n => {
const uN = n.toUpperCase();
let regex = new RegExp( '.*, '+uCountry, 'g' );
let res = uN.match(regex);
return res != null && res.length > 0 && uN.indexOf(uCity) >=0
};
const composeFn = R.compose(R.filter(isLike));
return composeFn(locationKeys)
}
// Exported search function that does the following
// When provided a city and a country name
// Tries to get the latitude/longitude from the cache,
// If not does a live search from the cities file
fillWithGeoInfo(city, country, force=false) {
let found = cachedLocations[_fromString(city, country)];
if (!found || force) {
found = this._searchLive(city, country);
cachedLocations[_fromString(city,country)] = found;
}
return found
}
// Does the following computations
// 1. Filters the locationKey which is "city, country" from the locationsKey
// 2. If multiple are found then takes the first
// 3. Expands the locationKey to a location by finding it in the locations
// object
// 4. Flattens as the output from the above step is an [[]]
// 5. If there are multiple matches, sorts the unique, usually the first one
// is returned.
_searchLive(city, country) {
const isLike = n => {
return n.indexOf(country) > 0 && n.indexOf(city) >=0
};
const expLocation = x => locations[x];
const countryEq = (a, b) => R.eqBy(e => a.country == b.country );
const composeFn = R.compose(R.uniqWith(countryEq), R.flatten , R.map(expLocation) , R.take(1), R.filter(isLike));
return composeFn(locationKeys)
}
}
return RioGeo;
}());
//# sourceMappingURL=bundle.js.map