feat(easel): implement multiple weather providers

This commit is contained in:
2026-06-23 16:22:17 +03:00
parent 3096f97aa7
commit d9129a4947
10 changed files with 321 additions and 19 deletions

View File

@@ -89,7 +89,9 @@ class GismeteoApi(WeatherApi):
lon=item["coordinates"]["longitude"],
country=item["translations"]["kk"]["country"]["name"],
country_code=item["country"]["code"].lower(),
district=item["translations"]["kk"]["district"]["name"],
district=(
item["translations"]["kk"]["district"]["name"] if item["translations"]["kk"]["district"] else ""
),
subdistrict=(
item["translations"]["kk"]["subdistrict"]["name"]
if "subdistrict" in item["translations"]["kk"]

View File

@@ -1,6 +1,7 @@
import datetime
import logging
from collections import defaultdict
from os import environ
from aiocache import cached
@@ -17,7 +18,7 @@ logger = logging.getLogger("openweather")
class OpenWeatherApi(WeatherApi):
PROVIDER = "openweather"
SOURCE = OpenWeather("517a6bccceaa1c48127f6199ec3fb7cf")
SOURCE = OpenWeather(environ["OPENWEATHER_KEY"])
@classmethod
def _parse_location(cls, location_id: str) -> tuple[float, float]:
@@ -32,7 +33,20 @@ class OpenWeatherApi(WeatherApi):
return await self.SOURCE.get_forecast(*self._parse_location(location_id))
async def find_locations(self, query: str) -> list[Location]:
raise NotImplementedError
result = await self.SOURCE.get_locations(query)
return [
Location(
id=f"{item.lat}:{item.lon}",
name=item.name,
lat=item.lat,
lon=item.lon,
country=item.country,
country_code=item.country.lower(),
district=item.state,
subdistrict="",
)
for item in result
]
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
data: Forecast = await self._get_location_forecast(location_id)

View File

@@ -67,6 +67,15 @@ class Forecast(Model):
list: list[ForecastItem]
class Location(Model):
name: str
local_names: dict[str, str]
lat: float
lon: float
country: str
state: str
class OpenWeather:
BASE_URL = "https://api.openweathermap.org"
@@ -78,4 +87,10 @@ class OpenWeather:
endpoint = f"data/2.5/forecast?lat={lat}&lon={lon}&appid={self._api_key}&units=metric"
response = await self._source.request(endpoint)
response_data = json.loads(response)
return Forecast(**response_data)
return Forecast.model_validate(response_data)
async def get_locations(self, query: str, limit: int = 5) -> list[Location]:
endpoint = f"geo/1.0/direct?q={query}&limit={limit}&appid={self._api_key}"
response = await self._source.request(endpoint)
response_data = json.loads(response)
return [Location.model_validate(item) for item in response_data]