feat(api): expose vanished flag on episodes
This commit is contained in:
@@ -110,6 +110,10 @@ pub struct Episode {
|
||||
/// §4.1. The only intent in the TV aggregate.
|
||||
pub wanted: bool,
|
||||
pub state: String,
|
||||
/// #122. The episode vanished upstream while a file of its own remained,
|
||||
/// which is why the row still exists. A conflict for the operator to
|
||||
/// resolve; nothing was deleted from disk.
|
||||
pub vanished: bool,
|
||||
pub search_attempts: i64,
|
||||
pub last_searched_at: Option<String>,
|
||||
}
|
||||
@@ -197,6 +201,7 @@ struct EpisodeRow {
|
||||
air_date: Option<String>,
|
||||
wanted: bool,
|
||||
state: String,
|
||||
vanished: bool,
|
||||
search_attempts: i64,
|
||||
last_searched_at: Option<String>,
|
||||
}
|
||||
@@ -345,7 +350,7 @@ async fn tv_by_series(
|
||||
.await?;
|
||||
let rows = sqlx::query_as!(
|
||||
EpisodeRow,
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.vanished AS "vanished!: bool", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
FROM episodes e JOIN seasons se ON se.id = e.season_id"#
|
||||
)
|
||||
.fetch_all(pool(state)?)
|
||||
@@ -390,7 +395,7 @@ async fn load_series(state: &AppState, id: i64) -> Result<Series, ApiError> {
|
||||
.collect();
|
||||
let episodes = sqlx::query_as!(
|
||||
EpisodeRow,
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.vanished AS "vanished!: bool", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ?"#,
|
||||
id
|
||||
)
|
||||
@@ -602,7 +607,7 @@ async fn load_seasons(state: &AppState, series_id: i64) -> Result<Vec<Season>, A
|
||||
.await?;
|
||||
let episodes = sqlx::query_as!(
|
||||
EpisodeRow,
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.vanished AS "vanished!: bool", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ? ORDER BY se.number, e.number"#,
|
||||
series_id
|
||||
)
|
||||
@@ -627,6 +632,7 @@ async fn load_seasons(state: &AppState, series_id: i64) -> Result<Vec<Season>, A
|
||||
air_date: episode.air_date.clone(),
|
||||
wanted: episode.wanted,
|
||||
state: episode.state.clone(),
|
||||
vanished: episode.vanished,
|
||||
search_attempts: episode.search_attempts,
|
||||
last_searched_at: episode.last_searched_at.clone(),
|
||||
})
|
||||
@@ -831,7 +837,7 @@ pub async fn update_season(
|
||||
async fn load_episode(state: &AppState, id: i64) -> Result<Episode, ApiError> {
|
||||
let row = sqlx::query_as!(
|
||||
EpisodeRow,
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
r#"SELECT se.series_id AS "series_id!: i64", e.id AS "id!: i64", e.season_id AS "season_id!: i64", e.number AS "number!: i64", e.title AS "title!: String", e.air_date, e.wanted AS "wanted!: bool", e.state AS "state!: String", e.vanished AS "vanished!: bool", e.search_attempts AS "search_attempts!: i64", e.last_searched_at
|
||||
FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE e.id = ?"#,
|
||||
id
|
||||
)
|
||||
@@ -846,6 +852,7 @@ async fn load_episode(state: &AppState, id: i64) -> Result<Episode, ApiError> {
|
||||
air_date: row.air_date,
|
||||
wanted: row.wanted,
|
||||
state: row.state,
|
||||
vanished: row.vanished,
|
||||
search_attempts: row.search_attempts,
|
||||
last_searched_at: row.last_searched_at,
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//!
|
||||
//! Refresh is idempotent: over unchanged TMDB data only the stamp moves.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use arr_core::tracking::{apply_auto_track, apply_tracked, RefreshedSeason};
|
||||
@@ -354,14 +354,14 @@ impl SeriesRefreshAction {
|
||||
known: &HashMap<i64, (i64, String, Option<String>, bool)>,
|
||||
detail: &TmdbSeasonDetail,
|
||||
) -> Result<bool, RefreshError> {
|
||||
let upstream: HashMap<i64, ()> = detail
|
||||
let upstream: HashSet<i64> = detail
|
||||
.episodes
|
||||
.iter()
|
||||
.map(|source| (i64::from(source.number), ()))
|
||||
.map(|source| i64::from(source.number))
|
||||
.collect();
|
||||
let mut changed = false;
|
||||
for (number, &(id, ..)) in known {
|
||||
if upstream.contains_key(number) {
|
||||
if upstream.contains(number) {
|
||||
continue;
|
||||
}
|
||||
let has_file = sqlx::query_scalar!(
|
||||
|
||||
Reference in New Issue
Block a user