import hashlib from datetime import datetime, timedelta from typing import Optional, Tuple from playwright.async_api import async_playwright, ViewportSize, FloatRect import logging logger = logging.getLogger(__name__) class ScheduleService: def __init__(self): self.base_url = "https://college.by/accounts/raspis/{mouth:02d}/{day:02d}-PODNAM.htm" def _make_url(self, day: int = 0) -> Tuple[str, int, int]: """Генерация URL для расписания""" d = datetime.now() if day == 0: if d.hour >= 12: d += timedelta(days=1) if d.weekday() == 6: d += timedelta(days=1) return self.base_url.format(day=d.day, mouth=d.month), d.day, d.month else: return self.base_url.format(day=int(day), mouth=d.month), int(day), int(d.month) async def get_schedule(self, group: str, day_offset: int = 0) -> Tuple[Optional[bytes], str, int, int]: """Получение скриншота расписания""" url, day, month = self._make_url(day_offset) async with async_playwright() as p: browser = await p.chromium.launch(headless=True) context = await browser.new_context(viewport=ViewportSize(width=400, height=3000)) page = await context.new_page() try: response = await page.goto(url, wait_until="networkidle", timeout=30000) if not response or response.status != 200: logger.warning(f"Ошибка загрузки страницы: {url}") return None, url, day, month locator = page.locator("p", has_text=group).first if await locator.count() > 0: await locator.scroll_into_view_if_needed() box = await locator.bounding_box() if box: clip_rect = FloatRect( x=float(max(box["x"] - 0, 0)), y=float(max(box["y"] - 0, 0)), width=float(box["width"] + 150), height=float(box["height"] + 100) ) return await page.screenshot(clip=clip_rect), url, day, month except Exception as e: logger.error(f"Ошибка при получении расписания: {e}") finally: await context.close() await browser.close() return None, url, day, month