Merge pull request #106 from crunchy-labs/feature/more-episode-number-format-options

Add relative episode number format option
This commit is contained in:
ByteDream 2023-01-10 20:17:52 +01:00 committed by GitHub
commit 4482d5482f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 160 additions and 106 deletions

View file

@ -4,7 +4,7 @@ use crate::cli::utils::{
interactive_season_choosing, FFmpegPreset,
};
use crate::utils::context::Context;
use crate::utils::format::{format_path, Format};
use crate::utils::format::Format;
use crate::utils::log::progress;
use crate::utils::os::{free_file, has_ffmpeg, is_special_file, tempfile};
use crate::utils::parse::{parse_url, UrlFilter};
@ -67,10 +67,9 @@ pub struct Archive {
{season_name} Name of the season\n \
{audio} Audio language of the video\n \
{resolution} Resolution of the video\n \
{padded_season_number} Number of the season padded to double digits\n \
{season_number} Number of the season\n \
{padded_episode_number} Number of the episode padded to double digits\n \
{episode_number} Number of the episode\n \
{relative_episode_number} Number of the episode relative to its season\
{series_id} ID of the series\n \
{season_id} ID of the season\n \
{episode_id} ID of the episode")]
@ -208,7 +207,7 @@ impl Execute for Archive {
format.stream.resolution,
format.stream.fps,
format.season_number,
format.number,
format.episode_number,
)
}
}
@ -234,7 +233,7 @@ impl Execute for Archive {
format.stream.resolution,
format.stream.fps,
format.season_number,
format.number
format.episode_number
)
}
}
@ -243,16 +242,17 @@ impl Execute for Archive {
for (formats, mut subtitles) in archive_formats {
let (primary, additionally) = formats.split_first().unwrap();
let path = free_file(format_path(
if self.output.is_empty() {
"{title}.mkv"
} else {
&self.output
}
.into(),
&primary,
true,
));
let path = free_file(
primary.format_path(
if self.output.is_empty() {
"{title}.mkv"
} else {
&self.output
}
.into(),
true,
),
);
info!(
"Downloading {} to '{}'",
@ -266,7 +266,7 @@ impl Execute for Archive {
tab_info!(
"Episode: S{:02}E{:02}",
primary.season_number,
primary.number
primary.episode_number
);
tab_info!(
"Audio: {} (primary), {}",
@ -318,7 +318,7 @@ impl Execute for Archive {
// Remove subtitles of deleted video
if only_audio {
subtitles.retain(|s| s.episode_id != additional.id);
subtitles.retain(|s| s.episode_id != additional.episode_id);
}
}
@ -395,7 +395,9 @@ async fn formats_from_series(
let mut result: BTreeMap<u32, BTreeMap<u32, (Vec<Format>, Vec<Subtitle>)>> = BTreeMap::new();
let mut primary_season = true;
for season in seasons {
for episode in season.episodes().await? {
let episodes = season.episodes().await?;
for episode in episodes.iter() {
if !url_filter.is_episode_valid(
episode.metadata.episode_number,
episode.metadata.season_number,
@ -434,7 +436,7 @@ async fn formats_from_series(
};
Some(subtitle)
}));
formats.push(Format::new_from_episode(episode, stream));
formats.push(Format::new_from_episode(episode, &episodes, stream));
}
primary_season = false;

View file

@ -4,7 +4,7 @@ use crate::cli::utils::{
interactive_season_choosing, FFmpegPreset,
};
use crate::utils::context::Context;
use crate::utils::format::{format_path, Format};
use crate::utils::format::Format;
use crate::utils::log::progress;
use crate::utils::os::{free_file, has_ffmpeg, is_special_file};
use crate::utils::parse::{parse_url, UrlFilter};
@ -16,6 +16,7 @@ use crunchyroll_rs::{
Episode, Locale, Media, MediaCollection, Movie, MovieListing, Season, Series,
};
use log::{debug, error, info, warn};
use std::borrow::Cow;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
@ -44,10 +45,9 @@ pub struct Download {
{season_name} Name of the season\n \
{audio} Audio language of the video\n \
{resolution} Resolution of the video\n \
{padded_season_number} Number of the season padded to double digits\n \
{season_number} Number of the season\n \
{padded_episode_number} Number of the episode padded to double digits\n \
{episode_number} Number of the episode\n \
{relative_episode_number} Number of the episode relative to its season\
{series_id} ID of the series\n \
{season_id} ID of the season\n \
{episode_id} ID of the episode")]
@ -148,7 +148,7 @@ impl Execute for Download {
episode.metadata.season_title,
episode.metadata.series_title
);
format_from_episode(&self, episode, &url_filter, false)
format_from_episode(&self, &episode, &url_filter, None, false)
.await?
.map(|fmt| vec![fmt])
}
@ -182,7 +182,7 @@ impl Execute for Download {
format.stream.resolution,
format.stream.fps,
format.season_number,
format.number,
format.episode_number,
)
}
}
@ -202,23 +202,24 @@ impl Execute for Download {
format.stream.resolution,
format.stream.fps,
format.season_number,
format.number
format.episode_number
)
}
}
}
for format in formats {
let path = free_file(format_path(
if self.output.is_empty() {
"{title}.mkv"
} else {
&self.output
}
.into(),
&format,
true,
));
let path = free_file(
format.format_path(
if self.output.is_empty() {
"{title}.mkv"
} else {
&self.output
}
.into(),
true,
),
);
info!(
"Downloading {} to '{}'",
@ -229,7 +230,11 @@ impl Execute for Download {
path.file_name().unwrap().to_str().unwrap()
}
);
tab_info!("Episode: S{:02}E{:02}", format.season_number, format.number);
tab_info!(
"Episode: S{:02}E{:02}",
format.season_number,
format.episode_number
);
tab_info!("Audio: {}", format.audio);
tab_info!(
"Subtitles: {}",
@ -388,8 +393,11 @@ async fn formats_from_season(
let mut formats = vec![];
for episode in season.episodes().await? {
if let Some(fmt) = format_from_episode(download, episode, url_filter, true).await? {
let episodes = season.episodes().await?;
for episode in episodes.iter() {
if let Some(fmt) =
format_from_episode(download, &episode, url_filter, Some(&episodes), true).await?
{
formats.push(fmt)
}
}
@ -399,8 +407,9 @@ async fn formats_from_season(
async fn format_from_episode(
download: &Download,
episode: Media<Episode>,
episode: &Media<Episode>,
url_filter: &UrlFilter,
season_episodes: Option<&Vec<Media<Episode>>>,
filter_audio: bool,
) -> Result<Option<Format>> {
if filter_audio && episode.metadata.audio_locale != download.audio {
@ -453,7 +462,21 @@ async fn format_from_episode(
)
};
Ok(Some(Format::new_from_episode(episode, stream)))
let season_eps = if Format::has_relative_episodes_fmt(&download.output) {
if let Some(eps) = season_episodes {
Cow::from(eps)
} else {
Cow::from(episode.season().await?.episodes().await?)
}
} else {
Cow::from(vec![])
};
Ok(Some(Format::new_from_episode(
episode,
&season_eps.to_vec(),
stream,
)))
}
async fn format_from_movie_listing(
@ -511,7 +534,7 @@ async fn format_from_movie(
}
};
Ok(Some(Format::new_from_movie(movie, stream)))
Ok(Some(Format::new_from_movie(&movie, stream)))
}
fn some_vec_or_none<T>(v: Vec<T>) -> Option<Vec<T>> {