Add year support to anime folder names

- Add year property to Serie entity with name_with_year
- Add year column to AnimeSeries database model
- Add get_year() method to AniworldLoader provider
- Extract year from folder names before fetching from API
- Update SerieScanner to populate year during rescan
- Update add_series endpoint to fetch and store year
- Optimize: check folder name for year before API call
This commit is contained in:
2026-01-11 19:47:47 +01:00
parent ccbd9768a2
commit 40ffb99c97
7 changed files with 241 additions and 28 deletions

View File

@@ -117,6 +117,44 @@ class SerieScanner:
if handler in self.events.on_progress:
self.events.on_progress.remove(handler)
def _extract_year_from_folder_name(self, folder_name: str) -> int | None:
"""Extract year from folder name if present.
Looks for year in format "(YYYY)" at the end of folder name.
Args:
folder_name: The folder name to check
Returns:
int or None: Year if found, None otherwise
Example:
>>> _extract_year_from_folder_name("Dororo (2025)")
2025
>>> _extract_year_from_folder_name("Dororo")
None
"""
if not folder_name:
return None
# Look for year in format (YYYY) - typically at end of name
match = re.search(r'\((\d{4})\)', folder_name)
if match:
try:
year = int(match.group(1))
# Validate year is reasonable (between 1900 and 2100)
if 1900 <= year <= 2100:
logger.debug(
"Extracted year from folder name: %s -> %d",
folder_name,
year
)
return year
except ValueError:
pass
return None
def subscribe_on_error(self, handler):
"""
Subscribe a handler to an event.
@@ -235,6 +273,33 @@ class SerieScanner:
and serie.key
and serie.key.strip()
):
# Try to extract year from folder name first
if not hasattr(serie, 'year') or not serie.year:
year_from_folder = self._extract_year_from_folder_name(folder)
if year_from_folder:
serie.year = year_from_folder
logger.info(
"Using year from folder name: %s (year=%d)",
folder,
year_from_folder
)
else:
# If not in folder name, fetch from provider
try:
serie.year = self.loader.get_year(serie.key)
if serie.year:
logger.info(
"Fetched year from provider: %s (year=%d)",
serie.key,
serie.year
)
except Exception as e:
logger.warning(
"Could not fetch year for %s: %s",
serie.key,
str(e)
)
# Delegate the provider to compare local files with
# remote metadata, yielding missing episodes per
# season. Results are saved back to disk so that both
@@ -611,19 +676,46 @@ class SerieScanner:
sum(len(eps) for eps in missing_episodes.values())
)
else:
# Try to extract year from folder name first
year = self._extract_year_from_folder_name(folder)
if year:
logger.info(
"Using year from folder name: %s (year=%d)",
folder,
year
)
else:
# If not in folder name, fetch from provider
try:
year = self.loader.get_year(key)
if year:
logger.info(
"Fetched year from provider: %s (year=%d)",
key,
year
)
except Exception as e:
logger.warning(
"Could not fetch year for %s: %s",
key,
str(e)
)
# Create new serie entry
serie = Serie(
key=key,
name="", # Will be populated by caller if needed
site=site,
folder=folder,
episodeDict=missing_episodes
episodeDict=missing_episodes,
year=year
)
self.keyDict[key] = serie
logger.debug(
"Created new series entry for %s with %d missing episodes",
"Created new series entry for %s with %d missing episodes (year=%s)",
key,
sum(len(eps) for eps in missing_episodes.values())
sum(len(eps) for eps in missing_episodes.values()),
year
)
# Notify completion