use anyhow::Result;
use clap::{
ArgAction, Parser, ValueEnum,
builder::styling::{self, Styles},
};
use kodik_parser::TranslationType;
use kodik_utils::{Jar, JarExt};
use log::LevelFilter;
use reqwest::Url;
const STYLES: Styles = Styles::styled()
.header(styling::AnsiColor::BrightGreen.on_default().bold())
.usage(styling::AnsiColor::BrightGreen.on_default().bold())
.literal(styling::AnsiColor::BrightCyan.on_default().bold())
.placeholder(styling::AnsiColor::Cyan.on_default());
#[derive(Parser, Debug)]
#[command(name = "kodik", styles = STYLES, arg_required_else_help = true, about = "CLI tool for getting direct links to files from Kodik")]
pub struct Config {
#[arg(value_name = "URL", required = true)]
pub urls: Vec<Url>,
#[arg(short = 'v', long, action = ArgAction::Count, default_value = "0")]
pub verbose: u8,
#[arg(short = 's', long, conflicts_with = "verbose")]
pub silent: bool,
#[arg(short = 'q', long, value_name = "QUALITY", default_value = "720")]
pub quality: Quality,
#[arg(long, value_name = "FILE")]
pub cookies: Option<String>,
#[arg(long, value_name = "TITLE")]
pub translation_title: Option<String>,
#[arg(long, value_name = "TYPE")]
pub translation_type: Option<TranslationTypeArg>,
#[arg(long, value_name = "MODE")]
pub related_mode: Option<RelatedMode>,
}
impl Config {
pub fn build(args: Vec<String>) -> Result<Self, clap::Error> {
Self::try_parse_from(args)
}
pub const fn level_filter(&self) -> LevelFilter {
if self.silent {
LevelFilter::Off
} else {
match self.verbose {
0 => LevelFilter::Info,
1 => LevelFilter::Debug,
_ => LevelFilter::Trace,
}
}
}
pub fn load_cookies(&self) -> Result<reqwest::cookie::Jar> {
Ok(match &self.cookies {
Some(path) => Jar::load_netscape(path)?,
None => Jar::default(),
})
}
}
#[derive(Debug, Clone, Copy, Default, ValueEnum)]
#[non_exhaustive]
pub enum Quality {
#[value(name = "360")]
P360 = 360,
#[value(name = "480")]
P480 = 480,
#[default]
#[value(name = "720")]
P720 = 720,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
#[non_exhaustive]
pub enum TranslationTypeArg {
Voice,
Subtitles,
}
impl From<TranslationTypeArg> for TranslationType {
fn from(arg: TranslationTypeArg) -> Self {
match arg {
TranslationTypeArg::Voice => Self::Voice,
TranslationTypeArg::Subtitles => Self::Subtitles,
}
}
}
#[derive(Debug, Clone, Copy, ValueEnum)]
#[non_exhaustive]
pub enum RelatedMode {
#[value(name = "all")]
All,
#[value(name = "essential")]
Essential,
}