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:
@@ -38,7 +38,7 @@ class Episode:
|
||||
title: str | None
|
||||
url: str # page de l'épisode chez la source
|
||||
season: int = 1
|
||||
|
||||
version: str | None = None # langue ("vf" / "vostfr") quand la source la distingue
|
||||
|
||||
@dataclass
|
||||
class TitleDetails:
|
||||
|
||||
@@ -259,29 +259,28 @@ class FrenchMangaScraper(SourceScraper):
|
||||
if season_match:
|
||||
season = int(season_match.group(1))
|
||||
|
||||
numbers: set[float] = set()
|
||||
info = data.get("info") or {}
|
||||
episodes: list[Episode] = []
|
||||
for version in versions:
|
||||
numbers: set[float] = set()
|
||||
for number_text in data.get(version) or {}:
|
||||
try:
|
||||
numbers.add(float(number_text))
|
||||
except ValueError:
|
||||
logger.warning("french_manga : numéro d'épisode invalide %r", number_text)
|
||||
|
||||
info = data.get("info") or {}
|
||||
episodes: list[Episode] = []
|
||||
for number in sorted(numbers):
|
||||
number_text = str(int(number)) if number.is_integer() else str(number)
|
||||
episode_info = info.get(number_text) or info.get(str(int(number)))
|
||||
label = episode_info.get("title") if isinstance(episode_info, dict) else None
|
||||
version = next((v for v in versions if number_text in (data.get(v) or {})), versions[0])
|
||||
episodes.append(
|
||||
Episode(
|
||||
number=number,
|
||||
title=label,
|
||||
url=f"{page_url}#{config['episodes']['fragment_prefix']}={version}-{number_text}",
|
||||
season=season,
|
||||
for number in sorted(numbers):
|
||||
number_text = str(int(number)) if number.is_integer() else str(number)
|
||||
episode_info = info.get(number_text) or info.get(str(int(number)))
|
||||
label = episode_info.get("title") if isinstance(episode_info, dict) else None
|
||||
episodes.append(
|
||||
Episode(
|
||||
number=number,
|
||||
title=label,
|
||||
url=f"{page_url}#{config['episodes']['fragment_prefix']}={version}-{number_text}",
|
||||
season=season,
|
||||
version=version,
|
||||
)
|
||||
)
|
||||
)
|
||||
if not episodes:
|
||||
raise ScrapeError(f"french_manga : aucun épisode trouvé pour {source_id}")
|
||||
return episodes
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user