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:
@@ -144,7 +144,13 @@ async fn run() -> Result<(), Error> {
|
||||
if let Some(tmdb_url) = config.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())
|
||||
.merge(arr_compat::router(compat))
|
||||
@@ -443,3 +449,42 @@ async fn shutdown() {
|
||||
|
||||
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