2023-09-23 15:56:21 +00:00
|
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
|
2023-09-30 17:22:55 +00:00
|
|
|
use isahc::{cookies::CookieJar, prelude::*, Request};
|
2023-09-23 15:56:21 +00:00
|
|
|
use once_cell::sync::OnceCell;
|
2023-09-30 16:16:20 +00:00
|
|
|
|
|
|
|
/// Stores a client with a persistent cookie store
|
2023-09-30 17:22:55 +00:00
|
|
|
static SESSION_COOKIE: OnceCell<CookieJar> = OnceCell::new();
|
2023-09-25 22:26:00 +00:00
|
|
|
/// Stores the last time a request was made, in seconds since UNIX epoch
|
2023-09-23 15:56:21 +00:00
|
|
|
static SESSION_TIME: OnceCell<u64> = OnceCell::new();
|
|
|
|
|
|
|
|
/// Makes a request to the online classroom, and returns the html string
|
2023-09-25 22:26:00 +00:00
|
|
|
pub async fn request(url: String) -> Result<String, String> {
|
|
|
|
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
|
|
|
|
|
|
|
|
ensure_session().await?;
|
|
|
|
|
2023-09-30 16:16:20 +00:00
|
|
|
// Get the stored client
|
2023-09-30 17:22:55 +00:00
|
|
|
let jar = SESSION_COOKIE
|
2023-09-30 16:16:20 +00:00
|
|
|
.get()
|
|
|
|
.expect("SESSION_COOKIE was not set, even after calling ensure_session");
|
2023-09-25 22:26:00 +00:00
|
|
|
|
2023-09-30 17:22:55 +00:00
|
|
|
let uri = format!("{}{}", classroom_url, url);
|
2023-09-30 16:16:20 +00:00
|
|
|
|
2023-09-30 17:22:55 +00:00
|
|
|
// Do the request
|
|
|
|
let response = Request::get(uri)
|
|
|
|
.cookie_jar(jar.clone())
|
|
|
|
.body(())
|
|
|
|
.or_else(|err| Err(format!("Error creating request: {:?}", err)))?
|
|
|
|
.send();
|
2023-09-25 22:26:00 +00:00
|
|
|
|
2023-09-30 17:22:55 +00:00
|
|
|
let mut response = match response {
|
2023-09-25 22:26:00 +00:00
|
|
|
Ok(r) => r,
|
2023-09-30 16:16:20 +00:00
|
|
|
Err(err) => return Err(format!("Error sending request: {:?}", err)),
|
2023-09-25 22:26:00 +00:00
|
|
|
};
|
|
|
|
|
2023-09-30 17:22:55 +00:00
|
|
|
match response.text() {
|
2023-09-25 22:26:00 +00:00
|
|
|
Ok(t) => Ok(t),
|
2023-09-30 16:16:20 +00:00
|
|
|
Err(err) => Err(format!("Error getting text from response: {:?}", err)),
|
2023-09-25 22:26:00 +00:00
|
|
|
}
|
2023-09-23 15:56:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes sure that the session cookie is set, and that it is valid
|
|
|
|
pub async fn ensure_session() -> Result<(), String> {
|
|
|
|
let last_usage_time = match SESSION_TIME.get() {
|
|
|
|
Some(time) => *time,
|
|
|
|
None => 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Get current time in seconds
|
|
|
|
let current_time = SystemTime::now()
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
.expect("Time went backwards")
|
|
|
|
.as_secs();
|
|
|
|
|
|
|
|
let time_passed = current_time - last_usage_time;
|
|
|
|
|
|
|
|
// Default PHP session timeout is 1440 seconds. Use a 1400 seconds timeout to be safe
|
|
|
|
if time_passed > 1400 {
|
|
|
|
login().await?;
|
|
|
|
if let Err(err) = SESSION_TIME.set(current_time) {
|
|
|
|
return Err(format!("Error setting session time: {:?}", err));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Logins to the online classroom, and sets the session cookie
|
|
|
|
async fn login() -> Result<(), String> {
|
2023-09-25 22:26:00 +00:00
|
|
|
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
|
2023-09-30 16:16:20 +00:00
|
|
|
let classroom_user =
|
2023-09-23 15:56:21 +00:00
|
|
|
std::env::var("CLASSROOM_USER").expect("CLASSROOM_USER env var is not set!");
|
2023-09-30 16:16:20 +00:00
|
|
|
let classroom_password =
|
2023-09-23 15:56:21 +00:00
|
|
|
std::env::var("CLASSROOM_PASSWORD").expect("CLASSROOM_PASSWORD env var is not set!");
|
|
|
|
|
2023-09-30 17:22:55 +00:00
|
|
|
let jar = CookieJar::new();
|
|
|
|
|
|
|
|
let response = Request::post(format!("{}/index.php", classroom_url))
|
|
|
|
.header("Content-Type", "application/x-www-form-urlencoded")
|
|
|
|
.cookie_jar(jar.clone())
|
|
|
|
.body(format!(
|
|
|
|
"login={}&password={}&submitAuth=&_qf__formLogin=",
|
|
|
|
classroom_user, classroom_password
|
|
|
|
))
|
|
|
|
.unwrap()
|
|
|
|
.send();
|
|
|
|
|
|
|
|
match response {
|
|
|
|
Ok(_) => match SESSION_COOKIE.set(jar.clone()) {
|
|
|
|
Ok(_) => Ok(()),
|
|
|
|
Err(error) => Err(format!("Error saving client: {:?}", error)),
|
|
|
|
},
|
2023-09-23 15:56:21 +00:00
|
|
|
Err(error) => Err(format!("Error connecting to online classroom: {:?}", error)),
|
|
|
|
}
|
|
|
|
}
|