use clap::Parser;
#[derive(Parser, Debug)]
#[command(name = "onionize")]
#[command(version, about = "Expose local ports via Tor Onion Services", long_about = None)]
pub struct Args {
#[arg(short, long, default_value_t = 3000)]
pub port: u16,
#[arg(short = 'H', long, default_value = "127.0.0.1")]
pub host: String,
#[arg(short, long, default_value = "my-ephemeral-service")]
pub nickname: String,
#[arg(short, long, default_value_t = false)]
pub verbose: bool,
#[arg(long, default_value_t = false)]
pub qr: bool,
#[arg(long, default_value_t = false)]
pub keygen: bool,
#[arg(long)]
pub auth: Option<String>,
#[arg(long, default_value_t = false)]
pub restricted: bool,
}
impl Args {
pub fn get_normalized_host(&self) -> String {
if self.host.eq_ignore_ascii_case("localhost") {
"127.0.0.1".to_string()
} else {
self.host.clone()
}
}
pub fn get_effective_nickname(&self) -> String {
if self.nickname == "my-ephemeral-service" {
let random_bytes = rand::random::<[u8; 3]>();
format!("proxy-{}", hex::encode(random_bytes))
} else {
self.nickname.clone()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_host_normalization() {
let args = Args::parse_from(["bin", "-H", "localhost"]);
assert_eq!(args.get_normalized_host(), "127.0.0.1");
let args_ip = Args::parse_from(["bin", "-H", "192.168.1.1"]);
assert_eq!(args_ip.get_normalized_host(), "192.168.1.1");
}
#[test]
fn test_nickname_generation() {
let args = Args::parse_from(["bin"]); let nick = args.get_effective_nickname();
assert!(nick.starts_with("proxy-"));
assert_ne!(nick, "my-ephemeral-service");
let args_custom = Args::parse_from(["bin", "-n", "custom-name"]);
assert_eq!(args_custom.get_effective_nickname(), "custom-name");
}
#[test]
fn test_custom_nickname_is_static() {
let args = Args::parse_from(["bin", "-n", "static-name"]);
assert_eq!(args.get_effective_nickname(), "static-name");
assert_eq!(args.get_effective_nickname(), "static-name");
}
#[test]
fn test_nickname_generation_randomness() {
let args1 = Args::parse_from(["bin"]);
let args2 = Args::parse_from(["bin"]);
let nick1 = args1.get_effective_nickname();
let nick2 = args2.get_effective_nickname();
assert!(nick1.starts_with("proxy-"));
assert!(nick2.starts_with("proxy-"));
assert_ne!(nick1, nick2, "Generated nicknames should be different");
}
}