mod error; mod nvd_fetcher; mod exploit_collector; use clap::Parser; use nvd_fetcher::{NvdCveFetcher, FeedType}; use exploit_collector::ExploitCollector; #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Cli { /// Type of NVD feed to download #[arg(value_enum, long, default_value_t = FeedType::Recent)] feed: FeedType, } #[tokio::main] async fn main() -> Result<(), Box> { // Parse command-line arguments let cli = Cli::parse(); // Initialize NVD CVE Fetcher let nvd_fetcher = NvdCveFetcher::new()?; // Fetch CVEs based on feed type let cves = nvd_fetcher.fetch_cves(cli.feed).await?; println!("Fetched {} CVEs", cves.len()); // Initialize ExploitCollector let collector = ExploitCollector::new()?; // Search and collect for each CVE for cve_id in cves { println!("Searching for repositories related to: {}", cve_id); match collector.search_cve_repos(&cve_id).await { Ok(repos) => { println!("Found {} repositories", repos.len()); // Save repositories to file if let Err(e) = collector.save_repositories(&cve_id, &repos) { eprintln!("Error saving repositories for {}: {}", cve_id, e); } // Print repository details (optional) for repo in &repos { println!("- {}", repo.full_name); println!(" URL: {}", repo.html_url); println!(" Stars: {}", repo.stargazers_count); if let Some(desc) = &repo.description { println!(" Description: {}", desc); } println!(); } } Err(e) => { eprintln!("Error searching for {}: {}", cve_id, e); } } } println!("Collection complete."); Ok(()) }