1#[macro_use]
59extern crate serde_derive;
60
61pub mod metas;
62pub mod models;
63pub mod traits;
64pub mod types;
65
66mod private_model;
67
68#[cfg(feature = "default")]
69pub mod psn {
70 use crossbeam_queue::SegQueue;
71 use derive_more::Display;
72 use reqwest::{Client, ClientBuilder, Error, Proxy};
73 use serde::de::DeserializeOwned;
74 use tang_rs::{Builder, Manager, ManagerFuture, Pool, PoolRef};
75
76 use crate::traits::PSNRequest;
77 use crate::types::PSNInner;
78
79 #[derive(Debug, Clone)]
80 pub struct PSN {
81 inner: Pool<PSNInnerManager>,
82 client: Client,
83 proxy_pool: Option<Pool<ProxyPoolManager>>,
84 }
85
86 #[derive(Debug, Display)]
88 pub enum PSNError {
89 #[display(fmt = "No http client is available and/or new client can't be made.")]
90 NoClient,
91 #[display(fmt = "No psn object is available")]
92 NoPSNInner,
93 #[display(fmt = "Failed to login in to PSN")]
94 AuthenticationFail,
95 #[display(fmt = "Request is timeout")]
96 TimeOut,
97 #[display(fmt = "Error from Reqwest: {}", _0)]
98 FromReqwest(Error),
99 #[display(fmt = "Error from PSN response: {}", _0)]
100 FromPSN(String),
101 #[display(fmt = "Error from Local: {}", _0)]
102 FromStd(std::io::Error),
103 }
104
105 pub struct PSNInnerManager {
106 inner: SegQueue<PSNInner>,
107 client: Client,
108 }
109
110 impl PSNInnerManager {
111 fn new() -> Self {
112 PSNInnerManager {
113 inner: SegQueue::new(),
114 client: ClientBuilder::new()
115 .build()
116 .expect("Failed to build http client for PSNInnerManager"),
117 }
118 }
119
120 fn add_psn_inner(&self, psn: PSNInner) {
121 self.inner.push(psn);
122 }
123 }
124
125 impl Manager for PSNInnerManager {
126 type Connection = PSNInner;
127 type Error = PSNError;
128
129 fn connect(&self) -> ManagerFuture<'_, Result<Self::Connection, Self::Error>> {
130 Box::pin(async move { self.inner.pop().map_err(|_| PSNError::NoClient) })
131 }
132
133 fn is_valid<'a>(
134 &'a self,
135 conn: &'a mut Self::Connection,
136 ) -> ManagerFuture<'a, Result<(), Self::Error>> {
137 Box::pin(async move {
138 if conn.should_refresh() {
139 conn.gen_access_from_refresh(&self.client).await
140 } else {
141 Ok(())
142 }
143 })
144 }
145
146 fn is_closed(&self, _conn: &mut Self::Connection) -> bool {
147 false
148 }
149 }
150
151 pub struct ProxyPoolManager {
152 proxies: SegQueue<(String, Option<String>, Option<String>)>,
153 marker: &'static str,
154 }
155
156 impl ProxyPoolManager {
157 fn new() -> Self {
158 ProxyPoolManager {
159 proxies: SegQueue::new(),
160 marker: "www.google.com",
161 }
162 }
163
164 fn add_proxy(&self, address: &str, username: Option<&str>, password: Option<&str>) {
165 self.proxies.push((
166 address.into(),
167 username.map(Into::into),
168 password.map(Into::into),
169 ));
170 }
171 }
172
173 impl Manager for ProxyPoolManager {
174 type Connection = Client;
175 type Error = PSNError;
176
177 fn connect(&self) -> ManagerFuture<'_, Result<Self::Connection, Self::Error>> {
178 Box::pin(async move {
179 let (address, username, password) =
180 self.proxies.pop().map_err(|_| PSNError::NoClient)?;
181 let proxy = match username {
182 Some(username) => Proxy::all(&address)
183 .map(|p| p.basic_auth(&username, password.as_deref().unwrap_or(""))),
184 None => Proxy::all(&address),
185 };
186
187 Client::builder()
188 .proxy(proxy.map_err(|_| PSNError::NoClient)?)
189 .build()
190 .map_err(|_| PSNError::NoClient)
191 })
192 }
193
194 fn is_valid<'a>(
195 &'a self,
196 conn: &'a mut Self::Connection,
197 ) -> ManagerFuture<'a, Result<(), Self::Error>> {
198 Box::pin(async move {
199 let _ = conn.get(self.marker).send().await?;
200 Ok(())
201 })
202 }
203
204 fn is_closed(&self, _conn: &mut Self::Connection) -> bool {
205 false
206 }
207 }
208
209 impl From<Error> for PSNError {
210 fn from(e: Error) -> Self {
211 PSNError::FromReqwest(e)
212 }
213 }
214
215 impl From<tokio::time::Elapsed> for PSNError {
216 fn from(_: tokio::time::Elapsed) -> Self {
217 PSNError::TimeOut
218 }
219 }
220
221 impl PSN {
222 pub fn new_client() -> Result<Client, PSNError> {
224 ClientBuilder::new().build().map_err(|_| PSNError::NoClient)
225 }
226
227 pub async fn new(psn_inner: Vec<PSNInner>) -> Self {
229 let mgr = PSNInnerManager::new();
230
231 let size = psn_inner.len() as u8;
232
233 for inner in psn_inner.into_iter() {
234 mgr.add_psn_inner(inner);
235 }
236
237 let inner_pool = Builder::new()
238 .always_check(true)
239 .idle_timeout(None)
240 .max_lifetime(None)
241 .min_idle(size)
242 .max_size(size)
243 .build(mgr)
244 .await
245 .expect("Failed to build PSNInner pool");
246
247 PSN {
248 inner: inner_pool,
249 client: Self::new_client().expect("Failed to build http client"),
250 proxy_pool: None,
251 }
252 }
253
254 pub async fn init_proxy(
284 mut self,
285 proxies: Vec<(&str, Option<&str>, Option<&str>)>,
286 ) -> Self {
287 let mgr = ProxyPoolManager::new();
288 let size = proxies.len() as u8;
289 for (address, username, password) in proxies.into_iter() {
290 mgr.add_proxy(address, username, password);
291 }
292
293 let pool = Builder::new()
294 .always_check(false)
295 .idle_timeout(None)
296 .max_lifetime(None)
297 .min_idle(size)
298 .max_size(size)
299 .build(mgr)
300 .await
301 .expect("Failed to build proxy pool");
302
303 self.proxy_pool = Some(pool);
304 self
305 }
306
307 pub fn add_proxy(&self, proxies: Vec<(&str, Option<&str>, Option<&str>)>) {
311 if let Some(pool) = &self.proxy_pool {
312 for (address, username, password) in proxies.into_iter() {
313 pool.get_manager().add_proxy(address, username, password);
314 }
315 }
316 }
317
318 pub async fn get_profile<T: DeserializeOwned + 'static>(
319 &self,
320 online_id: &str,
321 ) -> Result<T, PSNError> {
322 let (client, psn_inner) = self.get().await?;
323
324 psn_inner.get_profile(&client, online_id).await
325 }
326
327 pub async fn get_titles<T: DeserializeOwned + 'static>(
328 &self,
329 online_id: &str,
330 offset: u32,
331 ) -> Result<T, PSNError> {
332 let (client, psn_inner) = self.get().await?;
333
334 psn_inner.get_titles(&client, online_id, offset).await
335 }
336
337 pub async fn get_trophy_set<T: DeserializeOwned + 'static>(
338 &self,
339 online_id: &str,
340 np_communication_id: &str,
341 ) -> Result<T, PSNError> {
342 let (client, psn_inner) = self.get().await?;
343
344 psn_inner
345 .get_trophy_set(&client, online_id, np_communication_id)
346 .await
347 }
348
349 pub async fn get_message_threads<T: DeserializeOwned + 'static>(
350 &self,
351 offset: u32,
352 ) -> Result<T, PSNError> {
353 let (client, psn_inner) = self.get().await?;
354
355 psn_inner.get_message_threads(&client, offset).await
356 }
357
358 pub async fn get_message_thread<T: DeserializeOwned + 'static>(
359 &self,
360 thread_id: &str,
361 ) -> Result<T, PSNError> {
362 let (client, psn_inner) = self.get().await?;
363
364 psn_inner.get_message_thread(&client, thread_id).await
365 }
366
367 pub async fn generate_message_thread(&self, online_id: &str) -> Result<(), PSNError> {
368 let (client, psn_inner) = self.get().await?;
369
370 psn_inner.generate_message_thread(&client, online_id).await
371 }
372
373 pub async fn leave_message_thread(&self, thread_id: &str) -> Result<(), PSNError> {
374 let (client, psn_inner) = self.get().await?;
375
376 psn_inner.leave_message_thread(&client, thread_id).await
377 }
378
379 pub async fn send_message(
380 &self,
381 online_id: &str,
382 msg: Option<&str>,
383 path: Option<&str>,
384 thread_id: &str,
385 ) -> Result<(), PSNError> {
386 let (client, psn_inner) = self.get().await?;
387
388 psn_inner
389 .send_message(&client, online_id, msg, path, thread_id)
390 .await
391 }
392
393 pub async fn search_store_items<T: DeserializeOwned + 'static>(
394 &self,
395 lang: &str,
396 region: &str,
397 age: &str,
398 name: &str,
399 ) -> Result<T, PSNError> {
400 let (client, psn_inner) = self.get().await?;
401
402 psn_inner
403 .search_store_items(&client, lang, region, age, name)
404 .await
405 }
406
407 async fn get(&self) -> Result<(Client, PoolRef<'_, PSNInnerManager>), PSNError> {
408 let proxy_ref = self.get_proxy_cli().await?;
409 let inner_ref = self.inner.get().await?;
410
411 let client = match proxy_ref.as_ref() {
412 Some(proxy_ref) => (&**proxy_ref).clone(),
413 None => (&self.client).clone(),
414 };
415
416 drop(proxy_ref);
417
418 Ok((client, inner_ref))
419 }
420
421 async fn get_proxy_cli(&self) -> Result<Option<PoolRef<'_, ProxyPoolManager>>, PSNError> {
422 let fut = match self.proxy_pool.as_ref() {
423 Some(pool) => pool.get(),
424 None => return Ok(None),
425 };
426 let pool_ref = fut.await?;
427 Ok(Some(pool_ref))
428 }
429
430 pub fn clients_state(&self) -> u8 {
431 self.proxy_pool
432 .as_ref()
433 .map(|pool| pool.state().idle_connections)
434 .unwrap_or(0)
435 }
436 }
437}