use std::process::exit; use reqwest::Client; use clap::Parser; use session::Session; use std::io::{stdout, IsTerminal}; use crate::config::Config; use crate::api::{get_res, get_vqd, simulate_browser_reqs}; mod config; mod api; mod session; pub const GREEN: &str = "\x1b[1;32m"; pub const RED: &str = "\x1b[1;31m"; pub const BLUE: &str = "\x1b[34m"; pub const WARN: &str = "\x1b[33m"; pub const RESET: &str = "\x1b[0m"; pub const GRAY: &str = "\x1b[30m"; #[derive(Debug, Parser)] #[command(version, about, long_about = None)] struct Args { #[arg(long, default_value = "false", required = false, help = "If you want to agree to the DuckDuckGo TOS")] pub agree_tos: bool, #[arg()] pub query: Vec, } #[tokio::main] async fn main() { femme::start(); if ! stdout().is_terminal() { eprintln!("{RED}Refusing to run in a non-terminal environment{RESET}"); eprintln!("This is done to prevent API scraping."); exit(2) } let args = Args::parse(); let query = args.query.join(" ").trim().to_string(); if query.len() == 0 { exit(0); } let mut config = Config::load().unwrap(); if args.agree_tos { if ! config.tos { println!("{GREEN}TOS accepted{RESET}"); } config.set_tos(true).expect("Error saving config"); } config.check_tos(); println!("{GREEN}Contacting DuckDuckGo chat AI...{RESET}"); let cli = Client::new(); simulate_browser_reqs(&cli).await.unwrap(); let vqd = match Session::restore_vqd() { Some(v) => { v }, None => get_vqd(&cli).await.unwrap() }; println!("{vqd:?}"); get_res(&cli, query, vqd, &config).await; }