How to implement geoip in node.js and mongodb - mongodb

I have seen few examples of using geoip in node.js such as https://github.com/kuno/GeoIP.git and https://github.com/wadey/node-geoip. However what i want is to display the map showing geoip for the particular loged in user.How can it be implemented.

You can get a geolocation database (such as from http://www.maxmind.com) and store it in mongo. Each record contains an IP range (start/end) and the latitude/longitude associated with that IP range. IPs are represented as integers. You could create an index on the start field, and do a query on mongo to find the record with the largest value of start which is smaller than the IP of your client user, and look up the corresponding lat/lon.
As for plotting a map with this lat/lon, it's very easy to create a google map which is centered on a particular location: (View source at: http://code.google.com/apis/maps/documentation/javascript/v2/examples/map-simple.html)
There are a lot of different ways of storing/querying geolocation data, but this is just one possible approach using mongo that might work. Hope this helps.

The best module for GeoIP is https://github.com/kuno/GeoIP in my opinion (I actually used this module for a project and it worked perfectly for me). You have to download the database from Maxmind and also install some OS specific libraries and then compile the module.
There is no need to put the database into MongoDB unless you want to replicate easily across multiple servers. You can just put your database into a file and provide the path in the Node.js module.
Here is an example:
// Open the GeoLiteCity.dat file first.
var City = geoip.City;
var city = new City('/path/to/GeoLiteCity.dat');
console.log(city); // this contains country, city, lat, long, continent, postal code etc

I've just published an NPM module for the IPLocate.io API which I created, which lets you find the location (city, country and coordinates) based on an IP address.
Super easy, no databases to download, and 1,500 free requests per day.
Install
npm install node-iplocate
Usage
const iplocate = require("node-iplocate");
iplocate("8.8.8.8").then(function(results) {
console.log("IP Address: " + results.ip);
// IP Address: 8.8.8.8
console.log("Country: " + results.country + " (" + results.country_code + ")");
// Country: United States (US)
console.log("Continent: " + results.continent);
// Continent: North America
console.log("Organisation: " + results.org + " (" + results.asn + ")");
// Organisation: Google LLC (AS15169)
console.log(JSON.stringify(results, null, 2));
/*
{
"ip": "8.8.8.8",
"country": "United States",
"country_code": "US",
"city": null,
"continent": "North America",
"latitude": 37.751,
"longitude": -97.822,
"time_zone": null,
"postal_code": null,
"org": "Google LLC",
"asn": "AS15169"
}
*/
});
// Or with callbacks
iplocate("8.8.8.8", null, function(err, results) {
// ...
console.log(JSON.stringify(results, null, 2));
});
// Provide an API key from IPLocate.io
iplocate("8.8.8.8", { api_key: "abcdef" }).then(function(results) {
// ...
});

Python Implementation:
#!/usr/bin/python
#coding: utf-8
import os
import pygeoip
gi = pygeoip.GeoIP('GeoIP.dat')
gic = pygeoip.GeoIP('GeoIPCity.dat')
fl = file(r'apache-unique.log')
lines = fl.readlines()
for line in lines:
print gi.country_code_by_addr(line)
print gic.record_by_addr(line)
os.system('pause')

extending mpobrien's answer-
I found this to be easier and faster approach.
Download the binary db at maxmind
http://dev.maxmind.com/geoip/geoip2/geolite2/
http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
Use node-maxmind-db
https://github.com/PaddeK/node-maxmind-db
var mmdbreader = require('maxmind-db-reader');
// open database
var countries = mmdbreader.openSync('./countries.mmdb');
// get geodata
app.get('/api/v1/ip/', function(req, res) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
countries.getGeoData(ip, function(err, geodata) {
if(!err && geodata.location) return res.json({success: true, location: geodata.location});
return res.json({success: false, location: null, error: err});
});
});
Then you will have user location based on his ip address which you can display on map.
Benefits-
The bindary data file is small and easy to update. No db import export.
Just swap the file and reload the data. ie- mmdbreader.openSync()

Related

How to properly deploy a customer record script with NetSuite's suiteScript?

