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

View File

@@ -28,9 +28,9 @@
</div> </div>
</h3> </h3>
<ul class="app-list"> <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 %} {% for channel in channels %}
<li><a href="schedule/{{channel}}">{{channel}}</a></li> <li><a href="schedule/{{channel.id}}">{{channel.name}}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</body> </body>

View File

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

View File

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

View File

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

View File

@@ -6,23 +6,12 @@ from aiocache import cached
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from gallery.sketch.schedule.api import ScheduleApi from gallery.sketch.schedule.api import ScheduleApi
from gallery.sketch.schedule.catalog import ChannelId
from gallery.sketch.schedule.model import Channel, Schedule, ScheduleValue from gallery.sketch.schedule.model import Channel, Schedule, ScheduleValue
logger = logging.getLogger("matchtv") logger = logging.getLogger("matchtv")
CHANNEL_LIST = [
"matchtv",
"igra",
"arena",
"futbol-1",
"futbol-2",
"futbol-3",
"strana",
# "planeta",
]
class MatchTvApi(ScheduleApi): class MatchTvApi(ScheduleApi):
BASE_URL = "https://matchtv.ru" BASE_URL = "https://matchtv.ru"
CACHE_TTL = 30 * 60 CACHE_TTL = 30 * 60
@@ -46,7 +35,15 @@ class MatchTvApi(ScheduleApi):
return await response.text() return await response.text()
async def get_channels(self) -> list[str]: 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) @cached(ttl=CACHE_TTL)
async def get_channel_schedule( 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 use_enum_values = True
class Location(Model):
id: str
name: str
class Cloudness(str, Enum): class Cloudness(str, Enum):
CLEAR = "clear" CLEAR = "clear"
PARTLY_CLOUDY = "party_cloudy" PARTLY_CLOUDY = "party_cloudy"

View File

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