1use std::env;
8use std::net::UdpSocket;
9use std::process::Command;
10use owo_colors::OwoColorize;
11use atty;
12use get_if_addrs::get_if_addrs;
13pub fn print_host_summary() -> Result<(), String> {
18 if atty::is(atty::Stream::Stdout) {
20 }
22 println!("\n{}", "======HOST INFORMATION======".bright_yellow().bold());
23 let hostname = current_hostname().unwrap_or_else(|| "(unknown)".to_string());
24 let primary_ip = discover_primary_ip().unwrap_or_else(|| "(unavailable)".to_string());
25 println!("{} {}", "🖥️ Hostname :".bright_blue().bold(), hostname.white());
26 println!("{} {}", "🌐 Primary IP :".cyan().bold(), primary_ip.white());
27 println!("{} {} {}", "🧰 Platform :".magenta().bold(), env::consts::OS.white(), env::consts::ARCH.white());
28 println!("{} {}", "🗓️ Rust env :".bright_cyan().bold(), env::var("RUSTUP_TOOLCHAIN").unwrap_or_else(|_| "default".into()).bright_white());
29 println!("{}", "---------------------------------\n".bright_black());
30 Ok(())
31}
32
33pub fn print_network_summary() -> Result<(), String> {
34 println!("\n{}", "====== NETWORK INTERFACES ======".bright_yellow().bold());
35 let ifaces = get_if_addrs().map_err(|e| format!("Failed to get network interfaces: {}", e))?;
36 for iface in ifaces {
37 let name_colored = iface.name.bright_blue();
38 let ip = iface.addr.ip();
39 let ip_string = ip.to_string();
40 let ip_colored = ip_string.white();
41 println!("🔸 {} {}", name_colored, ip_colored);
42 }
43 println!("{}", "---------------------------------".bright_black());
44 Ok(())
45}
46
47fn current_hostname() -> Option<String> {
48 if let Ok(value) = env::var("HOSTNAME") {
50 if !value.is_empty() {
51 return Some(value);
52 }
53 }
54 if cfg!(target_os = "windows") {
55 if let Ok(value) = env::var("COMPUTERNAME") {
56 if !value.is_empty() {
57 return Some(value);
58 }
59 }
60 }
61
62 Command::new(if cfg!(target_os = "windows") { "hostname" } else { "hostname" })
64 .output()
65 .ok()
66 .and_then(|out| String::from_utf8(out.stdout).ok())
67 .map(|s| s.trim().to_string())
68 .filter(|s| !s.is_empty())
69}
70
71fn discover_primary_ip() -> Option<String> {
72 UdpSocket::bind(("0.0.0.0", 0))
75 .ok()
76 .and_then(|socket| {
77 socket
78 .connect(("8.8.8.8", 80))
79 .ok()
80 .and_then(|_| socket.local_addr().ok())
81 })
82 .map(|addr| addr.ip().to_string())
83}