feat(arr): offer subtitle providers to the API
Provider credentials are bootstrap config and never reach the database (DESIGN.md §10), so which providers exist is settled once at startup; which of them a search runs is the `providers_enabled` row the API reads per request. OpenSubtitles.com cannot be called without a registered API key, so without one it is not offered at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Generated
+1
@@ -94,6 +94,7 @@ dependencies = [
|
|||||||
"arr-meta",
|
"arr-meta",
|
||||||
"arr-parse",
|
"arr-parse",
|
||||||
"arr-probe",
|
"arr-probe",
|
||||||
|
"arr-subs",
|
||||||
"axum",
|
"axum",
|
||||||
"base64",
|
"base64",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ arr-indexer = { workspace = true }
|
|||||||
arr-meta = { workspace = true }
|
arr-meta = { workspace = true }
|
||||||
arr-parse = { workspace = true }
|
arr-parse = { workspace = true }
|
||||||
arr-probe = { workspace = true }
|
arr-probe = { workspace = true }
|
||||||
|
arr-subs = { workspace = true }
|
||||||
axum = { workspace = true }
|
axum = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
include_dir = { workspace = true }
|
include_dir = { workspace = true }
|
||||||
|
|||||||
@@ -144,7 +144,13 @@ async fn run() -> Result<(), Error> {
|
|||||||
if let Some(tmdb_url) = config.tmdb_url {
|
if let Some(tmdb_url) = config.tmdb_url {
|
||||||
upstreams = upstreams.with_tmdb_url(tmdb_url);
|
upstreams = upstreams.with_tmdb_url(tmdb_url);
|
||||||
}
|
}
|
||||||
let state = AppState::new(upstreams)?.with_database(database.clone());
|
let state = AppState::new(upstreams)?
|
||||||
|
.with_database(database.clone())
|
||||||
|
.with_subtitle_providers(subtitle_providers(
|
||||||
|
config.opensubtitles_api_key,
|
||||||
|
config.opensubtitles_username,
|
||||||
|
config.opensubtitles_password,
|
||||||
|
));
|
||||||
|
|
||||||
let app = arr_api::router(state.clone())
|
let app = arr_api::router(state.clone())
|
||||||
.merge(arr_compat::router(compat))
|
.merge(arr_compat::router(compat))
|
||||||
@@ -443,3 +449,42 @@ async fn shutdown() {
|
|||||||
|
|
||||||
tracing::info!("shutting down");
|
tracing::info!("shutting down");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The subtitle providers this deployment can reach (DESIGN.md §15).
|
||||||
|
///
|
||||||
|
/// Credentials are bootstrap config and never reach the database (§10), so
|
||||||
|
/// which providers *exist* is decided here, once, at startup; which of them a
|
||||||
|
/// search *runs* is the `providers_enabled` setting the API reads per
|
||||||
|
/// request. OpenSubtitles.com needs a registered API key to be called at all,
|
||||||
|
/// so without one it is not offered; Podnapisi is anonymous and always is.
|
||||||
|
///
|
||||||
|
/// Translation backends are not wired: none is implemented yet (#191-#193),
|
||||||
|
/// and `AppState` defaults to an empty registry, which makes a manual
|
||||||
|
/// translation answer "no such engine" rather than fail obscurely.
|
||||||
|
fn subtitle_providers(
|
||||||
|
opensubtitles_api_key: Option<String>,
|
||||||
|
username: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
|
) -> Vec<std::sync::Arc<dyn arr_subs::Provider>> {
|
||||||
|
let mut providers: Vec<std::sync::Arc<dyn arr_subs::Provider>> = Vec::new();
|
||||||
|
|
||||||
|
match arr_subs::Podnapisi::new() {
|
||||||
|
Ok(podnapisi) => providers.push(std::sync::Arc::new(podnapisi)),
|
||||||
|
Err(error) => tracing::warn!(%error, "Podnapisi not available"),
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(api_key) = opensubtitles_api_key else {
|
||||||
|
tracing::info!("no OpenSubtitles.com API key configured; that provider is off");
|
||||||
|
return providers;
|
||||||
|
};
|
||||||
|
match arr_subs::OpenSubtitles::new(arr_subs::OpenSubtitlesConfig {
|
||||||
|
api_key,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
}) {
|
||||||
|
Ok(opensubtitles) => providers.push(std::sync::Arc::new(opensubtitles)),
|
||||||
|
Err(error) => tracing::warn!(%error, "OpenSubtitles.com not available"),
|
||||||
|
}
|
||||||
|
|
||||||
|
providers
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user