node-ipdox 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ # [ISC License](https://spdx.org/licenses/ISC)
2
+
3
+ Copyright (c) 2023, Mikel Calvo <contact@mikelcalvo.net>
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ [![NPM version][npm-version-image]][npm-url]
2
+
3
+ # Node.JS IP Doxxer
4
+
5
+ IPDox is a simple and efficient IP geolocation library for Node.js. It fetches data from multiple geolocation APIs and provides a unified response. It also includes a caching mechanism to prevent unnecessary requests.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install node-ipdox --save
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```javascript
16
+ import { IPDox } from "node-ipdox";
17
+
18
+ const ipdox = new IPDox({ cacheTimeout: 43200000, maxRetries: 10 });
19
+
20
+ ipdox
21
+ .doxIP({ ip: "8.8.8.8" })
22
+ .then(response => console.log(response))
23
+ .catch(error => console.error(error));
24
+ ```
25
+
26
+ ## API
27
+
28
+ ### `new IPDox({ cacheTimeout, maxRetries })`
29
+
30
+ Creates a new instance of IPDox.
31
+
32
+ - `cacheTimeout` - The cache timeout in milliseconds (default: 43200000 (12 hours))
33
+ - `maxRetries` - Maximum number of retries if an API request fails (default: 10)
34
+
35
+ ### `ipdox.doxIP({ ip })`
36
+
37
+ Fetches geolocation data for the specified IP address.
38
+
39
+ - `ip` - IP address
40
+
41
+ Returns a Promise that resolves to an `IPDOXResponse` object.
42
+
43
+ ## IPDOXResponse
44
+
45
+ The `IPDOXResponse` object includes the following properties:
46
+
47
+ ```typescript
48
+ export interface IPDOXResponse {
49
+ ip: string; // IP address
50
+ country: string; // Country ISO code
51
+ city: string; // City name
52
+ continent: string; // Continent ISO code
53
+ latitude: number; // Latitude
54
+ longitude: number; // Longitude
55
+ zip: string; // Zip code
56
+ isp: string; // ISP name
57
+ proxy?: boolean; // Boolean indicating if the IP address is a proxy (might be undefined)
58
+ isHosting?: boolean; // Boolean indicating if the IP address is a hosting provider (might be undefined)
59
+ proxyInfo?: {
60
+ // Proxy information (might be undefined)
61
+ isVPN: boolean; // Boolean indicating if the IP address is a VPN (might be undefined)
62
+ isTOR: boolean; // Boolean indicating if the IP address is a TOR node (might be undefined)
63
+ isProxy: boolean; // Boolean indicating if the IP address is a proxy (might be undefined)
64
+ };
65
+ source: string; // Source API
66
+ }
67
+ ```
68
+
69
+ ## Contributing
70
+
71
+ Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
72
+
73
+ ## License
74
+
75
+ This project is licensed under the [ISC License](https://spdx.org/licenses/ISC).
76
+
77
+ ---
78
+
79
+ [npm-url]: https://npmjs.org/package/node-ipdox
80
+ [npm-version-image]: http://img.shields.io/npm/v/node-ipdox.svg?style=flat
@@ -0,0 +1,17 @@
1
+ import _IPDox from "./ipdox";
2
+ /**
3
+ * Main Class
4
+ */
5
+ export declare const IPDox: typeof _IPDox;
6
+ /**
7
+ * Constructor type
8
+ */
9
+ export { IPDOXConstructor } from "./types/IPDOXConstructor";
10
+ /**
11
+ * Params type
12
+ */
13
+ export { IPDOXRequest } from "./types/IPDOXRequest";
14
+ /**
15
+ * Response type
16
+ */
17
+ export { IPDOXResponse } from "./types/IPDOXResponse";
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.IPDox = void 0;
7
+ const ipdox_1 = __importDefault(require("./ipdox"));
8
+ /**
9
+ * Main Class
10
+ */
11
+ exports.IPDox = ipdox_1.default;
@@ -0,0 +1,31 @@
1
+ import { IPDOXRequest } from "./types/IPDOXRequest";
2
+ import { IPDOXResponse } from "./types/IPDOXResponse";
3
+ import { IPDOXConstructor } from "./types/IPDOXConstructor";
4
+ declare class IPDox {
5
+ private cache;
6
+ private cacheTimeout;
7
+ private maxRetries;
8
+ /**
9
+ * @description Creates an instance of ListSubscribers.
10
+ * @param {IPDOXConstructor} params - Params of the constructor
11
+ * @param {number} params.cacheTimeout - The cache timeout in milliseconds (default: 43200000 (12 hours))
12
+ *
13
+ *
14
+ */
15
+ constructor({ cacheTimeout, maxRetries }: IPDOXConstructor);
16
+ /**
17
+ * @description Get all the subscribers of a list
18
+ * @param {IPDOXRequest} params - Params of the request
19
+ * @param {string} params.ip - IP address
20
+ * @returns {Promise<IPDOXResponse>} - Promise of the response
21
+ * @memberof IPDox
22
+ */
23
+ doxIP({ ip }: IPDOXRequest): Promise<IPDOXResponse | undefined>;
24
+ private selectRandomAPI;
25
+ private cacheResponse;
26
+ private fetchIPHyphenAPIDotCom;
27
+ private fetchFreeIPAPIDotCom;
28
+ private fetchIPWhoDotIs;
29
+ private fetchIPAPIDotCo;
30
+ }
31
+ export default IPDox;
package/dist/ipdox.js ADDED
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const axios_1 = __importDefault(require("axios"));
16
+ const apis_1 = require("./utils/apis");
17
+ class IPDox {
18
+ /**
19
+ * @description Creates an instance of ListSubscribers.
20
+ * @param {IPDOXConstructor} params - Params of the constructor
21
+ * @param {number} params.cacheTimeout - The cache timeout in milliseconds (default: 43200000 (12 hours))
22
+ *
23
+ *
24
+ */
25
+ constructor({ cacheTimeout = 43200000, maxRetries = 10 }) {
26
+ this.cache = new Map();
27
+ this.cacheTimeout = cacheTimeout;
28
+ this.maxRetries = maxRetries;
29
+ }
30
+ /**
31
+ * @description Get all the subscribers of a list
32
+ * @param {IPDOXRequest} params - Params of the request
33
+ * @param {string} params.ip - IP address
34
+ * @returns {Promise<IPDOXResponse>} - Promise of the response
35
+ * @memberof IPDox
36
+ */
37
+ doxIP({ ip }) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ // Check if the IP is already in the cache
40
+ if (this.cache.has(ip)) {
41
+ const cachedResponse = this.cache.get(ip);
42
+ if (cachedResponse) {
43
+ return cachedResponse;
44
+ }
45
+ }
46
+ // Select a random API
47
+ let randomAPI = this.selectRandomAPI();
48
+ let response = null;
49
+ let retries = 0;
50
+ // Fetch data from the API
51
+ while (!response && retries < this.maxRetries) {
52
+ try {
53
+ switch (randomAPI) {
54
+ case apis_1.GeoAPIs.IP_HYPHEN_API_DOT_COM:
55
+ response = yield this.fetchIPHyphenAPIDotCom(ip);
56
+ break;
57
+ case apis_1.GeoAPIs.FREE_IP_API_DOT_COM:
58
+ response = yield this.fetchFreeIPAPIDotCom(ip);
59
+ break;
60
+ case apis_1.GeoAPIs.IPWHO_DOT_IS:
61
+ response = yield this.fetchIPWhoDotIs(ip);
62
+ break;
63
+ case apis_1.GeoAPIs.IPAPI_DOT_CO:
64
+ response = yield this.fetchIPAPIDotCo(ip);
65
+ break;
66
+ }
67
+ }
68
+ catch (error) {
69
+ // If the promise is rejected, select another random API and try again
70
+ randomAPI = this.selectRandomAPI();
71
+ retries++;
72
+ }
73
+ }
74
+ // If max retries reached and no response, return undefined
75
+ if (retries === this.maxRetries && !response) {
76
+ return undefined;
77
+ }
78
+ // Return the response
79
+ return response ? response : undefined;
80
+ });
81
+ }
82
+ selectRandomAPI() {
83
+ // Get a random entry from the enum
84
+ const randomEntry = Object.entries(apis_1.GeoAPIs)[Math.floor(Math.random() * Object.entries(apis_1.GeoAPIs).length)];
85
+ // Return the random entry
86
+ return randomEntry[1];
87
+ }
88
+ cacheResponse(ip, response) {
89
+ this.cache.set(ip, response);
90
+ // Remove from cache after timeout
91
+ setTimeout(() => this.cache.delete(ip), this.cacheTimeout);
92
+ }
93
+ fetchIPHyphenAPIDotCom(ip) {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ const requestURL = apis_1.GeoAPIs.IP_HYPHEN_API_DOT_COM + ip + "?fields=24899583";
96
+ const response = yield axios_1.default.get(requestURL);
97
+ if (response.data.status === "success") {
98
+ this.cacheResponse(ip, response.data);
99
+ return Promise.resolve({
100
+ ip: response.data.query,
101
+ country: response.data.countryCode,
102
+ city: response.data.city,
103
+ continent: response.data.continentCode,
104
+ latitude: response.data.lat,
105
+ longitude: response.data.lon,
106
+ zip: response.data.zip,
107
+ isp: response.data.isp,
108
+ proxy: response.data.proxy,
109
+ isHosting: response.data.hosting,
110
+ source: "ip-api.com"
111
+ });
112
+ }
113
+ else {
114
+ return Promise.reject();
115
+ }
116
+ });
117
+ }
118
+ fetchFreeIPAPIDotCom(ip) {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ const requestURL = apis_1.GeoAPIs.FREE_IP_API_DOT_COM + ip;
121
+ const response = yield axios_1.default.get(requestURL);
122
+ if (response.data.ipVersion === 4) {
123
+ this.cacheResponse(ip, response.data);
124
+ return Promise.resolve({
125
+ ip: response.data.ipAddress,
126
+ country: response.data.countryCode,
127
+ city: response.data.cityName,
128
+ continent: response.data.continentCode,
129
+ latitude: response.data.latitude,
130
+ longitude: response.data.longitude,
131
+ zip: response.data.zipCode,
132
+ isp: response.data.isp,
133
+ proxy: response.data.proxy,
134
+ isHosting: response.data.hosting,
135
+ source: "freeipapi.com"
136
+ });
137
+ }
138
+ else {
139
+ return Promise.reject();
140
+ }
141
+ });
142
+ }
143
+ fetchIPWhoDotIs(ip) {
144
+ return __awaiter(this, void 0, void 0, function* () {
145
+ const requestURL = apis_1.GeoAPIs.IPWHO_DOT_IS + ip;
146
+ const response = yield axios_1.default.get(requestURL);
147
+ if (response.data.success) {
148
+ this.cacheResponse(ip, response.data);
149
+ return Promise.resolve({
150
+ ip: response.data.ip,
151
+ country: response.data.country_code,
152
+ city: response.data.city,
153
+ continent: response.data.continent_code,
154
+ latitude: response.data.latitude,
155
+ longitude: response.data.longitude,
156
+ zip: response.data.postal,
157
+ isp: response.data.connection.isp,
158
+ proxy: false,
159
+ isHosting: false,
160
+ source: "ipwho.is"
161
+ });
162
+ }
163
+ else {
164
+ return Promise.reject();
165
+ }
166
+ });
167
+ }
168
+ fetchIPAPIDotCo(ip) {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ const requestURL = apis_1.GeoAPIs.IPAPI_DOT_CO + ip + "/json";
171
+ const response = yield axios_1.default.get(requestURL);
172
+ if (response.data.ip) {
173
+ this.cacheResponse(ip, response.data);
174
+ return Promise.resolve({
175
+ ip: response.data.ip,
176
+ country: response.data.country_code,
177
+ city: response.data.city,
178
+ continent: response.data.continent_code,
179
+ latitude: response.data.latitude,
180
+ longitude: response.data.longitude,
181
+ zip: response.data.postal,
182
+ isp: response.data.org,
183
+ source: "ipapi.co"
184
+ });
185
+ }
186
+ else {
187
+ return Promise.reject();
188
+ }
189
+ });
190
+ }
191
+ }
192
+ exports.default = IPDox;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Interface for the constructor
3
+ *
4
+ * @interface IPDOXConstructor
5
+ * @property {number} cacheTimeout The cache timeout in milliseconds (default: 43200000 (12 hours))
6
+ * @property {number} maxRetries The maximum number of retries (default: 10)
7
+ */
8
+ export interface IPDOXConstructor {
9
+ cacheTimeout?: number;
10
+ maxRetries?: number;
11
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Interface for the request
3
+ *
4
+ * @interface IPDOXRequest
5
+ * @property {string} ip The IP address
6
+ */
7
+ export interface IPDOXRequest {
8
+ ip: string;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Interface for the response
3
+ *
4
+ * @interface IPDOXResponse
5
+ * @property {string} ip The IP address
6
+ * @property {string} country The country (ISO 3166)
7
+ * @property {string} city The city
8
+ * @property {string} continent The continent (ISO 3166)
9
+ * @property {number} latitude The latitude
10
+ * @property {number} longitude The longitude
11
+ * @property {string} zip The ZIP code
12
+ * @property {string} isp The ISP (Internet Service Provider)
13
+ * @property {boolean} proxy Is the IP address a proxy?
14
+ * @property {boolean} isHosting Is the IP address a hosting provider?
15
+ * @property {object} proxyInfo Information about the proxy
16
+ * @property {boolean} proxyInfo.isVPN Is the IP address a VPN?
17
+ * @property {boolean} proxyInfo.isTOR Is the IP address a TOR node?
18
+ * @property {boolean} proxyInfo.isProxy Is the IP address a proxy?
19
+ * @property {string} source The source of the data
20
+ */
21
+ export interface IPDOXResponse {
22
+ ip: string;
23
+ country: string;
24
+ city: string;
25
+ continent: string;
26
+ latitude: number;
27
+ longitude: number;
28
+ zip: string;
29
+ isp: string;
30
+ proxy?: boolean;
31
+ isHosting?: boolean;
32
+ proxyInfo?: {
33
+ isVPN: boolean;
34
+ isTOR: boolean;
35
+ isProxy: boolean;
36
+ };
37
+ source: string;
38
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ export declare enum GeoAPIs {
2
+ IP_HYPHEN_API_DOT_COM = "http://ip-api.com/json/",
3
+ FREE_IP_API_DOT_COM = "https://freeipapi.com/api/json/",
4
+ IPWHO_DOT_IS = "https://ipwho.is/",
5
+ IPAPI_DOT_CO = "https://ipapi.co/"
6
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GeoAPIs = void 0;
4
+ var GeoAPIs;
5
+ (function (GeoAPIs) {
6
+ GeoAPIs["IP_HYPHEN_API_DOT_COM"] = "http://ip-api.com/json/";
7
+ GeoAPIs["FREE_IP_API_DOT_COM"] = "https://freeipapi.com/api/json/";
8
+ GeoAPIs["IPWHO_DOT_IS"] = "https://ipwho.is/";
9
+ GeoAPIs["IPAPI_DOT_CO"] = "https://ipapi.co/";
10
+ })(GeoAPIs || (exports.GeoAPIs = GeoAPIs = {}));
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "node-ipdox",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "author": "Mikel Calvo <contact@mikecalvo.net> (www.mikelcalvo.net)",
6
+ "keywords": ["geoip", "ip lookup", "ipdoxxing"],
7
+ "license": "ISC",
8
+ "readmeFilename": "README.md",
9
+ "homepage": "https://github.com/mikelcalvo/ipdox#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/mikelcalvo/ipdox/issues"
12
+ },
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "files": ["dist"],
16
+ "scripts": {
17
+ "test": "echo \"Error: no test specified\" && exit 1",
18
+ "format": "prettier --write \"**/*.ts\" \"**/*.js\" \"**/*.json\"",
19
+ "build": "tsc"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/mikelcalvo/node-ipdox.git"
24
+ },
25
+ "dependencies": {
26
+ "axios": "1.6.2"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "20.10.1",
30
+ "prettier": "3.1.0",
31
+ "typescript": "^5.3.2"
32
+ }
33
+ }