From 9a6e61173f6547673528701b622c7204c092f966 Mon Sep 17 00:00:00 2001 From: Tom Watson Date: Thu, 7 Jul 2022 18:08:20 +0700 Subject: [PATCH] Updated publicip to automatically update on detecting a change to default route --- bumblebee_status/modules/contrib/publicip.py | 130 +++++++++++-------- 1 file changed, 78 insertions(+), 52 deletions(-) diff --git a/bumblebee_status/modules/contrib/publicip.py b/bumblebee_status/modules/contrib/publicip.py index d043fce..c6ff2a8 100644 --- a/bumblebee_status/modules/contrib/publicip.py +++ b/bumblebee_status/modules/contrib/publicip.py @@ -1,88 +1,114 @@ """ -Displays zero or more of: +Displays information about the public IP address associated with the default route: * Public IP address * Country Name * Country Code * City Name - * Geographic Coordinates\ - -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 + * Geographic Coordinates Left mouse click on the widget forces immediate update +Any change to the default route will cause the widget to update + +Requirements: + * netifaces Parameters: -publicip.format: Format string (defaults to ‘{ip} ({country_code})’) - -Available format strings: -ip -country_name -country_code -city_name -coordinates + * publicip.format: Format string (defaults to ‘{ip} ({country_code})’) + * Available format strings - ip, country_name, country_code, city_name, coordinates Examples: -bumblebee-status -m publicip -p publicip.format="{ip} ({country_code})" -bumblebee-status -m publicip -p publicip.format="{ip} which is in {city_name}" -bumblebee-status -m publicip -p publicip.format="Your packets are right here: {coordinates}" + * bumblebee-status -m publicip -p publicip.format="{ip} ({country_code})" + * bumblebee-status -m publicip -p publicip.format="{ip} which is in {city_name}" + * bumblebee-status -m publicip -p publicip.format="Your packets are right here: {coordinates}" + +contributed by `tfwiii `_ - many thanks! """ +import re +import threading +import netifaces +import time + import core.module import core.widget -import core.decorators import core.input +import core.decorators + import util.format import util.location +def update_publicip_information(module): + widget = module.widget() + __previous_default_route = None + __current_default_route = None + __interval = 5 # Interval between default route change checks + + while True: + __current_default_route = netifaces.gateways()["default"][2] + + # Updates public ip information if a change to default route is detected + if __current_default_route != __previous_default_route: + # Sets __previous_default_route in preparation for next change check + __previous_default_route = __current_default_route + + # Refresh location information + util.location.reset() + + # Fetch fresh location information + __info = util.location.location_info() + + # Contstruct coordinates string + __lat = "{:.2f}".format(__info["latitude"]) + __lon = "{:.2f}".format(__info["longitude"]) + __coords = __lat + "°N" + "," + " " + __lon + "°E" + + # Set widget values + widget.set("public_ip", __info["public_ip"]) + widget.set("country_name", __info["country"]) + widget.set("country_code", __info["country_code"]) + widget.set("city_name", __info["city_name"]) + widget.set("coordinates", __coords) + + # Update widget values + core.event.trigger("update", [widget.module.id], redraw_only=True) + + # Wait __interval seconds before checking for default route changes again + time.sleep(__interval) + class Module(core.module.Module): @core.decorators.every(minutes=60) def __init__(self, config, theme): - super().__init__(config, theme, core.widget.Widget(self.public_ip)) + super().__init__(config, theme, core.widget.Widget(self.publicip)) + + self.__thread = None # Immediate update (override default) when left click on widget 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 = "" # Coordinates assoicated with public IP address - # By default show: (<2 letter country code>) self._format = self.parameter("format", "{ip} ({country_code})") + def publicip(self, widget): + return self._format.format( + ip = widget.get("public_ip", "-"), + country_name = widget.get("country_name", "-"), + country_code = widget.get("country_code", "-"), + city_name = widget.get("city_name", "-"), + coordinates = widget.get("coordinates", "-") + ) + def __click_update(self, event): util.location.reset() - def public_ip(self, widget): - if not self.__ip: - return "Error fetching IP" - else: - return self._format.format( - ip=self.__ip, - country_name=self.__country_name, - country_code=self.__country_code, - city_name=self.__city_name, - coordinates=self.__coordinates, - ) - def update(self): - try: - __info = util.location.location_info() - self.__ip = __info["public_ip"] - self.__country_name = __info["country"] - self.__country_code = __info["country_code"] - self.__city_name = __info["city_name"] - __lat = __info["latitude"] - __lon = __info["longitude"] - __lat = "{:.2f}".format(__lat) - __lon = "{:.2f}".format(__lon) - __output = __lat + "°N" + "," + " " + __lon + "°E" - self.__coordinates = __output - except Exception: - pass + if self.__thread is not None and self.__thread.is_alive(): + return + self.__thread = threading.Thread(target=update_publicip_information, args=(self,)) + self.__thread.start() + + def state(self, widget): + return widget.get("state", None) -# vim: tabstop=7 expandtab shiftwidth=4 softtabstop=4 +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4