Skip to content

Commit

Permalink
weather_owm module: switch to 3.0 API endpoint as 2.5 is deprecated (#…
Browse files Browse the repository at this point in the history
…2249)

closes #2246
  • Loading branch information
ultrabug authored May 22, 2024
1 parent 08fa99d commit 97d536b
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions py3status/modules/weather_owm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
This module uses OpenWeatherMap API (https://openweathermap.org).
setting `location` or `city` allows you to specify the location for the weather
you want displaying.
Requires a 3.0 API key for OpenWeatherMap (OWM) with a subscription which this
module will try as hard as it can to stay under the free tier limit.
Requires an API key for OpenWeatherMap (OWM), but the free tier allows you
enough requests/sec to get accurate weather even up to the minute.
Setting `location` or `city` allows you to specify the location for the weather
you want displaying.
I would highly suggest you install an additional font, such as the incredible
(and free!) Weather Icons font (https://erikflowers.github.io/weather-icons),
Expand Down Expand Up @@ -261,11 +261,12 @@
"""

import datetime
import json

# API information
OWM_CURR_ENDPOINT = "https://api.openweathermap.org/data/2.5/weather?"
OWM_FUTURE_ENDPOINT = "https://api.openweathermap.org/data/2.5/forecast?"
OWM_ONECALL_ENDPOINT = "https://api.openweathermap.org/data/2.5/onecall?"
OWM_ONECALL_ENDPOINT = "https://api.openweathermap.org/data/3.0/onecall?exclude=alerts,minutely"
IP_ENDPOINT = "http://geo.ultrabug.fr"

# Paths of information to extract from JSON
Expand Down Expand Up @@ -448,6 +449,18 @@ def post_config_hook(self):
# Generate our icon array
self.icons = self._get_icons()

# Implement safe-to-reload rate limit
cached_day = datetime.datetime.now(datetime.UTC).strftime("%Y%m%d")
self.cached_hits = json.loads(
self.py3.storage_get("cached_hits") or json.dumps({cached_day: 0})
)
self.cached_onecall_response = self.py3.storage_get("cached_onecall_response")

# We want to make sure users to not exceed the request limit
# to 3.0 API and get billed while taking into account that
# OWM does refresh its API data every 10min anyway.
self.cache_timeout = max(600, self.cache_timeout)

# Verify the units configuration
if self.unit_rain.lower() not in RAIN_UNITS:
raise Exception("unit_rain is not recognized")
Expand Down Expand Up @@ -817,6 +830,9 @@ def _format(self, current_wthr, fcsts, city, country):
return self.py3.safe_format(self.format, today)

def weather_owm(self):
# Prepare rate limit cache
cached_day = datetime.datetime.now(datetime.UTC).strftime("%Y%m%d")
cached_hits = self.cached_hits.get(cached_day, 0)
# Get weather information
loc_tz_info = self._get_loc_tz_info()
text = ""
Expand All @@ -840,9 +856,19 @@ def weather_owm(self):
except Exception:
raise Exception("no latitude/longitude found for your config")

# onecall = forecasts
onecall_api_params = {"lat": lat, "lon": lon}
onecall = self._get_onecall(onecall_api_params)
# onecall = forecasts rate limited
if cached_hits < 999:
onecall_api_params = {"lat": lat, "lon": lon}
onecall = self._get_onecall(onecall_api_params)
# update and store caches
self.cached_onecall_response = onecall
self.cached_hits[cached_day] = cached_hits + 1
self.py3.storage_set("cached_onecall_response", onecall)
self.py3.storage_set(
"cached_hits", json.dumps({cached_day: self.cached_hits[cached_day]})
)
else:
onecall = self.cached_onecall_response
onecall_daily = onecall["daily"]

fcsts_days = self.forecast_days + 1
Expand Down

0 comments on commit 97d536b

Please sign in to comment.