Nouvelle version réécrite de zéro : recherche multi-sources (Vostfree, French-Manga), extraction 2 niveaux, proxy vidéo intégré, streaming/téléchargement HLS, métadonnées Kitsu, bibliothèque locale, comptes JWT + administration, découverte fusionnée, indexeur Torznab (Sonarr/Prowlarr).
51 lines
2.1 KiB
Python
51 lines
2.1 KiB
Python
"""Extracteur Luluvid/Luluvdo (luluvdo.com, luluvid.com, lulustream.com) — embed → m3u8.
|
|
|
|
Famille StreamSB : la page embed configure jwplayer dans du JS packé
|
|
(p,a,c,k,e,d) avec `sources:[{file:"https://.../master.m3u8?t=<token>"}]`.
|
|
Le token CDN (tnmr.org…) est lié à l'IP **et à l'User-Agent** de la requête
|
|
d'embed : la VideoLink doit donc renvoyer le User-Agent du socle pour que le
|
|
téléchargement passe — sans lui, le CDN répond 403.
|
|
"""
|
|
|
|
import logging
|
|
import re
|
|
from urllib.parse import urlparse
|
|
|
|
from app.config import get_settings
|
|
from app.scrapers.base import HosterExtractor, ScrapeError, VideoLink, register_hoster
|
|
from app.scrapers.hosters._packer import unpack_packed_js
|
|
from app.scrapers.http import fetch
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_PATTERNS = (
|
|
re.compile(r'sources\s*:\s*\[\s*\{[^}]*?file\s*:\s*["\'](?P<url>[^"\']+\.m3u8[^"\']*)["\']'),
|
|
re.compile(r'file\s*:\s*["\'](?P<url>https?://[^"\']+?\.m3u8[^"\']*)["\']'),
|
|
re.compile(r'["\'](?P<url>https?://[^"\']*?\.m3u8(?:\?[^"\']*)?)["\']'),
|
|
)
|
|
|
|
|
|
@register_hoster
|
|
class LuluvdoExtractor(HosterExtractor):
|
|
name = "luluvdo"
|
|
domains = ("luluvdo.com", "luluvid.com", "lulustream.com")
|
|
|
|
async def extract(self, embed_url: str) -> VideoLink:
|
|
html = await fetch(embed_url)
|
|
for content in (html, unpack_packed_js(html) or ""):
|
|
for pattern in _PATTERNS:
|
|
for match in pattern.finditer(content):
|
|
url = match.group("url")
|
|
if url.startswith("http"):
|
|
return VideoLink(
|
|
url=url,
|
|
hoster=self.name,
|
|
headers={
|
|
"Referer": f"https://{urlparse(embed_url).hostname}/",
|
|
"User-Agent": get_settings().user_agent,
|
|
"Accept-Language": "fr-FR,fr;q=0.9,en;q=0.8",
|
|
},
|
|
is_hls=".m3u8" in url,
|
|
)
|
|
raise ScrapeError(f"luluvdo : URL vidéo introuvable dans {embed_url}")
|