feat: add catalog

This commit is contained in:
2024-08-16 00:59:56 +03:00
parent aae8bc8649
commit b3043c3c8c
11 changed files with 91 additions and 22 deletions

View File

@@ -7,6 +7,7 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from gallery.sketch.schedule.api import ScheduleApi
from gallery.sketch.schedule.catalog import BUNDLE
from gallery.version import __version__
from ..common.util import TagType, TagUtil
@@ -23,12 +24,13 @@ def mount(app: FastAPI):
async def get_schedule_list(request: Request):
schedule_api: ScheduleApi = request.app.state.schedule_api
channels = await schedule_api.get_channels()
channels_data = BUNDLE.select_items(channels)
return templates.TemplateResponse(
request=request,
name="index.html",
context={
"version": __version__,
"channels": channels,
"channels": channels_data,
},
)

View File

@@ -28,9 +28,9 @@
</div>
</h3>
<ul class="app-list">
<li style="margin-bottom: 0.25rem;"><a href="schedule/tag/today">all</a></li>
<li style="margin-bottom: 0.25rem; font-weight: bold;"><a href="schedule/tag/today">Все</a></li>
{% for channel in channels %}
<li><a href="schedule/{{channel}}">{{channel}}</a></li>
<li><a href="schedule/{{channel.id}}">{{channel.name}}</a></li>
{% endfor %}
</ul>
</body>

View File

@@ -7,6 +7,7 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.catalog import BUNDLE
from gallery.sketch.weather.mock import WEATHER_MOCK_DATA
from gallery.sketch.weather.model import WeatherResponse
from gallery.version import __version__
@@ -38,12 +39,13 @@ def mount(app: FastAPI):
async def get_weather_list(request: Request):
weather_api: WeatherApi = request.app.state.weather_api
locations = await weather_api.get_locations()
locations_data = BUNDLE.select_items(locations)
return templates.TemplateResponse(
request=request,
name="index.html",
context={
"version": __version__,
"locations": locations,
"locations": locations_data,
},
)

View File

@@ -29,7 +29,7 @@
</h3>
<ul class="app-list">
{% for location in locations %}
<li><a href="weather/{{location}}">{{location}}</a></li>
<li><a href="weather/{{location.id}}">{{location.name}}</a></li>
{% endfor %}
</ul>
</body>

View File

@@ -7,6 +7,7 @@ from aiocache import cached
from bs4 import BeautifulSoup
from gallery.sketch.weather.api import WeatherApi
from gallery.sketch.weather.catalog import LocationId
from gallery.sketch.weather.model import WeatherResponse, WeatherValue
from . import datehelp
@@ -81,8 +82,8 @@ class GismeteoApi(WeatherApi):
async def get_locations(self) -> list[str]:
return [
"orel-4432",
"zmiyevka-184640",
LocationId.OREL,
LocationId.ZMIYEVKA,
]
@cached(ttl=CACHE_TTL)

View File

@@ -6,23 +6,12 @@ from aiocache import cached
from bs4 import BeautifulSoup
from gallery.sketch.schedule.api import ScheduleApi
from gallery.sketch.schedule.catalog import ChannelId
from gallery.sketch.schedule.model import Channel, Schedule, ScheduleValue
logger = logging.getLogger("matchtv")
CHANNEL_LIST = [
"matchtv",
"igra",
"arena",
"futbol-1",
"futbol-2",
"futbol-3",
"strana",
# "planeta",
]
class MatchTvApi(ScheduleApi):
BASE_URL = "https://matchtv.ru"
CACHE_TTL = 30 * 60
@@ -46,7 +35,15 @@ class MatchTvApi(ScheduleApi):
return await response.text()
async def get_channels(self) -> list[str]:
return CHANNEL_LIST
return [
ChannelId.MATCH_TV,
ChannelId.MATCH_IGRA,
ChannelId.MATCH_ARENA,
ChannelId.MATCH_FUTBOL_1,
ChannelId.MATCH_FUTBOL_2,
ChannelId.MATCH_FUTBOL_3,
ChannelId.MATCH_STRANA,
]
@cached(ttl=CACHE_TTL)
async def get_channel_schedule(

11
gallery/sketch/catalog.py Normal file
View File

@@ -0,0 +1,11 @@
from typing import Generic, TypeVar
T = TypeVar("T")
class CatalogBundle(Generic[T]):
def __init__(self, items: list[T]) -> None:
self._items_by_id = {item.id: item for item in items}
def select_items(self, ids: list[str]) -> list[T]:
return [self._items_by_id[id_] for id_ in ids]

View File

@@ -0,0 +1,31 @@
from enum import Enum
from gallery.sketch.catalog import CatalogBundle
from .model import Channel
class ChannelId(str, Enum):
MATCH_TV = "matchtv"
MATCH_IGRA = "igra"
MATCH_ARENA = "arena"
MATCH_FUTBOL_1 = "futbol-1"
MATCH_FUTBOL_2 = "futbol-2"
MATCH_FUTBOL_3 = "futbol-3"
MATCH_STRANA = "strana"
def __str__(self) -> str:
return self.value
BUNDLE = CatalogBundle(
[
Channel(id=ChannelId.MATCH_TV, name="Матч ТВ"),
Channel(id=ChannelId.MATCH_IGRA, name="Матч! Игра"),
Channel(id=ChannelId.MATCH_ARENA, name="Матч! Арена"),
Channel(id=ChannelId.MATCH_FUTBOL_1, name="Футбол 1"),
Channel(id=ChannelId.MATCH_FUTBOL_2, name="Футбол 2"),
Channel(id=ChannelId.MATCH_FUTBOL_3, name="Футбол 3"),
Channel(id=ChannelId.MATCH_STRANA, name="Матч! Страна"),
]
)

View File

@@ -0,0 +1,21 @@
from enum import Enum
from gallery.sketch.catalog import CatalogBundle
from .model import Location
class LocationId(str, Enum):
OREL = "orel-4432"
ZMIYEVKA = "zmiyevka-184640"
def __str__(self) -> str:
return self.value
BUNDLE = CatalogBundle(
[
Location(id=LocationId.OREL, name="Орёл"),
Location(id=LocationId.ZMIYEVKA, name="Змиёвка"),
]
)

View File

@@ -9,6 +9,11 @@ class Model(BaseModel):
use_enum_values = True
class Location(Model):
id: str
name: str
class Cloudness(str, Enum):
CLEAR = "clear"
PARTLY_CLOUDY = "party_cloudy"

View File

@@ -20,5 +20,4 @@ def matchtv_api_fixture() -> MatchTvApi:
async def test_channel(matchtv_api: MatchTvApi):
result = await matchtv_api.get_channel_schedule("matchtv", datetime.date.today())
assert result is not None
assert len(result.items) > 0
print(">>", "\n".join(map(str, result.items)))
assert len(result.values) > 0