mirror of
https://github.com/crunchy-labs/crunchy-cli.git
synced 2026-01-21 04:02:00 -06:00
Format code
This commit is contained in:
parent
56411c6547
commit
fc6511a361
13 changed files with 42 additions and 48 deletions
|
|
@ -306,8 +306,8 @@ async fn get_format(
|
||||||
}
|
}
|
||||||
MergeBehavior::Audio => download_formats.push(DownloadFormat {
|
MergeBehavior::Audio => download_formats.push(DownloadFormat {
|
||||||
video: (
|
video: (
|
||||||
(*format_pairs.first().unwrap()).1.clone(),
|
format_pairs.first().unwrap().1.clone(),
|
||||||
(*format_pairs.first().unwrap()).0.audio.clone(),
|
format_pairs.first().unwrap().0.audio.clone(),
|
||||||
),
|
),
|
||||||
audios: format_pairs
|
audios: format_pairs
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ impl Filter for ArchiveFilter {
|
||||||
seasons.retain(|s| !remove_ids.contains(&s.id));
|
seasons.retain(|s| !remove_ids.contains(&s.id));
|
||||||
|
|
||||||
let duplicated_seasons = get_duplicated_seasons(&seasons);
|
let duplicated_seasons = get_duplicated_seasons(&seasons);
|
||||||
if duplicated_seasons.len() > 0 {
|
if !duplicated_seasons.is_empty() {
|
||||||
if self.interactive_input {
|
if self.interactive_input {
|
||||||
check_for_duplicated_seasons(&mut seasons);
|
check_for_duplicated_seasons(&mut seasons);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -139,8 +139,7 @@ impl Filter for ArchiveFilter {
|
||||||
if !matches!(self.visited, Visited::Series) {
|
if !matches!(self.visited, Visited::Series) {
|
||||||
let mut audio_locales: Vec<Locale> = seasons
|
let mut audio_locales: Vec<Locale> = seasons
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.audio_locales.clone())
|
.flat_map(|s| s.audio_locales.clone())
|
||||||
.flatten()
|
|
||||||
.collect();
|
.collect();
|
||||||
real_dedup_vec(&mut audio_locales);
|
real_dedup_vec(&mut audio_locales);
|
||||||
let missing_audio = missing_locales(&audio_locales, &self.archive.audio);
|
let missing_audio = missing_locales(&audio_locales, &self.archive.audio);
|
||||||
|
|
@ -158,8 +157,7 @@ impl Filter for ArchiveFilter {
|
||||||
|
|
||||||
let subtitle_locales: Vec<Locale> = seasons
|
let subtitle_locales: Vec<Locale> = seasons
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.subtitle_locales.clone())
|
.flat_map(|s| s.subtitle_locales.clone())
|
||||||
.flatten()
|
|
||||||
.collect();
|
.collect();
|
||||||
let missing_subtitle = missing_locales(&subtitle_locales, &self.archive.subtitle);
|
let missing_subtitle = missing_locales(&subtitle_locales, &self.archive.subtitle);
|
||||||
if !missing_subtitle.is_empty() {
|
if !missing_subtitle.is_empty() {
|
||||||
|
|
@ -211,7 +209,7 @@ impl Filter for ArchiveFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if eps.len() < before_len {
|
if eps.len() < before_len {
|
||||||
if eps.len() == 0 {
|
if eps.is_empty() {
|
||||||
if matches!(self.visited, Visited::Series) {
|
if matches!(self.visited, Visited::Series) {
|
||||||
warn!(
|
warn!(
|
||||||
"Season {} is not available with {} audio",
|
"Season {} is not available with {} audio",
|
||||||
|
|
@ -237,7 +235,7 @@ impl Filter for ArchiveFilter {
|
||||||
for episode in episodes.iter() {
|
for episode in episodes.iter() {
|
||||||
self.season_episodes
|
self.season_episodes
|
||||||
.entry(episode.season_id.clone())
|
.entry(episode.season_id.clone())
|
||||||
.or_insert(vec![])
|
.or_default()
|
||||||
.push(episode.clone())
|
.push(episode.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -290,7 +288,7 @@ impl Filter for ArchiveFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut subtitle_locales: Vec<Locale> =
|
let mut subtitle_locales: Vec<Locale> =
|
||||||
episodes.iter().map(|(_, s)| s.clone()).flatten().collect();
|
episodes.iter().flat_map(|(_, s)| s.clone()).collect();
|
||||||
real_dedup_vec(&mut subtitle_locales);
|
real_dedup_vec(&mut subtitle_locales);
|
||||||
let missing_subtitles = missing_locales(&subtitle_locales, &self.archive.subtitle);
|
let missing_subtitles = missing_locales(&subtitle_locales, &self.archive.subtitle);
|
||||||
if !missing_subtitles.is_empty()
|
if !missing_subtitles.is_empty()
|
||||||
|
|
@ -435,6 +433,6 @@ impl Filter for ArchiveFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_locales<'a>(available: &Vec<Locale>, searched: &'a Vec<Locale>) -> Vec<&'a Locale> {
|
fn missing_locales<'a>(available: &[Locale], searched: &'a [Locale]) -> Vec<&'a Locale> {
|
||||||
searched.iter().filter(|p| !available.contains(p)).collect()
|
searched.iter().filter(|p| !available.contains(p)).collect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ async fn get_format(
|
||||||
};
|
};
|
||||||
|
|
||||||
let subtitle = if let Some(subtitle_locale) = &download.subtitle {
|
let subtitle = if let Some(subtitle_locale) = &download.subtitle {
|
||||||
stream.subtitles.get(subtitle_locale).map(|s| s.clone())
|
stream.subtitles.get(subtitle_locale).cloned()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,14 @@ impl Filter for DownloadFilter {
|
||||||
async fn visit_series(&mut self, series: Series) -> Result<Vec<Season>> {
|
async fn visit_series(&mut self, series: Series) -> Result<Vec<Season>> {
|
||||||
// `series.audio_locales` isn't always populated b/c of crunchyrolls api. so check if the
|
// `series.audio_locales` isn't always populated b/c of crunchyrolls api. so check if the
|
||||||
// audio is matching only if the field is populated
|
// audio is matching only if the field is populated
|
||||||
if !series.audio_locales.is_empty() {
|
if !series.audio_locales.is_empty() && !series.audio_locales.contains(&self.download.audio)
|
||||||
if !series.audio_locales.contains(&self.download.audio) {
|
{
|
||||||
error!(
|
error!(
|
||||||
"Series {} is not available with {} audio",
|
"Series {} is not available with {} audio",
|
||||||
series.title, self.download.audio
|
series.title, self.download.audio
|
||||||
);
|
);
|
||||||
return Ok(vec![]);
|
return Ok(vec![]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut seasons = vec![];
|
let mut seasons = vec![];
|
||||||
for mut season in series.seasons().await? {
|
for mut season in series.seasons().await? {
|
||||||
|
|
@ -91,7 +90,7 @@ impl Filter for DownloadFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
let duplicated_seasons = get_duplicated_seasons(&seasons);
|
let duplicated_seasons = get_duplicated_seasons(&seasons);
|
||||||
if duplicated_seasons.len() > 0 {
|
if !duplicated_seasons.is_empty() {
|
||||||
if self.interactive_input {
|
if self.interactive_input {
|
||||||
check_for_duplicated_seasons(&mut seasons);
|
check_for_duplicated_seasons(&mut seasons);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -118,7 +117,7 @@ impl Filter for DownloadFilter {
|
||||||
for episode in episodes.iter() {
|
for episode in episodes.iter() {
|
||||||
self.season_episodes
|
self.season_episodes
|
||||||
.entry(episode.season_number)
|
.entry(episode.season_number)
|
||||||
.or_insert(vec![])
|
.or_default()
|
||||||
.push(episode.clone())
|
.push(episode.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ fn version() -> String {
|
||||||
let build_date = env!("BUILD_DATE");
|
let build_date = env!("BUILD_DATE");
|
||||||
|
|
||||||
if git_commit_hash.is_empty() {
|
if git_commit_hash.is_empty() {
|
||||||
format!("{}", package_version)
|
package_version.to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{} ({} {})", package_version, git_commit_hash, build_date)
|
format!("{} ({} {})", package_version, git_commit_hash, build_date)
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +250,7 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result<Crunchyroll> {
|
||||||
"Via `--lang` specified language is not supported. Supported languages: {}",
|
"Via `--lang` specified language is not supported. Supported languages: {}",
|
||||||
supported_langs
|
supported_langs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|l| format!("`{}` ({})", l.to_string(), l.to_human_readable()))
|
.map(|l| format!("`{}` ({})", l, l.to_human_readable()))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ impl FilterOptions {
|
||||||
|
|
||||||
pub fn filter_episodes(&self, mut episodes: Vec<Episode>) -> Vec<Episode> {
|
pub fn filter_episodes(&self, mut episodes: Vec<Episode>) -> Vec<Episode> {
|
||||||
episodes.retain(|e| {
|
episodes.retain(|e| {
|
||||||
self.check_audio_language(&vec![e.audio_locale.clone()])
|
self.check_audio_language(&[e.audio_locale.clone()])
|
||||||
&& self
|
&& self
|
||||||
.url_filter
|
.url_filter
|
||||||
.is_episode_valid(e.sequence_number, e.season_number)
|
.is_episode_valid(e.sequence_number, e.season_number)
|
||||||
|
|
@ -38,7 +38,7 @@ impl FilterOptions {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_audio_language(&self, audio: &Vec<Locale>) -> bool {
|
fn check_audio_language(&self, audio: &[Locale]) -> bool {
|
||||||
if !self.audio.is_empty() {
|
if !self.audio.is_empty() {
|
||||||
return self.audio.iter().any(|a| audio.contains(a));
|
return self.audio.iter().any(|a| audio.contains(a));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,7 @@ impl Format {
|
||||||
let stream_empty = self.check_pattern_count_empty(Scope::Stream)
|
let stream_empty = self.check_pattern_count_empty(Scope::Stream)
|
||||||
&& self.check_pattern_count_empty(Scope::Subtitle);
|
&& self.check_pattern_count_empty(Scope::Subtitle);
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
let mut tree: Vec<(Season, Vec<(Episode, Vec<Stream>)>)> = vec![];
|
let mut tree: Vec<(Season, Vec<(Episode, Vec<Stream>)>)> = vec![];
|
||||||
|
|
||||||
let series = if !series_empty {
|
let series = if !series_empty {
|
||||||
|
|
|
||||||
|
|
@ -296,7 +296,7 @@ impl Downloader {
|
||||||
]);
|
]);
|
||||||
// the empty language metadata is created to avoid that metadata from the original track
|
// the empty language metadata is created to avoid that metadata from the original track
|
||||||
// is copied
|
// is copied
|
||||||
metadata.extend([format!("-metadata:s:v:{}", i), format!("language=")])
|
metadata.extend([format!("-metadata:s:v:{}", i), "language=".to_string()])
|
||||||
}
|
}
|
||||||
for (i, meta) in audios.iter().enumerate() {
|
for (i, meta) in audios.iter().enumerate() {
|
||||||
input.extend(["-i".to_string(), meta.path.to_string_lossy().to_string()]);
|
input.extend(["-i".to_string(), meta.path.to_string_lossy().to_string()]);
|
||||||
|
|
@ -675,7 +675,7 @@ impl Downloader {
|
||||||
|
|
||||||
let result = download().await;
|
let result = download().await;
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
after_download_sender.send((-1 as i32, vec![]))?;
|
after_download_sender.send((-1, vec![]))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
@ -747,7 +747,7 @@ impl Downloader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_variant_file_size(variant_data: &VariantData, segments: &Vec<VariantSegment>) -> u64 {
|
fn estimate_variant_file_size(variant_data: &VariantData, segments: &[VariantSegment]) -> u64 {
|
||||||
(variant_data.bandwidth / 8) * segments.iter().map(|s| s.length.as_secs()).sum::<u64>()
|
(variant_data.bandwidth / 8) * segments.iter().map(|s| s.length.as_secs()).sum::<u64>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -788,8 +788,7 @@ pub fn get_video_length(path: &Path) -> Result<NaiveTime> {
|
||||||
/// [crunchy-labs/crunchy-cli#208](https://github.com/crunchy-labs/crunchy-cli/issues/208) for more
|
/// [crunchy-labs/crunchy-cli#208](https://github.com/crunchy-labs/crunchy-cli/issues/208) for more
|
||||||
/// information.
|
/// information.
|
||||||
fn fix_subtitles(raw: &mut Vec<u8>, max_length: NaiveTime) {
|
fn fix_subtitles(raw: &mut Vec<u8>, max_length: NaiveTime) {
|
||||||
let re =
|
let re = Regex::new(r"^Dialogue:\s\d+,(?P<start>\d+:\d+:\d+\.\d+),(?P<end>\d+:\d+:\d+\.\d+),")
|
||||||
Regex::new(r#"^Dialogue:\s\d+,(?P<start>\d+:\d+:\d+\.\d+),(?P<end>\d+:\d+:\d+\.\d+),"#)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// chrono panics if we try to format NaiveTime with `%2f` and the nano seconds has more than 2
|
// chrono panics if we try to format NaiveTime with `%2f` and the nano seconds has more than 2
|
||||||
|
|
@ -832,7 +831,7 @@ fn fix_subtitles(raw: &mut Vec<u8>, max_length: NaiveTime) {
|
||||||
line,
|
line,
|
||||||
format!(
|
format!(
|
||||||
"Dialogue: {},{},",
|
"Dialogue: {},{},",
|
||||||
format_naive_time(start.clone()),
|
format_naive_time(start),
|
||||||
&length_as_string
|
&length_as_string
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ impl FFmpegPreset {
|
||||||
description_details.push(format!("{} video quality/compression", q.to_string()))
|
description_details.push(format!("{} video quality/compression", q.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let description = if description_details.len() == 0 {
|
let description = if description_details.is_empty() {
|
||||||
format!(
|
format!(
|
||||||
"{} encoded with default video quality/compression",
|
"{} encoded with default video quality/compression",
|
||||||
codec.to_string()
|
codec.to_string()
|
||||||
|
|
@ -239,7 +239,7 @@ impl FFmpegPreset {
|
||||||
hwaccel.clone(),
|
hwaccel.clone(),
|
||||||
quality.clone(),
|
quality.clone(),
|
||||||
)) {
|
)) {
|
||||||
return Err(format!("ffmpeg preset is not supported"));
|
return Err("ffmpeg preset is not supported".to_string());
|
||||||
}
|
}
|
||||||
Ok(FFmpegPreset::Predefined(
|
Ok(FFmpegPreset::Predefined(
|
||||||
c,
|
c,
|
||||||
|
|
@ -247,7 +247,7 @@ impl FFmpegPreset {
|
||||||
quality.unwrap_or(FFmpegQuality::Normal),
|
quality.unwrap_or(FFmpegQuality::Normal),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("cannot use ffmpeg preset with without a codec"))
|
Err("cannot use ffmpeg preset with without a codec".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,10 +170,7 @@ impl SingleFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_episode(&self) -> bool {
|
pub fn is_episode(&self) -> bool {
|
||||||
match self.source {
|
matches!(self.source, MediaCollection::Episode(_))
|
||||||
MediaCollection::Episode(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,7 +178,7 @@ struct SingleFormatCollectionEpisodeKey(f32);
|
||||||
|
|
||||||
impl PartialOrd for SingleFormatCollectionEpisodeKey {
|
impl PartialOrd for SingleFormatCollectionEpisodeKey {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
self.0.partial_cmp(&other.0)
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Ord for SingleFormatCollectionEpisodeKey {
|
impl Ord for SingleFormatCollectionEpisodeKey {
|
||||||
|
|
@ -198,6 +195,7 @@ impl Eq for SingleFormatCollectionEpisodeKey {}
|
||||||
|
|
||||||
struct SingleFormatCollectionSeasonKey((u32, String));
|
struct SingleFormatCollectionSeasonKey((u32, String));
|
||||||
|
|
||||||
|
#[allow(clippy::incorrect_partial_ord_impl_on_ord_type)]
|
||||||
impl PartialOrd for SingleFormatCollectionSeasonKey {
|
impl PartialOrd for SingleFormatCollectionSeasonKey {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
let mut cmp = self.0 .0.partial_cmp(&other.0 .0);
|
let mut cmp = self.0 .0.partial_cmp(&other.0 .0);
|
||||||
|
|
@ -250,7 +248,7 @@ impl SingleFormatCollection {
|
||||||
format.season_number,
|
format.season_number,
|
||||||
format.season_id.clone(),
|
format.season_id.clone(),
|
||||||
)))
|
)))
|
||||||
.or_insert(BTreeMap::new())
|
.or_default()
|
||||||
.insert(
|
.insert(
|
||||||
SingleFormatCollectionEpisodeKey(format.sequence_number),
|
SingleFormatCollectionEpisodeKey(format.sequence_number),
|
||||||
single_formats,
|
single_formats,
|
||||||
|
|
@ -340,6 +338,7 @@ pub struct Format {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Format {
|
impl Format {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn from_single_formats(
|
pub fn from_single_formats(
|
||||||
mut single_formats: Vec<(SingleFormat, VariantData, Vec<(Subtitle, bool)>)>,
|
mut single_formats: Vec<(SingleFormat, VariantData, Vec<(Subtitle, bool)>)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
@ -349,7 +348,7 @@ impl Format {
|
||||||
(
|
(
|
||||||
single_format.audio.clone(),
|
single_format.audio.clone(),
|
||||||
subtitles
|
subtitles
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|(s, _)| s.locale.clone())
|
.map(|(s, _)| s.locale.clone())
|
||||||
.collect::<Vec<Locale>>(),
|
.collect::<Vec<Locale>>(),
|
||||||
)
|
)
|
||||||
|
|
@ -440,7 +439,7 @@ impl Format {
|
||||||
info!(
|
info!(
|
||||||
"Downloading {} to {}",
|
"Downloading {} to {}",
|
||||||
self.title,
|
self.title,
|
||||||
if is_special_file(&dst) || dst.to_str().unwrap() == "-" {
|
if is_special_file(dst) || dst.to_str().unwrap() == "-" {
|
||||||
dst.to_string_lossy().to_string()
|
dst.to_string_lossy().to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("'{}'", dst.to_str().unwrap())
|
format!("'{}'", dst.to_str().unwrap())
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@ pub fn system_locale() -> Locale {
|
||||||
pub fn all_locale_in_locales(locales: Vec<Locale>) -> Vec<Locale> {
|
pub fn all_locale_in_locales(locales: Vec<Locale>) -> Vec<Locale> {
|
||||||
if locales
|
if locales
|
||||||
.iter()
|
.iter()
|
||||||
.find(|l| l.to_string().to_lowercase().trim() == "all")
|
.any(|l| l.to_string().to_lowercase().trim() == "all")
|
||||||
.is_some()
|
|
||||||
{
|
{
|
||||||
Locale::all()
|
Locale::all()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ macro_rules! tab_info {
|
||||||
}
|
}
|
||||||
pub(crate) use tab_info;
|
pub(crate) use tab_info;
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
pub struct CliLogger {
|
pub struct CliLogger {
|
||||||
level: LevelFilter,
|
level: LevelFilter,
|
||||||
progress: Mutex<Option<ProgressBar>>,
|
progress: Mutex<Option<ProgressBar>>,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ pub fn has_ffmpeg() -> bool {
|
||||||
/// Get the temp directory either by the specified `CRUNCHY_CLI_TEMP_DIR` env variable or the dir
|
/// Get the temp directory either by the specified `CRUNCHY_CLI_TEMP_DIR` env variable or the dir
|
||||||
/// provided by the os.
|
/// provided by the os.
|
||||||
pub fn temp_directory() -> PathBuf {
|
pub fn temp_directory() -> PathBuf {
|
||||||
env::var("CRUNCHY_CLI_TEMP_DIR").map_or(env::temp_dir(), |d| PathBuf::from(d))
|
env::var("CRUNCHY_CLI_TEMP_DIR").map_or(env::temp_dir(), PathBuf::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Any tempfile should be created with this function. The prefix and directory of every file
|
/// Any tempfile should be created with this function. The prefix and directory of every file
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue