eeg_certs/backend/src/online_classroom/session.rs

138 lines
4.2 KiB
Rust
Raw Normal View History

use std::time::{SystemTime, UNIX_EPOCH};
use once_cell::sync::OnceCell;
2023-09-30 16:16:20 +00:00
use reqwest::{cookie::Jar, Client, Url};
2023-09-30 16:16:20 +00:00
use std::io::prelude::*;
/// Stores a client with a persistent cookie store
static SESSION_COOKIE: OnceCell<Client> = OnceCell::new();
2023-09-25 22:26:00 +00:00
/// Stores the last time a request was made, in seconds since UNIX epoch
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
let client = SESSION_COOKIE
.get()
.expect("SESSION_COOKIE was not set, even after calling ensure_session");
2023-09-25 22:26:00 +00:00
// Do the request
2023-09-30 16:16:20 +00:00
let req_builder = client
2023-09-25 22:26:00 +00:00
.get(format!("{}{}", classroom_url, url))
2023-09-30 16:16:20 +00:00
.build()
.unwrap();
println!("{:?}", req_builder);
let response = client.execute(req_builder).await;
2023-09-25 22:26:00 +00:00
let response = match response {
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 16:16:20 +00:00
// Check if there's a new cookie
if let Some(session_cookie) = response.cookies().find(|c| c.name() == "ch_sid") {
println!("new cookie: {}", session_cookie.value());
}
2023-09-25 22:26:00 +00:00
match response.text().await {
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
}
}
/// 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 =
std::env::var("CLASSROOM_USER").expect("CLASSROOM_USER env var is not set!");
2023-09-30 16:16:20 +00:00
let classroom_password =
std::env::var("CLASSROOM_PASSWORD").expect("CLASSROOM_PASSWORD env var is not set!");
let params = [
2023-09-30 16:16:20 +00:00
("login", classroom_user),
("password", classroom_password),
("submitAuth", "".into()),
("_qf__formLogin", "".into()),
];
2023-09-30 16:16:20 +00:00
let jar = Jar::default();
let client = Client::builder()
.cookie_store(true)
.cookie_provider(jar.into())
.build()
.unwrap();
// let client = Client::new();
let req = client
2023-09-25 22:26:00 +00:00
.post(format!("{}/index.php", classroom_url))
.form(&params)
2023-09-30 16:16:20 +00:00
.build().unwrap();
println!("{:?}\n", req);
let body_bytes= req.body().unwrap().as_bytes().unwrap();
println!("{:?}\n", std::str::from_utf8(body_bytes));
let result = client.execute(req)
.await;
match result {
Ok(response) => {
2023-09-30 16:16:20 +00:00
println!("{:?}\n\n", response);
let Some(session_cookie) = response.cookies().find(|c| c.name() == "ch_sid") else {
2023-09-30 16:16:20 +00:00
return Err("Response succeeded, but no session cookie was found".into());
};
2023-09-30 16:16:20 +00:00
// Save the client with the session cookie
println!("Got a cookie: {}", session_cookie.value());
let text = response.text().await.unwrap();
// save text to file
let mut f = std::fs::File::create("scraps/test.html").unwrap();
f.write_all(text.as_bytes()).unwrap();
match SESSION_COOKIE.set(client) {
Ok(_) => Ok(()),
2023-09-30 16:16:20 +00:00
Err(error) => Err(format!("Error saving client: {:?}", error)),
}
}
Err(error) => Err(format!("Error connecting to online classroom: {:?}", error)),
}
}