"""Extracteur Sibnet (video.sibnet.ru) — page shell/watch → mp4 direct. La page embed `shell.php?videoid=N` (ou la page publique `/videoN`) contient une config jwplayer du type `player.src([{src: "/v//.mp4"}])`. `shell.php` répond 403 depuis certains réseaux : on retombe alors sur la page publique de la vidéo, qui expose la même config. """ import logging import re from urllib.parse import urljoin from app.scrapers.base import HosterExtractor, ScrapeError, VideoLink, register_hoster from app.scrapers.http import fetch logger = logging.getLogger(__name__) _BASE = "https://video.sibnet.ru" _VIDEO_ID_RE = re.compile(r"(?:videoid=|/video)(\d+)") _MP4_PATTERNS = ( re.compile(r'player\.src\(\[\{src:\s*"(?P/v/[^"]+?\.mp4)"'), re.compile(r'["\'](?P/v/[0-9a-f]{32}/\d+\.mp4)["\']'), re.compile(r'["\'](?Phttps?://[^"\']*?/v/[^"\']+?\.mp4)["\']'), ) @register_hoster class SibnetExtractor(HosterExtractor): name = "sibnet" domains = ("video.sibnet.ru",) async def extract(self, embed_url: str) -> VideoLink: match = _VIDEO_ID_RE.search(embed_url) if not match: raise ScrapeError(f"sibnet : identifiant vidéo introuvable dans {embed_url}") video_id = match.group(1) watch_url = f"{_BASE}/video{video_id}" pages: list[tuple[str, str]] = [] try: pages.append(("embed", await fetch(embed_url, retries=0))) except ScrapeError as exc: logger.info( "sibnet : page embed %s inaccessible (%s), essai page publique", embed_url, exc ) try: pages.append(("watch", await fetch(watch_url, retries=1))) except ScrapeError as exc: logger.error("sibnet : page publique %s inaccessible : %s", watch_url, exc) for source, html in pages: url = self._find_mp4(html, source) if url: return VideoLink( url=url, hoster=self.name, headers={"Referer": watch_url}, is_hls=False, ) raise ScrapeError(f"sibnet : URL mp4 introuvable pour la vidéo {video_id}") def _find_mp4(self, html: str, source: str) -> str | None: for pattern in _MP4_PATTERNS: match = pattern.search(html) if match: url = urljoin(_BASE + "/", match.group("url")) logger.debug("sibnet : mp4 trouvé via %s → %s", source, url) return url return None