mirror of
https://github.com/crunchy-labs/crunchy-cli.git
synced 2026-01-21 20:22:01 -06:00
Merge pull request #257 from crunchy-labs/feature/relative_sequence_number
Add flags and option to control special episode behavior (#206, #241, #246)
This commit is contained in:
commit
4d01e2a4ec
7 changed files with 267 additions and 107 deletions
|
|
@ -29,8 +29,9 @@ pub struct SingleFormat {
|
|||
|
||||
pub episode_id: String,
|
||||
pub episode_number: String,
|
||||
pub sequence_number: f32,
|
||||
pub relative_episode_number: Option<u32>,
|
||||
pub sequence_number: f32,
|
||||
pub relative_sequence_number: Option<f32>,
|
||||
|
||||
pub duration: Duration,
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ impl SingleFormat {
|
|||
episode: Episode,
|
||||
subtitles: Vec<Locale>,
|
||||
relative_episode_number: Option<u32>,
|
||||
relative_sequence_number: Option<f32>,
|
||||
) -> Self {
|
||||
Self {
|
||||
identifier: if episode.identifier.is_empty() {
|
||||
|
|
@ -73,6 +75,7 @@ impl SingleFormat {
|
|||
},
|
||||
sequence_number: episode.sequence_number,
|
||||
relative_episode_number,
|
||||
relative_sequence_number,
|
||||
duration: episode.duration,
|
||||
source: episode.into(),
|
||||
}
|
||||
|
|
@ -92,8 +95,9 @@ impl SingleFormat {
|
|||
season_number: 1,
|
||||
episode_id: movie.id.clone(),
|
||||
episode_number: "1".to_string(),
|
||||
sequence_number: 1.0,
|
||||
relative_episode_number: Some(1),
|
||||
sequence_number: 1.0,
|
||||
relative_sequence_number: Some(1.0),
|
||||
duration: movie.duration,
|
||||
source: movie.into(),
|
||||
}
|
||||
|
|
@ -113,8 +117,9 @@ impl SingleFormat {
|
|||
season_number: 1,
|
||||
episode_id: music_video.id.clone(),
|
||||
episode_number: "1".to_string(),
|
||||
sequence_number: 1.0,
|
||||
relative_episode_number: Some(1),
|
||||
sequence_number: 1.0,
|
||||
relative_sequence_number: Some(1.0),
|
||||
duration: music_video.duration,
|
||||
source: music_video.into(),
|
||||
}
|
||||
|
|
@ -134,8 +139,9 @@ impl SingleFormat {
|
|||
season_number: 1,
|
||||
episode_id: concert.id.clone(),
|
||||
episode_number: "1".to_string(),
|
||||
sequence_number: 1.0,
|
||||
relative_episode_number: Some(1),
|
||||
sequence_number: 1.0,
|
||||
relative_sequence_number: Some(1.0),
|
||||
duration: concert.duration,
|
||||
source: concert.into(),
|
||||
}
|
||||
|
|
@ -328,8 +334,9 @@ pub struct Format {
|
|||
|
||||
pub episode_id: String,
|
||||
pub episode_number: String,
|
||||
pub sequence_number: f32,
|
||||
pub relative_episode_number: Option<u32>,
|
||||
pub sequence_number: f32,
|
||||
pub relative_sequence_number: Option<f32>,
|
||||
}
|
||||
|
||||
impl Format {
|
||||
|
|
@ -363,8 +370,9 @@ impl Format {
|
|||
season_number: first_format.season_number,
|
||||
episode_id: first_format.episode_id,
|
||||
episode_number: first_format.episode_number,
|
||||
sequence_number: first_format.sequence_number,
|
||||
relative_episode_number: first_format.relative_episode_number,
|
||||
sequence_number: first_format.sequence_number,
|
||||
relative_sequence_number: first_format.relative_sequence_number,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -400,9 +408,28 @@ impl Format {
|
|||
)
|
||||
.replace(
|
||||
"{relative_episode_number}",
|
||||
&sanitize(
|
||||
self.relative_episode_number.unwrap_or_default().to_string(),
|
||||
true,
|
||||
&format!(
|
||||
"{:0>2}",
|
||||
sanitize(
|
||||
self.relative_episode_number.unwrap_or_default().to_string(),
|
||||
true,
|
||||
)
|
||||
),
|
||||
)
|
||||
.replace(
|
||||
"{sequence_number}",
|
||||
&format!("{:0>2}", sanitize(self.sequence_number.to_string(), true)),
|
||||
)
|
||||
.replace(
|
||||
"{relative_sequence_number}",
|
||||
&format!(
|
||||
"{:0>2}",
|
||||
sanitize(
|
||||
self.relative_sequence_number
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
true,
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -446,7 +473,12 @@ impl Format {
|
|||
tab_info!("FPS: {:.2}", self.fps)
|
||||
}
|
||||
|
||||
pub fn has_relative_episodes_fmt<S: AsRef<str>>(s: S) -> bool {
|
||||
return s.as_ref().contains("{relative_episode_number}");
|
||||
pub fn is_special(&self) -> bool {
|
||||
self.sequence_number == 0.0 || self.sequence_number.fract() != 0.0
|
||||
}
|
||||
|
||||
pub fn has_relative_fmt<S: AsRef<str>>(s: S) -> bool {
|
||||
return s.as_ref().contains("{relative_episode_number}")
|
||||
|| s.as_ref().contains("{relative_sequence_number}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use regex::Regex;
|
|||
/// If `to_*` is [`None`] they're set to [`u32::MAX`].
|
||||
#[derive(Debug, Default)]
|
||||
pub struct InnerUrlFilter {
|
||||
from_episode: Option<u32>,
|
||||
to_episode: Option<u32>,
|
||||
from_episode: Option<f32>,
|
||||
to_episode: Option<f32>,
|
||||
from_season: Option<u32>,
|
||||
to_season: Option<u32>,
|
||||
}
|
||||
|
|
@ -39,10 +39,10 @@ impl UrlFilter {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn is_episode_valid(&self, episode: u32, season: u32) -> bool {
|
||||
pub fn is_episode_valid(&self, episode: f32, season: u32) -> bool {
|
||||
self.inner.iter().any(|f| {
|
||||
let from_episode = f.from_episode.unwrap_or(u32::MIN);
|
||||
let to_episode = f.to_episode.unwrap_or(u32::MAX);
|
||||
let from_episode = f.from_episode.unwrap_or(f32::MIN);
|
||||
let to_episode = f.to_episode.unwrap_or(f32::MAX);
|
||||
let from_season = f.from_season.unwrap_or(u32::MIN);
|
||||
let to_season = f.to_season.unwrap_or(u32::MAX);
|
||||
|
||||
|
|
@ -192,3 +192,13 @@ pub fn parse_resolution(mut resolution: String) -> Result<Resolution> {
|
|||
bail!("Could not find resolution")
|
||||
}
|
||||
}
|
||||
|
||||
/// Dirty implementation of [`f32::fract`] with more accuracy.
|
||||
pub fn fract(input: f32) -> f32 {
|
||||
if input.fract() == 0.0 {
|
||||
return 0.0;
|
||||
}
|
||||
format!("0.{}", input.to_string().split('.').last().unwrap())
|
||||
.parse::<f32>()
|
||||
.unwrap()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue