Add edit dialogs, library organizer, and TMDb pool migration

This commit is contained in:
2026-09-08 07:37:40 +02:00
parent 39712d7283
commit 79c9e34a5d
10 changed files with 1371 additions and 110 deletions
+24 -6
View File
@@ -76,9 +76,27 @@ def season_folder_name(season: int) -> str:
return "Specials" if season == 0 else f"Season {season:02d}"
def episode_filename(series_title: str, season: int, episode: int, ext: str) -> str:
"""Canonical episode filename ``Series SxxEyy.ext``."""
return f"{series_title} S{season:02d}E{episode:02d}{ext}"
def episode_body(stem: str) -> str:
"""The descriptive part of an episode filename, minus a leading ``SxxEyy`` code.
Keeps the original (release) filename so it survives into the canonical name,
while stripping an already-applied ``SxxEyy - `` prefix so repeated renames
don't double it. Returns ``""`` when the stem was only the code.
"""
s = _EPISODE_RE.sub("", stem, count=1) # drop the SxxEyy/NxNN token
s = re.sub(r"([\s._-])[\s._-]+", r"\1", s) # collapse separator runs
return s.strip(" ._-")
def episode_filename(season: int, episode: int, orig_stem: str, ext: str) -> str:
"""Canonical episode filename ``SxxEyy - {original name}.ext``.
Keeps the original filename after the code; when the original was only the
code (nothing descriptive left) it collapses to ``SxxEyy.ext``.
"""
code = f"S{season:02d}E{episode:02d}"
body = episode_body(orig_stem)
return f"{code} - {body}{ext}" if body else f"{code}{ext}"
def series_folder_stem(title: str, year: object = None, tmdb_id: object = None) -> str:
@@ -97,13 +115,13 @@ def series_folder_stem(title: str, year: object = None, tmdb_id: object = None)
return f"{title} [tmdbid-{id_s}]" if id_s.isdigit() else title
def is_canonical_episode(path: Path, series_title: str) -> bool:
"""True when ``path`` already follows ``Series SxxEyy`` in the right season."""
def is_canonical_episode(path: Path) -> bool:
"""True when ``path`` already follows ``SxxEyy - name`` in the right season."""
parsed = parse_episode(path.name)
if parsed is None:
return False
season, episode = parsed
expected = episode_filename(series_title, season, episode, path.suffix)
expected = episode_filename(season, episode, path.stem, path.suffix)
if path.name != expected:
return False
return path.parent.name == season_folder_name(season)