diff --git a/CHANGELOG.md b/CHANGELOG.md index 42bc856..e8319c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Support [ipwho.is](https://ipwho.is/) - Support [ipquery.io](http://api.ipquery.io/?format=json) - Support [wtfismyip.com](https://wtfismyip.com/json) +- Support [ident.me](https://ident.me/json) IPv6 API +- Support [tnedi.me](https://tnedi.me/json) IPv6 API +- Support [ip.sb](https://api.ip.sb/geoip) IPv6 API - `is_ipv6` function - `get_private_ipv6` function - `get_public_ipv6` function diff --git a/README.md b/README.md index 80bd33c..ec8c83a 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ Public IP and Location Info: #### IPv6 API -ℹ️ `ipv6-api` valid choices: [`auto-safe`, `auto`, `ip.sb`] +ℹ️ `ipv6-api` valid choices: [`auto-safe`, `auto`, `ip.sb`, `ident.me`, `tnedi.me`] ℹ️ The default value: `auto-safe` diff --git a/ipspot/ipv6.py b/ipspot/ipv6.py index e20ca59..5a66c7c 100644 --- a/ipspot/ipv6.py +++ b/ipspot/ipv6.py @@ -64,12 +64,78 @@ def _ip_sb_ipv6(geo: bool=False, timeout: Union[float, Tuple[float, float]] return {"status": False, "error": str(e)} +def _ident_me_ipv6(geo: bool=False, timeout: Union[float, Tuple[float, float]] + =5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]: + """ + Get public IP and geolocation using ident.me. + + :param geo: geolocation flag + :param timeout: timeout value for API + """ + try: + data = _get_json_standard(url="https://6.ident.me/json", timeout=timeout) + result = {"status": True, "data": {"ip": data["ip"], "api": "ident.me"}} + if geo: + geo_data = { + "city": data.get("city"), + "region": None, + "country": data.get("country"), + "country_code": data.get("cc"), + "latitude": data.get("latitude"), + "longitude": data.get("longitude"), + "organization": data.get("aso"), + "timezone": data.get("tz") + } + result["data"].update(geo_data) + return result + except Exception as e: + return {"status": False, "error": str(e)} + + +def _tnedi_me_ipv6(geo: bool=False, timeout: Union[float, Tuple[float, float]] + =5) -> Dict[str, Union[bool, Dict[str, Union[str, float]], str]]: + """ + Get public IP and geolocation using tnedi.me. + + :param geo: geolocation flag + :param timeout: timeout value for API + """ + try: + data = _get_json_standard(url="https://6.tnedi.me/json", timeout=timeout) + result = {"status": True, "data": {"ip": data["ip"], "api": "tnedi.me"}} + if geo: + geo_data = { + "city": data.get("city"), + "region": None, + "country": data.get("country"), + "country_code": data.get("cc"), + "latitude": data.get("latitude"), + "longitude": data.get("longitude"), + "organization": data.get("aso"), + "timezone": data.get("tz") + } + result["data"].update(geo_data) + return result + except Exception as e: + return {"status": False, "error": str(e)} + + IPV6_API_MAP = { IPv6API.IP_SB: { "thread_safe": True, "geo": True, "function": _ip_sb_ipv6 - } + }, + IPv6API.IDENT_ME: { + "thread_safe": True, + "geo": True, + "function": _ident_me_ipv6 + }, + IPv6API.TNEDI_ME: { + "thread_safe": True, + "geo": True, + "function": _tnedi_me_ipv6 + }, } diff --git a/ipspot/params.py b/ipspot/params.py index 3c2e9d6..9af9a6c 100644 --- a/ipspot/params.py +++ b/ipspot/params.py @@ -46,6 +46,8 @@ class IPv6API(Enum): AUTO = "auto" AUTO_SAFE = "auto-safe" IP_SB = "ip.sb" + IDENT_ME = "ident.me" + TNEDI_ME = "tnedi.me" PARAMETERS_NAME_MAP = { diff --git a/tests/test_ipv6_api.py b/tests/test_ipv6_api.py index 17575a2..4e36a2e 100644 --- a/tests/test_ipv6_api.py +++ b/tests/test_ipv6_api.py @@ -11,6 +11,23 @@ def test_public_ipv6_ip_sb_success(): assert is_ipv6(result["data"]["ip"]) assert set(result["data"].keys()) == DATA_ITEMS + +def test_public_ipv6_ident_me_success(): + result = get_public_ipv6(api=IPv6API.IDENT_ME, geo=True, timeout=40, max_retries=4, retry_delay=90) + assert result["status"] + assert is_ipv6(result["data"]["ip"]) + assert set(result["data"].keys()) == DATA_ITEMS + assert result["data"]["api"] == "ident.me" + + +def test_public_ipv6_tnedi_me_success(): + result = get_public_ipv6(api=IPv6API.TNEDI_ME, geo=True, timeout=40, max_retries=4, retry_delay=90) + assert result["status"] + assert is_ipv6(result["data"]["ip"]) + assert set(result["data"].keys()) == DATA_ITEMS + assert result["data"]["api"] == "tnedi.me" + + def test_public_ipv6_auto_success(): result = get_public_ipv6(api=IPv6API.AUTO, geo=True, timeout=40, max_retries=4, retry_delay=90) assert result["status"]