Choix de la langue VF/VOSTFR sur la fiche titre

- Episode : nouveau champ version (vf/vostfr)
- French-Manga : épisodes listés pour chaque langue disponible
  (VOSTFR puis VF) au lieu d'un choix automatique, fragment
  #ep=<version>-<num> déjà résolu par extract_embed_links
- Vostfree : langue déduite du titre h1 ou du slug de la fiche
- UI : filtre VOSTFR/VF/Tout (défaut VOSTFR), badge par épisode,
  téléchargement de saison limité à la langue filtrée, compteur
  d'épisodes unique, version incluse dans le nom de fichier
This commit is contained in:
Roman
2026-09-22 11:58:10 +00:00
parent 9148b5fb6a
commit affc97c527
5 changed files with 92 additions and 23 deletions
+12
View File
@@ -85,6 +85,7 @@ _SLUG_RE = re.compile(r"([^/]+)\.html?$")
_NUMBER_RE = re.compile(r"(\d+(?:[.,]\d+)?)")
_SEASON_RE = re.compile(r"Saison\s*:?\s*(\d+)", re.IGNORECASE)
_SAFE_FRAGMENT_RE = re.compile(r"^[A-Za-z0-9_-]+$")
_VERSION_RE = re.compile(r"\b(vostfr|vf)\b", re.IGNORECASE)
def _merged_config() -> dict:
@@ -246,8 +247,18 @@ class VostfreeScraper(SourceScraper):
return int(season_match.group(1))
return 1
def _detect_version(self, soup: BeautifulSoup, page_url: str) -> str | None:
config = _merged_config()
title_el = soup.select_one(config["details"]["title"])
for text in (self._text(title_el), page_url):
match = _VERSION_RE.search(text)
if match:
return match.group(1).lower()
return None
def _parse_episodes(self, soup: BeautifulSoup, page_url: str, season: int) -> list[Episode]:
config = _merged_config()
version = self._detect_version(soup, page_url)
options = soup.select(config["episodes"]["option"])
entries: list[tuple[str, str]] = []
seen_ids: set[str] = set()
@@ -274,6 +285,7 @@ class VostfreeScraper(SourceScraper):
title=label or f"Episode {index}",
url=f"{page_url}#{button_id}" if button_id else page_url,
season=season,
version=version,
)
)
return episodes