Skip to content

Commit 4e7ea1c

Browse files
authored
Merge pull request #52 from VikramTiwari/updates-for-license-key
fix: update config to use license key
2 parents 6eff6e0 + 37c2deb commit 4e7ea1c

File tree

8 files changed

+467
-226
lines changed

8 files changed

+467
-226
lines changed

.github/workflows/nodejs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99

1010
strategy:
1111
matrix:
12-
node-version: [8.x, 10.x, 12.x, 13.x]
12+
node-version: [10.x, 12.x, 13.x]
1313

1414
steps:
1515
- uses: actions/checkout@v1
@@ -24,3 +24,4 @@ jobs:
2424
npm test
2525
env:
2626
CI: true
27+
MAXMIND_LICENSE_KEY: ${{ secrets.MAXMIND_LICENSE_KEY }}

.travis.yml

Lines changed: 0 additions & 4 deletions
This file was deleted.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ npm install --save geo-from-ip
2020
yarn add --save geo-from-ip
2121
```
2222

23+
- Set `MAXMIND_LICENSE_KEY=<your_maxmind_license_key>` in your environment variables. Read more about [this change on MaxMind's blog](https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/).
24+
2325
- Use package to get geo data from IP
2426

2527
```javascript

lib/update.js

Lines changed: 93 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,122 @@
1-
'use strict'
1+
"use strict";
22

3-
const debug = require('debug')('geo-from-ip:updater')
4-
const fs = require('fs')
5-
const zlib = require('zlib')
6-
const async = require('async')
7-
const request = require('request')
3+
const debug = require("debug")("geo-from-ip:updater");
4+
const fs = require("fs");
5+
const path = require("path");
6+
const util = require("util");
7+
const streamPipeline = util.promisify(require("stream").pipeline);
8+
const fetch = require("node-fetch");
9+
const targz = require("targz");
810

9-
const config = require('../mmdb/config')
10-
debug(`Running update script with config: ${JSON.stringify(config)}`)
11+
if (process.env.MAXMIND_LICENSE_KEY === undefined) {
12+
debug(
13+
"Seems like you forgot to add MAXMIND_LICENSE_KEY to your environment variables. Read more: https://github.com/VikramTiwari/geo-from-ip#how-to-use"
14+
);
15+
process.exit(1);
16+
}
17+
18+
const config = require("../mmdb/config");
1119

