Updated contrib/publicip module and util/location

Added another API endpoint, Added options to display country name, country code, city name and lat/long coordinates, attempt to handle failure to fetch info from API endpoints cleanly
This commit is contained in:
Tom Watson 2022-07-06 01:05:25 +07:00
parent 6f4f163a7d
commit 218bfa2235
2 changed files with 163 additions and 13 deletions

View file

@ -1,22 +1,109 @@
"""Displays public IP address """
Displays public IP address and, optionally, Country Name, Country Code & City Name
Maximum refresh interval should be 5 minutes to avoid free SLA breach from providers
Note: 1 request/5 minutes is 8640 requests/month
Provider information contained in core.location
Left mouse click forces immediate update
Parameters (Default in brackets)_
ip (True) Public IP address
country_name (False) Display name of country associated with the IP
country_code (False) Display country code of country associated with the IP
city_name (False) Display name of city associated with the IP
coordinates (False) Display name of city associated with the IP
all (False) Display all information associate with the IP
Examples
By default only the public IP is shown
bumblebee-status -m publicip
To also include the country name...
bumblebee-status -m publicip -p publicip.country_name=True
To include all ava
""" """
import core.module import core.module
import core.widget import core.widget
import core.decorators import core.decorators
import core.input
import util.format
import util.location import util.location
class Module(core.module.Module): class Module(core.module.Module):
@core.decorators.every(minutes=60) @core.decorators.every(minutes=5)
def __init__(self, config, theme): def __init__(self, config, theme):
super().__init__(config, theme, core.widget.Widget(self.public_ip)) super().__init__(config, theme, core.widget.Widget(self.public_ip))
self.__ip = "" core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.__click_update)
self.__ip = "" # Public IP address
self.__country_name = "" # Country name associated with public IP address
self.__country_code = "" # Country code associated with public IP address
self.__city_name = "" # City name associated with public IP address
self.__coordinates = "" # Coordinated assoicated with public IP address
# Handle failure to get IP information
self.__ip_error = False
# Process option paramaters
self.__show_ip = util.format.asbool(
self.parameter("ip", True)
)
self.__show_country_name = util.format.asbool(
self.parameter("country_name", False)
)
self.__show_country_code = util.format.asbool(
self.parameter("country_code", False)
)
self.__show_city_name = util.format.asbool(self.parameter("city_name", False))
self.__show_coordinates = util.format.asbool(
self.parameter("coordinates", False)
)
self.__show_all = util.format.asbool(self.parameter("all", False))
def __click_update(self, event):
util.location.reset()
def public_ip(self, widget): def public_ip(self, widget):
return self.__ip or "n/a" __output = ""
if self.__ip:
if self.__show_ip or self.__show_all:
__output = self.__ip
self.__ip_error = False
else:
self.__ip_error = True
__output = "Error Getting IP"
if not self.__ip_error:
if self.__show_country_name or self.__show_all:
if self.__country_name:
__output += " " + self.__country_name
else:
__output += " " + "?"
if self.__show_country_code or self.__show_all:
if self.__country_code:
__output += " " + "(" + self.__country_code + ")"
else:
__output += " " + "(?)"
if self.__show_city_name or self.__show_all:
if self.__city_name:
__output += " " + self.__city_name
else:
__output += " " + "?"
if self.__show_coordinates or self.__show_all:
if self.__coordinates:
__output += " " + self.__coordinates
else:
__output += " " + "?"
return __output
def update(self): def update(self):
try: try:
@ -24,5 +111,33 @@ class Module(core.module.Module):
except Exception: except Exception:
self.__ip = None self.__ip = None
if self.__show_country_name or self.__show_all:
try:
self.__country_name = util.location.country_name()
except Exception:
self.__country_name = None
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 if self.__show_country_code or self.__show_all:
try:
self.__country_code = util.location.country_code()
except Exception:
self.__country_code = None
if self.__show_city_name or self.__show_all:
try:
self.__city_name = util.location.city_name()
except Exception:
self.__city_name = None
if self.__show_coordinates or self.__show_all:
try:
__tmp = util.location.coordinates()
__lat = "{:.2f}".format(__tmp[0])
__lon = "{:.2f}".format(__tmp[1])
__output = __lat + "°N" + "," + " " + __lon + "°E"
self.__coordinates = __output
except Exception:
self.__city_name = None
# vim: tabstop=7 expandtab shiftwidth=4 softtabstop=4

View file

@ -3,8 +3,10 @@ service and caches it for 12h (retries are done every
30m in case of problems) 30m in case of problems)
Right now, it uses (in order of preference): Right now, it uses (in order of preference):
- http://free.ipwhois.io/ - http://free.ipwhois.io/ - 10k free requests/month
- http://ipapi.co/ - http://ipapi.co/ - 30k free requests/month
- http://ip-api.com/ - ~2m free requests/month
""" """
@ -21,7 +23,9 @@ __sources = [
"mapping": { "mapping": {
"latitude": "latitude", "latitude": "latitude",
"longitude": "longitude", "longitude": "longitude",
"country_name": "country", "country_name": "country_name",
"country_code": "country_code",
"city": "city_name",
"ip": "public_ip", "ip": "public_ip",
}, },
}, },
@ -30,9 +34,22 @@ __sources = [
"mapping": { "mapping": {
"latitude": "latitude", "latitude": "latitude",
"longitude": "longitude", "longitude": "longitude",
"country": "country", "country": "country_name",
"country_code": "country_code",
"city": "city_name",
"ip": "public_ip", "ip": "public_ip",
}, },
},
{
"url": "http://ip-api.com/json",
"mapping": {
"latitude": "lat",
"longitude": "lon",
"country": "country_name",
"countryCode": "country_code",
"city": "city_name",
"query": "public_ip",
},
} }
] ]
@ -63,7 +80,10 @@ def __get(name):
global __data global __data
if not __data or __expired(): if not __data or __expired():
__load() __load()
if name in __data:
return __data[name] return __data[name]
else:
return None
def reset(): def reset():
@ -82,14 +102,29 @@ def coordinates():
return __get("latitude"), __get("longitude") return __get("latitude"), __get("longitude")
def country(): def country_name():
"""Returns the current country name """Returns the current country name
:return: country name :return: country name
:rtype: string :rtype: string
""" """
return __get("country") return __get("country_name")
def country_code():
"""Returns the current country code
:return: country code
:rtype: string
"""
return __get("country_code")
def city_name():
"""Returns the current city name
:return: city name
:rtype: string
"""
return __get("city_name")
def public_ip(): def public_ip():
"""Returns the current public IP """Returns the current public IP