index.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // GeoIP lookup service
  3. //
  4. // GeoIP cache TTL in ms
  5. var CACHE_TTL = (60 * 60 * 24 * 60 * 1000); // 60 days
  6. var config = require(__dirname + '/config.js');
  7. if (!config.maxmind) {
  8. console.error('FATAL: only MaxMind GeoIP2 is currently supported and is not configured in config.js');
  9. process.exit(1);
  10. }
  11. var geo = require('geoip2ws')(config.maxmind);
  12. var cache = require('levelup')(__dirname + '/cache.leveldb');
  13. function lookup(ip,callback)
  14. {
  15. cache.get(ip,function(err,cachedEntryJson) {
  16. if ((!err)&&(cachedEntryJson)) {
  17. try {
  18. var cachedEntry = JSON.parse(cachedEntryJson.toString());
  19. if (cachedEntry) {
  20. var ts = cachedEntry.ts;
  21. var r = cachedEntry.r;
  22. if ((ts)&&(r)) {
  23. if ((Date.now() - ts) < CACHE_TTL) {
  24. r._cached = true;
  25. return callback(null,r);
  26. }
  27. }
  28. }
  29. } catch (e) {}
  30. }
  31. geo(ip,function(err,result) {
  32. if (err)
  33. return callback(err,null);
  34. if ((!result)||(!result.location))
  35. return callback(new Error('null result'),null);
  36. cache.put(ip,JSON.stringify({
  37. ts: Date.now(),
  38. r: result
  39. }),function(err) {
  40. if (err)
  41. console.error('Error saving to cache: '+err);
  42. return callback(null,result);
  43. });
  44. });
  45. });
  46. };
  47. var linebuf = '';
  48. process.stdin.on('readable',function() {
  49. var chunk;
  50. while (null !== (chunk = process.stdin.read())) {
  51. for(var i=0;i<chunk.length;++i) {
  52. var c = chunk[i];
  53. if ((c == 0x0d)||(c == 0x0a)) {
  54. if (linebuf.length > 0) {
  55. var ip = linebuf;
  56. lookup(ip,function(err,result) {
  57. if ((err)||(!result)||(!result.location)) {
  58. return process.stdout.write(ip+',0,0,0,0,0,0\n');
  59. } else {
  60. var lat = parseFloat(result.location.latitude);
  61. var lon = parseFloat(result.location.longitude);
  62. // Convert to X,Y,Z coordinates from Earth's origin, Earth-as-sphere approximation.
  63. var latRadians = lat * 0.01745329251994; // PI / 180
  64. var lonRadians = lon * 0.01745329251994; // PI / 180
  65. var cosLat = Math.cos(latRadians);
  66. var x = Math.round((-6371.0) * cosLat * Math.cos(lonRadians)); // 6371 == Earth's approximate radius in kilometers
  67. var y = Math.round(6371.0 * Math.sin(latRadians));
  68. var z = Math.round(6371.0 * cosLat * Math.sin(lonRadians));
  69. return process.stdout.write(ip+',1,'+lat+','+lon+','+x+','+y+','+z+'\n');
  70. }
  71. });
  72. }
  73. linebuf = '';
  74. } else {
  75. linebuf += String.fromCharCode(c);
  76. }
  77. }
  78. }
  79. });
  80. process.stdin.on('end',function() {
  81. cache.close();
  82. process.exit(0);
  83. });