From 3971b767654bd50d4aa38ab624ffcddb34db6aa4 Mon Sep 17 00:00:00 2001 From: IP2Location Date: Wed, 19 Oct 2022 15:00:46 +0800 Subject: [PATCH] Added Country class to query country information and Region class to lookup the ISO 3166-2 subdivision code for country code and region name --- README.md | 46 +++++++++++++++++ package.json | 5 +- src/ip2location.d.ts | 35 ++++++++++++- src/ip2location.js | 116 ++++++++++++++++++++++++++++++++++++++++++- src/test.js | 18 ++++++- 5 files changed, 215 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ea87c75..4baae82 100644 --- a/README.md +++ b/README.md @@ -198,3 +198,49 @@ for (const x of cidr) { console.log(tools.cidrToIPV4("10.123.80.0/12")); console.log(tools.cidrToIPV6("2002:1234::abcd:ffff:c0a8:101/62")); ``` + +## COUNTRY CLASS + +## Methods +Below are the methods supported in this module. + +|Method Name|Description| +|---|---| +|getCountryInfo(countryCode)|Returns the country information.| + +## Usage + +```javascript +const {Country} = require("ip2location-nodejs"); + +let country = new Country("./IP2LOCATION-COUNTRY-INFORMATION-BASIC.CSV"); + +country.getCountryInfo("US").then(country_info => { + console.log(country_info); +}); + +country.getCountryInfo("").then(country_info => { + console.log(country_info); +}); +``` + +## REGION CLASS + +## Methods +Below are the methods supported in this module. + +|Method Name|Description| +|---|---| +|getRegionCode(countryCode, regionName)|Returns the region code for the supplied country code and region name.| + +## Usage + +```javascript +const {Region} = require("ip2location-nodejs"); + +let region = new Region("./IP2LOCATION-ISO3166-2.CSV"); + +region.getRegionCode("US", "California").then(region_code => { + console.log(region_code); +}); +``` diff --git a/package.json b/package.json index 587f9dd..209335b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ip2location-nodejs", - "version": "9.3.1", + "version": "9.4.1", "description": "IP2Location geolocation component", "keywords": [ "ip2location", @@ -22,7 +22,8 @@ "types": "src/ip2location.d.ts", "license": "MIT", "dependencies": { - "big-integer": "^1.6.47" + "big-integer": "^1.6.47", + "csv-parser": "^3.0.0" }, "repository": { "type": "git", diff --git a/src/ip2location.d.ts b/src/ip2location.d.ts index f5e977f..c1bc0c4 100644 --- a/src/ip2location.d.ts +++ b/src/ip2location.d.ts @@ -493,4 +493,37 @@ export class IPTools { * @returns The array with the starting and ending IPv6 addresses. */ cidrToIPV6(cidr: string): string[]; -} \ No newline at end of file +} +declare class Country { + /** + * Read the country information CSV file and parse the data. + * + * @param csvFile The full path to the country information CSV file. + */ + constructor(csvFile: any); + /** + * Retrieves the country information. + * + * @param countryCode The country code to get the country information. + * @returns The country information. + */ + getCountryInfo(countryCode?: string): Promise; + #private; +} +declare class Region { + /** + * Read the region information CSV file and parse the data. + * + * @param csvFile The full path to the region information CSV file. + */ + constructor(csvFile: any); + /** + * Retrieves the region code for the country code and region name. + * + * @param countryCode The country code to get the region code. + * @param regionName The region name to get the region code. + * @returns The region code. + */ + getRegionCode(countryCode?: string, regionName?: string): Promise; + #private; +} diff --git a/src/ip2location.js b/src/ip2location.js index a0b13d1..edf0d32 100644 --- a/src/ip2location.js +++ b/src/ip2location.js @@ -2,9 +2,10 @@ var net = require("net"); var fs = require("fs"); var bigInt = require("big-integer"); var https = require("https"); +const csv = require("csv-parser"); // For BIN queries -const VERSION = "9.3.1"; +const VERSION = "9.4.1"; const MAX_INDEX = 65536; const COUNTRY_POSITION = [ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1533,8 +1534,121 @@ class IPTools { } } +// Country class +class Country { + #fields = Array(); + #records = {}; + #fd; + #ready = false; + + constructor(csvFile) { + if (!fs.existsSync(csvFile)) { + throw new Error("The CSV file " + csvFile + " is not found."); + } + try { + fs.createReadStream(csvFile) + .pipe(csv(true)) + .on("data", (data) => { + if (data.country_code) { + this.#records[data.country_code] = data; + } else { + throw new Error("Invalid country information CSV file."); + } + }) + .on("end", () => { + this.#ready = true; + }); + } catch (err) { + throw new Error("Unable to read " + csvFile + "."); + } + } + + // Get country information + async getCountryInfo(countryCode = "") { + while (!this.#ready) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + countryCode = countryCode.trim(); + let results = Array(); + if (Object.keys(this.#records).length === 0) { + throw new Error("No record available."); + } + if (countryCode != "") { + if (this.#records[countryCode]) { + results.push(this.#records[countryCode]); + } + } else { + for (const elem in this.#records) { + results.push(this.#records[elem]); + } + } + return results; + } +} + +// Region class +class Region { + #fields = Array(); + #records = {}; + #fd; + #ready = false; + + constructor(csvFile) { + if (!fs.existsSync(csvFile)) { + throw new Error("The CSV file " + csvFile + " is not found."); + } + try { + fs.createReadStream(csvFile) + .pipe(csv(true)) + .on("data", (data) => { + if (data.subdivision_name) { + if (!this.#records[data.country_code]) { + this.#records[data.country_code] = Array(); + } + this.#records[data.country_code].push({ + code: data.code, + name: data.subdivision_name, + }); + } else { + throw new Error("Invalid region information CSV file."); + } + }) + .on("end", () => { + this.#ready = true; + }); + } catch (err) { + throw new Error("Unable to read " + csvFile + "."); + } + } + + // Get region code + async getRegionCode(countryCode = "", regionName = "") { + while (!this.#ready) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + countryCode = countryCode.trim(); + regionName = regionName.trim(); + if (Object.keys(this.#records).length === 0) { + throw new Error("No record available."); + } + if (this.#records[countryCode]) { + for (let x = 0; x < this.#records[countryCode].length; x++) { + let elem = this.#records[countryCode][x]; + if (regionName.toUpperCase() == elem.name.toUpperCase()) { + return elem.code; + } + } + return null; + } else { + return null; + } + } +} + module.exports = { IP2Location: IP2Location, IP2LocationWebService: IP2LocationWebService, IPTools: IPTools, + Country: Country, + Region: Region, }; diff --git a/src/test.js b/src/test.js index df30af5..612a545 100644 --- a/src/test.js +++ b/src/test.js @@ -1,4 +1,4 @@ -const {IP2Location, IP2LocationWebService, IPTools} = require("ip2location-nodejs"); +const {IP2Location, IP2LocationWebService, IPTools, Country, Region} = require("ip2location-nodejs"); let ip2location = new IP2Location(); @@ -84,3 +84,19 @@ for (const x of cidr) { } console.log(tools.cidrToIPV4("10.123.80.0/12")); console.log(tools.cidrToIPV6("2002:1234::abcd:ffff:c0a8:101/62")); + +let country = new Country("./IP2LOCATION-COUNTRY-INFORMATION-BASIC.CSV"); + +country.getCountryInfo("US").then(country_info => { + console.log(country_info); +}); + +country.getCountryInfo("").then(country_info => { + console.log(country_info); +}); + +let region = new Region("./IP2LOCATION-ISO3166-2.CSV"); + +region.getRegionCode("US", "California").then(region_code => { + console.log(region_code); +});