Skip to main content

htb_cli/cli/
user.rs

1use clap::Subcommand;
2
3use crate::api::HtbClient;
4use crate::output::{self, OutputFormat};
5
6#[derive(Subcommand)]
7pub enum UserCommand {
8    /// Show your profile
9    Me,
10    /// Show another user's profile
11    Info {
12        /// Username or user ID
13        user: String,
14    },
15}
16
17pub async fn handle(
18    client: &HtbClient,
19    cmd: UserCommand,
20    format: OutputFormat,
21) -> anyhow::Result<()> {
22    match cmd {
23        UserCommand::Me => {
24            let current = client.user().current().await?;
25            let profile = client.user().profile(current.id).await?;
26            let fields = vec![
27                ("Username", profile.name.clone()),
28                ("ID", profile.id.to_string()),
29                ("Rank", profile.rank.clone().unwrap_or_default()),
30                ("Points", profile.points.to_string()),
31                (
32                    "Ranking",
33                    profile
34                        .ranking
35                        .map(|r| format!("#{r}"))
36                        .unwrap_or_else(|| "-".into()),
37                ),
38                ("User Owns", profile.user_owns.to_string()),
39                ("System Owns", profile.system_owns.to_string()),
40                ("User Bloods", profile.user_bloods.to_string()),
41                ("System Bloods", profile.system_bloods.to_string()),
42                ("Country", profile.country_name.clone().unwrap_or_default()),
43                ("Server", profile.server.clone().unwrap_or_default()),
44            ];
45            output::print_detail(&profile, format, &fields);
46        }
47
48        UserCommand::Info { user } => {
49            let user_id: u64 = match user.parse() {
50                Ok(id) => id,
51                Err(_) => {
52                    anyhow::bail!("Please provide a numeric user ID. Username lookup is not supported by the API.");
53                }
54            };
55            let profile = client.user().profile(user_id).await?;
56            let fields = vec![
57                ("Username", profile.name.clone()),
58                ("ID", profile.id.to_string()),
59                ("Rank", profile.rank.clone().unwrap_or_default()),
60                ("Points", profile.points.to_string()),
61                (
62                    "Ranking",
63                    profile
64                        .ranking
65                        .map(|r| format!("#{r}"))
66                        .unwrap_or_else(|| "-".into()),
67                ),
68                ("User Owns", profile.user_owns.to_string()),
69                ("System Owns", profile.system_owns.to_string()),
70                ("Country", profile.country_name.clone().unwrap_or_default()),
71            ];
72            output::print_detail(&profile, format, &fields);
73        }
74    }
75    Ok(())
76}