use log::debug;
use reqwest::Client;
use serde::Deserialize;
use std::time::SystemTime;
use super::error::RedditError;
fn get_sys_time_in_secs() -> u64 {
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => n.as_secs(),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
}
}
#[derive(Deserialize, Debug, Clone)]
pub struct RedditAccessToken {
#[serde(rename = "access_token")]
token: String,
expires_in: u64,
#[serde(default = "get_sys_time_in_secs")]
created_at: u64,
}
impl RedditAccessToken {
pub fn is_expired(&self) -> bool {
let now = get_sys_time_in_secs();
debug!(
"Token created at: {}, expires in: {}. Now it's {}",
self.created_at, self.expires_in, now
);
self.created_at + self.expires_in < now }
pub fn token(&self) -> &str {
&self.token
}
}
#[derive(Debug, Deserialize, Hash, PartialEq, Eq, Clone)]
pub struct RedditApp {
pub client_id: String,
pub client_secret: String,
}
impl RedditApp {
pub fn new(client_id: String, client_secret: String) -> Self {
RedditApp {
client_id,
client_secret,
}
}
pub async fn fetch_access_token(
&self,
http_client: &Client,
) -> Result<RedditAccessToken, RedditError> {
let req = http_client
.post("https://www.reddit.com/api/v1/access_token")
.basic_auth(self.client_id.as_str(), Some(self.client_secret.as_str())) .header("Content-Type", "application/x-www-form-urlencoded")
.header("Accept", "application/json")
.body("grant_type=client_credentials") .build()?;
let res = http_client
.execute(req)
.await?
.json::<RedditAccessToken>()
.await?;
Ok(res)
}
}