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