use reqwest::{self, header::HeaderMap};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct BklrOptions {
#[serde(alias = "bak:ApiVersion")]
pub api_version: String,
#[serde(alias = "bak:AppVersion")]
pub app_version: String,
#[serde(alias = "bak:UserId")]
pub user_id: usize,
pub access_token: String,
pub refresh_token: String,
pub id_token: String,
pub expires_in: i32,
pub scope: Vec<String>
}
pub struct BklrApi {
pub url: String,
pub options: BklrOptions,
pub client: reqwest::Client
}
#[derive(Serialize, Deserialize)]
pub struct Grade {
mark_date: String,
edit_date: String,
caption: String,
theme: String,
mark_text: String, teacher_id: String,
r#type: char,
type_note: String,
weight: u8,
subject_id: usize,
is_new: bool,
is_points: bool,
calculated_mark_text: String,
class_rank_text: String, id: String,
points_text: String,
max_points: usize
}
impl BklrApi {
pub async fn get_marks(&self) -> Option<Vec<Grade>> {
let url = &self.url;
let access_token = &self.options.access_token;
let formatted_url = format!("{url}/api/3/marks");
let request = self.client.post(formatted_url).header("Authorization", format!("Bearer {access_token}")).send().await;
match request {
Ok(response) => match response.json::<Vec<Grade>>().await {
Ok(marks) => Some(marks),
Err(_) => None
}
Err(_) => None
}
}
}
pub async fn get_api(username: String, password: String, url: String) -> Option<BklrApi> {
let body = format!("client_id=ANDR&grant_type=password&username={username}&password={password}");
let mut headers = HeaderMap::new();
headers.append("Content-Type", "application/x-www-form-urlencoded".parse().unwrap());
let client = reqwest::Client::builder().default_headers(headers).build().unwrap();
let response = client.post(&url).body(body).send().await;
let options: Option<BklrOptions> = match response {
Ok(res) => Some(res.json::<BklrOptions>().await.unwrap()),
Err(why) => { println!("{}", why); None }
};
if options.is_some() {
Some(BklrApi { url, options: options.unwrap(), client })
} else {
None
}
}