82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
import datetime
|
|
import logging
|
|
|
|
import aiohttp
|
|
from aiocache import cached
|
|
from bs4 import BeautifulSoup
|
|
|
|
from gallery.sketch.schedule.api import ScheduleApi
|
|
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
|
|
|
|
USER_AGENT = (
|
|
"Mozilla/5.0 (X11; Linux x86_64) "
|
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
|
"Chrome/126.0.0.0 Safari/537.36"
|
|
)
|
|
|
|
async def _request(self, endpoint: str) -> str:
|
|
url = f"{self.BASE_URL}/{endpoint}"
|
|
logger.info(url)
|
|
async with aiohttp.ClientSession(
|
|
headers={
|
|
"User-Agent": self.USER_AGENT,
|
|
},
|
|
raise_for_status=True,
|
|
) as session:
|
|
async with session.request("GET", url) as response:
|
|
return await response.text()
|
|
|
|
async def get_channels(self) -> list[str]:
|
|
return CHANNEL_LIST
|
|
|
|
@cached(ttl=CACHE_TTL)
|
|
async def get_channel_schedule(
|
|
self, channel_id: str, date: datetime.date
|
|
) -> Schedule:
|
|
endpoint = f"channel/{channel_id}/tvguide?date={date:%d-%m-%Y}"
|
|
data = await self._request(endpoint)
|
|
soup = BeautifulSoup(data, features="html.parser")
|
|
values = []
|
|
channel_name = soup.select_one(".caption__heading").text.split("|")[0].strip()
|
|
current_day = datetime.datetime.combine(
|
|
date.today(), datetime.datetime.min.time()
|
|
)
|
|
end = current_day + datetime.timedelta(days=1, hours=6)
|
|
prev_value: ScheduleValue | None = None
|
|
for item in soup.select(".teleprogram-schedule .teleprogram-schedule__item"):
|
|
title = item.select_one(".teleprogram-item__title").text.strip()
|
|
time_str = item.select_one(".teleprogram-item__time").text.strip()
|
|
hours, minutes = map(int, time_str.split(":"))
|
|
item_date = current_day.replace(hour=hours, minute=minutes)
|
|
if prev_value is not None and item_date.hour < prev_value.start.hour:
|
|
current_day += datetime.timedelta(days=1)
|
|
item_date += datetime.timedelta(days=1)
|
|
live = "Прямая трансляция" in title
|
|
value = ScheduleValue(start=item_date, end=end, label=title, live=live)
|
|
values.append(value)
|
|
if prev_value is not None:
|
|
prev_value.end = item_date
|
|
prev_value = value
|
|
return Schedule(
|
|
channel=Channel(id=channel_id, name=channel_name), date=date, values=values
|
|
)
|