Implement multiple episode numbers

This commit is contained in:
2025-05-20 00:20:43 -06:00
parent 73c5e4af9b
commit 2b348851d7
11 changed files with 154 additions and 49 deletions
+2 -2
View File
@@ -23,8 +23,8 @@ impl Cli {
}
}
pub fn command(&self) -> &Command {
&self.command
pub fn command(self) -> Command {
self.command
}
}
+3
View File
@@ -25,6 +25,7 @@ pub enum Command {
season: u32,
},
/// Process a TMDB episode
#[command(trailing_var_arg = true)]
Episode {
#[arg(value_name = "TMDB_ID")]
id: u32,
@@ -32,5 +33,7 @@ pub enum Command {
season: u32,
#[arg(value_name = "EPISODE_NUM")]
episode: u32,
#[arg(value_name = "...")]
episodes: Vec<u32>,
},
}
+7 -6
View File
@@ -33,14 +33,14 @@ async fn main() -> Result<()> {
force,
output,
command,
} => exec_write(client, *force, output, command).await?,
Command::Update { output } => exec_update(client, output).await?,
} => exec_write(client, force, &output, command).await?,
Command::Update { output } => exec_update(client, &output).await?,
}
Ok(())
}
async fn exec_print(client: Client, command: &BackendCommand) -> Result<()> {
async fn exec_print(client: Client, command: BackendCommand) -> Result<()> {
match command {
BackendCommand::Tmdb { command } => {
let object = run::tmdb::TmdbObject::fetch(&client, command).await?;
@@ -54,7 +54,7 @@ async fn exec_write(
client: Client,
force: bool,
output: &Path,
command: &BackendCommand,
command: BackendCommand,
) -> Result<()> {
match command {
BackendCommand::Tmdb { command } => {
@@ -83,8 +83,9 @@ async fn exec_update(client: Client, output: &Path) -> Result<()> {
let content = fs::read_to_string(output)
.await
.with_context(|| format!("failed to read file at path: {}", output.display()))?;
let object: FlixObject = toml::from_str(&content).context("failed to deserialize flix file")?;
let object: FlixObject = toml::from_str(&content)
.with_context(|| format!("failed to deserialize flix file: {}", output.display()))?;
let command = object.backend_command()?;
exec_write(client, true, output, &command).await
exec_write(client, true, output, command).await
}
+9 -2
View File
@@ -1,6 +1,6 @@
use flix::model::{Collection, Episode, Movie, Season, Show, Verse};
use anyhow::{Result, bail};
use anyhow::{Result, anyhow, bail};
use crate::cli::BackendCommand;
use crate::cli::tmdb;
@@ -56,7 +56,14 @@ impl FlixObject {
tmdb::Command::Episode {
id: tmdb.show_id.into(),
season: episode.episode.season,
episode: episode.episode.number,
episode: episode
.episode
.number
.primary_episode_number()
.ok_or_else(|| {
anyhow!("the episode does not have a primary episode number")
})?,
episodes: episode.episode.number.additional_episode_numbers(),
}
.into()
}
+49 -21
View File
@@ -1,6 +1,7 @@
use flix::model::{
Collection, Episode, GenericCollection, GenericEpisode, GenericMovie, GenericSeason,
GenericShow, Movie, Season, Show, TmdbCollection, TmdbEpisode, TmdbMovie, TmdbSeason, TmdbShow,
Collection, Episode, EpisodeNumber, GenericCollection, GenericEpisode, GenericMovie,
GenericSeason, GenericShow, Movie, Season, Show, TmdbCollection, TmdbEpisode, TmdbMovie,
TmdbSeason, TmdbShow,
};
use flix_tmdb::Client;
use flix_tmdb::model::{
@@ -9,6 +10,7 @@ use flix_tmdb::model::{
};
use anyhow::{Context, Result};
use futures::{StreamExt, TryStreamExt, stream};
use crate::cli::tmdb::Command;
@@ -17,7 +19,7 @@ pub enum TmdbObject {
Movie(TMovie),
Show(TShow),
Season(TSeason, ShowId),
Episode(TEpisode, u32, ShowId),
Episode(TEpisode, Vec<u32>, u32, ShowId),
}
impl TmdbObject {
@@ -63,23 +65,34 @@ impl TmdbObject {
},
tmdb: Some(TmdbSeason { show_id }),
})?,
TmdbObject::Episode(tmdb, season_number, show_id) => toml::to_string(&Episode {
episode: GenericEpisode {
number: tmdb.episode_number,
season: season_number,
title: tmdb.title,
overview: tmdb.overview,
air_date: tmdb.air_date,
},
tmdb: Some(TmdbEpisode { show_id }),
})?,
TmdbObject::Episode(tmdb, mut episode_numbers, season_number, show_id) => {
toml::to_string(&Episode {
episode: GenericEpisode {
number: if episode_numbers.is_empty() {
EpisodeNumber::Single {
number: tmdb.episode_number,
}
} else {
episode_numbers.insert(0, tmdb.episode_number);
EpisodeNumber::Multiple {
numbers: episode_numbers,
}
},
season: season_number,
title: tmdb.title,
overview: tmdb.overview,
air_date: tmdb.air_date,
},
tmdb: Some(TmdbEpisode { show_id }),
})?
}
})
}
}
impl TmdbObject {
pub async fn fetch(client: &Client, command: &Command) -> Result<Self> {
Ok(match *command {
pub async fn fetch(client: &Client, command: Command) -> Result<Self> {
Ok(match command {
Command::Collection { id } => Self::Collection(
client
.collections()
@@ -113,17 +126,32 @@ impl TmdbObject {
id,
season,
episode,
} => Self::Episode(
client
episodes,
} => {
let mut episode = client
.episodes()
.get_details(id, season, episode, None)
.await
.with_context(|| {
format!("could not get show details for '{id}' S{season}E{episode}")
})?,
season,
id.into(),
),
})?;
let title = stream::once(async { Ok(episode.title) })
.chain(stream::iter(episodes.clone()).then(|episode| async move {
client
.episodes()
.get_details(id, season, episode, None)
.await
.with_context(|| {
format!("could not get show details for '{id}' S{season}E{episode}")
})
.map(|episode| episode.title)
}))
.try_collect::<Vec<_>>()
.await?
.join(" + ");
episode.title = title;
Self::Episode(episode, episodes, season, id.into())
}
})
}
}