Currently I'm writing an example script to get the hang of the suiteScript environment and get a better idea of how it all works. Right now I've written a script that looks like it should create and save a new customer record upon deployment. I dont run into any errors loading the script into NetSuite and I put the code through a debugger and the syntax seems right.
'''
/**
* #NApiVersion 2.x
* #NScriptType ClientScript
*/
define(["N/record"], function (r) {
function creatCustomer() {
var customer = record.create({
type: record.Type.CUSTOMER,
isDynamic: false,
defaultValues: null
});
customer.setValue(
{fieldId: "firstname", value: "James", ignoreFieldChange: false},
{fieldId: "lastname", value: "Halpert"},
{fieldId: "subsidiary",value: "Training 7"},
{fieldId: "email", value: "JHalpert#DM.com"},
{fieldId: "company Name",value: "Dunder Mifflin Test"}
);
customer.save({
enableSourcing: true,
ignoreMandatoryFields: false
});
}
return {
saveRecord: creatCustomer
};
});
'''
I think the problem might be deployment, but I don't know exactly what it could be. The script gets deployed but I can't find the customer record anywhere.
You should use the Netsuite help to read about script types and script type entry points. In particular client scripts are not generally used the way you have set that up.
This question has almost nothing in it regarding script deployment issues. (I'd expect to see at least one screen shot of the deployment screen)
For what you have written each time one of the deployment target records is saved a new customer record save will be attempted.
However the script you posted will error because:
the subsidiary value should be the internalid of the subsidiary - not the subsidiary name.
you are declaring 'N/record' as function(r) but then using it like record.create
record.setValue doesn't take a list of fieldId/value pairs
It may error if the user submitting the record doesn't have permissions to create customers.
It will likely error the second time it runs because a non-unique user name is being given. (Though this depends on how your account is configured)
One way to 'play' with scripts is to open a console window on any record in edit mode (and for some other screens) and you can run individual scripts like:
require(["N/record"], function (record) {
var customer = record.create({
type: record.Type.CUSTOMER,
isDynamic: false,
defaultValues: null
});
customer.setValue({fieldId: "firstname", value: "James"}); //, ignoreFieldChange: false}, <- this is for dynamic mode and client scripts
customer.setValue({fieldId: "lastname", value: "Halpert"});
customer.setValue({fieldId: "subsidiary",value: "Training 7"});
customer.setValue({fieldId: "email", value: "JHalpert#DM.com"});
customer.setValue({fieldId: "company Name",value: "Dunder Mifflin Test"});
var custId = customer.save({
enableSourcing: true,
ignoreMandatoryFields: false
});
console.log('created customer ', custId);
});

Is it better to use asyncStorage or to query hasura database for persistent latitude / longitude data in react native / expo app?

I am currently querying my Hasura database using userId to get location. This is for my video-based React Native / Expo application.
users(where: {id: {_eq: 1528}}) {
location
}
I then use location to query users near that one user.
users(
where:
{ location: {_st_d_within: {distance: 20000, from: $point }}},
) {
firstName
city
region
}
}
It turns out I cannot combine these two queries into one query, as mentioned here.
My question is: is it more efficient to query twice like above or to store location as asyncStorage within my Expo / React Native application?
If I store location within asyncStorage, I could use the following function to retrieve latitude, for example.
export const _retrieveLatitude = async () => {
try {
const value = await AsyncStorage.getItem('#latitude');
if (value !== null) {
return parseInt(value);
} else {
return 0;
}
} catch (error) {
return 0;
}
};
What is better practice?
Keep in mind, the only data being stored in latitude / longitude. This can be considered persistent data, because all I need from the user is her general location, rather than her specific location.

Here geocoder API: retrieve route number based on coordinates

I noticed that I can retrieve route number based on coordinates using geocoding service. If coordinates are located outside the city, instead of street name geocoder returns route number (which is very useful).
Sometimes however route has multiple numbers - eg. "A4/E65/5". Unfortunately geocoder returns only one number - eg. "5". Is there any chance that geocoder can return full number?
Goeocder might not work here, have you tried getLinkinfo ?
e.g
http://route.st.nlp.nokia.com/routing/6.2/getlinkinfo.xml?app_id=DemoAppId01082013GAL&app_code=AJKnXv84fjrb0KIHawS0Tg&waypoint=45.79728,16.13712&linkattributes=all
With Geocoding use "locationattributes=addressNames". That will return many name variants including several languages and road numbers, e.g.
street: [
{
value: "A5",
language: "de"
},
{
value: "E451",
language: "de"
}
]

Given a URL how can I figure out the Geo where it is likely to originating from?

I am working on a certain problem where given a URL I need to map it to a country. Even if I can reliably answer the question "Is this particular URL relevant to United States?" that should be sufficient.
I am happy to have false negatives but never a false positive.
Currently I am considering the following approach.
See if the domain name of the URL is in top 1000 .com domains on Alexa for USA.
Check if the the link was shared by US users on Facebook or twitter.
Has anyone solved this kind of problem before ?
You can use http://dev.maxmind.com/geoip/geoip2/geolite2/ but you need to get the IP address from your URLs domain before you can access the GeoIP database with this address.
There are a lot of interfaces to the GeoIP dataset for different languages: http://dev.maxmind.com/geoip/geoip2/downloadable/#MaxMind_APIs
Have a look at a sample NodeJS project here:
https://github.com/tobilg/GeoLocateURL
You can also try out the userinfo.io API or javascript library which is free and gets its data from a merge of several geolocation databases for more accuracy.
<script type="text/javascript" href="//cdnjs.cloudflare.com/ajax/libs/userinfo/1.0.0/userinfo.min.js"></script>
<script type="text/javascript">
UserInfo.getInfo(function(data) {
// the "data" object contains the info
}, function(err) {
// the "err" object contains useful information in case of an error
});
</script>
The response will look like:
{
request_date: "2014-09-18T04:11:25.154Z",
ip_address: "192.77.237.95",
position: {
latitude: 37.7758,
longitude: -122.4128,
accuracy: 3 // This is the accuracy radius, in kilometers
},
continent: {
name: "North America",
code: "NA",
},
country: {
name: "United States",
code: "US",
},
city: {
name: "San Francisco",
code: "94103"
}
}

Post to facebook with multiple cities target

I'm trying to post something with target parameters, and i can do that but specifying only one city. Is there any way to pass two or more cities?
I'm trying this way:
parameters.targeting = new {
countries = "some country",
cities = new [] { new { key = "city value" }, new { key = "other city value" } },
locales = "locale code"
};
But no success! How can i do this?
This is very unclear, but I am guessing you are just not formatting your array of cities correctly. See more here: https://developers.facebook.com/docs/reference/ads-api/targeting-specs/
I believe you should be using "name" instead of "key" for the cities, but again I really don't have enough information to go off of.
Specify key, radius & distance_unit. For key, see Targeting Search,
Cities. radius is a distance around cities, from 10 to 50 miles or 17
to 80 kilometers. distance_unit is mile or kilometer. Limit: 250.
Example: 'cities': [{'key':'2430536', 'radius':12,
'distance_unit':'mile'}]
Source: https://developers.facebook.com/docs/marketing-api/buying-api/targeting#location