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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user