refactor(gismeteo): add gismeteo location parser

This commit is contained in:
2026-09-17 16:39:07 +03:00
parent a12a81e26d
commit ece1a58a27
2 changed files with 40 additions and 32 deletions
+8 -30
View File
@@ -1,5 +1,4 @@
import datetime import datetime
import json
import logging import logging
from os import environ from os import environ
@@ -9,7 +8,7 @@ from gallery.sketch.source import ApiSource
from gallery.sketch.weather.api import WeatherApi from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.model import Location, WeatherResponse from gallery.sketch.weather.model import Location, WeatherResponse
from .parser import Context, GismeteoParser from .parser import Context, GismeteoForecastParser, GismeteoLocationParser
logger = logging.getLogger("gismeteo") logger = logging.getLogger("gismeteo")
@@ -27,7 +26,9 @@ def format_date(date: datetime.date) -> str:
class GismeteoApi(WeatherApi): class GismeteoApi(WeatherApi):
PROVIDER = "gismeteo" PROVIDER = "gismeteo"
parser = GismeteoParser()
forecast_parser = GismeteoForecastParser()
location_parser = GismeteoLocationParser()
def _build_source(self) -> ApiSource: def _build_source(self) -> ApiSource:
return ApiSource( return ApiSource(
@@ -39,33 +40,10 @@ class GismeteoApi(WeatherApi):
geo = "ru" geo = "ru"
latitude = 52.968498 latitude = 52.968498
longitude = 36.0695 longitude = 36.0695
data = json.loads( data = await self.source.request(
await self.source.request(
f"mq/city/q/?q={query}&geo={geo}&latitude={latitude}&longitude={longitude}&limit=10" f"mq/city/q/?q={query}&geo={geo}&latitude={latitude}&longitude={longitude}&limit=10"
) )
) return self.location_parser.parse(data)
result = []
for item in data["data"]:
result.append(
Location(
id=f"{item['slug']}-{item['id']}",
name=item["translations"]["kk"]["city"]["name"],
provider=self.provider,
lat=item["coordinates"]["latitude"],
lon=item["coordinates"]["longitude"],
country=item["translations"]["kk"]["country"]["name"],
country_code=item["country"]["code"].lower(),
district=(
item["translations"]["kk"]["district"]["name"] if item["translations"]["kk"]["district"] else ""
),
subdistrict=(
item["translations"]["kk"]["subdistrict"]["name"]
if "subdistrict" in item["translations"]["kk"]
else ""
),
)
)
return result
async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse: async def get_day(self, location_id: str, date: datetime.date) -> WeatherResponse:
max_date = datetime.date.today() + datetime.timedelta(days=9) max_date = datetime.date.today() + datetime.timedelta(days=9)
@@ -75,9 +53,9 @@ class GismeteoApi(WeatherApi):
) )
data = await self.source.request(f"weather-{location_id}/{format_date(date)}") data = await self.source.request(f"weather-{location_id}/{format_date(date)}")
context = Context(date, "day", data, 8) context = Context(date, "day", data, 8)
return self.parser.parse(context) return self.forecast_parser.parse(context)
async def get_days(self, location_id: str, days: int) -> WeatherResponse: async def get_days(self, location_id: str, days: int) -> WeatherResponse:
data = await self.source.request(f"weather-{location_id}/{days}-days") data = await self.source.request(f"weather-{location_id}/{days}-days")
context = Context(datetime.date.today(), "days", data) context = Context(datetime.date.today(), "days", data)
return self.parser.parse(context) return self.forecast_parser.parse(context)
+31 -1
View File
@@ -1,4 +1,5 @@
import datetime import datetime
import json
import logging import logging
import re import re
from typing import Literal, NamedTuple from typing import Literal, NamedTuple
@@ -10,6 +11,7 @@ from gallery.sketch.parse.date import parse_date
from gallery.sketch.parse.html import TableParser, TableValueParser from gallery.sketch.parse.html import TableParser, TableValueParser
from gallery.sketch.weather.model import ( from gallery.sketch.weather.model import (
Cloudness, Cloudness,
Location,
Precipitation, Precipitation,
Sky, Sky,
WeatherResponse, WeatherResponse,
@@ -201,7 +203,7 @@ class Context(NamedTuple):
values: int | None = None values: int | None = None
class GismeteoParser(Parser[Context, WeatherResponse]): class GismeteoForecastParser(Parser[Context, WeatherResponse]):
location_parser = LocationNameParser() location_parser = LocationNameParser()
table_parser = GismeteoTableParser() table_parser = GismeteoTableParser()
@@ -222,3 +224,31 @@ class GismeteoParser(Parser[Context, WeatherResponse]):
period=data.period, period=data.period,
values=values, values=values,
) )
class GismeteoLocationParser(Parser[str, list[Location]]):
def parse(self, data: str) -> list[Location]:
content = json.loads(data)
result = []
for item in content["data"]:
result.append(
Location(
id=f"{item['slug']}-{item['id']}",
name=item["translations"]["kk"]["city"]["name"],
provider="gismeteo", # TODO: provider module const
lat=item["coordinates"]["latitude"],
lon=item["coordinates"]["longitude"],
country=item["translations"]["kk"]["country"]["name"],
country_code=item["country"]["code"].lower(),
district=(
item["translations"]["kk"]["district"]["name"] if item["translations"]["kk"]["district"] else ""
),
subdistrict=(
item["translations"]["kk"]["subdistrict"]["name"]
if "subdistrict" in item["translations"]["kk"]
else ""
),
)
)
return result