whoxydse 0.1.1

Discover related top-level domains using Whoxy API: historical WHOIS, reverse WHOIS, and DNS verification
use crate::models::PivotConfig;
use clap::Parser;

/// WhoxyDSE - Discover related domains using Whoxy API
#[derive(Parser, Debug)]
#[command(name = "whoxydse")]
#[command(about = "Discover related top-level domains using Whoxy API", long_about = None)]
pub struct Config {
    /// Target domain to analyze
    #[arg(short, long)]
    pub domain: String,

    /// Whoxy API key (can also be set via WHOXY_API_KEY environment variable)
    #[arg(short = 'k', long = "api-key")]
    pub api_key: Option<String>,

    /// Use registrant/admin/tech names for reverse WHOIS lookup
    #[arg(long = "use-name", default_value_t = true)]
    pub use_name: bool,

    /// Don't use names for reverse WHOIS lookup
    #[arg(long = "no-name", conflicts_with = "use_name")]
    pub no_name: bool,

    /// Use email addresses for reverse WHOIS lookup
    #[arg(long = "use-email", default_value_t = true)]
    pub use_email: bool,

    /// Don't use emails for reverse WHOIS lookup
    #[arg(long = "no-email", conflicts_with = "use_email")]
    pub no_email: bool,

    /// Use company/organization names for reverse WHOIS lookup
    #[arg(long = "use-company", default_value_t = true)]
    pub use_company: bool,

    /// Don't use companies for reverse WHOIS lookup
    #[arg(long = "no-company", conflicts_with = "use_company")]
    pub no_company: bool,

    /// Continue with available APIs even if some fail (skip failed APIs)
    #[arg(long = "continue-on-fail")]
    pub continue_on_fail: bool,

    /// Verbose mode: show detailed HTTP requests and responses
    #[arg(short = 'v', long = "verbose")]
    pub verbose: bool,

    /// Manual identifier: name to search for (can be used multiple times)
    #[arg(long = "search-name")]
    pub search_names: Vec<String>,

    /// Manual identifier: email to search for (can be used multiple times)
    #[arg(long = "search-email")]
    pub search_emails: Vec<String>,

    /// Manual identifier: company to search for (can be used multiple times)
    #[arg(long = "search-company")]
    pub search_companies: Vec<String>,
}

impl Config {
    /// Get the API key from CLI arg or environment variable
    pub fn api_key(&self) -> String {
        self.api_key
            .clone()
            .or_else(|| std::env::var("WHOXY_API_KEY").ok())
            .expect("API key must be provided via --api-key flag or WHOXY_API_KEY environment variable")
    }

    /// Get the pivot configuration based on CLI flags
    pub fn pivot_config(&self) -> PivotConfig {
        PivotConfig {
            use_name: self.use_name && !self.no_name,
            use_email: self.use_email && !self.no_email,
            use_company: self.use_company && !self.no_company,
        }
    }
}