diff --git a/M3U8/scrapers/strmd.py b/M3U8/scrapers/strmd.py index 1f94fab..2e67b97 100644 --- a/M3U8/scrapers/strmd.py +++ b/M3U8/scrapers/strmd.py @@ -1,3 +1,4 @@ +import asyncio import re from functools import partial from pathlib import Path @@ -5,7 +6,7 @@ from typing import Any from urllib.parse import urljoin import httpx -from playwright.async_api import async_playwright +from playwright.async_api import BrowserContext, async_playwright from .utils import Cache, Time, get_logger, leagues, network @@ -49,6 +50,69 @@ async def refresh_api_cache( return data +async def process_event( + url: str, + url_num: int, + context: BrowserContext, + timeout: int | float = 10, +) -> str | None: + + page = await context.new_page() + + captured: list[str] = [] + + got_one = asyncio.Event() + + handler = partial( + network.capture_req, + captured=captured, + got_one=got_one, + ) + + page.on("request", handler) + + try: + await page.goto( + url, + wait_until="domcontentloaded", + timeout=15_000, + ) + + wait_task = asyncio.create_task(got_one.wait()) + + try: + await page.click(".jw-icon-display") + + await asyncio.wait_for(wait_task, timeout=timeout) + except asyncio.TimeoutError: + log.warning(f"URL {url_num}) Timed out waiting for M3U8.") + return + + finally: + if not wait_task.done(): + wait_task.cancel() + + try: + await wait_task + except asyncio.CancelledError: + pass + + if captured: + log.info(f"URL {url_num}) Captured M3U8") + return captured[0] + + log.warning(f"URL {url_num}) No M3U8 captured after waiting.") + return + + except Exception as e: + log.warning(f"URL {url_num}) Exception while processing: {e}") + return + + finally: + page.remove_listener("request", handler) + await page.close() + + async def get_events( client: httpx.AsyncClient, base_url: str, @@ -154,11 +218,10 @@ async def scrape(client: httpx.AsyncClient) -> None: for i, ev in enumerate(events, start=1): handler = partial( - network.process_event, + process_event, url=ev["link"], url_num=i, context=context, - log=log, ) url = await network.safe_process(