1use std::collections::HashMap;
2
3use log::warn;
4use serde_json::Value;
5
6use crate::{auth::OAuthToken, client::NadeoApiClient};
7
8pub trait OAuthApiClient: NadeoApiClient {
9 async fn get_oauth_token(&self) -> Result<OAuthToken, String>;
11
12 async fn get_oauth_permit_and_token(
13 &self,
14 ) -> Result<(OAuthToken, tokio::sync::SemaphorePermit), String> {
15 let permit = self.rate_limit().await;
16 let token = self.get_oauth_token().await?;
18 Ok((token, permit))
19 }
20
21 async fn get_display_names<T>(
27 &self,
28 account_ids: &[T],
29 ) -> Result<HashMap<String, String>, String>
30 where
31 T: Into<String> + Clone,
32 {
33 match account_ids.len() {
34 0 => return Ok(HashMap::new()),
35 x if x > 50 => return Err("Too many account ids (max 50)".to_string()),
36 _ => (),
37 };
38
39 let account_ids = account_ids
40 .iter()
41 .cloned()
42 .map(Into::into)
43 .collect::<Vec<String>>();
44 let mut account_ids_str = account_ids.join("&accountId[]=");
45 account_ids_str.insert_str(0, "accountId[]=");
46
47 let (token, permit) = self.get_oauth_permit_and_token().await?;
48
49 let rb = self
50 .oauth_get(
51 &format!("display-names?{}", account_ids_str),
52 &token,
53 &permit,
54 )
55 .await;
56
57 let resp = rb.send().await.map_err(|e| e.to_string())?;
58 drop(permit);
59
60 let status = resp.status().clone();
61 let headers = resp.headers().clone();
62 let url = resp.url().clone();
63 let body = resp.bytes().await.map_err(|e| e.to_string())?;
64 let j: Value = serde_json::from_slice(&body).map_err(|e| e.to_string())?;
66
67 if j.is_array() && j.as_array().unwrap().is_empty() {
68 return Ok(account_ids
70 .into_iter()
71 .map(|id| (id, "".to_string()))
72 .collect());
73 }
74
75 let obj = j.as_object().ok_or_else(|| {
77 warn!(
78 "Bad response from get_display_names\nNames = {:?}\nResponse = {:?} {:?} {:?}",
79 &account_ids_str, &status, &url, &headers
80 );
81 format!("Not a json obj: {:?}", &j)
82 })?;
83 let mut hm: HashMap<_, _> = obj
84 .iter()
85 .map(|(k, v)| (k.clone(), v.as_str().unwrap_or(k).to_string()))
86 .collect();
87
88 for id in account_ids {
90 if !hm.contains_key(&id) {
91 hm.insert(id, "".to_string());
92 }
93 }
94
95 Ok(hm)
96 }
97
98 }
100
101#[cfg(test)]
102mod tests {
103 use std::env;
104
105 use super::*;
106 use crate::{
107 auth::{NadeoClient, OAuthCredentials},
108 prelude::UserAgentDetails,
109 test_helpers::{get_test_creds, get_test_email},
110 user_agent_auto,
111 };
112
113 #[ignore]
115 #[tokio::test]
116 async fn test_get_display_names() {
117 let creds = get_test_creds();
118 let client = NadeoClient::create(creds, user_agent_auto!(&get_test_email()), 10)
119 .await
120 .unwrap();
121 let client_id =
122 env::var("NADEO_API_TEST_OAUTH_ID").expect("NADEO_API_TEST_OAUTH_ID not set");
123 let client_secret =
124 env::var("NADEO_API_TEST_OAUTH_SECRET").expect("NADEO_API_TEST_OAUTH_SECRET not set");
125 let client = client
126 .with_oauth(OAuthCredentials::new(&client_id, &client_secret))
127 .unwrap();
128 let names_hm = client
129 .get_display_names(&vec![
130 "5b4d42f4-c2de-407d-b367-cbff3fe817bc",
131 "0a2d1bc0-4aaa-4374-b2db-3d561bdab1c9",
132 ])
133 .await
134 .unwrap();
135 println!("{:?}", names_hm);
136 assert_eq!(names_hm.len(), 2);
137 assert_eq!(
138 names_hm.get("5b4d42f4-c2de-407d-b367-cbff3fe817bc"),
139 Some(&"tooInfinite".to_string())
140 );
141 assert_eq!(
142 names_hm.get("0a2d1bc0-4aaa-4374-b2db-3d561bdab1c9"),
143 Some(&"XertroV".to_string())
144 );
145 }
146}