Add movie support to Fetch Data: local title/year guessing plus TMDB movie lookup

- renamr-core::matching: guess_movie() extracts a movie title (and release year, if
  present) from a filename using the same year/quality-token boundary heuristics real
  release names follow, as a fallback when guess_episode() finds no season/episode
  marker.
- renamr-core::web::tmdb: search_movie()/lookup_movie() mirror the TV client, reusing
  the same Sorensen-Dice title-disambiguation as lookup_episode(), narrowed further by
  TMDB's own primary_release_year filter when a year was locally guessed. Also exposed
  search_tv_best_match() and fixed a latent gap where the real Fetch Data command path
  (metadata.rs::fetch_season) bypassed the fuzzy show-name disambiguation entirely,
  doing its own raw first-result selection instead of reusing it.
- src-tauri: new guess_movie command and fetch_movie_metadata command/types
  (MovieFetchQuery/Outcome/Result), registered alongside the existing TV commands.
- Frontend: Item now tracks mediaKind ("tv"/"movie"/null); Match tries guess_episode
  then falls back to guess_movie; Fetch Data resolves TV and movie targets via their
  own commands concurrently and merges results. A single batch can mix TV and movie
  files - each only fills in the fields that apply to it. Movie fields ({movie name},
  {year}, reusing {airdate} for release date, matching FileBot's own unified binding)
  are documented in the naming-scheme field reference.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Renamr Scaffold
2026-08-29 04:04:16 +00:00
co-authored by Claude Sonnet 5
parent 93b5ac5e56
commit 45a9f5d523
6 changed files with 616 additions and 127 deletions
+12 -1
View File
@@ -4,7 +4,7 @@ mod metadata;
mod settings;
use renamr_core::format::ExpressionFormat;
use renamr_core::matching::{self, EpisodeGuess};
use renamr_core::matching::{self, EpisodeGuess, MovieGuess};
use renamr_core::rename::{self, RenamePlanItem, RenameResult};
use renamr_core::string_bindings;
use std::collections::HashMap;
@@ -30,6 +30,15 @@ fn guess_episode(filename: String) -> Option<EpisodeGuess> {
matching::guess_episode(&filename)
}
/// Guesses a movie title (and release year, if present) from a filename using local
/// regex/heuristic patterns only - no network calls. Callers should try
/// `guess_episode` first and only fall back to this when it returns `None`; see
/// `matching::guess_movie` for why.
#[tauri::command]
fn guess_movie(filename: String) -> Option<MovieGuess> {
matching::guess_movie(&filename)
}
/// Executes a batch of planned on-disk renames (optionally moving files into
/// subfolders - see `renamr_core::rename`; conflicting targets are always skipped,
/// never overwritten). The UI is expected to have already shown the user the full
@@ -54,8 +63,10 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![
render_expression,
guess_episode,
guess_movie,
execute_rename,
metadata::fetch_metadata,
metadata::fetch_movie_metadata,
settings::get_tmdb_token,
settings::save_tmdb_token,
history::list_rename_history,