use ibdl_common::{
post::{extension::Extension, rating::Rating, NameType},
ImageBoards,
};
use std::path::PathBuf;
use clap::Parser;
use crate::{generate_output_path, generate_output_path_precise, ImageBoardArg, RatingArg};
#[derive(Parser, Debug)]
#[clap(name = "Imageboard Downloader", author, version, about, long_about = None)]
pub struct Cli {
#[clap(value_parser, required = true)]
pub tags: Vec<String>,
#[clap(short, long, value_enum, ignore_case = true, default_value_t = ImageBoardArg(ImageBoards::Danbooru))]
pub imageboard: ImageBoardArg,
#[clap(
short,
long,
value_name = "PATH",
help_heading = "SAVE",
conflicts_with("precise_output")
)]
pub output: Option<PathBuf>,
#[clap(
short = 'O',
value_name = "PATH",
help_heading = "SAVE",
conflicts_with("output")
)]
pub precise_output: Option<PathBuf>,
#[clap(
short = 'd',
value_name = "NUMBER",
value_parser(clap::value_parser!(u8).range(1..=20)),
default_value_t = 5,
help_heading = "DOWNLOAD"
)]
pub simultaneous_downloads: u8,
#[clap(short, long, action, help_heading = "GENERAL")]
pub auth: bool,
#[clap(long, action, default_value_t = false, help_heading = "GENERAL")]
pub safe_mode: bool,
#[clap(
long = "id",
value_parser,
default_value_t = false,
help_heading = "SAVE"
)]
pub save_file_as_id: bool,
#[clap(long, value_parser, default_value_t = false, help_heading = "SAVE")]
pub no_animated: bool,
#[clap(short, long, value_parser, help_heading = "DOWNLOAD")]
pub limit: Option<u16>,
#[clap(long, value_parser, default_value_t = false, help_heading = "GENERAL")]
pub disable_blacklist: bool,
#[clap(long, value_parser, default_value_t = false, help_heading = "SAVE")]
pub cbz: bool,
#[clap(
short,
long,
value_parser,
help_heading = "DOWNLOAD",
value_name = "PAGE"
)]
pub start_page: Option<u16>,
#[clap(
short,
long,
value_parser,
help_heading = "GENERAL",
conflicts_with("safe_mode")
)]
pub rating: Vec<RatingArg>,
#[clap(long, value_parser, default_value_t = false, help_heading = "SAVE")]
pub ignore_unknown: bool,
#[clap(long, value_parser, default_value_t = false, help_heading = "SAVE")]
pub annotate: bool,
#[clap(short, long, value_parser, help_heading = "GENERAL")]
pub exclude: Vec<String>,
#[clap(long, value_parser, help_heading = "DOWNLOAD")]
pub force_extension: Option<String>,
#[clap(
long = "pool",
value_parser,
value_name = "ID",
conflicts_with("tags"),
conflicts_with("save_file_as_id"),
requires("precise_output")
)]
pub pool_id: Option<u32>,
#[clap(long = "latest", value_parser, requires("pool_id"))]
pub latest_first: bool,
}
impl Cli {
pub fn name_type(&self) -> NameType {
if self.save_file_as_id {
NameType::ID
} else {
NameType::MD5
}
}
#[inline]
pub fn selected_ratings(&self) -> Vec<Rating> {
let mut ratings: Vec<Rating> = Vec::with_capacity(4);
if self.rating.is_empty() {
if self.safe_mode {
ratings.push(Rating::Safe);
} else {
ratings.push(Rating::Safe);
ratings.push(Rating::Questionable);
ratings.push(Rating::Explicit)
}
} else {
self.rating.iter().for_each(|item| ratings.push(item.0));
};
if !self.ignore_unknown {
ratings.push(Rating::Unknown);
}
ratings
}
pub fn get_extension(&self) -> Option<Extension> {
if let Some(ext) = &self.force_extension {
return Some(Extension::guess_format(ext));
}
None
}
pub fn generate_save_path(&self) -> Result<PathBuf, std::io::Error> {
let raw_save_path = if let Some(path) = &self.output {
path.to_owned()
} else if let Some(precise_path) = &self.precise_output {
precise_path.to_owned()
} else {
std::env::current_dir()?
};
let dirname = if self.output.is_some() {
assert_eq!(self.precise_output, None);
generate_output_path(&raw_save_path, *self.imageboard, &self.tags, self.cbz)
} else if self.precise_output.is_some() {
assert_eq!(self.output, None);
generate_output_path_precise(&raw_save_path, self.cbz)
} else if let Some(id) = self.pool_id {
if self.cbz {
raw_save_path.join(format!("{}.cbz", id))
} else {
raw_save_path.join(id.to_string())
}
} else {
raw_save_path
};
Ok(dirname)
}
}