Add OpenSubtitles subtitle search + download (new Subtitles panel)

New web client (crates/aurora-curator-core/src/web/opensubtitles.rs, 9 tests):
search, login, download, and fetch-subtitle-text against OpenSubtitles' REST
API. Search only needs a free app-level API key; download additionally needs
the end user's own OpenSubtitles account login (username/password -> JWT),
since downloads are quota-limited per account. Settings gained three new
fields (opensubtitles_api_key/username/password) following the existing
TMDB/OMDb credential pattern, with one deliberate exception: the password is
never returned to the frontend, only whether one is saved
(has_opensubtitles_password), since it's a real account password rather than
an API token.

New src-tauri/src/subtitles.rs wraps search/download as Tauri commands and
writes a downloaded subtitle right next to its video file
(Show.S01E01.mkv -> Show.S01E01.en.srt).

New src/components/SubtitlesPanel.tsx is the first real screen behind a
sidebar entry besides Rename (previously a stub) - load a video, auto-fill
the search form from the same local guess_episode/guess_movie Match uses,
search, and download with live remaining/allowed quota shown per result.

TheTVDB was considered instead but deliberately skipped for now: its v4 API
requires either a paid commercial license or a per-end-user paid TheTVDB
subscription just to log in, unlike every other source in this app.

