feat(api): series, season and episode endpoints (#81)
This commit was merged in pull request #81.
This commit is contained in:
@@ -7,7 +7,7 @@ use std::path::Path;
|
||||
|
||||
pub mod policy;
|
||||
|
||||
pub use policy::{MoviePolicy, PolicyColumns, PolicyError};
|
||||
pub use policy::{MoviePolicy, PolicyColumns, PolicyError, TitlePolicy};
|
||||
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous};
|
||||
use sqlx::{migrate::MigrateError, SqlitePool};
|
||||
|
||||
@@ -27,13 +27,13 @@ pub enum PolicyError {
|
||||
},
|
||||
}
|
||||
|
||||
/// The effective policy for one movie, plus the root it is attached to.
|
||||
/// The effective policy for one title, plus the root it is attached to.
|
||||
///
|
||||
/// The root's `kind` and `audience` are the Transmission label and the
|
||||
/// on-disk layout (§7.1, §7.4), and they only exist together with the policy,
|
||||
/// so they are returned together.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MoviePolicy {
|
||||
pub struct TitlePolicy {
|
||||
pub policy: Policy,
|
||||
/// Per-title relaxations and tightenings of the root policy (§5.1).
|
||||
pub overrides: TitleOverrides,
|
||||
@@ -45,6 +45,9 @@ pub struct MoviePolicy {
|
||||
pub root_path: String,
|
||||
}
|
||||
|
||||
/// What [`Db::movie_policy`] returned before episodes needed the same shape.
|
||||
pub type MoviePolicy = TitlePolicy;
|
||||
|
||||
/// The raw policy columns, as the `policies` table stores them (§5.5, §10).
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PolicyColumns {
|
||||
@@ -139,7 +142,7 @@ impl Db {
|
||||
///
|
||||
/// If the query fails, or a policy column does not hold the JSON its
|
||||
/// migration promises.
|
||||
pub async fn movie_policy(&self, movie_id: i64) -> Result<Option<MoviePolicy>, PolicyError> {
|
||||
pub async fn movie_policy(&self, movie_id: i64) -> Result<Option<TitlePolicy>, PolicyError> {
|
||||
let row = sqlx::query!(
|
||||
r#"
|
||||
SELECT m.overrides AS "overrides!: String",
|
||||
@@ -184,7 +187,82 @@ impl Db {
|
||||
}
|
||||
.to_policy()?;
|
||||
|
||||
Ok(Some(MoviePolicy {
|
||||
Ok(Some(TitlePolicy {
|
||||
policy,
|
||||
overrides: TitleOverrides {
|
||||
only_4k: overrides.only_4k,
|
||||
allow_english_audio: overrides.allow_english_audio,
|
||||
},
|
||||
root_id: row.root_id,
|
||||
root_kind: row.root_kind,
|
||||
root_audience: row.root_audience,
|
||||
root_path: row.root_path,
|
||||
}))
|
||||
}
|
||||
|
||||
/// The policy attached to an episode's series root, with that series'
|
||||
/// overrides.
|
||||
///
|
||||
/// Overrides sit on the series (§5.1): an episode is a leaf carrying
|
||||
/// intent, never its own policy.
|
||||
///
|
||||
/// `None` when the episode does not exist.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the query fails, or a policy column does not hold the JSON its
|
||||
/// migration promises.
|
||||
pub async fn episode_policy(
|
||||
&self,
|
||||
episode_id: i64,
|
||||
) -> Result<Option<TitlePolicy>, PolicyError> {
|
||||
let row = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.overrides AS "overrides!: String",
|
||||
r.id AS "root_id!: i64",
|
||||
r.kind AS "root_kind!: String",
|
||||
r.audience AS "root_audience!: String",
|
||||
r.path AS "root_path!: String",
|
||||
p.id AS "policy_id!: i64",
|
||||
p.name AS "policy_name!: String",
|
||||
p.required_audio AS "required_audio!: String",
|
||||
p.dub_blacklist AS "dub_blacklist!: String",
|
||||
p.hdr_rules AS "hdr_rules!: String",
|
||||
p.size_bands AS "size_bands!: String",
|
||||
p.resolution_pref AS "resolution_pref!: String",
|
||||
p.source_weights AS "source_weights!: String",
|
||||
p.score_weights AS "score_weights!: String"
|
||||
FROM episodes e
|
||||
JOIN seasons se ON se.id = e.season_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
JOIN roots r ON r.id = s.root_id
|
||||
JOIN policies p ON p.id = r.policy_id
|
||||
WHERE e.id = ?
|
||||
"#,
|
||||
episode_id
|
||||
)
|
||||
.fetch_optional(self.pool())
|
||||
.await?;
|
||||
|
||||
let Some(row) = row else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let overrides: OverridesJson = json("overrides", &row.overrides)?;
|
||||
let policy = PolicyColumns {
|
||||
id: row.policy_id,
|
||||
name: row.policy_name,
|
||||
required_audio: row.required_audio,
|
||||
dub_blacklist: row.dub_blacklist,
|
||||
hdr_rules: row.hdr_rules,
|
||||
size_bands: row.size_bands,
|
||||
resolution_pref: row.resolution_pref,
|
||||
source_weights: row.source_weights,
|
||||
score_weights: row.score_weights,
|
||||
}
|
||||
.to_policy()?;
|
||||
|
||||
Ok(Some(TitlePolicy {
|
||||
policy,
|
||||
overrides: TitleOverrides {
|
||||
only_4k: overrides.only_4k,
|
||||
|
||||
Reference in New Issue
Block a user