84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
import datetime
|
|
import json
|
|
import logging
|
|
from os import environ
|
|
|
|
from fastapi import HTTPException, status
|
|
|
|
from gallery.sketch.source import ApiSource
|
|
from gallery.sketch.weather.api import WeatherApi
|
|
from gallery.sketch.weather.model import Location, WeatherResponse
|
|
|
|
from .parser import Context, GismeteoParser
|
|
|
|
logger = logging.getLogger("gismeteo")
|
|
|
|
|
|
def format_date(date: datetime.date) -> str:
|
|
today = datetime.date.today()
|
|
days = (date - today).days
|
|
if days == 0:
|
|
return "today"
|
|
elif days == 1:
|
|
return "tomorrow"
|
|
else:
|
|
return f"{days + 1}-day"
|
|
|
|
|
|
class GismeteoApi(WeatherApi):
|
|
PROVIDER = "gismeteo"
|
|
parser = GismeteoParser()
|
|
|
|
def _build_source(self) -> ApiSource:
|
|
return ApiSource(
|
|
"https://www.gismeteo.ru",
|
|
cookies={"xauth": auth} if (auth := environ.get("GISMETEO_AUTH")) else None,
|
|
)
|
|
|
|
async def find_locations(self, query: str) -> list[Location]:
|
|
geo = "ru"
|
|
latitude = 52.968498
|
|
longitude = 36.0695
|
|
data = json.loads(
|
|
await self.source.request(
|
|
f"mq/city/q/?q={query}&geo={geo}&latitude={latitude}&longitude={longitude}&limit=10"
|
|
)
|
|
)
|
|
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:
|
|
max_date = datetime.date.today() + datetime.timedelta(days=9)
|
|
if date > max_date:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail={"max_date": max_date.strftime("%Y-%m-%d")}
|
|
)
|
|
data = await self.source.request(f"weather-{location_id}/{format_date(date)}")
|
|
context = Context(date, "day", data, 8)
|
|
return self.parser.parse(context)
|
|
|
|
async def get_days(self, location_id: str, days: int) -> WeatherResponse:
|
|
data = await self.source.request(f"weather-{location_id}/{days}-days")
|
|
context = Context(datetime.date.today(), "days", data)
|
|
return self.parser.parse(context)
|