torbridge-cli 0.1.1

A CLI tool to get Tor Bridges from BridgeDB
Documentation
use std::error::Error;
use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;

use viuer::{print_from_file, Config};

fn base64_to_image(base64_image: &str) -> Result<(), Box<dyn Error>> {
    #[allow(deprecated)]
    let decoded_image = base64::decode(base64_image.replace("data:image/jpeg;base64,", ""))?;

    let mut file_path = dirs::cache_dir().unwrap_or(PathBuf::new());
    file_path.push(".bridgedb_captcha.jpeg");

    let mut file = fs::File::create(file_path)?;

    file.write_all(&decoded_image)?;

    Ok(())
}

fn prompt_transport_mode(transport_modes: &[(String, String)]) -> String {
    for (index, (_key, value)) in transport_modes.iter().enumerate() {
        println!("[{}] {}", index, value);
    }

    let mut user_input = String::new();
    print!("Choose your transport: ");
    io::stdout().flush().unwrap();
    io::stdin().read_line(&mut user_input).unwrap();

    match user_input.trim().parse::<usize>() {
        Ok(index) if index < transport_modes.len() => transport_modes[index].0.to_string(),
        _ => "obfs4".to_string(),
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    eprintln!("Getting available transports from BridgeDB");

    let transport_modes = lib::get_transport_modes().await?;

    let transport = prompt_transport_mode(&transport_modes);

    let captcha = lib::request_transport(&transport).await?;

    base64_to_image(&captcha.0)?;

    let viuer_config = Config {
        transparent: false,
        absolute_offset: false,
        x: 0,
        y: 0,
        restore_cursor: false,
        width: None,
        height: None,
        truecolor: true,
        use_kitty: true,
        use_iterm: true,
    };

    let mut file_path = dirs::cache_dir().unwrap_or(PathBuf::new());
    file_path.push(".bridgedb_captcha.jpeg");

    print_from_file(&file_path, &viuer_config)?;

    print!("Enter the captcha: ");
    io::stdout().flush().unwrap();

    let mut captcha_answer = String::new();
    io::stdin()
        .read_line(&mut captcha_answer)
        .expect("Failed to read line");

    let bridgedb_response =
        lib::submit_answer(&transport, captcha.1, captcha_answer.trim().to_string()).await?;

    println!("Your bridges:\n{}", bridgedb_response);

    fs::remove_file(file_path)?;

    Ok(())
}