1use log::debug;
2use reqwest::header::{HeaderValue, AUTHORIZATION, CONTENT_LENGTH};
3pub use reqwest::{Error as RqError, RequestBuilder, Response};
4pub use serde_json::Value;
5use tokio::sync::{SemaphorePermit, TryLockError};
6
7use crate::{auth::*, urls::*};
8
9pub enum MonthlyCampaignType {
10 Royal,
11 TOTD,
12}
13
14pub async fn run_req<'a>(
16 (req, permit): (RequestBuilder, SemaphorePermit<'a>),
17) -> Result<Value, RqError> {
18 let start = std::time::Instant::now();
19 let (client, req) = req.build_split();
21 let req = req?;
22 let url = req.url().to_string();
23 let resp = client.execute(req).await?;
24 let resp = resp.error_for_status()?;
25 let r = resp.json().await?;
26 debug!(
27 "Request took: {:.3} s ( URL = {} )",
28 start.elapsed().as_secs_f64(),
29 url
30 );
31 drop(permit);
32 Ok(r)
33}
34
35pub trait NadeoApiClient {
36 async fn get_client(&self) -> &reqwest::Client;
37
38 async fn rate_limit(&self) -> SemaphorePermit;
39
40 async fn get_file_size(&self, url: &str) -> Result<u64, RqError> {
41 let resp = self.get_client().await.head(url).send().await?;
42 Ok(resp
43 .headers()
44 .get(CONTENT_LENGTH)
45 .map_or(0, |v| v.to_str().unwrap_or("0").parse().unwrap_or(1)))
46 }
47
48 fn get_auth_token(&self, audience: NadeoAudience) -> Result<String, TryLockError>;
49
50 async fn aget_auth_token(&self, audience: NadeoAudience) -> String;
51
52 fn get_auth_header(&self, audience: NadeoAudience) -> Result<String, TryLockError> {
53 Ok(format!("nadeo_v1 t={}", &self.get_auth_token(audience)?))
54 }
55
56 async fn aget_auth_header(&self, audience: NadeoAudience) -> String {
57 format!("nadeo_v1 t={}", &self.aget_auth_token(audience).await)
58 }
59
60 async fn get_auth_header_value(&self, audience: NadeoAudience) -> HeaderValue {
61 let mut hv = HeaderValue::from_str(&self.aget_auth_header(audience).await).unwrap();
62 hv.set_sensitive(true);
63 hv
64 }
65
66 async fn oauth_get<'a>(
67 &self,
68 path: &str,
69 token: &OAuthToken,
70 _permit: &SemaphorePermit<'a>,
71 ) -> RequestBuilder {
72 let rb = self
73 .get_client()
74 .await
75 .get(&format!("{}{}", OAUTH_URL, path))
76 .header(AUTHORIZATION, token.get_authz_header());
77 rb
78 }
79
80 async fn core_get(&self, path: &str) -> (RequestBuilder, SemaphorePermit) {
81 (
82 self.get_client()
83 .await
84 .get(&format!("{}{}", CORE_URL, path))
85 .header(AUTHORIZATION, self.get_auth_header_value(Core).await),
86 self.rate_limit().await,
87 )
88 }
89
90 async fn run_core_get(&self, path: &str) -> Result<Value, RqError> {
91 run_req(self.core_get(path).await).await
92 }
93
94 async fn core_post_bytes(&self, path: &str, body: &[u8]) -> (RequestBuilder, SemaphorePermit) {
95 (
96 self.get_client()
97 .await
98 .post(&format!("{}{}", CORE_URL, path))
99 .header(AUTHORIZATION, self.get_auth_header_value(Core).await)
100 .body(body.to_vec()),
101 self.rate_limit().await,
102 )
103 }
104 async fn run_core_post_bytes(&self, path: &str, body: &[u8]) -> Result<Value, RqError> {
105 run_req(self.core_post_bytes(path, body).await).await
106 }
107
108 async fn core_post(&self, path: &str, body: &Value) -> (RequestBuilder, SemaphorePermit) {
109 (
110 self.get_client()
111 .await
112 .post(&format!("{}{}", CORE_URL, path))
113 .header(AUTHORIZATION, self.get_auth_header_value(Core).await)
114 .json(body),
115 self.rate_limit().await,
116 )
117 }
118 async fn run_core_post(&self, path: &str, body: &Value) -> Result<Value, RqError> {
119 run_req(self.core_post(path, body).await).await
120 }
121
122 async fn live_get(&self, path: &str) -> (RequestBuilder, SemaphorePermit) {
123 (
124 self.get_client()
125 .await
126 .get(&format!("{}{}", LIVE_URL, path))
127 .header(AUTHORIZATION, self.get_auth_header_value(Live).await),
128 self.rate_limit().await,
129 )
130 }
131 async fn run_live_get(&self, path: &str) -> Result<Value, RqError> {
132 run_req(self.live_get(path).await).await
133 }
134
135 async fn live_post_bytes(&self, path: &str, body: &[u8]) -> (RequestBuilder, SemaphorePermit) {
136 (
137 self.get_client()
138 .await
139 .post(&format!("{}{}", LIVE_URL, path))
140 .header(AUTHORIZATION, self.get_auth_header_value(Live).await)
141 .body(body.to_vec()),
142 self.rate_limit().await,
143 )
144 }
145 async fn run_live_post_bytes(&self, path: &str, body: &[u8]) -> Result<Value, RqError> {
146 run_req(self.live_post_bytes(path, body).await).await
147 }
148
149 async fn live_post(&self, path: &str, body: &Value) -> (RequestBuilder, SemaphorePermit) {
150 (
151 self.get_client()
152 .await
153 .post(&format!("{}{}", LIVE_URL, path))
154 .header(AUTHORIZATION, self.get_auth_header_value(Live).await)
155 .json(body),
156 self.rate_limit().await,
157 )
158 }
159 async fn run_live_post(&self, path: &str, body: &Value) -> Result<Value, RqError> {
160 run_req(self.live_post(path, body).await).await
161 }
162
163 async fn meet_get(&self, path: &str) -> (RequestBuilder, SemaphorePermit) {
164 (
165 self.get_client()
166 .await
167 .get(&format!("{}{}", MEET_URL, path))
168 .header(AUTHORIZATION, self.get_auth_header_value(Live).await),
169 self.rate_limit().await,
170 )
171 }
172 async fn run_meet_get(&self, path: &str) -> Result<Value, RqError> {
173 run_req(self.meet_get(path).await).await
174 }
175
176 async fn meet_post_bytes(&self, path: &str, body: &[u8]) -> (RequestBuilder, SemaphorePermit) {
177 (
178 self.get_client()
179 .await
180 .post(&format!("{}{}", MEET_URL, path))
181 .header(AUTHORIZATION, self.get_auth_header_value(Live).await)
182 .body(body.to_vec()),
183 self.rate_limit().await,
184 )
185 }
186 async fn run_meet_post_bytes(&self, path: &str, body: &[u8]) -> Result<Value, RqError> {
187 run_req(self.meet_post_bytes(path, body).await).await
188 }
189
190 async fn meet_post(&self, path: &str, body: &Value) -> (RequestBuilder, SemaphorePermit) {
191 (
192 self.get_client()
193 .await
194 .post(&format!("{}{}", MEET_URL, path))
195 .header(AUTHORIZATION, self.get_auth_header_value(Live).await)
196 .json(body),
197 self.rate_limit().await,
198 )
199 }
200 async fn run_meet_post(&self, path: &str, body: &Value) -> Result<Value, RqError> {
201 run_req(self.meet_post(path, body).await).await
202 }
203}