Compare commits
3 Commits
315838604e
...
8012d9b8ed
| Author | SHA1 | Date | |
|---|---|---|---|
| 8012d9b8ed | |||
| 3a6faa85be | |||
| 1af61aa3c7 |
@@ -54,7 +54,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
{% for value in response.values %}
|
{% for value in response.values %}
|
||||||
<td class="cloudness">
|
<td class="cloudness" data-bs-toggle="tooltip" data-bs-title="{{ value.sky }}">
|
||||||
{% for icon in value.sky | cloudness_icon %}
|
{% for icon in value.sky | cloudness_icon %}
|
||||||
<div class="icon">{{icon}}</div>
|
<div class="icon">{{icon}}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import logging
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from fastapi import HTTPException, status
|
||||||
|
|
||||||
from gallery.sketch.source import ApiSource
|
from gallery.sketch.source import ApiSource
|
||||||
from gallery.sketch.weather.api import WeatherApi
|
from gallery.sketch.weather.api import WeatherApi
|
||||||
@@ -99,6 +100,11 @@ class GismeteoApi(WeatherApi):
|
|||||||
return result
|
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)
|
||||||
|
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}/{datehelp.dump(date)}")
|
data = await self.SOURCE.request(f"weather-{location_id}/{datehelp.dump(date)}")
|
||||||
return self._parse_oneday(date, data)
|
return self._parse_oneday(date, data)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
@@ -15,6 +16,8 @@ from gallery.sketch.weather.model import (
|
|||||||
|
|
||||||
from .core import BaseWidgetParser, RowParser
|
from .core import BaseWidgetParser, RowParser
|
||||||
|
|
||||||
|
logger = logging.getLogger("gismeteo")
|
||||||
|
|
||||||
ONE_DAY_PARSER = BaseWidgetParser(".widget.widget-oneday .widget-items")
|
ONE_DAY_PARSER = BaseWidgetParser(".widget.widget-oneday .widget-items")
|
||||||
DAYS_PARSER = BaseWidgetParser(".widget.widget-days .widget-items")
|
DAYS_PARSER = BaseWidgetParser(".widget.widget-days .widget-items")
|
||||||
|
|
||||||
@@ -57,6 +60,7 @@ class SkyParser(RowParser[Sky]):
|
|||||||
|
|
||||||
CLOUDNESS_MAP: dict[str, Cloudness] = {
|
CLOUDNESS_MAP: dict[str, Cloudness] = {
|
||||||
"ясно": Cloudness.CLEAR,
|
"ясно": Cloudness.CLEAR,
|
||||||
|
"безоблачно": Cloudness.CLEAR,
|
||||||
"малооблачно": Cloudness.PARTLY_CLOUDY,
|
"малооблачно": Cloudness.PARTLY_CLOUDY,
|
||||||
"облачно": Cloudness.CLOUDY,
|
"облачно": Cloudness.CLOUDY,
|
||||||
"пасмурно": Cloudness.MAINLY_CLOUDY,
|
"пасмурно": Cloudness.MAINLY_CLOUDY,
|
||||||
@@ -64,8 +68,10 @@ class SkyParser(RowParser[Sky]):
|
|||||||
|
|
||||||
PRECIPITATION_MAP: dict[str, Precipitation] = {
|
PRECIPITATION_MAP: dict[str, Precipitation] = {
|
||||||
"без осадков": Precipitation.NO,
|
"без осадков": Precipitation.NO,
|
||||||
"небольшой дождь": Precipitation.SMALL_RAIN,
|
"небольшой дождь": Precipitation.SMALL_RAIN, # TODO: remove it?
|
||||||
|
"небольшой дождь": Precipitation.SMALL_RAIN,
|
||||||
"сильный дождь": Precipitation.HEAVY_RAIN,
|
"сильный дождь": Precipitation.HEAVY_RAIN,
|
||||||
|
"ливневый дождь": Precipitation.SHOWER,
|
||||||
"дождь": Precipitation.RAIN,
|
"дождь": Precipitation.RAIN,
|
||||||
"ливень": Precipitation.SHOWER,
|
"ливень": Precipitation.SHOWER,
|
||||||
"снег": Precipitation.SNOW,
|
"снег": Precipitation.SNOW,
|
||||||
@@ -78,22 +84,35 @@ class SkyParser(RowParser[Sky]):
|
|||||||
"небольшой мокрый снег": Precipitation.SNOW,
|
"небольшой мокрый снег": Precipitation.SNOW,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
THUNDER = "гроза"
|
||||||
|
FOG = "дымка"
|
||||||
|
|
||||||
def parse_row(self, tag: Tag) -> Iterable[Sky]:
|
def parse_row(self, tag: Tag) -> Iterable[Sky]:
|
||||||
for item in tag.select(".widget-row[data-row=icon-tooltip] > .row-item"):
|
for item in tag.select(".widget-row[data-row=icon-tooltip] > .row-item"):
|
||||||
sky_str = item.attrs["data-tooltip"]
|
sky_str = item.attrs["data-tooltip"]
|
||||||
values = {item.strip().lower() for item in sky_str.split(",")}
|
values = {item.strip().lower() for item in sky_str.split(",")}
|
||||||
cloudness = Cloudness.CLEAR
|
cloudness = Cloudness.CLEAR
|
||||||
precipitation = Precipitation.NO
|
precipitation = Precipitation.NO
|
||||||
thunder = "гроза" in values
|
thunder = False
|
||||||
fog = "дымка" in values
|
fog = False
|
||||||
|
if self.THUNDER in values:
|
||||||
|
thunder = True
|
||||||
|
values.remove(self.THUNDER)
|
||||||
|
if self.FOG in values:
|
||||||
|
fog = True
|
||||||
|
values.remove(self.FOG)
|
||||||
for k, v in self.CLOUDNESS_MAP.items():
|
for k, v in self.CLOUDNESS_MAP.items():
|
||||||
if k in values:
|
if k in values:
|
||||||
cloudness = v
|
cloudness = v
|
||||||
|
values.remove(k)
|
||||||
break
|
break
|
||||||
for k, v in self.PRECIPITATION_MAP.items():
|
for k, v in self.PRECIPITATION_MAP.items():
|
||||||
if k in values:
|
if k in values:
|
||||||
precipitation = v
|
precipitation = v
|
||||||
|
values.remove(k)
|
||||||
break
|
break
|
||||||
|
if values:
|
||||||
|
logger.warning("unknown sky values: %s:", values)
|
||||||
yield Sky(
|
yield Sky(
|
||||||
cloudness=cloudness,
|
cloudness=cloudness,
|
||||||
precipitation=precipitation,
|
precipitation=precipitation,
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import "./main.scss";
|
import * as bootstrap from "bootstrap";
|
||||||
import "bootstrap";
|
|
||||||
import "./theme";
|
|
||||||
import "./language";
|
|
||||||
import "./components";
|
import "./components";
|
||||||
|
import "./language";
|
||||||
|
import "./main.scss";
|
||||||
|
import "./theme";
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", (event) => {
|
||||||
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||||
|
const tooltipList = [...tooltipTriggerList].map((tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||||
|
});
|
||||||
|
|||||||
2
static/src/lib/bootstrap.scss
vendored
2
static/src/lib/bootstrap.scss
vendored
@@ -37,7 +37,7 @@
|
|||||||
//@import "bootstrap/scss/close";
|
//@import "bootstrap/scss/close";
|
||||||
//@import "bootstrap/scss/toasts";
|
//@import "bootstrap/scss/toasts";
|
||||||
//@import "bootstrap/scss/modal";
|
//@import "bootstrap/scss/modal";
|
||||||
//@import "bootstrap/scss/tooltip";
|
@import "bootstrap/scss/tooltip";
|
||||||
//@import "bootstrap/scss/popover";
|
//@import "bootstrap/scss/popover";
|
||||||
//@import "bootstrap/scss/carousel";
|
//@import "bootstrap/scss/carousel";
|
||||||
//@import "bootstrap/scss/spinners";
|
//@import "bootstrap/scss/spinners";
|
||||||
|
|||||||
Reference in New Issue
Block a user