diff --git a/config.toml.template b/config.toml.template index 4eb8e31..6baed2c 100644 --- a/config.toml.template +++ b/config.toml.template @@ -22,5 +22,7 @@ workspace="myotherworkspace.slack.com" token="xoxc-01234567890-012345678912-0123456789123-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" cookie_d="xoxd-00000000000000000000000%2B0000000000000000000000000%2B000000000000000000000000000000000000000000000000%2F0000000000%2B0000000000000000000000000000000000%2F000%2F0000000000000000000000000000000000%3D" -[weatherstack] -api_access_key="0123456789abcdef0123456789abcdef" +[weatherprovider] +# Supported names are "weatherstack" and "weatherapi" +name="weatherstack" +api_access_key="0123456789abcdef0123456789abcdef" \ No newline at end of file diff --git a/wspp/main.py b/wspp/main.py index 96e6dd0..621a3b3 100644 --- a/wspp/main.py +++ b/wspp/main.py @@ -12,7 +12,7 @@ from threading import Event from typing import Optional -from wspp import image, schedule, slack, weatherstack +from wspp import image, schedule, slack, weather from wspp.settings import settings from wspp.sunrisesunset import SunriseSunset @@ -40,10 +40,8 @@ def update_profile_photo_from_weather(): sunrise_sunset = SunriseSunset.create( latitude=settings.wspp.latitude, longitude=settings.wspp.longitude ) - weather_code = weatherstack.get_current_weather_code( - settings=settings.weatherstack, - latitude=settings.wspp.latitude, - longitude=settings.wspp.longitude, + weather_code = weather.get_current_weather_code( + settings=settings, is_day=sunrise_sunset.is_day_now, ) if cache.last_weather_code != weather_code: diff --git a/wspp/settings.py b/wspp/settings.py index 5346ca6..09e23dc 100644 --- a/wspp/settings.py +++ b/wspp/settings.py @@ -1,3 +1,4 @@ +import enum import tomllib from pathlib import Path from typing import Any @@ -11,7 +12,7 @@ ) from typing_extensions import Annotated -from wspp import slack, weatherstack +from wspp import slack class WsppSettings(BaseModel): @@ -21,6 +22,16 @@ class WsppSettings(BaseModel): polling_interval_s: PositiveInt = 7200 +class ProviderName(enum.Enum): + WEATHERSTACK = "weatherstack" + WEATHERAPI = "weatherapi" + + +class WeatherproviderSettings(BaseModel): + name: ProviderName + api_access_key: str + + # https://github.com/pydantic/pydantic/issues/2335 class TOMLConfigSettingsSource(PydanticBaseSettingsSource): def get_field_value( @@ -34,7 +45,7 @@ def __call__(self) -> dict[str, Any]: class Settings(BaseSettings): wspp: WsppSettings - weatherstack: weatherstack.WeatherstackSettings + weatherprovider: WeatherproviderSettings slack: list[slack.SlackSettings] @classmethod diff --git a/wspp/weather.py b/wspp/weather.py new file mode 100644 index 0000000..d664f8e --- /dev/null +++ b/wspp/weather.py @@ -0,0 +1,25 @@ +from wspp import weatherapi, weatherstack +from wspp.settings import ProviderName, Settings + + +def get_current_weather_code( + settings: Settings, + is_day: bool, +) -> int: + """ + :return: The weather_code for the current condition at the location defined + in the environment variable. + """ + if not is_day: + return 999 + + if settings.weatherprovider.name == ProviderName.WEATHERSTACK: + provider_function = weatherstack.get_current_weather_code + else: + provider_function = weatherapi.get_current_weather_code + + return provider_function( + api_access_key=settings.weatherprovider.api_access_key, + latitude=settings.wspp.latitude, + longitude=settings.wspp.longitude, + ) diff --git a/wspp/weatherapi.py b/wspp/weatherapi.py new file mode 100644 index 0000000..9de9881 --- /dev/null +++ b/wspp/weatherapi.py @@ -0,0 +1,32 @@ +import re + +import requests + + +def get_current_weather_code( + api_access_key: str, + latitude: float, + longitude: float, +) -> int: + """ + :return: The weather_code for the current condition at the location defined + in the environment variable. + """ + response = requests.get( + url="http://api.weatherapi.com/v1/current.json", + params={ + "key": api_access_key, + "q": f"{latitude},{longitude}", + "aqi": "no", + }, + ) + if not response.ok: + raise Exception(response.text) + response_data: dict = response.json() + # ex: //cdn.weatherapi.com/weather/64x64/day/248.png + icon = response_data["current"]["condition"]["icon"] + pattern = re.compile(r"^.*/([0-9]*).png$") + tokens = pattern.findall(icon) + code = tokens[-1] + + return code diff --git a/wspp/weatherstack.py b/wspp/weatherstack.py index 01969a2..73b943f 100644 --- a/wspp/weatherstack.py +++ b/wspp/weatherstack.py @@ -1,27 +1,19 @@ import requests -from pydantic import BaseModel - - -class WeatherstackSettings(BaseModel): - api_access_key: str def get_current_weather_code( - settings: WeatherstackSettings, + api_access_key: str, latitude: float, longitude: float, - is_day: bool, ) -> int: """ :return: The weather_code for the current condition at the location defined in the environment variable. """ - if not is_day: - return 999 response = requests.get( url="http://api.weatherstack.com/current", params={ - "access_key": settings.api_access_key, + "access_key": api_access_key, "query": f"{latitude},{longitude}", }, )