ipspot 0.3__py3-none-any.whl → 0.5__py3-none-any.whl
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.
- ipspot/__init__.py +2 -1
- ipspot/cli.py +70 -15
- ipspot/ipv4.py +492 -122
- ipspot/ipv6.py +245 -0
- ipspot/params.py +29 -6
- ipspot/utils.py +41 -2
- {ipspot-0.3.dist-info → ipspot-0.5.dist-info}/METADATA +167 -30
- ipspot-0.5.dist-info/RECORD +14 -0
- {ipspot-0.3.dist-info → ipspot-0.5.dist-info}/WHEEL +1 -1
- {ipspot-0.3.dist-info → ipspot-0.5.dist-info}/licenses/AUTHORS.md +2 -0
- ipspot-0.3.dist-info/RECORD +0 -13
- {ipspot-0.3.dist-info → ipspot-0.5.dist-info}/entry_points.txt +0 -0
- {ipspot-0.3.dist-info → ipspot-0.5.dist-info}/licenses/LICENSE +0 -0
- {ipspot-0.3.dist-info → ipspot-0.5.dist-info}/top_level.txt +0 -0
ipspot/ipv4.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import Union, Dict, List, Tuple
|
|
|
6
6
|
import requests
|
|
7
7
|
from requests.adapters import HTTPAdapter
|
|
8
8
|
from urllib3.poolmanager import PoolManager
|
|
9
|
-
from .utils import is_loopback
|
|
9
|
+
from .utils import is_loopback, _get_json_standard, _attempt_with_retries
|
|
10
10
|
from .params import REQUEST_HEADERS, IPv4API
|
|
11
11
|
|
|
12
12
|
|
|
@@ -53,6 +53,21 @@ class IPv4HTTPAdapter(HTTPAdapter):
|
|
|
53
53
|
socket.getaddrinfo = self._original_getaddrinfo
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
def _get_json_ipv4_forced(url: str, timeout: Union[float, Tuple[float, float]]) -> dict:
|
|
57
|
+
"""
|
|
58
|
+
Send GET request with forced IPv4 using IPv4HTTPAdapter that returns JSON response.
|
|
59
|
+
|
|
60
|
+
:param url: API url
|
|
61
|
+
:param timeout: timeout value for API
|
|
62
|
+
"""
|
|
63
|
+
with requests.Session() as session:
|
|
64
|
+
session.mount("http://", IPv4HTTPAdapter())
|
|
65
|
+
session.mount("https://", IPv4HTTPAdapter())
|
|
66
|
+
response = session.get(url, headers=REQUEST_HEADERS, timeout=timeout)
|
|
67
|
+
response.raise_for_status()
|
|
68
|
+
return response.json()
|
|
69
|
+
|
|
70
|
+
|
|
56
71
|
def is_ipv4(ip: str) -> bool:
|
|
57
72
|
"""
|
|
58
73
|
Check if the given input is a valid IPv4 address.
|
|
@@ -81,8 +96,8 @@ def get_private_ipv4() -> Dict[str, Union[bool, Dict[str, str], str]]:
|
|
|
81
96
|
return {"status": False, "error": str(e)}
|
|
82
97
|
|
|
83
98
|
|
|
84
|
-
def
|
|
85
|
-
|
|
99
|
+
def _ip_sb_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
100
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
86
101
|
"""
|
|
87
102
|
Get public IP and geolocation using ip.sb.
|
|
88
103
|
|
|
@@ -90,30 +105,139 @@ def _ipsb_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
|
90
105
|
:param timeout: timeout value for API
|
|
91
106
|
"""
|
|
92
107
|
try:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
result["data"].update(geo_data)
|
|
110
|
-
return result
|
|
108
|
+
data = _get_json_standard(url="https://api-ipv4.ip.sb/geoip", timeout=timeout)
|
|
109
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ip.sb"}}
|
|
110
|
+
if geo:
|
|
111
|
+
geo_data = {
|
|
112
|
+
"city": data.get("city"),
|
|
113
|
+
"region": data.get("region"),
|
|
114
|
+
"country": data.get("country"),
|
|
115
|
+
"country_code": data.get("country_code"),
|
|
116
|
+
"latitude": data.get("latitude"),
|
|
117
|
+
"longitude": data.get("longitude"),
|
|
118
|
+
"organization": data.get("organization"),
|
|
119
|
+
"timezone": data.get("timezone")
|
|
120
|
+
}
|
|
121
|
+
result["data"].update(geo_data)
|
|
122
|
+
return result
|
|
111
123
|
except Exception as e:
|
|
112
124
|
return {"status": False, "error": str(e)}
|
|
113
125
|
|
|
114
126
|
|
|
115
|
-
def
|
|
116
|
-
|
|
127
|
+
def _ipleak_net_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
128
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
129
|
+
"""
|
|
130
|
+
Get public IP and geolocation using ipleak.net.
|
|
131
|
+
|
|
132
|
+
:param geo: geolocation flag
|
|
133
|
+
:param timeout: timeout value for API
|
|
134
|
+
"""
|
|
135
|
+
try:
|
|
136
|
+
data = _get_json_standard(url="https://ipv4.ipleak.net/json/", timeout=timeout)
|
|
137
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ipleak.net"}}
|
|
138
|
+
if geo:
|
|
139
|
+
geo_data = {
|
|
140
|
+
"city": data.get("city_name"),
|
|
141
|
+
"region": data.get("region_name"),
|
|
142
|
+
"country": data.get("country_name"),
|
|
143
|
+
"country_code": data.get("country_code"),
|
|
144
|
+
"latitude": data.get("latitude"),
|
|
145
|
+
"longitude": data.get("longitude"),
|
|
146
|
+
"organization": data.get("isp_name"),
|
|
147
|
+
"timezone": data.get("time_zone")
|
|
148
|
+
}
|
|
149
|
+
result["data"].update(geo_data)
|
|
150
|
+
return result
|
|
151
|
+
except Exception as e:
|
|
152
|
+
return {"status": False, "error": str(e)}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _my_ip_io_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
156
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
157
|
+
"""
|
|
158
|
+
Get public IP and geolocation using my-ip.io.
|
|
159
|
+
|
|
160
|
+
:param geo: geolocation flag
|
|
161
|
+
:param timeout: timeout value for API
|
|
162
|
+
"""
|
|
163
|
+
try:
|
|
164
|
+
data = _get_json_standard(url="https://api4.my-ip.io/v2/ip.json", timeout=timeout)
|
|
165
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "my-ip.io"}}
|
|
166
|
+
if geo:
|
|
167
|
+
geo_data = {
|
|
168
|
+
"city": data.get("city"),
|
|
169
|
+
"region": data.get("region"),
|
|
170
|
+
"country": data.get("country", {}).get("name"),
|
|
171
|
+
"country_code": data.get("country", {}).get("code"),
|
|
172
|
+
"latitude": data.get("location", {}).get("lat"),
|
|
173
|
+
"longitude": data.get("location", {}).get("lon"),
|
|
174
|
+
"organization": data.get("asn", {}).get("name"),
|
|
175
|
+
"timezone": data.get("timeZone")
|
|
176
|
+
}
|
|
177
|
+
result["data"].update(geo_data)
|
|
178
|
+
return result
|
|
179
|
+
except Exception as e:
|
|
180
|
+
return {"status": False, "error": str(e)}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _ifconfig_co_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]] # very low rate limit
|
|
184
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
185
|
+
"""
|
|
186
|
+
Get public IP and geolocation using ifconfig.co.
|
|
187
|
+
|
|
188
|
+
:param geo: geolocation flag
|
|
189
|
+
:param timeout: timeout value for API
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
data = _get_json_ipv4_forced(url="https://ifconfig.co/json", timeout=timeout)
|
|
193
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ifconfig.co"}}
|
|
194
|
+
if geo:
|
|
195
|
+
geo_data = {
|
|
196
|
+
"city": data.get("city"),
|
|
197
|
+
"region": data.get("region_name"),
|
|
198
|
+
"country": data.get("country"),
|
|
199
|
+
"country_code": data.get("country_iso"),
|
|
200
|
+
"latitude": data.get("latitude"),
|
|
201
|
+
"longitude": data.get("longitude"),
|
|
202
|
+
"organization": data.get("asn_org"),
|
|
203
|
+
"timezone": data.get("time_zone")
|
|
204
|
+
}
|
|
205
|
+
result["data"].update(geo_data)
|
|
206
|
+
return result
|
|
207
|
+
except Exception as e:
|
|
208
|
+
return {"status": False, "error": str(e)}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _ipapi_co_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
212
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
213
|
+
"""
|
|
214
|
+
Get public IP and geolocation using ipapi.co.
|
|
215
|
+
|
|
216
|
+
:param geo: geolocation flag
|
|
217
|
+
:param timeout: timeout value for API
|
|
218
|
+
"""
|
|
219
|
+
try:
|
|
220
|
+
data = _get_json_ipv4_forced(url="https://ipapi.co/json/", timeout=timeout)
|
|
221
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ipapi.co"}}
|
|
222
|
+
if geo:
|
|
223
|
+
geo_data = {
|
|
224
|
+
"city": data.get("city"),
|
|
225
|
+
"region": data.get("region"),
|
|
226
|
+
"country": data.get("country_name"),
|
|
227
|
+
"country_code": data.get("country_code"),
|
|
228
|
+
"latitude": data.get("latitude"),
|
|
229
|
+
"longitude": data.get("longitude"),
|
|
230
|
+
"organization": data.get("org"),
|
|
231
|
+
"timezone": data.get("timezone")
|
|
232
|
+
}
|
|
233
|
+
result["data"].update(geo_data)
|
|
234
|
+
return result
|
|
235
|
+
except Exception as e:
|
|
236
|
+
return {"status": False, "error": str(e)}
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def _ip_api_com_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
240
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
117
241
|
"""
|
|
118
242
|
Get public IP and geolocation using ip-api.com.
|
|
119
243
|
|
|
@@ -121,34 +245,29 @@ def _ipapi_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
|
121
245
|
:param timeout: timeout value for API
|
|
122
246
|
"""
|
|
123
247
|
try:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
"organization": data.get("org"),
|
|
142
|
-
"timezone": data.get("timezone")
|
|
143
|
-
}
|
|
144
|
-
result["data"].update(geo_data)
|
|
145
|
-
return result
|
|
248
|
+
data = _get_json_ipv4_forced(url="http://ip-api.com/json/", timeout=timeout)
|
|
249
|
+
if data.get("status") != "success":
|
|
250
|
+
return {"status": False, "error": "ip-api lookup failed"}
|
|
251
|
+
result = {"status": True, "data": {"ip": data["query"], "api": "ip-api.com"}}
|
|
252
|
+
if geo:
|
|
253
|
+
geo_data = {
|
|
254
|
+
"city": data.get("city"),
|
|
255
|
+
"region": data.get("regionName"),
|
|
256
|
+
"country": data.get("country"),
|
|
257
|
+
"country_code": data.get("countryCode"),
|
|
258
|
+
"latitude": data.get("lat"),
|
|
259
|
+
"longitude": data.get("lon"),
|
|
260
|
+
"organization": data.get("org"),
|
|
261
|
+
"timezone": data.get("timezone")
|
|
262
|
+
}
|
|
263
|
+
result["data"].update(geo_data)
|
|
264
|
+
return result
|
|
146
265
|
except Exception as e:
|
|
147
266
|
return {"status": False, "error": str(e)}
|
|
148
267
|
|
|
149
268
|
|
|
150
|
-
def
|
|
151
|
-
|
|
269
|
+
def _ipinfo_io_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
270
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
152
271
|
"""
|
|
153
272
|
Get public IP and geolocation using ipinfo.io.
|
|
154
273
|
|
|
@@ -156,27 +275,50 @@ def _ipinfo_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
|
156
275
|
:param timeout: timeout value for API
|
|
157
276
|
"""
|
|
158
277
|
try:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
278
|
+
data = _get_json_ipv4_forced(url="https://ipinfo.io/json", timeout=timeout)
|
|
279
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ipinfo.io"}}
|
|
280
|
+
if geo:
|
|
281
|
+
loc = data.get("loc", "").split(",")
|
|
282
|
+
geo_data = {
|
|
283
|
+
"city": data.get("city"),
|
|
284
|
+
"region": data.get("region"),
|
|
285
|
+
"country": None,
|
|
286
|
+
"country_code": data.get("country"),
|
|
287
|
+
"latitude": float(loc[0]) if len(loc) == 2 else None,
|
|
288
|
+
"longitude": float(loc[1]) if len(loc) == 2 else None,
|
|
289
|
+
"organization": data.get("org"),
|
|
290
|
+
"timezone": data.get("timezone")
|
|
291
|
+
}
|
|
292
|
+
result["data"].update(geo_data)
|
|
293
|
+
return result
|
|
294
|
+
except Exception as e:
|
|
295
|
+
return {"status": False, "error": str(e)}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _reallyfreegeoip_org_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
299
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
300
|
+
"""
|
|
301
|
+
Get public IP and geolocation using reallyfreegeoip.org.
|
|
302
|
+
|
|
303
|
+
:param geo: geolocation flag
|
|
304
|
+
:param timeout: timeout value for API
|
|
305
|
+
"""
|
|
306
|
+
try:
|
|
307
|
+
data = _get_json_ipv4_forced(url="https://reallyfreegeoip.org/json/", timeout=timeout)
|
|
308
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "reallyfreegeoip.org"}}
|
|
309
|
+
if geo:
|
|
310
|
+
geo_data = {
|
|
311
|
+
"city": data.get("city"),
|
|
312
|
+
"region": data.get("region_name"),
|
|
313
|
+
"country": data.get("country_name"),
|
|
314
|
+
"country_code": data.get("country_code"),
|
|
315
|
+
"latitude": data.get("latitude"),
|
|
316
|
+
"longitude": data.get("longitude"),
|
|
317
|
+
"organization": None, # does not provide organization
|
|
318
|
+
"timezone": data.get("time_zone")
|
|
319
|
+
}
|
|
320
|
+
result["data"].update(geo_data)
|
|
321
|
+
return result
|
|
180
322
|
except Exception as e:
|
|
181
323
|
return {"status": False, "error": str(e)}
|
|
182
324
|
|
|
@@ -190,30 +332,27 @@ def _ident_me_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
|
190
332
|
:param timeout: timeout value for API
|
|
191
333
|
"""
|
|
192
334
|
try:
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
result["data"].update(geo_data)
|
|
210
|
-
return result
|
|
335
|
+
data = _get_json_standard(url="https://4.ident.me/json", timeout=timeout)
|
|
336
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ident.me"}}
|
|
337
|
+
if geo:
|
|
338
|
+
geo_data = {
|
|
339
|
+
"city": data.get("city"),
|
|
340
|
+
"region": None,
|
|
341
|
+
"country": data.get("country"),
|
|
342
|
+
"country_code": data.get("cc"),
|
|
343
|
+
"latitude": data.get("latitude"),
|
|
344
|
+
"longitude": data.get("longitude"),
|
|
345
|
+
"organization": data.get("aso"),
|
|
346
|
+
"timezone": data.get("tz")
|
|
347
|
+
}
|
|
348
|
+
result["data"].update(geo_data)
|
|
349
|
+
return result
|
|
211
350
|
except Exception as e:
|
|
212
351
|
return {"status": False, "error": str(e)}
|
|
213
352
|
|
|
214
353
|
|
|
215
|
-
def
|
|
216
|
-
|
|
354
|
+
def _tnedi_me_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
355
|
+
=5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
217
356
|
"""
|
|
218
357
|
Get public IP and geolocation using tnedi.me.
|
|
219
358
|
|
|
@@ -221,53 +360,284 @@ def _tnedime_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]
|
|
|
221
360
|
:param timeout: timeout value for API
|
|
222
361
|
"""
|
|
223
362
|
try:
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
363
|
+
data = _get_json_standard(url="https://4.tnedi.me/json", timeout=timeout)
|
|
364
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "tnedi.me"}}
|
|
365
|
+
if geo:
|
|
366
|
+
geo_data = {
|
|
367
|
+
"city": data.get("city"),
|
|
368
|
+
"region": None,
|
|
369
|
+
"country": data.get("country"),
|
|
370
|
+
"country_code": data.get("cc"),
|
|
371
|
+
"latitude": data.get("latitude"),
|
|
372
|
+
"longitude": data.get("longitude"),
|
|
373
|
+
"organization": data.get("aso"),
|
|
374
|
+
"timezone": data.get("tz")
|
|
375
|
+
}
|
|
376
|
+
result["data"].update(geo_data)
|
|
377
|
+
return result
|
|
378
|
+
except Exception as e:
|
|
379
|
+
return {"status": False, "error": str(e)}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def _myip_la_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]=5
|
|
383
|
+
) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
384
|
+
"""
|
|
385
|
+
Get public IP and geolocation using myip.la.
|
|
386
|
+
|
|
387
|
+
:param geo: geolocation flag
|
|
388
|
+
:param timeout: timeout value for API
|
|
389
|
+
"""
|
|
390
|
+
try:
|
|
391
|
+
data = _get_json_ipv4_forced(url="https://api.myip.la/en?json", timeout=timeout)
|
|
392
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "myip.la"}}
|
|
393
|
+
if geo:
|
|
394
|
+
loc = data.get("location", {})
|
|
395
|
+
geo_data = {
|
|
396
|
+
"city": loc.get("city"),
|
|
397
|
+
"region": loc.get("province"),
|
|
398
|
+
"country": loc.get("country_name"),
|
|
399
|
+
"country_code": loc.get("country_code"),
|
|
400
|
+
"latitude": float(loc.get("latitude")) if loc.get("latitude") else None,
|
|
401
|
+
"longitude": float(loc.get("longitude")) if loc.get("longitude") else None,
|
|
402
|
+
"organization": None,
|
|
403
|
+
"timezone": None
|
|
404
|
+
}
|
|
405
|
+
result["data"].update(geo_data)
|
|
406
|
+
return result
|
|
407
|
+
except Exception as e:
|
|
408
|
+
return {"status": False, "error": str(e)}
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def _freeipapi_com_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]=5
|
|
412
|
+
) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
413
|
+
"""
|
|
414
|
+
Get public IP and geolocation using freeipapi.com.
|
|
415
|
+
|
|
416
|
+
:param geo: geolocation flag
|
|
417
|
+
:param timeout: timeout value for API
|
|
418
|
+
"""
|
|
419
|
+
try:
|
|
420
|
+
data = _get_json_ipv4_forced(url="https://freeipapi.com/api/json", timeout=timeout)
|
|
421
|
+
result = {"status": True, "data": {"ip": data["ipAddress"], "api": "freeipapi.com"}}
|
|
422
|
+
if geo:
|
|
423
|
+
geo_data = {
|
|
424
|
+
"city": data.get("cityName"),
|
|
425
|
+
"region": data.get("regionName"),
|
|
426
|
+
"country": data.get("countryName"),
|
|
427
|
+
"country_code": data.get("countryCode"),
|
|
428
|
+
"latitude": data.get("latitude"),
|
|
429
|
+
"longitude": data.get("longitude"),
|
|
430
|
+
"organization": None,
|
|
431
|
+
"timezone": data.get("timeZone")
|
|
432
|
+
}
|
|
433
|
+
result["data"].update(geo_data)
|
|
434
|
+
return result
|
|
435
|
+
except Exception as e:
|
|
436
|
+
return {"status": False, "error": str(e)}
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def _ipquery_io_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]=5
|
|
440
|
+
) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
441
|
+
"""
|
|
442
|
+
Get public IP and geolocation using ipquery.io.
|
|
443
|
+
|
|
444
|
+
:param geo: geolocation flag
|
|
445
|
+
:param timeout: timeout value for API
|
|
446
|
+
"""
|
|
447
|
+
try:
|
|
448
|
+
data = _get_json_ipv4_forced(url="https://api.ipquery.io/?format=json", timeout=timeout)
|
|
449
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ipquery.io"}}
|
|
450
|
+
if geo:
|
|
451
|
+
loc = data.get("location", {})
|
|
452
|
+
isp = data.get("isp", {})
|
|
453
|
+
geo_data = {
|
|
454
|
+
"city": loc.get("city"),
|
|
455
|
+
"region": loc.get("state"),
|
|
456
|
+
"country": loc.get("country"),
|
|
457
|
+
"country_code": loc.get("country_code"),
|
|
458
|
+
"latitude": loc.get("latitude"),
|
|
459
|
+
"longitude": loc.get("longitude"),
|
|
460
|
+
"timezone": loc.get("timezone"),
|
|
461
|
+
"organization": isp.get("org"),
|
|
462
|
+
}
|
|
463
|
+
result["data"].update(geo_data)
|
|
464
|
+
return result
|
|
465
|
+
except Exception as e:
|
|
466
|
+
return {"status": False, "error": str(e)}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def _ipwho_is_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]=5
|
|
470
|
+
) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
471
|
+
"""
|
|
472
|
+
Get public IP and geolocation using ipwho.is.
|
|
473
|
+
|
|
474
|
+
:param geo: geolocation flag
|
|
475
|
+
:param timeout: timeout value for API
|
|
476
|
+
"""
|
|
477
|
+
try:
|
|
478
|
+
data = _get_json_ipv4_forced(url="https://ipwho.is", timeout=timeout)
|
|
479
|
+
result = {"status": True, "data": {"ip": data["ip"], "api": "ipwho.is"}}
|
|
480
|
+
if geo:
|
|
481
|
+
connection = data.get("connection", {})
|
|
482
|
+
timezone = data.get("timezone", {})
|
|
483
|
+
geo_data = {
|
|
484
|
+
"city": data.get("city"),
|
|
485
|
+
"region": data.get("region"),
|
|
486
|
+
"country": data.get("country"),
|
|
487
|
+
"country_code": data.get("country_code"),
|
|
488
|
+
"latitude": data.get("latitude"),
|
|
489
|
+
"longitude": data.get("longitude"),
|
|
490
|
+
"organization": connection.get("org"),
|
|
491
|
+
"timezone": timezone.get("id")
|
|
492
|
+
}
|
|
493
|
+
result["data"].update(geo_data)
|
|
494
|
+
return result
|
|
495
|
+
except Exception as e:
|
|
496
|
+
return {"status": False, "error": str(e)}
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def _wtfismyip_com_ipv4(geo: bool=False, timeout: Union[float, Tuple[float, float]]=5
|
|
500
|
+
) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
501
|
+
"""
|
|
502
|
+
Get public IP and geolocation using wtfismyip.com.
|
|
503
|
+
|
|
504
|
+
:param geo: geolocation flag
|
|
505
|
+
:param timeout: timeout value for API
|
|
506
|
+
"""
|
|
507
|
+
try:
|
|
508
|
+
data = _get_json_standard(url="https://json.ipv4.wtfismyip.com", timeout=timeout)
|
|
509
|
+
result = {"status": True, "data": {"ip": data["YourFuckingIPAddress"], "api": "wtfismyip.com"}}
|
|
510
|
+
if geo:
|
|
511
|
+
geo_data = {
|
|
512
|
+
"city": data.get("YourFuckingCity"),
|
|
513
|
+
"region": None,
|
|
514
|
+
"country": data.get("YourFuckingCountry"),
|
|
515
|
+
"country_code": data.get("YourFuckingCountryCode"),
|
|
516
|
+
"latitude": None,
|
|
517
|
+
"longitude": None,
|
|
518
|
+
"organization": data.get("YourFuckingISP"),
|
|
519
|
+
"timezone": None
|
|
520
|
+
}
|
|
521
|
+
result["data"].update(geo_data)
|
|
522
|
+
return result
|
|
242
523
|
except Exception as e:
|
|
243
524
|
return {"status": False, "error": str(e)}
|
|
244
525
|
|
|
245
526
|
|
|
246
|
-
|
|
247
|
-
|
|
527
|
+
IPV4_API_MAP = {
|
|
528
|
+
IPv4API.IFCONFIG_CO: {
|
|
529
|
+
"thread_safe": False,
|
|
530
|
+
"geo": True,
|
|
531
|
+
"function": _ifconfig_co_ipv4
|
|
532
|
+
},
|
|
533
|
+
IPv4API.IDENT_ME: {
|
|
534
|
+
"thread_safe": True,
|
|
535
|
+
"geo": True,
|
|
536
|
+
"function": _ident_me_ipv4
|
|
537
|
+
},
|
|
538
|
+
IPv4API.TNEDI_ME: {
|
|
539
|
+
"thread_safe": True,
|
|
540
|
+
"geo": True,
|
|
541
|
+
"function": _tnedi_me_ipv4
|
|
542
|
+
},
|
|
543
|
+
IPv4API.IP_SB: {
|
|
544
|
+
"thread_safe": True,
|
|
545
|
+
"geo": True,
|
|
546
|
+
"function": _ip_sb_ipv4
|
|
547
|
+
},
|
|
548
|
+
IPv4API.IPLEAK_NET: {
|
|
549
|
+
"thread_safe": True,
|
|
550
|
+
"geo": True,
|
|
551
|
+
"function": _ipleak_net_ipv4
|
|
552
|
+
},
|
|
553
|
+
IPv4API.MY_IP_IO: {
|
|
554
|
+
"thread_safe": True,
|
|
555
|
+
"geo": True,
|
|
556
|
+
"function": _my_ip_io_ipv4
|
|
557
|
+
},
|
|
558
|
+
IPv4API.IP_API_COM: {
|
|
559
|
+
"thread_safe": False,
|
|
560
|
+
"geo": True,
|
|
561
|
+
"function": _ip_api_com_ipv4
|
|
562
|
+
},
|
|
563
|
+
IPv4API.IPINFO_IO: {
|
|
564
|
+
"thread_safe": False,
|
|
565
|
+
"geo": True,
|
|
566
|
+
"function": _ipinfo_io_ipv4
|
|
567
|
+
},
|
|
568
|
+
IPv4API.IPAPI_CO: {
|
|
569
|
+
"thread_safe": False,
|
|
570
|
+
"geo": True,
|
|
571
|
+
"function": _ipapi_co_ipv4
|
|
572
|
+
},
|
|
573
|
+
IPv4API.REALLYFREEGEOIP_ORG: {
|
|
574
|
+
"thread_safe": False,
|
|
575
|
+
"geo": True,
|
|
576
|
+
"function": _reallyfreegeoip_org_ipv4
|
|
577
|
+
},
|
|
578
|
+
IPv4API.FREEIPAPI_COM: {
|
|
579
|
+
"thread_safe": False,
|
|
580
|
+
"geo": True,
|
|
581
|
+
"function": _freeipapi_com_ipv4,
|
|
582
|
+
},
|
|
583
|
+
IPv4API.MYIP_LA: {
|
|
584
|
+
"thread_safe": False,
|
|
585
|
+
"geo": True,
|
|
586
|
+
"function": _myip_la_ipv4,
|
|
587
|
+
},
|
|
588
|
+
IPv4API.IPQUERY_IO: {
|
|
589
|
+
"thread_safe": False,
|
|
590
|
+
"geo": True,
|
|
591
|
+
"function": _ipquery_io_ipv4,
|
|
592
|
+
},
|
|
593
|
+
IPv4API.IPWHO_IS: {
|
|
594
|
+
"thread_safe": False,
|
|
595
|
+
"geo": True,
|
|
596
|
+
"function": _ipwho_is_ipv4,
|
|
597
|
+
},
|
|
598
|
+
IPv4API.WTFISMYIP_COM: {
|
|
599
|
+
"thread_safe": True,
|
|
600
|
+
"geo": True,
|
|
601
|
+
"function": _wtfismyip_com_ipv4
|
|
602
|
+
},
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def get_public_ipv4(api: IPv4API=IPv4API.AUTO_SAFE, geo: bool=False,
|
|
607
|
+
timeout: Union[float, Tuple[float, float]]=5,
|
|
608
|
+
max_retries: int = 0,
|
|
609
|
+
retry_delay: float = 1.0) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]:
|
|
248
610
|
"""
|
|
249
611
|
Get public IPv4 and geolocation info based on the selected API.
|
|
250
612
|
|
|
251
613
|
:param api: public IPv4 API
|
|
252
614
|
:param geo: geolocation flag
|
|
253
615
|
:param timeout: timeout value for API
|
|
616
|
+
:param max_retries: number of retries
|
|
617
|
+
:param retry_delay: delay between retries (in seconds)
|
|
254
618
|
"""
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
619
|
+
if api in [IPv4API.AUTO, IPv4API.AUTO_SAFE]:
|
|
620
|
+
for _, api_data in IPV4_API_MAP.items():
|
|
621
|
+
if api == IPv4API.AUTO_SAFE and not api_data["thread_safe"]:
|
|
622
|
+
continue
|
|
623
|
+
func = api_data["function"]
|
|
624
|
+
result = _attempt_with_retries(
|
|
625
|
+
func=func,
|
|
626
|
+
max_retries=max_retries,
|
|
627
|
+
retry_delay=retry_delay,
|
|
628
|
+
geo=geo,
|
|
629
|
+
timeout=timeout)
|
|
266
630
|
if result["status"]:
|
|
267
631
|
return result
|
|
268
632
|
return {"status": False, "error": "All attempts failed."}
|
|
269
633
|
else:
|
|
270
|
-
|
|
271
|
-
if
|
|
272
|
-
|
|
634
|
+
api_data = IPV4_API_MAP.get(api)
|
|
635
|
+
if api_data:
|
|
636
|
+
func = api_data["function"]
|
|
637
|
+
return _attempt_with_retries(
|
|
638
|
+
func=func,
|
|
639
|
+
max_retries=max_retries,
|
|
640
|
+
retry_delay=retry_delay,
|
|
641
|
+
geo=geo,
|
|
642
|
+
timeout=timeout)
|
|
273
643
|
return {"status": False, "error": "Unsupported API: {api}".format(api=api)}
|