-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
130 lines (116 loc) · 4.06 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
const express = require('express')
const bodyParser = require('body-parser');
const compression = require('compression');
const fetch = require('node-fetch');
const maxmind = require('maxmind');
const fs = require('fs-extra');
const tar = require('tar');
const path = require('path');
const schedule = require('node-schedule');
const resolve = file => path.resolve(__dirname, file);
const app = express();
const downloadUrl = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz';
let ipLookup;
function createDbInstance() {
ipLookup = maxmind.openSync(resolve('./ipDataBase.mmdb'), {
cache: {
max: 50000, // Max items in cache, by default it's 6000
},
watchForUpdates: true,
});
}
async function fetchAndProcessFile() {
const fileName = downloadUrl.split('/').pop();
try {
const responseFile = await fetch(downloadUrl);
const tmpFileStream = fs.createWriteStream(fileName);
responseFile.body.pipe(tmpFileStream)
.on('finish', () => {
console.log(' [x] Compressed DB file downloaded and saved');
const filePath = resolve(`./${fileName}`);
tar.extract({
file: filePath,
newer: true,
}).then(() => {
fs.readdir(resolve(`./`), (err, fileNames) => {
const extractedFolder = fileNames.find(file => !path.extname(file) && file.toLowerCase().includes('geolite'));
const extractedFolderPath = resolve(`./${extractedFolder}`);
fs.readdir(extractedFolderPath, async(err, subFolderFiles) => {
const ipDatabaseFile = subFolderFiles.find(file => path.extname(file).toLowerCase() === '.mmdb');
try {
await fs.move(resolve(`./${extractedFolder}/${ipDatabaseFile}`), resolve(`./ipDataBase.mmdb`), {
overwrite: true
});
createDbInstance();
fs.remove(filePath);
fs.remove(extractedFolderPath);
console.log(' [x] DB file processed and ready');
} catch (e) {
console.error(' [x] Move of processed file failed with error: ', e.message);
console.info(' [x] Using older file');
}
});
});
});
});
} catch (e) {
console.error(' [x] Processing of older file failed with error: ', e.message);
}
}
if (fs.existsSync(resolve('./ipDataBase.mmdb'))) {
createDbInstance();
}
console.log(' [x] Scheduling the task to fetch the database at 00:00 hrs on every Sunday');
schedule.scheduleJob({
hour: 00,
minute: 00,
dayOfWeek: 0
}, function () {
console.log('Scheduled task to be executed now');
fetchAndProcessFile();
});
fetchAndProcessFile();
/*
Setup the actual server code
*/
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.all('/', async(req, res) => {
res.header('Access-Control-Allow-Origin', '*');
try {
const ip = req.query.ip;
if (!ip) {
return res.status(422).json({
message: 'IP is required',
status: 'failed'
});
}
const lookupObj = ipLookup.get(ip);
const responseObj = {
ip,
}
try {
responseObj.continent = lookupObj.continent.names.en;
responseObj.country_code = lookupObj.country.iso_code;
responseObj.country_name = lookupObj.country.names.en;
responseObj.time_zone = lookupObj.location.time_zone;
responseObj.latitude = lookupObj.location.latitude;
responseObj.longitude = lookupObj.location.longitude;
responseObj.accuracy_radius = lookupObj.location.accuracy_radius;
responseObj.city = lookupObj.city.names.en;
responseObj.region_name = lookupObj.subdivisions[0].names.en;
} catch (err) {}
res.json(responseObj);
} catch (err) {
console.error('Error: ', err.message, err.stack);
res.status(500).json({
message: 'unable to process request',
error: err.toString()
})
}
});
console.log(' [x] Starting first time fetch of the IP Database');
app.listen(3000, () => console.log(' [x] IP Resolver app listening on port 3000'))