136 lines
4.4 KiB
Rust
136 lines
4.4 KiB
Rust
use crate::{json_result::JsonResult, model::classroom_user::ClassroomPerson};
|
|
|
|
use super::session::request;
|
|
use rocket::{http::Status, serde::json::Json};
|
|
use scraper::{ElementRef, Html, Selector};
|
|
use urlencoding::encode;
|
|
|
|
|
|
|
|
// Instead of requesting pages and managing session & cookies manually,
|
|
// create a wrapper that:
|
|
// - Checks if the session cookie is valid
|
|
// - If not, tries to login
|
|
// - Makes the request
|
|
// - Returns the html string, or an error
|
|
|
|
#[get("/classroom/users/<full_name>")]
|
|
pub async fn get_users(full_name: String) -> (Status, Json<JsonResult<Vec<ClassroomPerson>>>) {
|
|
let html = request(format!(
|
|
"/main/admin/user_list.php?keyword={}&submit=&_qf__search_simple=",
|
|
encode(full_name.as_str())
|
|
))
|
|
.await;
|
|
|
|
match html {
|
|
Ok(html) => match parse_users(&html) {
|
|
Ok(users) => (Status::Ok, JsonResult::ok(users)),
|
|
Err(reason) => {
|
|
// println!("{}", html);
|
|
(Status::InternalServerError, JsonResult::err(reason))
|
|
}
|
|
},
|
|
Err(reason) => (Status::InternalServerError, JsonResult::err(reason)),
|
|
}
|
|
}
|
|
|
|
fn parse_users(file: &str) -> Result<Vec<ClassroomPerson>, String> {
|
|
// Selectors
|
|
let Ok(form_selector) = Selector::parse("form#form_users_id") else {
|
|
return Err("Error parsing form#form_users_id selector".into());
|
|
};
|
|
let Ok(tr_selector) = Selector::parse("tr:not(:first-child)") else {
|
|
return Err("Error parsing tr:not(:first-child) selector".into());
|
|
};
|
|
let Ok(td_selector) = Selector::parse("td") else {
|
|
return Err("Error parsing td selector".into());
|
|
};
|
|
|
|
let fragment = Html::parse_document(file);
|
|
|
|
let form_element = match fragment.select(&form_selector).next() {
|
|
Some(el) => el,
|
|
// If the form is not found, it may mean that no users were found
|
|
None => {
|
|
let Ok(secondary_button) = Selector::parse("#img_plus_and_minus") else {
|
|
return Err("Error parsing secondary button selector".into());
|
|
};
|
|
|
|
match fragment.select(&secondary_button).next() {
|
|
Some(_) => return Ok(Vec::new()),
|
|
None => return Err("Error parsing html: no form or empty form found.".into()),
|
|
}
|
|
}
|
|
};
|
|
|
|
let mut result_vec = Vec::new();
|
|
for element in form_element.select(&tr_selector) {
|
|
let td_vec: Vec<_> = element.select(&td_selector).collect();
|
|
|
|
if td_vec.len() != 12 {
|
|
return Err(format!(
|
|
"Error parsing tr: td elements count is not 12, but {}",
|
|
td_vec.len()
|
|
));
|
|
}
|
|
|
|
result_vec.push(get_person_data(&td_vec)?);
|
|
}
|
|
|
|
Ok(result_vec)
|
|
}
|
|
|
|
fn get_person_data(td_vec: &Vec<ElementRef>) -> Result<ClassroomPerson, String> {
|
|
// Surnames
|
|
let surname_ref = td_vec[3];
|
|
let name_ref = td_vec[4];
|
|
let username_ref = td_vec[5];
|
|
|
|
// Selectors
|
|
let a_selector = Selector::parse("a").expect("Error parsing `a` selector");
|
|
|
|
//
|
|
// Get the href of the surname link
|
|
//
|
|
let surnames_a_node = surname_ref
|
|
.first_child()
|
|
.ok_or("Expected the 3rd td element to have a children")?;
|
|
|
|
let surnames_a_element = surnames_a_node
|
|
.value()
|
|
.as_element()
|
|
.ok_or("Expected the 3rd td element to have an html children")?;
|
|
|
|
let href_value = surnames_a_element
|
|
.attr("href")
|
|
.ok_or("Expected the 3rd td element's children to have an href attribute")?;
|
|
|
|
// Get the surname
|
|
let Some(surname_a_element) = surname_ref.select(&a_selector).next() else {
|
|
return Err("Expected the 3rd td element to have an `a` element".into());
|
|
};
|
|
let surname = surname_a_element.inner_html();
|
|
|
|
// Get the name
|
|
let Some(surnames_a_element) = name_ref.select(&a_selector).next() else {
|
|
return Err("Expected the 4th td element to have an `a` element".into());
|
|
};
|
|
let name = surnames_a_element.inner_html();
|
|
|
|
// Get the username
|
|
let username = username_ref.inner_html();
|
|
|
|
// Parse user_id from href
|
|
// format: https://testing.aulavirtual.eegsac.com/main/admin/user_information.php?user_id=1087
|
|
// Get the position of 'user_id='
|
|
let user_id_start = href_value.find("user_id=").ok_or("Error parsing user_id")? + 8;
|
|
let user_id = href_value[user_id_start..].to_string();
|
|
|
|
Ok(ClassroomPerson {
|
|
name,
|
|
surname,
|
|
username,
|
|
user_id,
|
|
})
|
|
}
|