rarbg_api/token.rs
1extern crate reqwest;
2
3use std::collections::HashMap;
4use std::time::SystemTime;
5
6use crate::ENDPOINT;
7use crate::USER_AGENT;
8
9use reqwest::{Client, Response};
10use serde::{Deserialize, Serialize};
11
12#[derive(Clone, Serialize, Deserialize, Debug)]
13pub struct Token {
14 value: String,
15 created_at: SystemTime,
16}
17
18impl Token {
19 /// Return the value of the token obtained from the API.
20 ///
21 /// # Example
22 ///
23 /// ```no_run
24 /// use rarbg_api::token::Token;
25 ///
26 /// #[tokio::main]
27 /// async fn main() {
28 /// let token = Token::new("RustExample").await;
29 /// let value = token.value();
30 /// }
31 /// ```
32 pub fn value(&self) -> &str {
33 self.value.as_str()
34 }
35
36 /// Returns the time when the token was created.
37 ///
38 /// # Example
39 ///
40 /// ```no_run
41 /// use rarbg_api::token::Token;
42 ///
43 /// #[tokio::main]
44 /// async fn main() {
45 /// let token = Token::new("RustExample").await;
46 /// let time_of_creation = token.created_at();
47 /// }
48 /// ```
49 pub fn created_at(&self) -> &SystemTime {
50 &self.created_at
51 }
52
53 /// Create a Token with the value obtained from the API.
54 /// This token can be use to make requests to the API.
55 ///
56 /// # Panics
57 ///
58 /// Panics if a token cannot be retrieve from the API.
59 ///
60 /// # Example
61 ///
62 /// ```no_run
63 /// use rarbg_api::token::Token;
64 ///
65 /// #[tokio::main]
66 /// async fn main() {
67 /// let token = Token::new("RustExample").await;
68 /// }
69 /// ```
70 pub async fn new(app_id: &str) -> Self {
71 let response = Token::get(app_id).await;
72 let content = Token::parse(response).await;
73 let value = content.get("token");
74 match value {
75 Some(token) => Token {
76 value: token.clone(),
77 created_at: SystemTime::now(),
78 },
79 None => panic!("Failed to retrieve a token from RARBG API."),
80 }
81 }
82
83 async fn get(app_id: &str) -> Response {
84 let client: Client = Client::builder().user_agent(USER_AGENT).build().unwrap();
85 let response = client
86 .get(ENDPOINT)
87 .query(&[("get_token", "get_token")])
88 .query(&[("app_id", app_id)])
89 .send()
90 .await;
91 match response {
92 Ok(response) => response,
93 Err(reason) => panic!("{}", reason),
94 }
95 }
96
97 async fn parse(response: Response) -> HashMap<String, String> {
98 match response.json().await {
99 Ok(json) => json,
100 Err(reason) => panic!("{}", reason),
101 }
102 }
103
104 /// Verifies that the token is still valid to use it with the API.
105 /// Officially, a token is valid for 15 minutes but we keep this token valid for 10 minutes.
106 ///
107 /// # Example
108 ///
109 /// ```no_run
110 /// use rarbg_api::token::Token;
111 ///
112 /// #[tokio::main]
113 /// async fn main() {
114 /// let token = Token::new("RustExample").await;
115 /// assert!(token.is_valid(), "Token should be valid !");
116 /// }
117 /// ```
118 pub fn is_valid(&self) -> bool {
119 let sys_time = SystemTime::now();
120 let difference = sys_time.duration_since(self.created_at);
121 match difference {
122 Ok(duration) => {
123 duration.as_secs() as f64 + f64::from(duration.subsec_nanos()) * 1e-9 < 600.0
124 } // < 10 min
125 Err(_) => false,
126 }
127 }
128}