1220
/**
13-
* check if remote file is newer
14-
* @param {String} dest path for local file
15-
* @param {String} remote path for remote file
16-
* @param {Function} cb true/false
21+
* uncompresses the zipped file into folders and does cleanup of remaining files and folders
22+
* @param {String} zipped path to zipped file
23+
* @param {Object} database database object
1724
*/
18-
function isRemoteNewer (dest, remote, cb) {
19-
// if no file
20-
if (!fs.existsSync(dest)) {
21-
cb(null, false)
22-
} else {
23-
// if dest file is not a file, remove it
24-
const stats = fs.statSync(dest)
25-
if (!stats.isFile()) {
26-
debug(`${dest} is not a file`)
27-
fs.unlink(dest, () => {
28-
debug(`${dest} deleted`)
29-
})
30-
}
31-
32-
request(
25+
async function uncompress(zipped, database) {
26+
new Promise((resolve, reject) => {
27+
targz.decompress(
3328
{
34-
url: remote,
35-
headers: {
36-
'If-Modified-Since': stats.mtime.toUTCString()
29+
src: zipped,
30+
dest: config.dbDir,
31+
tar: {
32+
ignore: function(name) {
33+
return path.extname(name) !== ".mmdb";
34+
}
3735
}
3836
},
39-
res => {
40-
if (res === null) {
41-
cb(null, true)
37+
err => {
38+
if (err) {
39+
debug(err);
40+
reject();
4241
} else {
43-
cb(null, false)
42+
fs.readdirSync(config.dbDir).forEach(file => {
43+
if (fs.lstatSync(`${config.dbDir}/${file}`).isDirectory()) {
44+
fs.renameSync(
45+
`${config.dbDir}/${file}/${database.filename}.mmdb`,
46+
`${config.dbDir}/${database.filename}.mmdb`
47+
);
48+
fs.rmdirSync(`${config.dbDir}/${file}`);
49+
}
50+
});
51+
fs.unlinkSync(`${config.dbDir}/${database.filename}.tar.gz`);
52+
resolve();
4453
}
4554
}
46-
)
47-
}
55+
);
56+
});
4857
}
4958

5059
/**
51-
* downloads file
52-
* @param {String} dest path for local file
53-
* @param {String} remote path for remote file
54-
* @param {Function} cb true/false
60+
* download database and unzip
61+
*
62+
* @param {Object} database database to download
5563
*/
56-
function download (dest, remote, cb) {
57-
request
58-
.get(remote)
59-
.pipe(zlib.createGunzip())
60-
.pipe(fs.createWriteStream(dest))
61-
.on('error', error => {
62-
cb(error, false)
63-
})
64-
.on('finish', () => {
65-
cb(null, true)
66-
})
64+
async function download(database) {
65+
const zipped = `${config.dbDir}/${database.filename}.tar.gz`;
66+
const response = await fetch(database.remote);
67+
await streamPipeline(response.body, fs.createWriteStream(zipped));
68+
debug("download complete, uncompressing");
69+
await uncompress(zipped, database);
70+
debug("ready!");
6771
}
6872

6973
/**
70-
* runs downloads for all the files
71-
* @param {String} item which database
72-
* @param {Function} cb true/false
74+
* check if remote file is newer
75+
*
76+
* @param {Object} database database to download
7377
*/
74-
function dl (item, cb) {
75-
const dest = config.dbDir + '/' + item.local
78+
async function isRemoteNewer(database) {
79+
const mmdb = `${config.dbDir}/${database.filename}.mmdb`;
80+
// if no file
81+
if (!fs.existsSync(mmdb)) {
82+
debug("file does not exist");
83+
return true;
84+
} else {
85+
// if dest file is not a file, remove it
86+
const stats = fs.statSync(mmdb);
87+
if (!stats.isFile()) {
88+
debug(`${mmdb} is not a file`);
89+
fs.unlinkSync(mmdb, () => {
90+
debug(`${mmdb} deleted`);
91+
});
92+
}
7693

77-
isRemoteNewer(dest, item.remote, (err, newer) => {
78-
if (err) {
79-
cb(err, false)
80-
} else if (!err && newer) {
81-
cb(null, false)
82-
} else if (!err && !newer) {
83-
// begin downloading
84-
debug(`downloading ${dest}`)
94+
const response = await fetch(database.remote, {
95+
method: "GET",
96+
headers: {
97+
"If-Modified-Since": stats.mtime.toUTCString()
98+
}
99+
});
85100

86-
download(dest, item.remote, (err, done) => {
87-
if (err) {
88-
cb(err, false)
89-
} else if (!err && !done) {
90-
cb(null, false)
91-
} else if (!err && done) {
92-
cb(null, true)
93-
}
94-
})
101+
if (response === null) {
102+
return true;
95103
}
96-
})
104+
return false;
105+
}
97106
}
98107

99108
/**
100-
* Runs a sync function to download the files
101-
*
102-
* @param {any} cb
109+
* sync databases to local
103110
*/
104-
function sync (cb) {
105-
async.eachSeries(config.geoIpDbs, dl, err => {
106-
cb(err, true)
107-
})
111+
function sync() {
112+
config.geoIpDbs.forEach(async database => {
113+
if (await isRemoteNewer(database)) {
114+
debug("remote is newer, downloading");
115+
await download(database);
116+
}
117+
});
108118
}
109119

110-
async.eachSeries(config.geoIpDbs, dl, err => {
111-
if (err) {
112-
debug(`🚨 Error: ${err}`)
113-
} else {
114-
debug(`🚀 All set!`)
115-
}
116-
})
120+
sync();
117121

118-
module.exports.sync = sync
122+
module.exports.sync = sync;

mmdb/config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// where your GeoIP databases are stored
44
exports.dbDir = __dirname
55

6-
// local-filename, remote geolite-url
6+
// local:filename, remote:geolite-url
77
exports.geoIpDbs = [{
8-
local: 'GeoLite2-City.mmdb',
9-
remote: 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz'
8+
filename: 'GeoLite2-City',
9+
remote: `https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=${process.env.MAXMIND_LICENSE_KEY}&suffix=tar.gz`
1010
}]

mmdb/fileslist.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## Free Databases [https://dev.maxmind.com/geoip/geoip2/geolite2/]
22

3-
> GeoLite2-City.mmdb [https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz]
4-
> GeoLite2-Country.mmdb [https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz]
3+
> GeoLite2-City.mmdb [https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City]
4+
> GeoLite2-Country.mmdb [https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country]
55
66
## Paid databases [https://www.maxmind.com/en/geoip2-databases]
77

0 commit comments

Comments
 (0)