# `src/core/migrate.py` One-off migration of an existing pool to the Jellyfin naming convention. Older pools carry files like `Title.ext` / `Title (rok).ext` with **no TMDb id**. This matches each such movie against TMDb by title + year and proposes a `tmdbid` (and the missing year, which TMDb supplies), so the file can be renamed to `Title (rok) [tmdbid].ext` and Jellyfin can match it deterministically. The classification is deliberately **conservative**: only an exact (diacritics-insensitive) title match with a matching year and a single candidate is `auto`; everything else is `ambiguous` for the user to confirm. Source: [`src/core/migrate.py`](../../src/core/migrate.py) ## Classes ### `MatchProposal` *class · line 19* ```python class MatchProposal: ``` One movie's proposed TMDb match. ## Functions ### `normalize` *function · line 33* ```python normalize(text: str) -> str ``` Fold a title for comparison: strip diacritics/punctuation, lowercase. ### `_year_close` *function · line 41* ```python _year_close(a: Optional[str], b: Optional[str]) -> bool ``` True when two year strings are both numeric and differ by at most one year (release years often disagree by one). ### `classify` *function · line 47* ```python classify(title: str, year: Optional[str], candidates: list) -> tuple[str, object] ``` Return `(status, chosen)` for a title/year against TMDb candidates. `auto` requires an exact normalized-title match, a year within ±1, and that exactly one candidate qualifies. Otherwise `ambiguous` (top hit preselected) or `no_match` when there are no candidates.