144 tests passing (workspace). Updated README (status paragraph, project
layout, new "Subtitles" section, roadmap items 5/6/7).
This commit is contained in:
Renamr Scaffold
2026-08-29 14:08:17 +00:00
parent c158befa83
commit b47d28375b
10 changed files with 1550 additions and 25 deletions
+85 -19
View File
@@ -38,7 +38,11 @@ presets, recalled with a click or a `1`-`9` keypress (persisted locally, same pa
Settings/History). The app can also be driven entirely from the command line —
`aurora-curator -rename --format "<naming scheme>" [options] <file-or-folder>...` — for
scripting batch renames without opening the window at all; see "Command-line usage"
below. See "Porting roadmap" below.
below. A new Subtitles panel searches and downloads subtitle files from
[OpenSubtitles](https://www.opensubtitles.com/) — load a video, its title/season/episode
(or movie title/year) auto-fills from the same local matching "Match" uses, pick a
result, and the subtitle is saved right next to the video ready for any player to pick
up automatically; see "Subtitles" below. See "Porting roadmap" below.
The naming scheme is fully user-editable from the app (the "Naming Scheme" button next
to the New Names list) — the default is `{show name} - {season number}x{episode
@@ -144,7 +148,12 @@ crates/aurora-curator-core/ Pure Rust core: naming-expression engine (ported),
`apikey` query-param auth rather than TMDB's Bearer token) — all
three disambiguated via
`similarity/` and tested against a mocked HTTP server via
`mockito`, the on-disk
`mockito`, plus a fourth web client that isn't a metadata
lookup at all — `web/opensubtitles.rs` (search + login +
download against OpenSubtitles' REST API; search only needs an
app-level API key, download additionally needs the end user's own
account login, since downloads are quota-limited per account —
see "Subtitles" below), the on-disk
rename engine (`rename/` — Move/Copy/Symlink actions,
Skip/Auto-number/Override conflict policies, can also organize
into (auto-created) subfolders when
@@ -154,7 +163,7 @@ crates/aurora-curator-core/ Pure Rust core: naming-expression engine (ported),
argument parsing/file expansion (`cli/` — no Tauri or network
dependency at all, see "Command-line usage" below). Not yet
ported: full media metadata bindings, other web datasource
clients (TheTVDB/AniDB/OpenSubtitles/etc). No Tauri dependency, so
clients (TheTVDB/AniDB/etc). No Tauri dependency, so
it builds and unit-tests standalone.
src-tauri/ Tauri app shell: exposes aurora-curator-core as commands to the frontend
(naming-scheme rendering, filename matching for both TV and
@@ -164,8 +173,14 @@ src-tauri/ Tauri app shell: exposes aurora-curator-core as commands
is the stored movie source — independent of the TV source)
— executing a rename
plan, native file/folder dialogs, drag-and-drop expansion), plus
`settings.rs` (TMDB token, OMDb API key, and which TV *and* movie
metadata source Fetch Data uses — two independent settings),
`settings.rs` (TMDB token, OMDb API key, OpenSubtitles API key +
account login, and which TV *and* movie
metadata source Fetch Data uses — independent settings; the
OpenSubtitles password is the one credential this module never
returns to the frontend, only whether one is saved),
`subtitles.rs` (search/download commands wrapping
`aurora-curator-core::web::opensubtitles`, saving a downloaded
subtitle right next to its video file),
`history.rs` (rename history/undo
log), `presets.rs` (up to 9 saved naming schemes) — all three
stored as JSON in the OS app-config directory — `cli.rs` (the
@@ -184,7 +199,10 @@ src/ React + TypeScript UI (Vite). Faithful recreation of the
confirm-before-touching-disk modal for the actual
rename, a History panel that can undo a past rename, Align Up/Down
list reordering, and a Presets panel (plus `1`-`9` hotkeys) for
saved naming schemes.
saved naming schemes. `SubtitlesPanel.tsx` is a separate top-level
panel (its own Subtitle Settings modal, its own credential state)
reached from the sidebar's "Subtitles" entry — the first sidebar
entry besides Rename to be a real screen rather than a stub.
scripts/gen_icons.py Regenerates src-tauri/icons/ from the real logo mark
(`scripts/logo/icon-source.png`, cropped from the supplied
lockup) — replace that source image to change the look.
@@ -209,9 +227,10 @@ npm run tauri dev
npm run tauri build
```
Verified in the environment this was built in: `cargo test --workspace` (all 128
passing, including the TMDB, TVmaze, and OMDb client tests — those run against a local
mock HTTP server via `mockito`, no live network or API key needed to build/test), `cargo
Verified in the environment this was built in: `cargo test --workspace` (all 144
passing, including the TMDB, TVmaze, OMDb, and OpenSubtitles client tests — those run
against a local mock HTTP server via `mockito`, no live network or API key needed to
build/test), `cargo
check -p aurora-curator` (compiles clean against real Tauri + GTK/WebKit system
libraries), and `npm run build` (TypeScript type-checks, Vite bundles). The actual GUI
window has **not** been visually verified anywhere yet — that sandbox has no display.
@@ -296,6 +315,44 @@ tree (see "Organizing into subfolders" above) — a naming scheme's own `/` alre
organizing into a subfolder, and relaxing that invariant just for `--output` wasn't
judged worth it.
## Subtitles
The Subtitles sidebar panel searches and downloads subtitle files from
[OpenSubtitles](https://www.opensubtitles.com/) — the first thing in Aurora Curator that
fetches an actual media file (a subtitle) rather than title/air-date text.
**Load Video File…** picks one video, then reuses the exact same local filename-based
matching "Match" uses (`guess_episode`/`guess_movie`) to pre-fill the search form with a
show title + season/episode, or a movie title + year — all editable before searching,
and usable on their own with no video loaded at all if you'd rather just type a title.
Results show the release name, language, an **HD** badge, a **Hash match** badge when
OpenSubtitles matched the file by an exact content hash rather than a text search (a
much stronger signal than a title match alone), an **HI** badge for hearing-impaired
tracks, the uploader, and the download count. Downloading saves the file right next to
the video with the language code inserted before the extension (`Show.S01E01.mkv` →
`Show.S01E01.en.srt`) — the convention most media players look for automatically, so
there's nothing further to configure.
OpenSubtitles splits credentials in a way no other source in this app does:
- **Searching** only needs a free **API key** — register an account at
[opensubtitles.com](https://www.opensubtitles.com/) and create one under Account → API
Consumers, then paste it into Subtitle Settings.
- **Downloading** additionally needs your own OpenSubtitles account **username and
password**, entered in the same Settings panel — OpenSubtitles logs you in to check a
daily download quota tied to your account (shown after every successful download as
"N/M downloads left today"; the exact number depends on your account's standing with
OpenSubtitles and can change on their end, so Aurora Curator always shows the live
figure it gets back rather than a hardcoded promise). Search works with no login at
all, so you can browse what's available before deciding whether to save a password.
Like every other credential in this app, both are stored locally in the OS app-config
directory and only ever sent to `api.opensubtitles.com` — with one extra precaution
specific to a real account password: Aurora Curator never sends the saved password back
to its own interface once it's saved (every other credential's "already saved" check
does briefly see the real value; the password doesn't), and the Settings panel only ever
shows *whether* a password is on file, never the value itself.
## Porting roadmap (not yet done)
Roughly in priority order — each references the original FileBot source file it's
@@ -354,8 +411,15 @@ ported from, for anyone picking this up:
items resolve against respectively (TMDB stays the default for both; a batch can mix
sources across its TV and movie halves) — disambiguating multi-result searches via
the similarity-scoring pass described in item 3 above rather than blindly trusting
any source's top-ranked hit. All other sources (TheTVDB, AniDB, OpenSubtitles) are not
yet started.
any source's top-ranked hit. **OpenSubtitles is also done, but as a subtitle source
rather than a fourth title-metadata source** — `crates/aurora-curator-core/src/web/opensubtitles.rs`,
wired to the new Subtitles panel (see "Subtitles" above) rather than to Fetch Data's
TV/movie pickers, since it fetches subtitle files, not episode/movie titles. All
other sources (TheTVDB, AniDB) are not yet started — **TheTVDB was deliberately
skipped**: as of this writing its v4 API requires either a paid commercial license or
the "user-supported" model, where every end user needs their own paid TheTVDB
subscription (~$12/year) just to get the PIN its login flow requires, unlike the
three free-to-use sources above — worth revisiting if that changes.
6. **Rename engine + CLI** — `net.filebot.cli.CmdlineOperations` (1235 lines) and
`ArgumentBean` (415 lines, the full flag surface: `-rename`, `--db`, `--format`,
`--action`, `--conflict`, `-get-subtitles`, `-script`, etc.). The rename operation is
@@ -378,16 +442,18 @@ ported from, for anyone picking this up:
`-non-strict`/`-h` (`crates/aurora-curator-core/src/cli` for pure argument parsing and
directory expansion, `src-tauri/src/cli.rs` for the orchestration — local matching,
optional TMDB/TVmaze/OMDb lookup, and the actual rename, all without ever constructing a
Tauri `App`); see "Command-line usage" above. `--output <dir>` and `-get-subtitles`/
`-script`/the rest of FileBot's non-rename CLI modes are not ported — `-get-
subtitles` and `-script` have no analog yet since subtitle-fetching and a script-mode
runtime aren't built at all.
Tauri `App`); see "Command-line usage" above. `--output <dir>` and `-script`/the rest
of FileBot's non-rename CLI modes are not ported. `-get-subtitles` has no CLI analog
yet — subtitle fetching (see "Subtitles" above) is GUI-only so far, reached from its
own sidebar panel rather than a command-line flag.
7. **The rest of the UI** — the Rename panel (file loading, drag-drop, live preview,
local TV/movie matching, confirmed rename with per-item exclude, rename history/undo,
Align Up/Down reordering, naming-scheme Presets with `1`-`9` hotkeys) is built; the
other five sidebar panels (Episodes/Subtitles/SFV/Filter/List) are still stub
screens. Align Up/Down is button-based (swaps the selected file with its neighbor),
not the original's drag-and-drop-within-a-list interaction.
Align Up/Down reordering, naming-scheme Presets with `1`-`9` hotkeys) is built, and so
is the Subtitles panel (search + download via OpenSubtitles, see "Subtitles" above) —
the first of the other five sidebar panels to become a real screen. The remaining
four (Episodes/SFV/Filter/List) are still stub screens. Align Up/Down is button-based
(swaps the selected file with its neighbor), not the original's
drag-and-drop-within-a-list interaction.
8. **Undo/history for renames** — done, as a flat JSON-backed undo stack rather than a
full port of `net.filebot.HistoryDialog`'s session/element log
(`crates/aurora-curator-core/src/history`, `src-tauri/src/history.rs`). Every successful