7 Commits

Author SHA1 Message Date
a91ec12d22 ci(version): 0.3.3 2026-06-22 15:33:36 +03:00
9c862863e5 fix(gismeteo): fix precipitation parser 2026-06-22 15:33:19 +03:00
fc59e52337 ci(version): 0.3.2 2026-06-20 18:59:43 +03:00
3e93a41400 fix(gismeteo): fix date-time row parsing 2026-06-20 18:59:27 +03:00
c2cd18386b refactor(easel): update api router 2026-06-16 21:18:16 +03:00
2bca3dd75a ci(version): 0.3.1 2026-06-16 20:17:37 +03:00
469bd9bc1f feat(easel): add version to header 2026-06-16 20:17:12 +03:00
13 changed files with 5298 additions and 5284 deletions

View File

@@ -4,8 +4,7 @@ from fastapi.staticfiles import StaticFiles
from gallery.sketch.bundle import ApiBundle
from gallery.util import root_path
from .route import api, doc
from .route.view import router as view_router
from .route import api, doc, view
def build_app(api_bundle: ApiBundle) -> FastAPI:
@@ -17,6 +16,6 @@ def build_app(api_bundle: ApiBundle) -> FastAPI:
app.state.api = api_bundle
app.mount("/static", StaticFiles(directory=root_path / "static/dist"))
doc.mount(app)
api.mount(app)
app.include_router(view_router)
app.include_router(api.router)
app.include_router(view.router)
return app

View File

@@ -1,8 +1,7 @@
from fastapi import FastAPI
from fastapi import APIRouter
from . import schedule, weather
def mount(app: FastAPI):
weather.mount(app)
schedule.mount(app)
router = APIRouter(prefix="/api", tags=["API"])
router.include_router(weather.router)
router.include_router(schedule.router)

View File

@@ -1,18 +1,20 @@
import datetime
from fastapi import FastAPI
from fastapi import APIRouter
from gallery.easel.core import AppRequest
from gallery.sketch.schedule.model import ChannelId, Schedule
router = APIRouter(prefix="/schedule")
def mount(app: FastAPI):
@app.get("/api/schedule/channels", tags=["API"])
async def get_api_schedule_channels(request: AppRequest) -> list[ChannelId]:
schedule_api = request.app.state.api.schedule
return await schedule_api.get_channels()
@app.get("/api/schedule/{channel}/{date}", tags=["API"])
async def get_api_schedule_channel_schedule(request: AppRequest, channel: str, date: datetime.date) -> Schedule:
schedule_api = request.app.state.api.schedule
return await schedule_api.get_channel_schedule(ChannelId(channel), date)
@router.get("/channels")
async def get_api_schedule_channels(request: AppRequest) -> list[ChannelId]:
schedule_api = request.app.state.api.schedule
return await schedule_api.get_channels()
@router.get("/{channel}/{date}")
async def get_api_schedule_channel_schedule(request: AppRequest, channel: str, date: datetime.date) -> Schedule:
schedule_api = request.app.state.api.schedule
return await schedule_api.get_channel_schedule(ChannelId(channel), date)

View File

@@ -1,23 +1,26 @@
import datetime
from fastapi import FastAPI
from fastapi import APIRouter
from gallery.easel.core import AppRequest
from gallery.sketch.weather.model import Location, WeatherResponse
router = APIRouter(prefix="/weather")
def mount(app: FastAPI):
@app.get("/api/weather/locations", tags=["API"])
async def get_api_weather_locations(request: AppRequest, query: str) -> list[Location]:
weather_api = request.app.state.api.weather
return await weather_api.find_locations(query)
@app.get("/api/weather/{location}/day/{date}", tags=["API"])
async def get_api_weather_day(request: AppRequest, location: str, date: datetime.date) -> WeatherResponse:
weather_api = request.app.state.api.weather
return await weather_api.get_day(location, date)
@router.get("/locations")
async def get_api_weather_locations(request: AppRequest, query: str) -> list[Location]:
weather_api = request.app.state.api.weather
return await weather_api.find_locations(query)
@app.get("/api/weather/{location}/days/{days}", tags=["API"])
async def get_api_weather_days(request: AppRequest, location: str, days: int) -> WeatherResponse:
weather_api = request.app.state.api.weather
return await weather_api.get_days(location, days)
@router.get("/{location}/day/{date}")
async def get_api_weather_day(request: AppRequest, location: str, date: datetime.date) -> WeatherResponse:
weather_api = request.app.state.api.weather
return await weather_api.get_day(location, date)
@router.get("/{location}/days/{days}")
async def get_api_weather_days(request: AppRequest, location: str, days: int) -> WeatherResponse:
weather_api = request.app.state.api.weather
return await weather_api.get_days(location, days)

View File

@@ -5,7 +5,7 @@ from .schedule import router as schedule_router
from .translation import set_language
from .weather import router as weather_router
router = APIRouter(dependencies=[Depends(set_language)])
router = APIRouter(tags=["view"], dependencies=[Depends(set_language)])
router.include_router(common_router)
router.include_router(weather_router)
router.include_router(schedule_router)

View File

@@ -30,6 +30,9 @@
{% block header %}{% endblock %}
</div>
<ul class="navbar-nav flex-row flex-wrap ms-md-auto">
<li class="nav-item me-2">
<span class="nav-link">{{ version }}</span>
</li>
<li class="nav-item dropdown">
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center"
id="bd-language"

View File

@@ -39,14 +39,11 @@ class DateParser(RowParser[datetime.datetime]):
KEY = "date"
def parse_row(self, tag: Tag) -> Iterable[datetime.datetime]:
datetime_date_tag = tag.select_one(".widget-row.widget-row-datetime-date > .row-item")
if datetime_date_tag:
date_str = datetime_date_tag.find(text=True, recursive=False).text
date = dateparser.parse(date_str, languages=["ru"])
for item in tag.select(".widget-row.widget-row-datetime-time > .row-item"):
time_str = item.text
time = dateparser.parse(time_str, languages=["ru"])
time = time.replace(year=date.year, month=date.month, day=date.day)
datetime_time_row = tag.select_one(".widget-row.widget-row-datetime-time")
if datetime_time_row:
for item in datetime_time_row.select(".row-item > time-value"):
timestamp = int(item.attrs["timestamp"])
time = datetime.datetime.fromtimestamp(timestamp)
yield time
else:
for item in tag.select(".widget-row.widget-row-date > .row-item"):
@@ -174,7 +171,7 @@ class PrecipitationParser(RowParser[float]):
def parse_row(self, tag: Tag) -> Iterable[float]:
for item in tag.select(".widget-row[data-row=precipitation-bars] > .row-item > .item-unit"):
yield float(item.text.replace(",", "."))
yield float(item.text.replace(",", ".").replace("< ", ""))
class PressureParser(RowParser[list[int]]):

View File

@@ -1,5 +1,3 @@
__version__ = "0.2.2"
import tomllib
from pathlib import Path

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "gallery"
version = "0.3.0"
version = "0.3.3"
description = ""
authors = ["shmyga <shmyga.z@gmail.com>"]
readme = "README.md"

View File

@@ -1,12 +1,12 @@
{
"name": "gallery",
"version": "0.3.0",
"version": "0.3.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "gallery",
"version": "0.3.0",
"version": "0.3.3",
"license": "ISC",
"dependencies": {
"@popperjs/core": "^2.11.8",

View File

@@ -1,6 +1,6 @@
{
"name": "gallery",
"version": "0.3.0",
"version": "0.3.3",
"scripts": {
"build": "vite build",
"dev": "vite build --watch"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long