spotify_cli/cli/commands/
user.rs1use crate::endpoints::user::{get_current_user, get_users_profile, get_users_top_items};
2use crate::io::output::{ErrorKind, Response};
3use crate::types::{TopArtistsResponse, TopTracksResponse, UserPrivate, UserPublic};
4
5use super::with_client;
6
7pub async fn user_profile() -> Response {
8 with_client(|client| async move {
9 match get_current_user::get_current_user(&client).await {
10 Ok(Some(payload)) => match serde_json::from_value::<UserPrivate>(payload.clone()) {
11 Ok(user) => {
12 let name = user.display_name.as_deref().unwrap_or(&user.id);
13 let product = user.product.as_deref().unwrap_or("free");
14 Response::success_with_payload(200, format!("{} ({})", name, product), payload)
15 }
16 Err(_) => Response::success_with_payload(200, "User profile", payload),
17 },
18 Ok(None) => Response::err(404, "User not found", ErrorKind::NotFound),
19 Err(e) => Response::from_http_error(&e, "Failed to get user profile"),
20 }
21 })
22 .await
23}
24
25pub async fn user_top(item_type: &str, range: &str, limit: u8) -> Response {
26 let item_type = item_type.to_string();
27 let range = range.to_string();
28
29 with_client(|client| async move {
30 let time_range = match range.as_str() {
31 "short" => "short_term",
32 "medium" => "medium_term",
33 "long" => "long_term",
34 _ => "medium_term",
35 };
36
37 match get_users_top_items::get_users_top_items(
38 &client,
39 &item_type,
40 Some(time_range),
41 Some(limit),
42 None,
43 )
44 .await
45 {
46 Ok(Some(payload)) => {
47 let range_desc = match range.as_str() {
48 "short" => "4 weeks",
49 "medium" => "6 months",
50 "long" => "all time",
51 _ => "6 months",
52 };
53
54 let count = if item_type == "tracks" {
56 serde_json::from_value::<TopTracksResponse>(payload.clone())
57 .ok()
58 .map(|r| r.items.len())
59 } else {
60 serde_json::from_value::<TopArtistsResponse>(payload.clone())
61 .ok()
62 .map(|r| r.items.len())
63 };
64
65 let msg = match count {
66 Some(n) => format!("Top {} {} ({})", n, item_type, range_desc),
67 None => format!("Top {} ({})", item_type, range_desc),
68 };
69 Response::success_with_payload(200, msg, payload)
70 }
71 Ok(None) => Response::success_with_payload(
72 200,
73 format!("No top {} found", item_type),
74 serde_json::json!({ "items": [] }),
75 ),
76 Err(e) => Response::from_http_error(&e, &format!("Failed to get top {}", item_type)),
77 }
78 })
79 .await
80}
81
82pub async fn user_get(user_id: &str) -> Response {
84 let user_id = user_id.to_string();
85
86 with_client(|client| async move {
87 match get_users_profile::get_users_profile(&client, &user_id).await {
88 Ok(Some(payload)) => match serde_json::from_value::<UserPublic>(payload.clone()) {
89 Ok(user) => {
90 let name = user.display_name.as_deref().unwrap_or(&user.id);
91 Response::success_with_payload(200, name.to_string(), payload)
92 }
93 Err(_) => Response::success_with_payload(200, format!("User {}", user_id), payload),
94 },
95 Ok(None) => Response::err(404, "User not found", ErrorKind::NotFound),
96 Err(e) => Response::from_http_error(&e, "Failed to get user profile"),
97 }
98 })
99 .await
100}